Skip to content

Commit 38ee819

Browse files
committed
Test for clearing state on non-const method (independent of accessors)
Also fix a warning about copies in for-each loop.
1 parent 07c2f6c commit 38ee819

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ void handleNonConstMemberCall(const CallExpr *CE,
603603
LatticeTransferState &State) {
604604
// When a non-const member function is called, reset some state.
605605
if (RecordLoc != nullptr) {
606-
for (const auto [Field, FieldLoc] : RecordLoc->children()) {
606+
for (const auto& [Field, FieldLoc] : RecordLoc->children()) {
607607
if (isSupportedOptionalType(Field->getType())) {
608608
auto *FieldRecordLoc = cast_or_null<RecordStorageLocation>(FieldLoc);
609609
if (FieldRecordLoc) {

clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,26 @@ TEST_P(UncheckedOptionalAccessTest, OptionalReturnedFromFuntionCall) {
21672167
)");
21682168
}
21692169

2170+
TEST_P(UncheckedOptionalAccessTest, OptionalFieldModified) {
2171+
ExpectDiagnosticsFor(
2172+
R"(
2173+
#include "unchecked_optional_access_test.h"
2174+
2175+
struct Foo {
2176+
$ns::$optional<std::string> opt;
2177+
void clear(); // assume this may modify the opt field's state
2178+
};
2179+
2180+
void target(Foo& foo) {
2181+
if (foo.opt) {
2182+
foo.opt.value();
2183+
foo.clear();
2184+
foo.opt.value(); // [[unsafe]]
2185+
}
2186+
}
2187+
)");
2188+
}
2189+
21702190
TEST_P(UncheckedOptionalAccessTest, StdSwap) {
21712191
ExpectDiagnosticsFor(
21722192
R"(

0 commit comments

Comments
 (0)