Skip to content

Commit b2e5ee1

Browse files
committed
first iteration of fix
1 parent 94c0a0b commit b2e5ee1

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/bde/types/bdlb_nullablevalue.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ class NullableValue : public bsl::optional<T> {
2020
const T &value() const &;
2121
T &value() &;
2222

23+
constexpr T &makeValue();
24+
25+
template <typename U>
26+
constexpr T &makeValue(U&& v);
27+
28+
template <typename... ARGS>
29+
constexpr T &makeValueInplace(ARGS &&... args);
30+
2331
// 'operator bool' is inherited from bsl::optional
2432

2533
constexpr bool isNull() const noexcept;

clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ void nullable_value_after_swap(BloombergLP::bdlb::NullableValue<int> &opt1, Bloo
141141
}
142142
}
143143

144+
void nullable_value_make_value(BloombergLP::bdlb::NullableValue<int> &opt1, BloombergLP::bdlb::NullableValue<int> &opt2) {
145+
if (opt1.isNull()) {
146+
opt1.makeValue(42);
147+
}
148+
149+
opt1.value();
150+
151+
if (opt2.isNull()) {
152+
opt2.makeValueInplace(42);
153+
}
154+
155+
opt2.value();
156+
}
157+
144158
template <typename T>
145159
void function_template_without_user(const absl::optional<T> &opt) {
146160
opt.value(); // no-warning

clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,19 @@ auto buildTransferMatchSwitch() {
985985
isOptionalMemberCallWithNameMatcher(hasName("isNull")),
986986
transferOptionalIsNullCall)
987987

988+
// NullableValue::makeValue, NullableValue::makeValueInplace
989+
// Only NullableValue has these methods, but this
990+
// will also pass for other types
991+
.CaseOfCFGStmt<CXXMemberCallExpr>(
992+
isOptionalMemberCallWithNameMatcher(hasAnyName("makeValue", "makeValueInplace")),
993+
[](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &,
994+
LatticeTransferState &State) {
995+
if (RecordStorageLocation *Loc =
996+
getImplicitObjectLocation(*E, State.Env)) {
997+
setHasValue(*Loc, State.Env.getBoolLiteralValue(true), State.Env);
998+
}
999+
})
1000+
9881001
// optional::emplace
9891002
.CaseOfCFGStmt<CXXMemberCallExpr>(
9901003
isOptionalMemberCallWithNameMatcher(hasName("emplace")),

0 commit comments

Comments
 (0)