Author: Yitzhak Mandelbaum Date: 2022-09-22T19:16:31Z New Revision: 0b12efc7a42c187400f7df18d5fd629d92d2747e
URL: https://github.com/llvm/llvm-project/commit/0b12efc7a42c187400f7df18d5fd629d92d2747e DIFF: https://github.com/llvm/llvm-project/commit/0b12efc7a42c187400f7df18d5fd629d92d2747e.diff LOG: [clang][dataflow] Add support for nested method calls. Extend the context-sensitive analysis to handle a call to a method (of the same class) from within a method. That, is a member-call expression through `this`. Differential Revision: https://reviews.llvm.org/D134432 Added: Modified: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 8b761bef226ac..71ab89d56ed90 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -216,7 +216,10 @@ Environment Environment::pushCall(const CallExpr *Call) const { if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) { if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) { - Env.ThisPointeeLoc = getStorageLocation(*Arg, SkipPast::Reference); + if (!isa<CXXThisExpr>(Arg)) + Env.ThisPointeeLoc = getStorageLocation(*Arg, SkipPast::Reference); + // Otherwise (when the argument is `this`), retain the current + // environment's `ThisPointeeLoc`. } } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 4616265ad2598..3a827577bd78f 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -4359,7 +4359,7 @@ TEST(TransferTest, ContextSensitiveMethodSetter) { std::string Code = R"( class MyClass { public: - bool setField(bool Val) { Field = Val; } + void setField(bool Val) { Field = Val; } bool Field; }; @@ -4392,7 +4392,7 @@ TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { class MyClass { public: bool getField() { return Field; } - bool setField(bool Val) { Field = Val; } + void setField(bool Val) { Field = Val; } private: bool Field; @@ -4421,6 +4421,73 @@ TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { {TransferOptions{ContextSensitiveOptions{}}}); } + +TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { + std::string Code = R"( + class MyClass { + public: + void Inner() { MyField = true; } + void Outer() { Inner(); } + + bool MyField; + }; + + void target() { + MyClass MyObj; + MyObj.Outer(); + bool Foo = MyObj.MyField; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));; + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); + + auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); + EXPECT_TRUE(Env.flowConditionImplies(FooVal)); + }, + {TransferOptions{ContextSensitiveOptions{}}}); +} + +TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { + std::string Code = R"( + class MyClass { + public: + bool Inner() { return MyField; } + bool Outer() { return Inner(); } + + bool MyField; + }; + + void target() { + MyClass MyObj; + MyObj.MyField = true; + bool Foo = MyObj.Outer(); + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));; + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); + + auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); + EXPECT_TRUE(Env.flowConditionImplies(FooVal)); + }, + {TransferOptions{ContextSensitiveOptions{}}}); +} + TEST(TransferTest, ContextSensitiveConstructorBody) { std::string Code = R"( class MyClass { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits