[clang] 0b12efc - [clang][dataflow] Add support for nested method calls.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 22 12:16:55 PDT 2022


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 {


        


More information about the cfe-commits mailing list