diff options
author | martinboehme <mboehme@google.com> | 2024-04-10 21:27:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-10 21:27:10 +0200 |
commit | 7549b45825a05fc24fcdbacf006461165aa042cb (patch) | |
tree | ce8923e5d429fd0c1d19bc77eaa44d30764bc401 /clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | |
parent | e3ef4612c18845876cda9a13c3435e102f74a3aa (diff) | |
download | llvm-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.cpp | 172 |
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) { |