[NFC] [FlowSensitive] [StatusOr] Add tests for pointer receivers Reviewers: jvoung Reviewed By: jvoung Pull Request: https://github.com/llvm/llvm-project/pull/180079
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp index f842abe..9c804b7 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -3984,6 +3984,134 @@ )cc"); } +TEST_P(UncheckedStatusOrAccessModelTest, PointerReceivers) { + // The following examples are not sound as there could be opaque calls between + // the ok() and the value() calls that change the StatusOr value. However, + // this is the behavior that users expect so it is here to stay. + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUSOR_INT* sor) { + sor->value(); // [[unsafe]] + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUSOR_INT* sor) { + sor->emplace(1); + sor->value(); + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUSOR_INT* sor) { + if (sor->ok()) + sor->value(); + else + sor->value(); // [[unsafe]] + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + void target(STATUS* s) { + STATUSOR_INT* sor = Make<STATUSOR_INT*>(); + if (!s->ok()) return; + if (*s == sor->status()) + sor->value(); + else + sor->value(); // [[unsafe]] + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + struct Foo { + STATUSOR_INT* sor; + }; + + void target(Foo foo) { + if (foo.sor->ok()) + foo.sor->value(); + else + foo.sor->value(); // [[unsafe]] + } + )cc"); + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + struct Foo { + STATUSOR_INT* sor; + }; + + void target(Foo foo) { + if (foo.sor->status().ok()) + foo.sor->value(); + else + foo.sor->value(); // [[unsafe]] + } + )cc"); +} + +TEST_P(UncheckedStatusOrAccessModelTest, PointerReceiversWithSelfReferentials) { + // Same as PointerReceivers, but with a self-referential pointer. + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + struct Bar; + struct Foo { + STATUSOR_INT* sor; + Bar* bar; + }; + struct Bar { + Foo* foo; + }; + + void target(Bar* bar) { + if (bar->foo->sor->status().ok()) + bar->foo->sor->value(); + else + bar->foo->sor->value(); // [[unsafe]] + } + )cc"); + + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + struct Foo { + Foo* next; + STATUSOR_INT* sor; + }; + + void target(Foo* foo) { + if (foo->next->sor->status().ok()) + // False positive, should be safe. + foo->next->sor->value(); // [[unsafe]] + else + foo->next->sor->value(); // [[unsafe]] + } + )cc"); +} + +TEST_P(UncheckedStatusOrAccessModelTest, PointerReceiversWithUnion) { + ExpectDiagnosticsFor(R"cc( +#include "unchecked_statusor_access_test_defs.h" + + union Foo { + STATUSOR_INT* sor; + }; + + void target(Foo foo) { + if (foo.sor->ok()) + foo.sor->value(); + else + foo.sor->value(); // [[unsafe]] + } + )cc"); +} + TEST_P(UncheckedStatusOrAccessModelTest, PointerLike) { ExpectDiagnosticsFor(R"cc( #include "unchecked_statusor_access_test_defs.h"