aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
diff options
context:
space:
mode:
authormartinboehme <mboehme@google.com>2024-04-10 21:27:10 +0200
committerGitHub <noreply@github.com>2024-04-10 21:27:10 +0200
commit7549b45825a05fc24fcdbacf006461165aa042cb (patch)
treece8923e5d429fd0c1d19bc77eaa44d30764bc401 /clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
parente3ef4612c18845876cda9a13c3435e102f74a3aa (diff)
downloadllvm-7549b45825a05fc24fcdbacf006461165aa042cb.zip
llvm-7549b45825a05fc24fcdbacf006461165aa042cb.tar.gz
llvm-7549b45825a05fc24fcdbacf006461165aa042cb.tar.bz2
Revert "[clang][dataflow] Propagate locations from result objects to initializers." (#88315)
Reverts llvm/llvm-project#87320 This is causing buildbots to fail because `isOriginalRecordConstructor()` is now unused.
Diffstat (limited to 'clang/unittests/Analysis/FlowSensitive/TransferTest.cpp')
-rw-r--r--clang/unittests/Analysis/FlowSensitive/TransferTest.cpp172
1 files changed, 57 insertions, 115 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 00dafb2..ca055a4 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -1582,9 +1582,10 @@ TEST(TransferTest, FieldsDontHaveValuesInConstructorWithBaseClass) {
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
- // The field of the base class should already have been initialized with
- // a value by the base constructor.
- EXPECT_NE(getFieldValue(Env.getThisPointeeStorageLocation(), "BaseVal",
+ // FIXME: The field of the base class should already have been
+ // initialized with a value by the base constructor. This test documents
+ // the current buggy behavior.
+ EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "BaseVal",
ASTCtx, Env),
nullptr);
EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
@@ -2997,12 +2998,8 @@ TEST(TransferTest, ResultObjectLocation) {
TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
std::string Code = R"(
- struct Inner {};
- struct Outer {
- Inner I = {};
- };
-
- void funcWithDefaultArg(Outer O = {});
+ struct S {};
+ void funcWithDefaultArg(S s = S());
void target() {
funcWithDefaultArg();
// [[p]]
@@ -3061,7 +3058,13 @@ TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
- EXPECT_EQ(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
+ // FIXME: The result object location for the `CXXDefaultInitExpr` should
+ // be the location of the member variable being initialized, but we
+ // don't do this correctly yet; see also comments in
+ // `builtinTransferInitializer()`.
+ // For the time being, we just document the current erroneous behavior
+ // here (this should be `EXPECT_EQ` when the behavior is fixed).
+ EXPECT_NE(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
});
}
@@ -3098,79 +3101,6 @@ TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
});
}
-TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
- std::string Code = R"(
- namespace std {
- template <typename T>
- struct initializer_list {};
- } // namespace std
-
- void target() {
- std::initializer_list<int> list = {1};
- // [[p]]
- }
- )";
-
- using ast_matchers::cxxStdInitializerListExpr;
- using ast_matchers::match;
- using ast_matchers::selectFirst;
- runDataflow(
- Code,
- [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
- ASTContext &ASTCtx) {
- const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
-
- auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
- "std_init_list",
- match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
- ASSERT_NE(StdInitList, nullptr);
-
- EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
- &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
- });
-}
-
-TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
- std::string Code = R"(
- struct A {
- A(int);
- };
-
- void target(bool b) {
- A a = b ? A(0) : A(1);
- (void)0; // [[p]]
- }
- )";
- using ast_matchers::cxxConstructExpr;
- using ast_matchers::equals;
- using ast_matchers::hasArgument;
- using ast_matchers::integerLiteral;
- using ast_matchers::match;
- using ast_matchers::selectFirst;
- using ast_matchers::traverse;
- runDataflow(
- Code,
- [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
- ASTContext &ASTCtx) {
- const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
-
- auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
- "construct",
- match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
- .bind("construct"),
- ASTCtx));
- auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
- "construct",
- match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
- .bind("construct"),
- ASTCtx));
-
- auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
- EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
- EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
- });
-}
-
TEST(TransferTest, StaticCast) {
std::string Code = R"(
void target(int Foo) {
@@ -5956,38 +5886,6 @@ TEST(TransferTest, ContextSensitiveReturnRecord) {
{BuiltinOptions{ContextSensitiveOptions{}}});
}
-TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
- std::string Code = R"(
- struct S {
- S() { self = this; }
- S *self;
- };
-
- S makeS() {
- // RVO guarantees that this will be constructed directly into `MyS`.
- return S();
- }
-
- void target() {
- S MyS = makeS();
- // [[p]]
- }
- )";
- runDataflow(
- Code,
- [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
- ASTContext &ASTCtx) {
- const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
-
- auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
-
- auto *SelfVal =
- cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
- EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
- },
- {BuiltinOptions{ContextSensitiveOptions{}}});
-}
-
TEST(TransferTest, ContextSensitiveMethodLiteral) {
std::string Code = R"(
class MyClass {
@@ -6932,6 +6830,50 @@ TEST(TransferTest, LambdaCaptureThis) {
});
}
+TEST(TransferTest, DifferentReferenceLocInJoin) {
+ // This test triggers a case where the storage location for a reference-type
+ // variable is different for two states being joined. We used to believe this
+ // could not happen and therefore had an assertion disallowing this; this test
+ // exists to demonstrate that we can handle this condition without a failing
+ // assertion. See also the discussion here:
+ // https://discourse.llvm.org/t/70086/6
+ std::string Code = R"(
+ namespace std {
+ template <class T> struct initializer_list {
+ const T* begin();
+ const T* end();
+ };
+ }
+
+ void target(char* p, char* end) {
+ while (p != end) {
+ if (*p == ' ') {
+ p++;
+ continue;
+ }
+
+ auto && range = {1, 2};
+ for (auto b = range.begin(), e = range.end(); b != e; ++b) {
+ }
+ (void)0;
+ // [[p]]
+ }
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+ // Joining environments with different storage locations for the same
+ // declaration results in the declaration being removed from the joined
+ // environment.
+ const ValueDecl *VD = findValueDecl(ASTCtx, "range");
+ ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
+ });
+}
+
// This test verifies correct modeling of a relational dependency that goes
// through unmodeled functions (the simple `cond()` in this case).
TEST(TransferTest, ConditionalRelation) {