diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -215,8 +215,11 @@ Env.ReturnLoc = getStorageLocation(*Call, SkipPast::Reference); if (const auto *MethodCall = dyn_cast(Call)) { - if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) { - Env.ThisPointeeLoc = getStorageLocation(*Arg, SkipPast::Reference); + if (const Expr *Arg = MethodCall->getImplicitObjectArgument()){ + if(!isa(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 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -4359,7 +4359,7 @@ 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 @@ 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 @@ {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> &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(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> &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(Env.getValue(*FooDecl, SkipPast::None)); + EXPECT_TRUE(Env.flowConditionImplies(FooVal)); + }, + {TransferOptions{ContextSensitiveOptions{}}}); +} + TEST(TransferTest, ContextSensitiveConstructorBody) { std::string Code = R"( class MyClass {