[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-09-09 Thread Sam Estep via Phabricator via cfe-commits
samestep accepted this revision.
samestep added a comment.

@ymandel Huh, interesting! I'll go ahead and abandon this patch, then?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132251: [clang][dataflow] Dummy patch

2022-08-19 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132251

Files:
  clang/include/clang/Analysis/FlowSensitive/Transfer.h


Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -25,6 +25,7 @@
   /// The maximum depth to analyze. A value of zero is equivalent to disabling
   /// context-sensitive analysis entirely.
   unsigned Depth = 2;
+  signed Breadth = 3;
 };
 
 struct TransferOptions {


Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -25,6 +25,7 @@
   /// The maximum depth to analyze. A value of zero is equivalent to disabling
   /// context-sensitive analysis entirely.
   unsigned Depth = 2;
+  signed Breadth = 3;
 };
 
 struct TransferOptions {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132242: [clang][dataflow] Dummy patch 2

2022-08-19 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Depends On D132241 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132242

Files:
  clang/include/clang/Analysis/FlowSensitive/Transfer.h


Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -37,6 +37,7 @@
   virtual ~StmtToEnvMap() = default;
 
   // hello
+  // goodbye
 
   /// Returns the environment of the basic block that contains `S` or nullptr 
if
   /// there isn't one.


Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -37,6 +37,7 @@
   virtual ~StmtToEnvMap() = default;
 
   // hello
+  // goodbye
 
   /// Returns the environment of the basic block that contains `S` or nullptr if
   /// there isn't one.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132241: [clang][dataflow] Dummy patch 1

2022-08-19 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132241

Files:
  clang/include/clang/Analysis/FlowSensitive/Transfer.h


Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -36,6 +36,8 @@
 public:
   virtual ~StmtToEnvMap() = default;
 
+  // hello
+
   /// Returns the environment of the basic block that contains `S` or nullptr 
if
   /// there isn't one.
   /// FIXME: Ensure that the result can't be null and return a const reference.


Index: clang/include/clang/Analysis/FlowSensitive/Transfer.h
===
--- clang/include/clang/Analysis/FlowSensitive/Transfer.h
+++ clang/include/clang/Analysis/FlowSensitive/Transfer.h
@@ -36,6 +36,8 @@
 public:
   virtual ~StmtToEnvMap() = default;
 
+  // hello
+
   /// Returns the environment of the basic block that contains `S` or nullptr if
   /// there isn't one.
   /// FIXME: Ensure that the result can't be null and return a const reference.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131809: [clang][dataflow] Add an option for context-sensitive depth

2022-08-15 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2efc8f8d6561: [clang][dataflow] Add an option for 
context-sensitive depth (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131809/new/

https://reviews.llvm.org/D131809

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3902,6 +3902,36 @@
   {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}});
 }
 
+TEST(TransferTest, ContextSensitiveDepthZero) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
+}
+
 TEST(TransferTest, ContextSensitiveSetTrue) {
   std::string Code = R"(
 bool GiveBool();
@@ -4000,7 +4030,7 @@
   {TransferOptions{ContextSensitiveOptions{}}});
 }
 
-TEST(TransferTest, ContextSensitiveSetTwoLayers) {
+TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
   std::string Code = R"(
 bool GiveBool();
 void SetBool1(bool ) { Var = true; }
@@ -4028,7 +4058,146 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {TransferOptions{ContextSensitiveOptions{}}});
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool2(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+void SetBool3(bool ) { SetBool2(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool3(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+void 

[PATCH] D131809: [clang][dataflow] Add an option for context-sensitive depth

2022-08-15 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 452783.
samestep added a comment.

Address Stanislav's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131809/new/

https://reviews.llvm.org/D131809

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3902,6 +3902,36 @@
   {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}});
 }
 
+TEST(TransferTest, ContextSensitiveDepthZero) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
+}
+
 TEST(TransferTest, ContextSensitiveSetTrue) {
   std::string Code = R"(
 bool GiveBool();
@@ -4000,7 +4030,7 @@
   {TransferOptions{ContextSensitiveOptions{}}});
 }
 
-TEST(TransferTest, ContextSensitiveSetTwoLayers) {
+TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
   std::string Code = R"(
 bool GiveBool();
 void SetBool1(bool ) { Var = true; }
@@ -4028,7 +4058,146 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {TransferOptions{ContextSensitiveOptions{}}});
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool2(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+void SetBool3(bool ) { SetBool2(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool3(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+void SetBool3(bool ) { SetBool2(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool3(Foo);
+  // [[p]]
+}
+  )";
+  

[PATCH] D131809: [clang][dataflow] Add an option for context-sensitive depth

2022-08-15 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:665
+if (!(Options.ContextSensitiveOpts &&
+  Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))
   return;

samestep wrote:
> xazax.hun wrote:
> > Alternatively, `canDescend` could get the optional `ContextSensitiveOpts` 
> > and we can do all the checking there. 
> Ah, good idea!
Oh... actually that doesn't work quite so nicely, because it introduces a 
circular dependency between `Transfer.h` and `DataflowEnvironment.h`. I'll 
leave it as-is for now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131809/new/

https://reviews.llvm.org/D131809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131809: [clang][dataflow] Add an option for context-sensitive depth

2022-08-15 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:210
+ const DeclContext *Callee) const {
+  return CallString.size() <= MaxDepth &&
+ std::find(CallString.begin(), CallString.end(), Callee) ==

sgatev wrote:
> If `canDescend` is supposed to return false for `MaxDepth = 0`, shouldn't 
> this be `<`?
I don't follow; could you clarify? The `CallStack` should always be nonempty.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:665
+if (!(Options.ContextSensitiveOpts &&
+  Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))
   return;

xazax.hun wrote:
> Alternatively, `canDescend` could get the optional `ContextSensitiveOpts` and 
> we can do all the checking there. 
Ah, good idea!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131809/new/

https://reviews.llvm.org/D131809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131809: [clang][dataflow] Add an option for context-sensitive depth

2022-08-12 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131809

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4000,7 +4000,7 @@
   {TransferOptions{ContextSensitiveOptions{}}});
 }
 
-TEST(TransferTest, ContextSensitiveSetTwoLayers) {
+TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
   std::string Code = R"(
 bool GiveBool();
 void SetBool1(bool ) { Var = true; }
@@ -4028,7 +4028,146 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {TransferOptions{ContextSensitiveOptions{}}});
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool2(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+void SetBool3(bool ) { SetBool2(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool3(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
+}
+
+TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+void SetBool3(bool ) { SetBool2(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool3(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {TransferOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
+}
+
+TEST(TransferTest, ContextSensitiveMutualRecursion) {
+  std::string Code = R"(
+bool Pong(bool X, bool Y);
+
+bool Ping(bool X, bool Y) {
+  if (X) {
+return Y;
+  } else {
+return Pong(!X, Y);
+  }
+}
+
+bool Pong(bool X, bool Y) {
+  if (Y) {
+return X;
+  } else {
+return Ping(X, !Y);
+  }
+}
+
+void target() {
+  bool Foo = Ping(false, false);
+  // 

[PATCH] D131779: [clang][dataflow] Encode options using llvm::Optional

2022-08-12 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb3f1a6bf1080: [clang][dataflow] Encode options using 
llvm::Optional (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131779/new/

https://reviews.llvm.org/D131779

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -64,7 +64,10 @@
  LangStandard::Kind Std = LangStandard::lang_cxx17,
  bool ApplyBuiltinTransfer = true,
  llvm::StringRef TargetFun = "target") {
-  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+  runDataflow(Code, Match,
+  {ApplyBuiltinTransfer ? TransferOptions{}
+: llvm::Optional()},
+  Std, TargetFun);
 }
 
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
@@ -3896,8 +3899,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+  {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTrue) {
@@ -3926,8 +3928,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetFalse) {
@@ -3956,8 +3957,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
@@ -3997,8 +3997,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTwoLayers) {
@@ -4029,8 +4028,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
@@ -4071,8 +4069,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
@@ -4117,8 +4114,7 @@
 EXPECT_TRUE(Env.flowConditionImplies(BazVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnVoid) {
@@ -4138,8 +4134,7 @@
 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
 // This just tests that the analysis doesn't crash.
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnTrue) {
@@ -4166,8 +4161,7 @@
 *cast(Env.getValue(*FooDecl, 

[PATCH] D131779: [clang][dataflow] Encode options using llvm::Optional

2022-08-12 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 452196.
samestep added a comment.

Remove unnecessary explicit call to hasValue


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131779/new/

https://reviews.llvm.org/D131779

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -64,7 +64,10 @@
  LangStandard::Kind Std = LangStandard::lang_cxx17,
  bool ApplyBuiltinTransfer = true,
  llvm::StringRef TargetFun = "target") {
-  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+  runDataflow(Code, Match,
+  {ApplyBuiltinTransfer ? TransferOptions{}
+: llvm::Optional()},
+  Std, TargetFun);
 }
 
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
@@ -3896,8 +3899,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+  {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTrue) {
@@ -3926,8 +3928,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetFalse) {
@@ -3956,8 +3957,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
@@ -3997,8 +3997,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTwoLayers) {
@@ -4029,8 +4028,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
@@ -4071,8 +4069,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
@@ -4117,8 +4114,7 @@
 EXPECT_TRUE(Env.flowConditionImplies(BazVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnVoid) {
@@ -4138,8 +4134,7 @@
 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
 // This just tests that the analysis doesn't crash.
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnTrue) {
@@ -4166,8 +4161,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
   },
-  

[PATCH] D131779: [clang][dataflow] Encode options using llvm::Optional

2022-08-12 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:70
+   ? TransferOptions{}
+   : llvm::Optional()}) {}
 

sgatev wrote:
> 
I tried that, but I get the following error message:

> Incompatible operand types ('TransferOptions' and 'const NoneType')



Comment at: clang/include/clang/Analysis/FlowSensitive/Transfer.h:31
+  /// unsupported.
+  llvm::Optional ContextSensitiveOpts;
 };

sgatev wrote:
> Perhaps keep the name `ContextSensitive`? In the context of `TransferOptions` 
> it seems clear what this is. 
I don't have a strong preference either way; does anyone else have an opinion 
on this?



Comment at: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp:322
 case CFGElement::Initializer:
-  if (Analysis.applyBuiltinTransfer())
+  if (Analysis.builtinTransferOptions().hasValue())
 transferCFGInitializer(*Element.getAs(), State);

sgatev wrote:
> For consistency.
Ah thanks! Will do.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:69
+  {ApplyBuiltinTransfer ? TransferOptions{}
+: llvm::Optional()},
+  Std, TargetFun);

sgatev wrote:
> 
Same error mentioned above.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131779/new/

https://reviews.llvm.org/D131779

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131779: [clang][dataflow] Encode options using llvm::Optional

2022-08-12 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 452193.
samestep added a comment.

Use llvm::None per Gábor's suggestion


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131779/new/

https://reviews.llvm.org/D131779

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -64,7 +64,10 @@
  LangStandard::Kind Std = LangStandard::lang_cxx17,
  bool ApplyBuiltinTransfer = true,
  llvm::StringRef TargetFun = "target") {
-  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+  runDataflow(Code, Match,
+  {ApplyBuiltinTransfer ? TransferOptions{}
+: llvm::Optional()},
+  Std, TargetFun);
 }
 
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
@@ -3896,8 +3899,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+  {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTrue) {
@@ -3926,8 +3928,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetFalse) {
@@ -3956,8 +3957,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
@@ -3997,8 +3997,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTwoLayers) {
@@ -4029,8 +4028,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
@@ -4071,8 +4069,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
@@ -4117,8 +4114,7 @@
 EXPECT_TRUE(Env.flowConditionImplies(BazVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnVoid) {
@@ -4138,8 +4134,7 @@
 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
 // This just tests that the analysis doesn't crash.
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnTrue) {
@@ -4166,8 +4161,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
   },
-  

[PATCH] D131779: [clang][dataflow] Encode options using llvm::Optional

2022-08-12 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131779

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -64,7 +64,10 @@
  LangStandard::Kind Std = LangStandard::lang_cxx17,
  bool ApplyBuiltinTransfer = true,
  llvm::StringRef TargetFun = "target") {
-  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+  runDataflow(Code, Match,
+  {ApplyBuiltinTransfer ? TransferOptions{}
+: llvm::Optional()},
+  Std, TargetFun);
 }
 
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
@@ -3896,8 +3899,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+  {TransferOptions{llvm::Optional()}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTrue) {
@@ -3926,8 +3928,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetFalse) {
@@ -3956,8 +3957,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
@@ -3997,8 +3997,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetTwoLayers) {
@@ -4029,8 +4028,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
@@ -4071,8 +4069,7 @@
 EXPECT_FALSE(Env.flowConditionImplies(BarVal));
 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
@@ -4117,8 +4114,7 @@
 EXPECT_TRUE(Env.flowConditionImplies(BazVal));
 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnVoid) {
@@ -4138,8 +4134,7 @@
 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
 // This just tests that the analysis doesn't crash.
   },
-  {/*.ApplyBuiltinTransfer=*/true,
-   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+  {TransferOptions{ContextSensitiveOptions{}}});
 }
 
 TEST(TransferTest, ContextSensitiveReturnTrue) {
@@ -4166,8 +4161,7 @@
 *cast(Env.getValue(*FooDecl, SkipPast::None));
 

[PATCH] D131600: [clang][dataflow] Don't crash when caller args are missing storage locations

2022-08-10 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG43b298ea1282: [clang][dataflow] Dont crash when caller 
args are missing storage locations (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131600/new/

https://reviews.llvm.org/D131600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp


Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,6 +4229,27 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnInt) {
+  std::string Code = R"(
+int identity(int x) { return x; }
+
+void target() {
+  int y = identity(42);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 TEST(TransferTest, ContextSensitiveMethodLiteral) {
   std::string Code = R"(
 class MyClass {
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -253,7 +253,8 @@
 
 const Expr *Arg = Args[ArgIndex];
 auto *ArgLoc = getStorageLocation(*Arg, SkipPast::Reference);
-assert(ArgLoc != nullptr);
+if (ArgLoc == nullptr)
+  continue;
 
 const VarDecl *Param = *ParamIt;
 auto  = createStorageLocation(*Param);
Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -140,8 +140,6 @@
   ///  The body of the callee must not reference globals.
   ///
   ///  The arguments of `Call` must map 1:1 to the callee's parameters.
-  ///
-  ///  Each argument of `Call` must already have a `StorageLocation`.
   Environment pushCall(const CallExpr *Call) const;
   Environment pushCall(const CXXConstructExpr *Call) const;
 


Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,6 +4229,27 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnInt) {
+  std::string Code = R"(
+int identity(int x) { return x; }
+
+void target() {
+  int y = identity(42);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 TEST(TransferTest, ContextSensitiveMethodLiteral) {
   std::string Code = R"(
 class MyClass {
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -253,7 +253,8 @@
 
 const Expr *Arg = Args[ArgIndex];
 auto *ArgLoc = getStorageLocation(*Arg, SkipPast::Reference);
-assert(ArgLoc != nullptr);
+if (ArgLoc == nullptr)
+  continue;
 
 const VarDecl *Param = *ParamIt;
 auto  = createStorageLocation(*Param);
Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -140,8 +140,6 @@
   ///  The body of the callee must not reference globals.
   ///
   ///  The arguments of `Call` must map 1:1 to the callee's parameters.
-  ///
-  ///  Each argument of `Call` must already have a 

[PATCH] D131600: [clang][dataflow] Don't crash when caller args are missing storage locations

2022-08-10 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp


Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,6 +4229,27 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnInt) {
+  std::string Code = R"(
+int identity(int x) { return x; }
+
+void target() {
+  int y = identity(42);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 TEST(TransferTest, ContextSensitiveMethodLiteral) {
   std::string Code = R"(
 class MyClass {
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -253,7 +253,8 @@
 
 const Expr *Arg = Args[ArgIndex];
 auto *ArgLoc = getStorageLocation(*Arg, SkipPast::Reference);
-assert(ArgLoc != nullptr);
+if (ArgLoc == nullptr)
+  continue;
 
 const VarDecl *Param = *ParamIt;
 auto  = createStorageLocation(*Param);
Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -140,8 +140,6 @@
   ///  The body of the callee must not reference globals.
   ///
   ///  The arguments of `Call` must map 1:1 to the callee's parameters.
-  ///
-  ///  Each argument of `Call` must already have a `StorageLocation`.
   Environment pushCall(const CallExpr *Call) const;
   Environment pushCall(const CXXConstructExpr *Call) const;
 


Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,6 +4229,27 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnInt) {
+  std::string Code = R"(
+int identity(int x) { return x; }
+
+void target() {
+  int y = identity(42);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 TEST(TransferTest, ContextSensitiveMethodLiteral) {
   std::string Code = R"(
 class MyClass {
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -253,7 +253,8 @@
 
 const Expr *Arg = Args[ArgIndex];
 auto *ArgLoc = getStorageLocation(*Arg, SkipPast::Reference);
-assert(ArgLoc != nullptr);
+if (ArgLoc == nullptr)
+  continue;
 
 const VarDecl *Param = *ParamIt;
 auto  = createStorageLocation(*Param);
Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -140,8 +140,6 @@
   ///  The body of the callee must not reference globals.
   ///
   ///  The arguments of `Call` must map 1:1 to the callee's parameters.
-  ///
-  ///  Each argument of `Call` must already have a `StorageLocation`.
   Environment pushCall(const CallExpr *Call) const;
   Environment 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-10 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG000c8fef86ab: [clang][dataflow] Analyze constructor bodies 
(authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-10 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 451445.
samestep added a comment.

Address Stanislav's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
-  // Note that 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-10 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:379
+  /// Shared implementation of `pushCall` overloads.
+  void pushCallInternal(const FunctionDecl *FuncDecl,
+ArrayRef Args);

sgatev wrote:
> Let's add a note that unlike `pushCall`, this member is invoked on the 
> environment of the callee.
Will do, thanks!



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:380
+  void pushCallInternal(const FunctionDecl *FuncDecl,
+ArrayRef Args);
+

sgatev wrote:
> `#include "llvm/ADT/ArrayRef.h"`
When I add this, I get a warning: "Included header `ArrayRef.h` is not used 
directly"



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:667-670
+const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
+
+if (!CFCtx)
+  return;

sgatev wrote:
> 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:224
   // FIXME: Support references here.
-  Env.ReturnLoc = Env.getStorageLocation(*Call, SkipPast::Reference);
+  ReturnLoc = getStorageLocation(*Call, SkipPast::Reference);
 

ymandel wrote:
> I'd go farther: just duplicate this line in both `pushCalls` and then the two 
> `if` that follow can be moved out as well. at that point, I think `Call` is 
> no longer needed.
Smart! Done.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 451267.
samestep added a comment.

Remove Call parameter from pushCallInternal method


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 451265.
samestep added a comment.

Pull type-specific logic into overloads


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
-  // 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:219-245
   // FIXME: Support references here.
-  Env.ReturnLoc = Env.getStorageLocation(*Call, SkipPast::Reference);
+  ReturnLoc = getStorageLocation(*Call, SkipPast::Reference);
 
-  const auto *FuncDecl = Call->getDirectCallee();
-  assert(FuncDecl != nullptr);
   // FIXME: In order to allow the callee to reference globals, we probably need
   // to call `initGlobalVars` here in some way.
 
   if (const auto *MethodCall = dyn_cast(Call)) {

xazax.hun wrote:
> ymandel wrote:
> > I think you can push all of this logic to the type-specialized `pushCalls` 
> > now and just have pushCallInternal take the FunctionDecl, ArrayRef, etc.. 
> > WDYT?
> +1, I like that.
Great idea, thanks! Doing that now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 451259.
samestep added a comment.

Use ArrayRef


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
-  // Note that it is important 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D131438#3710697 , @xazax.hun wrote:

> I feel like this is a repeated pattern. The CSA solved a very similar issue 
> by introducing the CallEvent class hierarchy. I also remember seeing many 
> disparate code snippets littered throughout the clang codebase that tries to 
> deal with the problem of not having facilities to treat call-like nodes 
> uniformly. At some point, I believe there were even some AST changes or 
> supporting structures proposed to ameliorate this problem, but I can't find 
> those at the moment. While I think it might be OK to introduce yet another 
> workaround here, this is a cleanup that is long overdue, and I hope someone 
> will have the time to actually improve the situation. Sorry for the rant, I 
> will actually look at the code but had to vent this.

No worries at all for the rant, I appreciate the broader context. I was 
definitely surprised to learn that the two types don't share a common ancestor.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:248-258
+  for (unsigned ArgIndex = 0; ArgIndex < NumArgs; ++ParamIt, ++ArgIndex) {
 assert(ParamIt != FuncDecl->param_end());
 
-const Expr *Arg = *ArgIt;
-auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
+const Expr *Arg;
+if (const auto *ConstructExpr = dyn_cast(Call)) {
+  Arg = ConstructExpr->getArg(ArgIndex);
+} else if (const auto *NonConstructExpr = dyn_cast(Call)) {

xazax.hun wrote:
> I think the more idiomatic solution in Clang is to create an ArrayRef for the 
> arguments from the `ConstructExpr` and the `CallExpr`. The args should be 
> stored in a continuous memory area in both cases so you should be able to 
> create the ArrayRef in constant time and you would no longer need to have 
> these pesky if statements in your loop. 
Ah OK, thanks! How should I do that? I was previously using iterators but it 
looked like the types were different between `CallExpr` and `CXXConstructExpr`, 
so I switched away from iterators in this patch; is there an easy way to make 
the `ArrayRef`?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131280: [clang][dataflow] Parameterize analysis by explicit map of analyzable functions.

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h:71-74
+/// Builds a map of top-level functions and methods of top-level classes sounds
+/// in the given AST, mapping from fully qualified function name to the
+/// `ControlFlowContext` that corresponds to that function. Fully qualified
+/// names are used so that we can related same-named functions from two




Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131280/new/

https://reviews.llvm.org/D131280

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 451233.
samestep added a comment.

Narrow public signature of pushCall


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
-  // 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 451134.
samestep added a comment.

Address Yitzie's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,106 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorDefault) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() = default;
+
+  bool MyField = true;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
-  // Note that it 

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-09 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:138
   ///
+  ///  `Call` must be either a `CallExpr` or a `CXXConstructExpr`.
+  ///

sgatev wrote:
> How about we define overloads that take these types instead of taking an 
> `Expr` here? This should remove the need for type-checking and guarding 
> against bad input in the implementation. `transferInlineCall` can be a 
> template if necessary.
Hmm I guess we could; is there much of a benefit to doing this templated?



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:678-684
+if (const auto *NonConstructExpr = dyn_cast(S)) {
+  // Note that it is important for the storage location of `S` to be set
+  // before `pushCall`, because the latter uses it to set the storage
+  // location for `return`.
+  auto  = Env.createStorageLocation(*S);
+  Env.setStorageLocation(*S, ReturnLoc);
+}

ymandel wrote:
> Why can't this stay in `VisitCallExpr`?
I had it there in an earlier version of this patch; it was causing tests to 
fail (the `SelfReferential*` ones, if I remember correctly).



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:4371
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(

ymandel wrote:
> What about a default constructor, including when there are field initializers 
> like:
> ```
>  class MyClass {
> public:
>   MyClass() = default;
> 
>   bool MyField = true;
> };
> ```
> 
> Should we expect to handle that correctly? If so, can you add some tests?
Good idea! I'll add a test for this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-08 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 450951.
samestep added a comment.

Fix bug


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,72 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,7 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
-  // Note that it is important for the storage location of `S` to be set
-  // before `pushCall`, because the latter uses it to set the storage
-  // location for `return`.
-  auto  = Env.createStorageLocation(*S);
-  Env.setStorageLocation(*S, ReturnLoc);
-  auto CalleeEnv = Env.pushCall(S);
-
-  // FIXME: Use the same analysis as the caller for the callee. Note,
-  // though, that doing so would require support for changing the analysis's
-  // ASTContext.
-  assert(
-  CFCtx->getDecl() != nullptr &&
-  "ControlFlowContexts in the environment should always carry a decl");
-  auto Analysis = NoopAnalysis(CFCtx->getDecl()->getASTContext(),
-   DataflowAnalysisOptions());
-
-  auto BlockToOutputState =
-  dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv);
-  assert(BlockToOutputState);
-  assert(ExitBlock < BlockToOutputState->size());
-
-  auto ExitState = (*BlockToOutputState)[ExitBlock];
-  

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-08 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 450944.
samestep added a comment.

Tweaks


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131438/new/

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,72 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -526,45 +528,13 @@
 return;
   Env.setStorageLocation(*S, *ArgLoc);
 } else if (const FunctionDecl *F = S->getDirectCallee()) {
-  // This case is for context-sensitive analysis.
-  if (!Options.ContextSensitive)
-return;
-
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
   // Note that it is important for the storage location of `S` to be set
   // before `pushCall`, because the latter uses it to set the storage
   // location for `return`.
   auto  = Env.createStorageLocation(*S);
   Env.setStorageLocation(*S, ReturnLoc);
-  auto CalleeEnv = Env.pushCall(S);
-
-  // FIXME: Use the same analysis as the caller for the callee. Note,
-  // though, that doing so would require support for changing the analysis's
-  // ASTContext.
-  assert(
-  CFCtx->getDecl() != nullptr &&
-  "ControlFlowContexts in the environment should always carry a decl");
-  auto Analysis = NoopAnalysis(CFCtx->getDecl()->getASTContext(),
-   DataflowAnalysisOptions());
-
-  auto BlockToOutputState =
-  dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv);
-  assert(BlockToOutputState);
-  assert(ExitBlock < BlockToOutputState->size());
-
-  auto ExitState = (*BlockToOutputState)[ExitBlock];
-  

[PATCH] D131438: [clang][dataflow] Analyze constructor bodies

2022-08-08 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131438

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4368,4 +4368,72 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveConstructorBody) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() { MyField = true; }
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveConstructorInitializer) {
+  std::string Code = R"(
+class MyClass {
+public:
+  MyClass() : MyField(true) {}
+
+  bool MyField;
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.MyField;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -444,6 +444,8 @@
 Env.setStorageLocation(*S, Loc);
 if (Value *Val = Env.createValue(S->getType()))
   Env.setValue(Loc, *Val);
+
+transferInlineCall(S, ConstructorDecl);
   }
 
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
@@ -530,41 +532,13 @@
   if (!Options.ContextSensitive)
 return;
 
-  const ControlFlowContext *CFCtx = Env.getControlFlowContext(F);
-  if (!CFCtx)
-return;
-
-  // FIXME: We don't support context-sensitive analysis of recursion, so
-  // we should return early here if `F` is the same as the `FunctionDecl`
-  // holding `S` itself.
-
-  auto ExitBlock = CFCtx->getCFG().getExit().getBlockID();
-
   // Note that it is important for the storage location of `S` to be set
   // before `pushCall`, because the latter uses it to set the storage
   // location for `return`.
   auto  = Env.createStorageLocation(*S);
   Env.setStorageLocation(*S, ReturnLoc);
-  auto CalleeEnv = Env.pushCall(S);
-
-  // FIXME: Use the same analysis as the caller for the callee. Note,
-  // though, that doing so would require support for changing the analysis's
-  // ASTContext.
-  assert(
-  CFCtx->getDecl() != nullptr &&
-  "ControlFlowContexts in the environment should always carry a decl");
-  auto Analysis = NoopAnalysis(CFCtx->getDecl()->getASTContext(),
-   DataflowAnalysisOptions());
-
-  auto BlockToOutputState =
-  dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv);
-  assert(BlockToOutputState);
-  assert(ExitBlock < BlockToOutputState->size());
-
-  auto ExitState = (*BlockToOutputState)[ExitBlock];
-  assert(ExitState);
-
-  Env.popCall(ExitState->Env);
+
+  transferInlineCall(S, 

[PATCH] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8611a77ee7ee: [clang][dataflow] Analyze method bodies 
(authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131170/new/

https://reviews.llvm.org/D131170

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,4 +4229,143 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveMethodLiteral) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool giveBool() { return true; }
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.giveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodGetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool getField() { return Field; }
+
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.Field = true;
+  bool Foo = MyObj.getField();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodSetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool setField(bool Val) { Field = Val; }
+
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.setField(true);
+  bool Foo = MyObj.Field;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool getField() { return Field; }
+  bool setField(bool Val) { Field = Val; }
+
+private:
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.setField(true);
+  bool Foo = MyObj.getField();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0eaecbbc2318: [clang][dataflow] Handle return statements 
(authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,25 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 450058.
samestep added a comment.

Add Stanislav's suggested comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,25 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val == nullptr)
+  return;
+
+// FIXME: Support reference-type returns.
+if (Val->getKind() == 

[PATCH] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:217
+const Expr *Arg = MethodCall->getImplicitObjectArgument();
+Env.ThisPointeeLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
+  }

sgatev wrote:
> samestep wrote:
> > sgatev wrote:
> > > What if `Arg` is null?
> > Good point, thanks; under what circumstances can that happen? In any case, 
> > I'm adding a guard for this.
> It can be null if the argument isn't modeled and there's no value assigned to 
> its storage location.
Hmm I don't quite follow; `Arg` just comes from calling 
`getImplicitObjectArgument` on the `CXXMemberCallExpr`, right? So shouldn't it 
only depend on the AST, and be completely independent of what we do or don't 
model?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131170/new/

https://reviews.llvm.org/D131170

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 449986.
samestep added a comment.

Address Stanislav's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131170/new/

https://reviews.llvm.org/D131170

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,4 +4229,143 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveMethodLiteral) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool giveBool() { return true; }
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.giveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodGetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool getField() { return Field; }
+
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.Field = true;
+  bool Foo = MyObj.getField();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodSetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool setField(bool Val) { Field = Val; }
+
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.setField(true);
+  bool Foo = MyObj.Field;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool getField() { return Field; }
+  bool setField(bool Val) { Field = Val; }
+
+private:
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.setField(true);
+  bool Foo = MyObj.getField();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   

[PATCH] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:383
   StorageLocation *ReturnLoc = nullptr;
-  // FIXME: Move `ThisPointeeLoc` here from `DataflowAnalysisContext`.
+  StorageLocation *ThisPointeeLoc = nullptr;
 

sgatev wrote:
> Let's add a brief comment explaining what this is and when it is expected to 
> be non-null.
Will do, thanks.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:217
+const Expr *Arg = MethodCall->getImplicitObjectArgument();
+Env.ThisPointeeLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
+  }

sgatev wrote:
> What if `Arg` is null?
Good point, thanks; under what circumstances can that happen? In any case, I'm 
adding a guard for this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131170/new/

https://reviews.llvm.org/D131170

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131170

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4229,4 +4229,143 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveMethodLiteral) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool giveBool() { return true; }
+};
+
+void target() {
+  MyClass MyObj;
+  bool Foo = MyObj.giveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodGetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool getField() { return Field; }
+
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.Field = true;
+  bool Foo = MyObj.getField();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodSetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool setField(bool Val) { Field = Val; }
+
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.setField(true);
+  bool Foo = MyObj.Field;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
+  std::string Code = R"(
+class MyClass {
+public:
+  bool getField() { return Field; }
+  bool setField(bool Val) { Field = Val; }
+
+private:
+  bool Field;
+};
+
+void target() {
+  MyClass MyObj;
+  MyObj.setField(true);
+  bool Foo = MyObj.getField();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 449976.
samestep added a comment.

Revert an unnecessary little change


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,25 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val == nullptr)
+  return;
+
+// FIXME: Support reference-type returns.
+if (Val->getKind() == 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 449975.
samestep added a comment.

Use CallExpr location for ReturnLoc


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,25 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val == nullptr)
+  return;
+
+// FIXME: Support reference-type returns.
+if (Val->getKind() == 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 449958.
samestep added a comment.

Don't assert returns to not be references


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,25 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val == nullptr)
+  return;
+
+// FIXME: Support reference-type returns.
+if (Val->getKind() == 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:348
+auto *Loc = Env.getReturnStorageLocation();
+assert(Loc != nullptr);
+// FIXME: Model NRVO.

sgatev wrote:
> samestep wrote:
> > sgatev wrote:
> > > Let's do `if (Loc == nullptr) return;`
> > I don't think we want to do that, right? Shouldn't the `return` storage 
> > location always be set? Or is this about the "analyzing fragments rather 
> > than full functions" thing we discussed yesterday?
> I think it's related. If we are going with always initializing the `return` 
> storage location then I guess at some point we should be able to make 
> `Environment::getReturnStorageLocation` return a reference? In that case I'm 
> fine with keeping the assert around in the meantime.
OK; yeah, I think the intention is that we're always initializing it. I'll 
leave this code as is for now, then.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:564
+  assert(ReturnLoc != nullptr);
+  Env.setStorageLocation(*S, *ReturnLoc);
+  Env.popCall(ExitEnv);

sgatev wrote:
> samestep wrote:
> > sgatev wrote:
> > > We use stable storage locations to ensure convergence. In that spirit, 
> > > shouldn't we assign `ReturnLoc`'s value to `S`'s storage location instead 
> > > of changing the storage location? Alternatively, we can pass `S`'s 
> > > storage location to `pushCall` so that it can store it as `ReturnLoc`.
> > Could you clarify how this hurts convergence? My understanding is that 
> > `ReturnLoc` here is already stable, so this would make `S`'s storage 
> > location stable too.
> If I follow correctly, `ReturnLoc` here is the result of 
> `Env.createStorageLocation(ReturnType)` which isn't stable. Each call to 
> `createStorageLocation` returns a fresh storage location.
Ah I see, you're right. Is there a way to make a stable storage location for 
the `return`? My intuition is that we can't just pass `S`'s storage location to 
`pushCall`, because we want the storage location for the `return` to be the 
same across analysis of different callsites to the callee (similar to how we 
currently use the same storage location for a given parameter of the callee, 
regardless of how many times we analyze it). But maybe it would be fine; 
@ymandel do you have any thoughts on this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:345
+// FIXME: Support reference-type returns.
+assert(Val->getKind() != Value::Kind::Reference);
+

sgatev wrote:
> Let's do `if (Val->getKind() == Value::Kind::Reference) return;`. Otherwise 
> the framework will be unusable in practice.
Makes sense, will do.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:348
+auto *Loc = Env.getReturnStorageLocation();
+assert(Loc != nullptr);
+// FIXME: Model NRVO.

sgatev wrote:
> Let's do `if (Loc == nullptr) return;`
I don't think we want to do that, right? Shouldn't the `return` storage 
location always be set? Or is this about the "analyzing fragments rather than 
full functions" thing we discussed yesterday?



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:564
+  assert(ReturnLoc != nullptr);
+  Env.setStorageLocation(*S, *ReturnLoc);
+  Env.popCall(ExitEnv);

sgatev wrote:
> We use stable storage locations to ensure convergence. In that spirit, 
> shouldn't we assign `ReturnLoc`'s value to `S`'s storage location instead of 
> changing the storage location? Alternatively, we can pass `S`'s storage 
> location to `pushCall` so that it can store it as `ReturnLoc`.
Could you clarify how this hurts convergence? My understanding is that 
`ReturnLoc` here is already stable, so this would make `S`'s storage location 
stable too.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-03 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 449752.
samestep added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,24 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val == nullptr)
+  return;
+
+// FIXME: Support reference-type returns.
+assert(Val->getKind() != Value::Kind::Reference);
+
+auto *Loc 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-08-03 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 449667.
samestep added a comment.

Rebase and address all comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4121,4 +4121,112 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnVoid) {
+  std::string Code = R"(
+void Noop() { return; }
+
+void target() {
+  Noop();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+// This just tests that the analysis doesn't crash.
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnArg) {
+  std::string Code = R"(
+bool GiveBool();
+bool GiveBack(bool Arg) { return Arg; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBack(Foo);
+  bool Baz = Foo == Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*BazDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(BazVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,24 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::None);
+if (Val == nullptr)
+  return;
+
+// FIXME: Support reference-type returns.
+assert(Val->getKind() != 

[PATCH] D131039: [clang][dataflow] Add cache of `ControlFlowContext`s for function decls.

2022-08-03 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

Looks awesome, thanks @ymandel!




Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:23
 #include "clang/AST/Stmt.h"
-#include "clang/Analysis/CFG.h"
 #include "clang/Analysis/FlowSensitive/ControlFlowContext.h"

I'm guessing this change is unrelated to the patch as a whole?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131039/new/

https://reviews.llvm.org/D131039

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131065: [clang][dataflow] Store DeclContext of block being analysed in Environment if available.

2022-08-03 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:216
 
   const auto *FuncDecl = Call->getDirectCallee();
   assert(FuncDecl != nullptr);

I think you need to set the `DeclCtx` field here (or at least, somewhere in 
this method).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131065/new/

https://reviews.llvm.org/D131065

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131014: [clang][dataflow] Make the type of the post visit callback consistent

2022-08-02 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

Seems reasonable  I'm curious though, why does this not require 
`clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp` to be 
updated?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131014/new/

https://reviews.llvm.org/D131014

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-07-29 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa6ddc6848782: [clang][dataflow] Handle multiple 
context-sensitive calls to the same function (authored by samestep).

Changed prior to commit:
  https://reviews.llvm.org/D130726?vs=448698=448703#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130726/new/

https://reviews.llvm.org/D130726

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3960,4 +3960,165 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool , bool Val) { Var = Val; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBool();
+  SetBool(Foo, true);
+  SetBool(Bar, false);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTwoLayers) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool2(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetMultipleLines) {
+  std::string Code = R"(
+void SetBools(bool , bool ) {
+  Var1 = true;
+  Var2 = false;
+}
+
+void target() {
+  bool Foo = false;
+  bool Bar = true;
+  SetBools(Foo, Bar);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+

[PATCH] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-07-29 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 448698.
samestep added a comment.

Add more comments and tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130726/new/

https://reviews.llvm.org/D130726

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3960,4 +3960,165 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool , bool Val) { Var = Val; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBool();
+  SetBool(Foo, true);
+  SetBool(Bar, false);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTwoLayers) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool1(bool ) { Var = true; }
+void SetBool2(bool ) { SetBool1(Var); }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool2(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetMultipleLines) {
+  std::string Code = R"(
+void SetBools(bool , bool ) {
+  Var1 = true;
+  Var2 = false;
+}
+
+void target() {
+  bool Foo = false;
+  bool Bar = true;
+  SetBools(Foo, Bar);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
+  std::string Code = R"(
+void 

[PATCH] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-07-29 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:3963
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(

ymandel wrote:
> ymandel wrote:
> > samestep wrote:
> > > ymandel wrote:
> > > > Are there more scenarios testable at this point? e.g
> > > > 1. 2 layers of callees
> > > > 2. more than one line of code inside the body?
> > > > 3. one than one CFG block in the body?
> > > > 
> > > > If so, please add tests for those that are supported.
> > > 1. This currently isn't supported.
> > > 2. This should work.
> > > 3. This should work.
> > > 
> > > For (2) and (3), should I add those tests now, or do that in a followup 
> > > patch?
> > > 1. This currently isn't supported.
> > What's limiting us here? Just curious, not asking you to update the 
> > comments, etc.
> > 
> > > 2. This should work.
> > > 3. This should work.
> > > 
> > > For (2) and (3), should I add those tests now, or do that in a followup 
> > > patch?
> > 
> > may as well add them now. thx
> > 1. This currently isn't supported.
> > 2. This should work.
> > 3. This should work.
> > 
> > For (2) and (3), should I add those tests now, or do that in a followup 
> > patch?
> 
> 
> What's limiting us here? Just curious, not asking you to update the comments, 
> etc.

Nothing's really limiting us; all I meant was that currently we don't turn on 
context-sensitivity for the sub-analysis when we analyze the callee, and I 
don't want to turn that on until I've added support both for limiting the depth 
and for selecting the set of symbols to analyze using an allowlist.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130726/new/

https://reviews.llvm.org/D130726

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 448438.
samestep added a comment.

Address some of Yitzie's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130726/new/

https://reviews.llvm.org/D130726

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3960,4 +3960,45 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool , bool Val) { Var = Val; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBool();
+  SetBool(Foo, true);
+  SetBool(Bar, false);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -534,7 +534,7 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env = ExitState->Env;
+  Env.popCall(ExitState->Env);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -203,14 +203,6 @@
 Environment Environment::pushCall(const CallExpr *Call) const {
   Environment Env(*this);
 
-  // FIXME: Currently this only works if the callee is never a method and the
-  // same callee is never analyzed from multiple separate callsites. To
-  // generalize this, we'll need to store a "context" field (probably a stack of
-  // `const CallExpr *`s) in the `Environment`, and then change the
-  // `DataflowAnalysisContext` class to hold a map from contexts to "frames",
-  // where each frame stores its own version of what are currently the
-  // `DeclToLoc`, `ExprToLoc`, and `ThisPointeeLoc` fields.
-
   const auto *FuncDecl = Call->getDirectCallee();
   assert(FuncDecl != nullptr);
   const auto *Body = FuncDecl->getBody();
@@ -228,16 +220,40 @@
   for (; ArgIt != ArgEnd; ++ParamIt, ++ArgIt) {
 assert(ParamIt != ParamEnd);
 
-const VarDecl *Param = *ParamIt;
 const Expr *Arg = *ArgIt;
 auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
 assert(ArgLoc != nullptr);
-Env.setStorageLocation(*Param, *ArgLoc);
+
+const VarDecl *Param = *ParamIt;
+auto  = Env.createStorageLocation(*Param);
+Env.setStorageLocation(*Param, Loc);
+
+QualType ParamType = Param->getType();
+if (ParamType->isReferenceType()) {
+  auto  = Env.takeOwnership(std::make_unique(*ArgLoc));
+  Env.setValue(Loc, Val);
+} else if (auto *ArgVal = Env.getValue(*ArgLoc)) {
+  Env.setValue(Loc, *ArgVal);
+} else if (Value *Val = Env.createValue(ParamType)) {
+  Env.setValue(Loc, *Val);
+}
   }
 
   return Env;
 }
 
+void Environment::popCall(const Environment ) {
+  // We ignore `DACtx` because it's already the same in both. We don't bring
+  // back `DeclToLoc` and `ExprToLoc` because we want to be able to later
+  // analyze the same callee in a different context, and `setStorageLocation`
+  // requires there to not already be a storage location assigned. Conceptually,
+  // these maps capture 

[PATCH] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:227
+
+const VarDecl *Param = *ParamIt;
+auto  = Env.createStorageLocation(*Param);

ymandel wrote:
> maybe mention in the patch description that it also improves the modeling of 
> parameter initialization?
Good point; done.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:236
+  Env.setValue(Loc, *ArgVal);
+}
   }

ymandel wrote:
> Add an `else` that calls `createValue` on the decl's type, and then sets it, 
> like `VisitDeclStmt`?
Ah yes, I meant to do this before but forgot; will do that now.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:3963
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(

ymandel wrote:
> Are there more scenarios testable at this point? e.g
> 1. 2 layers of callees
> 2. more than one line of code inside the body?
> 3. one than one CFG block in the body?
> 
> If so, please add tests for those that are supported.
1. This currently isn't supported.
2. This should work.
3. This should work.

For (2) and (3), should I add those tests now, or do that in a followup patch?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130726/new/

https://reviews.llvm.org/D130726

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130593: [clang][dataflow] Separate context by frame

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

Here is the new patch: D130726 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130593/new/

https://reviews.llvm.org/D130593

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, tschuett, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130726

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3960,4 +3960,45 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool , bool Val) { Var = Val; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBool();
+  SetBool(Foo, true);
+  SetBool(Bar, false);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -534,7 +534,7 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env = ExitState->Env;
+  Env.popCall(ExitState->Env);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -203,14 +203,6 @@
 Environment Environment::pushCall(const CallExpr *Call) const {
   Environment Env(*this);
 
-  // FIXME: Currently this only works if the callee is never a method and the
-  // same callee is never analyzed from multiple separate callsites. To
-  // generalize this, we'll need to store a "context" field (probably a stack of
-  // `const CallExpr *`s) in the `Environment`, and then change the
-  // `DataflowAnalysisContext` class to hold a map from contexts to "frames",
-  // where each frame stores its own version of what are currently the
-  // `DeclToLoc`, `ExprToLoc`, and `ThisPointeeLoc` fields.
-
   const auto *FuncDecl = Call->getDirectCallee();
   assert(FuncDecl != nullptr);
   const auto *Body = FuncDecl->getBody();
@@ -228,16 +220,35 @@
   for (; ArgIt != ArgEnd; ++ParamIt, ++ArgIt) {
 assert(ParamIt != ParamEnd);
 
-const VarDecl *Param = *ParamIt;
 const Expr *Arg = *ArgIt;
 auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
 assert(ArgLoc != nullptr);
-Env.setStorageLocation(*Param, *ArgLoc);
+
+const VarDecl *Param = *ParamIt;
+auto  = Env.createStorageLocation(*Param);
+Env.setStorageLocation(*Param, Loc);
+
+if (Param->getType()->isReferenceType()) {
+  auto  = Env.takeOwnership(std::make_unique(*ArgLoc));
+  Env.setValue(Loc, Val);
+} else if (auto *ArgVal = Env.getValue(*ArgLoc)) {
+  Env.setValue(Loc, *ArgVal);
+}
   }
 
   return Env;
 }
 
+void Environment::popCall(const Environment ) {
+  // We ignore `DACtx` because it's already the same in both. We don't bring
+  // back `DeclToLoc` and `ExprToLoc` because we want to be able to later
+  // analyze the same callee in a different context, and `setStorageLocation`
+  // requires there to not already be a storage location assigned.
+  this->LocToVal = std::move(CalleeEnv.LocToVal);
+  this->MemberLocToStruct = 

[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:103
   if (Value *MergedVal = MergedEnv.createValue(Type))
 if (Model.merge(Type, *Val1, Env1, *Val2, Env2, *MergedVal, MergedEnv))
   return MergedVal;

sgatev wrote:
> We should probably pass `TookSecondBranch` here so that models can also use 
> it in the implementation of `merge`. Could be in a follow up, but let's leave 
> a FIXME.
FIXME added; thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 448405.
samestep added a comment.

Add FIXME about passing `TookSecondBranch` to `merge`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
  clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -1175,4 +1175,33 @@
   });
 }
 
+TEST_F(FlowConditionTest, JoinBackedge) {
+  std::string Code = R"(
+void target(bool Cond) {
+  bool Foo = true;
+  while (true) {
+(void)0;
+// [[p]]
+Foo = false;
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  = *cast(Env.getValue(*FooDecl, SkipPast::None));
+
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  });
+}
+
 } // namespace
Index: clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
@@ -179,7 +179,8 @@
   Context.addFlowConditionConstraint(FC2, C2);
   Context.addFlowConditionConstraint(FC2, C3);
 
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.joinFlowConditions(FC1, FC2, B);
   EXPECT_FALSE(Context.flowConditionImplies(FC3, C1));
   EXPECT_FALSE(Context.flowConditionImplies(FC3, C2));
   EXPECT_TRUE(Context.flowConditionImplies(FC3, C3));
@@ -500,23 +501,27 @@
   // FC2 = Y
   auto  = Context.makeFlowConditionToken();
   Context.addFlowConditionConstraint(FC2, Y);
-  // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  // JoinedFC = ((!B && FC1) || (B && FC2)) && Z = ((!B && X) || (B && Y)) && Z
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.joinFlowConditions(FC1, FC2, B);
   Context.addFlowConditionConstraint(JoinedFC, Z);
 
-  // If any of X, Y is true, JoinedFC is equivalent to Z
-  auto  =
-  Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
-  auto  =
-  Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
+  // If any of (!B && X), (B && Y) is true, JoinedFC is equivalent to Z
+  auto  = Context.buildAndSubstituteFlowCondition(
+  JoinedFC, {{, }, {, }});
+  auto  = Context.buildAndSubstituteFlowCondition(
+  JoinedFC, {{, }, {, }});
   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithXTrue, Z));
   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithYTrue, Z));
 
-  // If Z is true, JoinedFC is equivalent to (X || Y)
+  // If Z is true, JoinedFC is equivalent to ((!B && X) || (B && Y))
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithZTrue, Context.getOrCreateDisjunction(X, Y)));
+  JoinedFCWithZTrue,
+  Context.getOrCreateDisjunction(
+  Context.getOrCreateConjunction(Context.getOrCreateNegation(B), X),
+  Context.getOrCreateConjunction(B, Y;
 
   // If any of X, Y is false, JoinedFC is equivalent to the conjunction of the
   // other value and Z
@@ -525,9 +530,13 @@
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithXFalse, Context.getOrCreateConjunction(Y, Z)));
+  JoinedFCWithXFalse,
+  Context.getOrCreateConjunction(Context.getOrCreateConjunction(B, Y), Z)));
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithYFalse, Context.getOrCreateConjunction(X, Z)));
+  JoinedFCWithYFalse,
+  Context.getOrCreateConjunction(
+  Context.getOrCreateConjunction(Context.getOrCreateNegation(B), X),
+  Z)));
 
   // If Z is false, JoinedFC is false
   auto  =
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-28 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:114
+  ///
+  ///  `return` must not be assigned a storage location.
+  void setReturnStorageLocation(StorageLocation ) {

sgatev wrote:
> li.zhe.hua wrote:
> > samestep wrote:
> > > li.zhe.hua wrote:
> > > > Fix this as well? A reader shouldn't need to root around in private 
> > > > implementation details to understand the requirements for calling a 
> > > > function.
> > > Could you clarify what you mean? I was simply copying the signature and 
> > > docstring from `setThisPointeeStorageLocation`.
> > You've marked `return` in backticks. There is no parameter named `return` 
> > and it is unclear what `return` refers to. My best guess is that this is a 
> > typo of `ReturnLoc`, which is a private data member. So this is a public 
> > interface with a requirement that a private data member has some property. 
> > This should instead reframe the requirement as properties from the external 
> > reader's perspective.
> That was my guess initially too, but my next best guess is that `return` in 
> backticks stands for the keyword/AST node. In any case, let's make it less 
> ambiguous and let's not add requirements based on implementation details. How 
> about: `The return value must not be assigned a storage location.`?
Ah sorry, I understand now; you simply meant that I should make the same change 
here that @gribozavr2 suggested I make to the other docstrings? I'll go ahead 
and do that (once I am able to re-export this patch again).



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:338-339
+if (Loc == nullptr) {
+  // The outermost context does not set a storage location for `return`, so
+  // in that case we just ignore `return` statements.
+  return;

sgatev wrote:
> samestep wrote:
> > sgatev wrote:
> > > Let's make this a FIXME to set a storage location for the outermost 
> > > context too.
> > @sgatev I could add a `FIXME` for that, or I could just do it in this same 
> > patch; do you have a preference between those two options?
> Same patch works!
Cool, I have an update to this patch which does that, so I'll export it here as 
soon as I am able to do so.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:3908
+  Var = true;
+  return;
+}

li.zhe.hua wrote:
> samestep wrote:
> > li.zhe.hua wrote:
> > > Why is this change to the test necessary?
> > This is mentioned in the patch description (updated earlier today); it's 
> > not necessary, but I added it to get a bit of extra coverage for some cases 
> > in the `VisitReturnStmt` method this patch adds.
> Please add the coverage as a separate test. Separate behaviors should be 
> tested as separate tests. go/unit-testing-practices#behavior-testing
Makes sense, I'll do that. Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130593: [clang][dataflow] Separate context by frame

2022-07-27 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

Note: after some discussion with @ymandel, we've decided to adjust our design 
for this. A new patch is on the way which will replace this one.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130593/new/

https://reviews.llvm.org/D130593

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-27 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:114
+  ///
+  ///  `return` must not be assigned a storage location.
+  void setReturnStorageLocation(StorageLocation ) {

li.zhe.hua wrote:
> Fix this as well? A reader shouldn't need to root around in private 
> implementation details to understand the requirements for calling a function.
Could you clarify what you mean? I was simply copying the signature and 
docstring from `setThisPointeeStorageLocation`.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:221
+
   // FIXME: Currently this only works if the callee is never a method and the
   // same callee is never analyzed from multiple separate callsites. To

li.zhe.hua wrote:
> I'm a little unclear on what "this" is. Is it this entire function, or just 
> the call to `getDirectCallee()`? Can this comment be moved somewhere more 
> appropriate, and specifically, so it is touching the code that is most 
> relevant to it? It is currently floating in the middle of the function, and 
> it's unclear to me why new code is being added above it vs. below it.
Yes, this comment is not meant to be present in this patch; I am trying to 
update the parent patch to remove this comment, but am currently unable to do 
export it to Phabricator for technical reasons. I should be able to do that 
tomorrow.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:3908
+  Var = true;
+  return;
+}

li.zhe.hua wrote:
> Why is this change to the test necessary?
This is mentioned in the patch description (updated earlier today); it's not 
necessary, but I added it to get a bit of extra coverage for some cases in the 
`VisitReturnStmt` method this patch adds.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-27 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 448044.
samestep added a comment.

Set a storage location for the outermost context too


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3903,7 +3903,10 @@
 TEST(TransferTest, ContextSensitiveSetTrue) {
   std::string Code = R"(
 bool GiveBool();
-void SetBool(bool ) { Var = true; }
+void SetBool(bool ) {
+  Var = true;
+  return;
+}
 
 void target() {
   bool Foo = GiveBool();
@@ -3933,7 +3936,10 @@
 TEST(TransferTest, ContextSensitiveSetFalse) {
   std::string Code = R"(
 bool GiveBool();
-void SetBool(bool ) { Var = false; }
+void SetBool(bool ) {
+  Var = false;
+  return;
+}
 
 void target() {
   bool Foo = GiveBool();
@@ -4001,4 +4007,60 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,21 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Ret = S->getRetValue();
+if (Ret == nullptr)
+  return;
+
+auto *Val = Env.getValue(*Ret, SkipPast::Reference);
+if (Val == nullptr)
+  return;
+
+auto *Loc = Env.getReturnStorageLocation();
+assert(Loc != nullptr);
+// FIXME: Model NRVO.
+Env.setValue(*Loc, *Val);
+  }
+
   void VisitMemberExpr(const MemberExpr *S) {
 ValueDecl *Member = S->getMemberDecl();
 assert(Member != nullptr);
@@ -534,7 +549,11 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env.popCall(ExitState->Env);
+  auto  = ExitState->Env;
+  auto *ReturnLoc = ExitEnv.getReturnStorageLocation();
+  assert(ReturnLoc != nullptr);
+  Env.setStorageLocation(*S, *ReturnLoc);
+  Env.popCall(ExitEnv);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -179,6 +179,10 @@
   if (Value *ParamVal = createValue(ParamDecl->getType()))
 setValue(ParamLoc, *ParamVal);
 }
+
+QualType ReturnType = FuncDecl->getReturnType();
+auto  = 

[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-27 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

@gribozavr2 I rebased again, should work now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-27 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 448026.
samestep added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
  clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -1175,4 +1175,33 @@
   });
 }
 
+TEST_F(FlowConditionTest, JoinBackedge) {
+  std::string Code = R"(
+void target(bool Cond) {
+  bool Foo = true;
+  while (true) {
+(void)0;
+// [[p]]
+Foo = false;
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  = *cast(Env.getValue(*FooDecl, SkipPast::None));
+
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  });
+}
+
 } // namespace
Index: clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
@@ -179,7 +179,8 @@
   Context.addFlowConditionConstraint(FC2, C2);
   Context.addFlowConditionConstraint(FC2, C3);
 
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.joinFlowConditions(FC1, FC2, B);
   EXPECT_FALSE(Context.flowConditionImplies(FC3, C1));
   EXPECT_FALSE(Context.flowConditionImplies(FC3, C2));
   EXPECT_TRUE(Context.flowConditionImplies(FC3, C3));
@@ -500,23 +501,27 @@
   // FC2 = Y
   auto  = Context.makeFlowConditionToken();
   Context.addFlowConditionConstraint(FC2, Y);
-  // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  // JoinedFC = ((!B && FC1) || (B && FC2)) && Z = ((!B && X) || (B && Y)) && Z
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.joinFlowConditions(FC1, FC2, B);
   Context.addFlowConditionConstraint(JoinedFC, Z);
 
-  // If any of X, Y is true, JoinedFC is equivalent to Z
-  auto  =
-  Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
-  auto  =
-  Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
+  // If any of (!B && X), (B && Y) is true, JoinedFC is equivalent to Z
+  auto  = Context.buildAndSubstituteFlowCondition(
+  JoinedFC, {{, }, {, }});
+  auto  = Context.buildAndSubstituteFlowCondition(
+  JoinedFC, {{, }, {, }});
   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithXTrue, Z));
   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithYTrue, Z));
 
-  // If Z is true, JoinedFC is equivalent to (X || Y)
+  // If Z is true, JoinedFC is equivalent to ((!B && X) || (B && Y))
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithZTrue, Context.getOrCreateDisjunction(X, Y)));
+  JoinedFCWithZTrue,
+  Context.getOrCreateDisjunction(
+  Context.getOrCreateConjunction(Context.getOrCreateNegation(B), X),
+  Context.getOrCreateConjunction(B, Y;
 
   // If any of X, Y is false, JoinedFC is equivalent to the conjunction of the
   // other value and Z
@@ -525,9 +530,13 @@
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithXFalse, Context.getOrCreateConjunction(Y, Z)));
+  JoinedFCWithXFalse,
+  Context.getOrCreateConjunction(Context.getOrCreateConjunction(B, Y), Z)));
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithYFalse, Context.getOrCreateConjunction(X, Z)));
+  JoinedFCWithYFalse,
+  Context.getOrCreateConjunction(
+  Context.getOrCreateConjunction(Context.getOrCreateNegation(B), X),
+  Z)));
 
   // If Z is false, JoinedFC is false
   auto  =
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ 

[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-27 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:338-339
+if (Loc == nullptr) {
+  // The outermost context does not set a storage location for `return`, so
+  // in that case we just ignore `return` statements.
+  return;

sgatev wrote:
> Let's make this a FIXME to set a storage location for the outermost context 
> too.
@sgatev I could add a `FIXME` for that, or I could just do it in this same 
patch; do you have a preference between those two options?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130593: [clang][dataflow] Separate context by frame

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D130593#3681126 , @xazax.hun wrote:

> While separate call strings are properly isolated from each other, repeated 
> analysis of the same call is not:|
>
>   while (...)
>   {
> foo(...);
>   }
>
> In the above code snippet, we will end up analyzing foo with leftover state 
> from the previous iteration. The analysis can potentially observe state 
> private to the previous call in the current call. Do I miss something or is 
> this intentional?

Correct, you didn't miss something. I'm not really sure of the best way to deal 
with this; in the short term, my plan is to only allow analysis of a callee 
when it is not already present in the call-string. @ymandel any ideas for the 
longer term?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130593/new/

https://reviews.llvm.org/D130593

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:110
 
+  /// Assigns `Loc` as the storage location of `return`.
+  ///

gribozavr2 wrote:
> 
Done.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:120-121
+
+  /// Returns the storage location assigned to `return` or null if `return` has
+  /// no assigned storage location.
+  StorageLocation *getReturnStorageLocation() const { return ReturnLoc; }

gribozavr2 wrote:
> 
Done.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:224-225
 
+  /// Returns the storage location assigned to `return` in the environment or
+  /// null if `return` has no assigned storage location in the environment.
+  StorageLocation *getReturnStorageLocation() const;

gribozavr2 wrote:
> 
Done.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:347
+assert(Val != nullptr);
+Env.setValue(*Loc, *Val);
+  }

gribozavr2 wrote:
> Please add a TODO about modeling NRVO.
Added, thanks! I hadn't realized this would be necessary.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 447906.
samestep added a comment.

Address Dmitri's review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130600/new/

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4001,4 +4001,60 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,22 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Loc = Env.getReturnStorageLocation();
+if (Loc == nullptr) {
+  // The outermost context does not set a storage location for `return`, so
+  // in that case we just ignore `return` statements.
+  return;
+}
+
+auto *Ret = S->getRetValue();
+assert(Ret != nullptr);
+auto *Val = Env.getValue(*Ret, SkipPast::Reference);
+assert(Val != nullptr);
+// FIXME: Model NRVO.
+Env.setValue(*Loc, *Val);
+  }
+
   void VisitMemberExpr(const MemberExpr *S) {
 ValueDecl *Member = S->getMemberDecl();
 assert(Member != nullptr);
@@ -534,7 +550,11 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env.popCall(ExitState->Env);
+  auto  = ExitState->Env;
+  auto *ReturnLoc = ExitEnv.getReturnStorageLocation();
+  assert(ReturnLoc != nullptr);
+  Env.setStorageLocation(*S, *ReturnLoc);
+  Env.popCall(ExitEnv);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -204,6 +204,16 @@
   Environment Env(*this);
   Env.CallStr.push_back(Call);
 
+  const auto *FuncDecl = Call->getDirectCallee();
+  assert(FuncDecl != nullptr);
+
+  auto *ReturnLoc = DACtx->getFrame(Env.CallStr).getReturnStorageLocation();
+  if (ReturnLoc == nullptr) {
+QualType ReturnType = FuncDecl->getReturnType();
+DACtx->getFrame(Env.CallStr)
+.setReturnStorageLocation(Env.createStorageLocation(ReturnType));
+  }
+
   // FIXME: Currently this only works if the callee is never a method and the
   // same callee is never analyzed from multiple separate callsites. To
   // generalize this, we'll need to store a "context" field (probably a stack of
@@ 

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D130306#3680942 , @chapuni wrote:

> A few variables cause warinings in -Asserts.

Thanks for pointing this out! How should I address this? Should I just inline 
the definitions of those variables into the `assert`s themselves?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130600: [clang][dataflow] Handle return statements

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, tschuett, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Depends On D130593 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130600

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4001,4 +4001,60 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnTrue) {
+  std::string Code = R"(
+bool GiveBool() { return true; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveReturnFalse) {
+  std::string Code = R"(
+bool GiveBool() { return false; }
+
+void target() {
+  bool Foo = GiveBool();
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -332,6 +332,21 @@
   std::make_unique(*ThisPointeeLoc)));
   }
 
+  void VisitReturnStmt(const ReturnStmt *S) {
+auto *Loc = Env.getReturnStorageLocation();
+if (Loc == nullptr) {
+  // The outermost context does not set a storage location for `return`, so
+  // in that case we just ignore `return` statements.
+  return;
+}
+
+auto *Ret = S->getRetValue();
+assert(Ret != nullptr);
+auto *Val = Env.getValue(*Ret, SkipPast::Reference);
+assert(Val != nullptr);
+Env.setValue(*Loc, *Val);
+  }
+
   void VisitMemberExpr(const MemberExpr *S) {
 ValueDecl *Member = S->getMemberDecl();
 assert(Member != nullptr);
@@ -534,7 +549,11 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env.popCall(ExitState->Env);
+  auto  = ExitState->Env;
+  auto *ReturnLoc = ExitEnv.getReturnStorageLocation();
+  assert(ReturnLoc != nullptr);
+  Env.setStorageLocation(*S, *ReturnLoc);
+  Env.popCall(ExitEnv);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -204,6 +204,16 @@
   Environment Env(*this);
   Env.CallStr.push_back(Call);
 
+  const auto *FuncDecl = Call->getDirectCallee();
+  assert(FuncDecl != nullptr);
+
+  auto *ReturnLoc = DACtx->getFrame(Env.CallStr).getReturnStorageLocation();
+  if (ReturnLoc == nullptr) {
+QualType ReturnType = FuncDecl->getReturnType();
+DACtx->getFrame(Env.CallStr)
+.setReturnStorageLocation(Env.createStorageLocation(ReturnType));
+  }
+
   // FIXME: Currently this only works if the callee is never a method and the
   // same callee is never analyzed 

[PATCH] D130593: [clang][dataflow] Separate context by frame

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 447808.
samestep added a comment.

Use operator[] instead of try_emplace for C++14 compatibility


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130593/new/

https://reviews.llvm.org/D130593

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3960,4 +3960,45 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool , bool Val) { Var = Val; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBool();
+  SetBool(Foo, true);
+  SetBool(Bar, false);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -534,7 +534,7 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env = ExitState->Env;
+  Env.popCall(ExitState->Env);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -154,7 +154,7 @@
 : DACtx(), FlowConditionToken(()) {}
 
 Environment::Environment(const Environment )
-: DACtx(Other.DACtx), DeclToLoc(Other.DeclToLoc),
+: DACtx(Other.DACtx), CallStr(Other.CallStr), DeclToLoc(Other.DeclToLoc),
   ExprToLoc(Other.ExprToLoc), LocToVal(Other.LocToVal),
   MemberLocToStruct(Other.MemberLocToStruct),
   FlowConditionToken(>forkFlowCondition(*Other.FlowConditionToken)) {
@@ -192,7 +192,7 @@
   // FIXME: Add support for union types.
   if (!ThisPointeeType->isUnionType()) {
 auto  = createStorageLocation(ThisPointeeType);
-DACtx.setThisPointeeStorageLocation(ThisPointeeLoc);
+DACtx.getFrame(CallStr).setThisPointeeStorageLocation(ThisPointeeLoc);
 if (Value *ThisPointeeVal = createValue(ThisPointeeType))
   setValue(ThisPointeeLoc, *ThisPointeeVal);
   }
@@ -202,6 +202,7 @@
 
 Environment Environment::pushCall(const CallExpr *Call) const {
   Environment Env(*this);
+  Env.CallStr.push_back(Call);
 
   // FIXME: Currently this only works if the callee is never a method and the
   // same callee is never analyzed from multiple separate callsites. To
@@ -238,6 +239,17 @@
   return Env;
 }
 
+void Environment::popCall(const Environment ) {
+  // We ignore `DACtx` because it's already the same in both. We don't want the
+  // callee's `CallStr` because it is one level deeper than ours. We don't bring
+  // back `DeclToLoc` and `ExprToLoc` because their mappings are only valid for
+  // the `CallStr` in `CalleeEnv`, and we want to be able to later analyze the
+  // same callee in a different context.
+  this->LocToVal = std::move(CalleeEnv.LocToVal);
+  this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct);
+  this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
+}
+
 bool 

[PATCH] D130593: [clang][dataflow] Separate context by frame

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, tschuett, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130593

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3960,4 +3960,45 @@
/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
 }
 
+TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool , bool Val) { Var = Val; }
+
+void target() {
+  bool Foo = GiveBool();
+  bool Bar = GiveBool();
+  SetBool(Foo, true);
+  SetBool(Bar, false);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+
+auto  =
+*cast(Env.getValue(*BarDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(BarVal));
+EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -534,7 +534,7 @@
   auto ExitState = (*BlockToOutputState)[ExitBlock];
   assert(ExitState);
 
-  Env = ExitState->Env;
+  Env.popCall(ExitState->Env);
 }
   }
 
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -154,7 +154,7 @@
 : DACtx(), FlowConditionToken(()) {}
 
 Environment::Environment(const Environment )
-: DACtx(Other.DACtx), DeclToLoc(Other.DeclToLoc),
+: DACtx(Other.DACtx), CallStr(Other.CallStr), DeclToLoc(Other.DeclToLoc),
   ExprToLoc(Other.ExprToLoc), LocToVal(Other.LocToVal),
   MemberLocToStruct(Other.MemberLocToStruct),
   FlowConditionToken(>forkFlowCondition(*Other.FlowConditionToken)) {
@@ -192,7 +192,7 @@
   // FIXME: Add support for union types.
   if (!ThisPointeeType->isUnionType()) {
 auto  = createStorageLocation(ThisPointeeType);
-DACtx.setThisPointeeStorageLocation(ThisPointeeLoc);
+DACtx.getFrame(CallStr).setThisPointeeStorageLocation(ThisPointeeLoc);
 if (Value *ThisPointeeVal = createValue(ThisPointeeType))
   setValue(ThisPointeeLoc, *ThisPointeeVal);
   }
@@ -202,6 +202,7 @@
 
 Environment Environment::pushCall(const CallExpr *Call) const {
   Environment Env(*this);
+  Env.CallStr.push_back(Call);
 
   // FIXME: Currently this only works if the callee is never a method and the
   // same callee is never analyzed from multiple separate callsites. To
@@ -238,6 +239,17 @@
   return Env;
 }
 
+void Environment::popCall(const Environment ) {
+  // We ignore `DACtx` because it's already the same in both. We don't want the
+  // callee's `CallStr` because it is one level deeper than ours. We don't bring
+  // back `DeclToLoc` and `ExprToLoc` because their mappings are only valid for
+  // the `CallStr` in `CalleeEnv`, and we want to be able to later analyze the
+  // same callee in a different context.
+  this->LocToVal = std::move(CalleeEnv.LocToVal);
+  this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct);
+  this->FlowConditionToken = 

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG300fbf56f89a: [clang][dataflow] Analyze calls to in-TU 
functions (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+   

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 447758.
samestep added a comment.

Use different name for TransferOptions field


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+   

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGfa2b83d07eca: [clang][dataflow] Analyze calls to in-TU 
functions (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+   

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 447750.
samestep added a comment.

Be explicit when constructing TransferOptions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+  

[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D130270#3679273 , @gribozavr2 
wrote:

> Sorry, could you rebase the patch? It does not apply cleanly anymore.

Done; I didn't see any conflicts when I rebased, but hopefully the issue on 
your end is resolved now?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 447656.
samestep added a comment.

Rebase and add Yitzie's assertion


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
  clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -1175,4 +1175,33 @@
   });
 }
 
+TEST_F(FlowConditionTest, JoinBackedge) {
+  std::string Code = R"(
+void target(bool Cond) {
+  bool Foo = true;
+  while (true) {
+(void)0;
+// [[p]]
+Foo = false;
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  = *cast(Env.getValue(*FooDecl, SkipPast::None));
+
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  });
+}
+
 } // namespace
Index: clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
@@ -179,7 +179,8 @@
   Context.addFlowConditionConstraint(FC2, C2);
   Context.addFlowConditionConstraint(FC2, C3);
 
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.joinFlowConditions(FC1, FC2, B);
   EXPECT_FALSE(Context.flowConditionImplies(FC3, C1));
   EXPECT_FALSE(Context.flowConditionImplies(FC3, C2));
   EXPECT_TRUE(Context.flowConditionImplies(FC3, C3));
@@ -435,38 +436,49 @@
   // FC2 = Y
   auto  = Context.makeFlowConditionToken();
   Context.addFlowConditionConstraint(FC2, Y);
-  // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  // JoinedFC = ((!B && FC1) || (B && FC2)) && Z = ((!B && X) || (B && Y)) && Z
+  auto  = Context.createAtomicBoolValue();
+  auto  = Context.joinFlowConditions(FC1, FC2, B);
   Context.addFlowConditionConstraint(JoinedFC, Z);
 
-  // If any of X, Y is true in JoinedFC, JoinedFC = (X || Y) && Z is equivalent
-  // to evaluating the remaining Z
-  auto  =
-  Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
-  auto  =
-  Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
+  // If any of (!B && X), (B && Y) is true in JoinedFC,
+  // JoinedFC = ((!B && X) || (B && Y)) && Z is equivalent to evaluating the
+  // remaining Z
+  auto  = Context.buildAndSubstituteFlowCondition(
+  JoinedFC, {{, }, {, }});
+  auto  = Context.buildAndSubstituteFlowCondition(
+  JoinedFC, {{, }, {, }});
   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithXTrue, Z));
   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithYTrue, Z));
 
-  // If Z is true in JoinedFC, JoinedFC = (X || Y) && Z is equivalent to
-  // evaluating the remaining disjunction (X || Y)
+  // If Z is true in JoinedFC, JoinedFC = ((!B && X) || (B && Y)) && Z is
+  // equivalent to evaluating the remaining disjunction ((!B && X) || (B && Y))
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithZTrue, Context.getOrCreateDisjunction(X, Y)));
-
-  // If any of X, Y is false in JoinedFC, JoinedFC = (X || Y) && Z is equivalent
-  // to evaluating the conjunction of the other value and Z
+  JoinedFCWithZTrue,
+  Context.getOrCreateDisjunction(
+  Context.getOrCreateConjunction(Context.getOrCreateNegation(B), X),
+  Context.getOrCreateConjunction(B, Y;
+
+  // If any of X, Y is false in JoinedFC,
+  // JoinedFC = ((!B && X) || (B && Y)) && Z is equivalent to evaluating the
+  // conjunction of the other disjunct and Z
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   auto  =
   Context.buildAndSubstituteFlowCondition(JoinedFC, {{, }});
   EXPECT_TRUE(Context.equivalentBoolValues(
-  JoinedFCWithXFalse, Context.getOrCreateConjunction(Y, Z)));
+  JoinedFCWithXFalse,
+  

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-26 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

@xazax.hun Do you have anything else you'd like addressed/changed (either here 
or in the doc we shared with you) before I land this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-25 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D130306#3676672 , @xazax.hun wrote:

> Thanks! Knowing the context, I am much happier with the direction overall. Is 
> the plan to analyze a mock of std::optional instead of the actual code in the 
> STL? How will that mock be shipped? Would that be embedded in the binary?

Glad to hear it! Yes, the current plan is to analyze a mock of `std::optional` 
instead of the actual type. One reason for this is that we would like to use 
the same mock to model multiple different `optional` types (e.g. 
`absl::optional`) using the same mock. Our current plan is to embed it directly 
in the binary.

> Overall, I am excited for context-sensitive analysis, and some of my concerns 
> are addressed. Looking forward to the follow-up patches :)

Thanks Gábor! I'll let @ymandel and others respond to your other points; also, 
thanks for the links, those resources look very helpful.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-25 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D130306#3673120 , @xazax.hun wrote:

> Thanks! I think this is a major design decision, and I'd love to see a 
> discussion about the alternatives considered before jumping to an 
> implementation. Specifically, I'd like to know if summaries are out of scope 
> or something you would consider in the future. Knowing this is useful because 
> this can influence how the code should be reviewed. E.g., if you plan to have 
> multiple ways to do context sensitive analysis in the future, we should make 
> sure that the current code will not lock us in in the inline substitution 
> approach. If summaries are not planned at all, this is not a concern.

This is a good question. I shared with you our design doc, which may help 
clarify somewhat; please let me know if you have further concerns.

> The Clang Static Analyzer is using this approach and it was a long way to 
> iron out all the corner cases where the performance was bad. It has many cuts 
> including maximum number of visits for a basic block, maximum call stack 
> depth, not inlining functions after a certain size threshold and so on. 
> Basically, it took some time to get the right performance and precision. But 
> overall, the inline substitution approach will never scale to large call 
> stacks/long calling contexts. On the other hand, a summary-based approach can 
> potentially find bugs across a really large number of function calls with 
> reasonable costs. Mainly because the same function is not reanalyzed for 
> every context.

That makes a lot of sense. From what you're saying, it sounds like we'll avoid 
that in our plan by keeping contexts small due to only context-sensitively 
analyzing simple models that we write ourselves.

> I see. This was not clear to me from the description of the patch notes. It 
> seems to me that the goal here is to simplify the modeling of certain types, 
> not general context-sensitive analysis. I reviewed this patch with the wrong 
> idea in mind. If that is the goal, the current approach makes sense. But I 
> think the comments should make clear what the intended use case and the 
> limitations of the current approach is.

Fair point. Hopefully the intended use case will become more clear in the code 
itself as I follow up with further patches; if not then I can modify the 
comments to clarify that. Are there any specific things you'd like to see 
written comments in this patch itself before landing?

> The main reason I wanted to call this out because it increasingly seems to be 
> whenever a decision needs to be made, the framework is getting less and less 
> sound. Basically, many design decisions here are very similar to what the 
> Clang Static Analyzer is doing.  Since Clang already has an analysis 
> framework for unsound analysis, I wanted to avoid you reinventing the wheel 
> and doing something similar to CSA instead of providing something new for the 
> use cases that cannot be covered by the CSA.

This makes sense; in this case, though, the unsoundness is already present 
(this patch does nothing to change the way we analyze calls to functions for 
which we can't see the body), so if anything, unsoundness is reduced here. I'll 
let @ymandel respond to this in more detail, though.

> Oh, my bad! I somehow blinked and totally skipped that comment.

No worries! This patch is a bit large so it's easy to miss. Thanks for taking 
the time to review in such detail!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446958.
samestep added a comment.

Appease -Wmissing-field-initializers


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+   

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h:64
   TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
   : Options({ApplyBuiltinTransfer}) {}
 

li.zhe.hua wrote:
> Nit: `-Wmissing-field-initializers` is apparently enabled, and starts warning 
> on this.
Ah thanks, will fix.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:42
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,

li.zhe.hua wrote:
> For the purposes of the test, there's really only 3 states:
> 
>   # No built-in transfer
>   # Built-in transfer, no context-sensitive
>   # Built-in transfer, with context-sensitive
> 
> It may be more readable for tests to have a 3-state enum, that `runDataFlow` 
> will then use to produce the corresponding `DataflowAnalysisOptions`. As is, 
> a snippet like
> 
> ```
>   {/*.ApplyBuiltinTransfer=*/true,
>/*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
> ```
> 
> is rough to read. Good enum names with good comments would probably make this 
> much better. WDYT?
I agree that there are only 3 states, but I also think that conceptually this 
really is a multi-layered thing; either we apply the built-in transfer or not, 
and then if we do apply the builtin transfer, there's some set of options we 
pass to it. Thus, it doesn't seem right to just collapse it into a flat enum; 
I'm not sure though.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:67
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer}, Std, TargetFun);
+}

li.zhe.hua wrote:
> Nit: `-Wmissing-field-initializers` is apparently enabled, and starts warning 
> on this.
Same here; thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446915.
samestep added a comment.

Update comment about default parameters


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:220
+  assert(Body != nullptr);
+  initGlobalVars(*Body, Env);
+

ymandel wrote:
> samestep wrote:
> > ymandel wrote:
> > > samestep wrote:
> > > > ymandel wrote:
> > > > > I wonder how this will work between caller and callee. Do we need 
> > > > > separate global var state in the frame? If so, maybe mention that as 
> > > > > well in the FIXME above.
> > > > Could you clarify what you mean? Perhaps I just don't understand 
> > > > exactly what is meant by "global vars" here.
> > > https://github.com/llvm/llvm-project/blob/main/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp#L131-L135
> > > 
> > > ```
> > > /// Initializes global storage values that are declared or referenced from
> > > /// sub-statements of `S`.
> > > // FIXME: Add support for resetting globals after function calls to enable
> > > // the implementation of sound analyses.
> > > ```
> > > Since this already mentions a need to reset after function calls, seemed 
> > > relevant here.
> > Hmm, OK. I pretty much just pattern-matched from the `Environment` 
> > constructor right above this method implementation. Would it be better for 
> > me to instead just remove this `initGlobalVars` call for now and replace it 
> > with a `FIXME` saying that we'll probably need to call this but it's 
> > unclear how exactly to do so?
> SGTM. We can note this constraint on models' reference implementations. 
> Specifically, that they cannot reference globals.
Done.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:231
+  // parameters still need to be given `StorageLocation`s anyway, so this code
+  // will need to be generalized later.
+  for (; ArgIt != ArgEnd; ++ParamIt, ++ArgIt) {

gribozavr2 wrote:
> The Clang AST includes argument expressions for defaulted arguments, so I 
> believe there shouldn't be anything left to do here, it should just work.
Oh nice! I'm updating this comment, thanks.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:3896
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+  },

gribozavr2 wrote:
> 
Good idea, done.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446914.
samestep added a comment.

Don't allow globals


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,95 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ 

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446855.
samestep added a comment.

Fix typo in comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,94 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, 

[PATCH] D130305: [clang][dataflow] Refactor ApplyBuiltinTransfer field out into DataflowAnalysisOptions struct

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGaed1ab8cabac: [clang][dataflow] Refactor 
ApplyBuiltinTransfer field out into… (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130305/new/

https://reviews.llvm.org/D130305

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h


Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -30,6 +30,14 @@
 namespace clang {
 namespace dataflow {
 
+struct DataflowAnalysisOptions {
+  /// Determines whether to apply the built-in transfer functions.
+  // FIXME: Remove this option once the framework supports composing analyses
+  // (at which point the built-in transfer functions can be simply a standalone
+  // analysis).
+  bool ApplyBuiltinTransfer = true;
+};
+
 /// Type-erased lattice element container.
 ///
 /// Requirements:
@@ -42,16 +50,17 @@
 
 /// Type-erased base class for dataflow analyses built on a single lattice 
type.
 class TypeErasedDataflowAnalysis : public Environment::ValueModel {
-  /// Determines whether to apply the built-in transfer functions.
-  // FIXME: Remove this option once the framework supports composing analyses
-  // (at which point the built-in transfer functions can be simply a standalone
-  // analysis).
-  bool ApplyBuiltinTransfer;
+  DataflowAnalysisOptions Options;
 
 public:
-  TypeErasedDataflowAnalysis() : ApplyBuiltinTransfer(true) {}
+  TypeErasedDataflowAnalysis() : Options({}) {}
+
+  /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
   TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
-  : ApplyBuiltinTransfer(ApplyBuiltinTransfer) {}
+  : Options({ApplyBuiltinTransfer}) {}
+
+  TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
+  : Options(Options) {}
 
   virtual ~TypeErasedDataflowAnalysis() {}
 
@@ -80,7 +89,7 @@
 
   /// Determines whether to apply the built-in transfer functions, which model
   /// the heap and stack in the `Environment`.
-  bool applyBuiltinTransfer() const { return ApplyBuiltinTransfer; }
+  bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; }
 };
 
 /// Type-erased model of the program at a given program point.
Index: clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
@@ -24,13 +24,17 @@
 
 class NoopAnalysis : public DataflowAnalysis {
 public:
+  /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
+  NoopAnalysis(ASTContext , bool ApplyBuiltinTransfer)
+  : DataflowAnalysis(Context,
+ApplyBuiltinTransfer) {}
+
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
   /// functions that model memory during the analysis. Their results are not
   /// used by `NoopAnalysis`, but tests that need to inspect the environment
   /// should enable them.
-  NoopAnalysis(ASTContext , bool ApplyBuiltinTransfer)
-  : DataflowAnalysis(Context,
-ApplyBuiltinTransfer) {}
+  NoopAnalysis(ASTContext , DataflowAnalysisOptions Options)
+  : DataflowAnalysis(Context, Options) {}
 
   static NoopLattice initialElement() { return {}; }
 
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -63,9 +63,15 @@
   using Lattice = LatticeT;
 
   explicit DataflowAnalysis(ASTContext ) : Context(Context) {}
+
+  /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
   explicit DataflowAnalysis(ASTContext , bool ApplyBuiltinTransfer)
   : TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
 
+  explicit DataflowAnalysis(ASTContext ,
+DataflowAnalysisOptions Options)
+  : TypeErasedDataflowAnalysis(Options), Context(Context) {}
+
   ASTContext () final { return Context; }
 
   TypeErasedLattice typeErasedInitialElement() final {


Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ 

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:220
+  assert(Body != nullptr);
+  initGlobalVars(*Body, Env);
+

ymandel wrote:
> samestep wrote:
> > ymandel wrote:
> > > I wonder how this will work between caller and callee. Do we need 
> > > separate global var state in the frame? If so, maybe mention that as well 
> > > in the FIXME above.
> > Could you clarify what you mean? Perhaps I just don't understand exactly 
> > what is meant by "global vars" here.
> https://github.com/llvm/llvm-project/blob/main/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp#L131-L135
> 
> ```
> /// Initializes global storage values that are declared or referenced from
> /// sub-statements of `S`.
> // FIXME: Add support for resetting globals after function calls to enable
> // the implementation of sound analyses.
> ```
> Since this already mentions a need to reset after function calls, seemed 
> relevant here.
Hmm, OK. I pretty much just pattern-matched from the `Environment` constructor 
right above this method implementation. Would it be better for me to instead 
just remove this `initGlobalVars` call for now and replace it with a `FIXME` 
saying that we'll probably need to call this but it's unclear how exactly to do 
so?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446842.
samestep added a comment.

Address Yitzie's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,94 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, 

[PATCH] D130305: [clang][dataflow] Refactor ApplyBuiltinTransfer field out into DataflowAnalysisOptions struct

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446841.
samestep added a comment.

Mark bool constructors as deprecated


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130305/new/

https://reviews.llvm.org/D130305

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h


Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -30,6 +30,14 @@
 namespace clang {
 namespace dataflow {
 
+struct DataflowAnalysisOptions {
+  /// Determines whether to apply the built-in transfer functions.
+  // FIXME: Remove this option once the framework supports composing analyses
+  // (at which point the built-in transfer functions can be simply a standalone
+  // analysis).
+  bool ApplyBuiltinTransfer = true;
+};
+
 /// Type-erased lattice element container.
 ///
 /// Requirements:
@@ -42,16 +50,17 @@
 
 /// Type-erased base class for dataflow analyses built on a single lattice 
type.
 class TypeErasedDataflowAnalysis : public Environment::ValueModel {
-  /// Determines whether to apply the built-in transfer functions.
-  // FIXME: Remove this option once the framework supports composing analyses
-  // (at which point the built-in transfer functions can be simply a standalone
-  // analysis).
-  bool ApplyBuiltinTransfer;
+  DataflowAnalysisOptions Options;
 
 public:
-  TypeErasedDataflowAnalysis() : ApplyBuiltinTransfer(true) {}
+  TypeErasedDataflowAnalysis() : Options({}) {}
+
+  /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
   TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
-  : ApplyBuiltinTransfer(ApplyBuiltinTransfer) {}
+  : Options({ApplyBuiltinTransfer}) {}
+
+  TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
+  : Options(Options) {}
 
   virtual ~TypeErasedDataflowAnalysis() {}
 
@@ -80,7 +89,7 @@
 
   /// Determines whether to apply the built-in transfer functions, which model
   /// the heap and stack in the `Environment`.
-  bool applyBuiltinTransfer() const { return ApplyBuiltinTransfer; }
+  bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; }
 };
 
 /// Type-erased model of the program at a given program point.
Index: clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
@@ -24,13 +24,17 @@
 
 class NoopAnalysis : public DataflowAnalysis {
 public:
+  /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
+  NoopAnalysis(ASTContext , bool ApplyBuiltinTransfer)
+  : DataflowAnalysis(Context,
+ApplyBuiltinTransfer) {}
+
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
   /// functions that model memory during the analysis. Their results are not
   /// used by `NoopAnalysis`, but tests that need to inspect the environment
   /// should enable them.
-  NoopAnalysis(ASTContext , bool ApplyBuiltinTransfer)
-  : DataflowAnalysis(Context,
-ApplyBuiltinTransfer) {}
+  NoopAnalysis(ASTContext , DataflowAnalysisOptions Options)
+  : DataflowAnalysis(Context, Options) {}
 
   static NoopLattice initialElement() { return {}; }
 
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -63,9 +63,15 @@
   using Lattice = LatticeT;
 
   explicit DataflowAnalysis(ASTContext ) : Context(Context) {}
+
+  /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
   explicit DataflowAnalysis(ASTContext , bool ApplyBuiltinTransfer)
   : TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
 
+  explicit DataflowAnalysis(ASTContext ,
+DataflowAnalysisOptions Options)
+  : TypeErasedDataflowAnalysis(Options), Context(Context) {}
+
   ASTContext () final { return Context; }
 
   TypeErasedLattice typeErasedInitialElement() final {


Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -30,6 +30,14 @@
 namespace clang {
 namespace dataflow {
 
+struct 

[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:208
+
+  // TODO: Currently this only works if the callee is never a method and the
+  // same callee is never analyzed from multiple separate callsites. To

ymandel wrote:
> 
OK, I'll change this; would you like for me to replace all the other `TODO`s 
with `FIXME`s, as well?



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:220
+  assert(Body != nullptr);
+  initGlobalVars(*Body, Env);
+

ymandel wrote:
> I wonder how this will work between caller and callee. Do we need separate 
> global var state in the frame? If so, maybe mention that as well in the FIXME 
> above.
Could you clarify what you mean? Perhaps I just don't understand exactly what 
is meant by "global vars" here.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:237
+const Expr *Arg = *ArgIt;
+// TODO: Confirm that this is the correct `SkipPast` to use here.
+auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);

ymandel wrote:
> I'm pretty sure we want `SkipPast::Reference`. That will ensure that the 
> parameter and argument share the same underlying location. Otherwise, in the 
> case of references, the parameter will point to the reference location object 
> rather than just directly to the location.
OK, thank you! I'll make that change.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:517
+
+  // TODO: Cache these CFGs.
+  auto CFCtx = ControlFlowContext::build(F, F->getBody(), );

ymandel wrote:
> here and below: s/TODO/FIXME.
Will do.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:524
+  auto CalleeEnv = Env.pushCall(S);
+  auto Analysis = NoopAnalysis(ASTCtx, /*ApplyBuiltinTransfer=*/true);
+

ymandel wrote:
> This seems worth a FIXME or, at least, an explanation.  It implies that with 
> the current design, we can't support general-purpose analyses, which we 
> should probably fix. Given our goal of supporting models that don't involve 
> specialized lattices, I think this is a good compromise for the short term, 
> but not a stable solution for the framework (hence  FIXME sounds right).
Good point, and @xazax.hun pointed this out as well. I'll add a `FIXME` here, 
at least.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added a comment.

In D130306#3670259 , @xazax.hun wrote:

> There are many ways to introduce context sensitivity into the framework, this 
> patch seems to take the "inline substitution" approach, the same approach the 
> Clang Static Analyzer is taking. While this approach is relatively easy to 
> implement and has great precision, it also has some scalability problems. Did 
> you also consider a summary-based approach? In general, I believe the inline 
> substitution approach results in an easier to use interface for the users of 
> the framework, but I am a bit concerned about the scalability problems.

Good point, thanks! Yes, we considered a summary-based approach, but we decided 
not to use it because (as you mentioned) it would be much more difficult to 
implement, especially for callees with nontrivial CFGs, which would result in a 
nontrivial flow condition instead of just `Value`s in the `Environment`.

Could you elaborate on what specific scalability problems you are concerned 
about? The main one that comes to mind for me is unpredictable cost due to the 
potential for arbitrary callee bodies to be present in the translation unit. 
While this particular patch doesn't address that concern, we definitely have 
plans to do so: I'm guessing that will take the form of providing the analysis 
an allowlist of symbols of which it is allowed to analyze the bodies, so it 
would treat any symbols not in that list as if their bodies are not available 
in the TU regardless.

To clarify, the main reason we want context-sensitive analysis is to allow us 
to simplify our definitions of some models, such as the `optional` checker 
model. The goal is to provide the analysis a mock implementation of an 
`optional` type, and then use context-sensitive analysis (probably just one or 
two layers deep) to model the constructors and methods.

> Some other related questions:
>
> - Why call noop analysis? As far as I understand, this would only update the 
> environment but not the lattice of the current analysis, i.e., if the 
> analysis is computing some information like liveness, that information would 
> not be context sensitive. Do I miss something?

The alternative in this case would be to use the same analysis for the callee 
that is already being used for the caller? I agree that would be nicer to serve 
a broader category of use cases. I didn't do that in this patch for a couple 
reasons:

1. In the short term, that would require threading more information through to 
the builtin transfer function, while this patch was meant to just be a minimum 
viable product.
2. In the longer term, we probably don't need that for our specific goals (just 
modeling simple fields of mock classes) mentioned above.

However, if you have a suggestion for a way to construct an instance of the 
outer analysis here, that would definitely be useful.

> - Why limit the call depth to 1? The patch mentions recursive functions. In 
> case of the Clang Static Analyzer, the call depth is 4. I think if we go with 
> the inline substitution approach, we want this parameter to be tunable, 
> because different analyses might have different sweet spots for the call 
> stack depth.

There's no particular reason for this. We plan to support more call stack depth 
soon. This would probably make sense as a field in the `TransferOptions` struct.

> - The CSA also has other tunables, e.g., small functions are always inlined 
> and large functions are never inlined.

See my response earlier about an allowlist for symbols to inline.

> - Currently, it looks like the framework assumes functions that cannot be 
> inlined are not doing anything. This is an unsound assumption, and I wonder 
> if we should change that before we try to settle on the best values for the 
> tunable parameters.

Agreed, this assumption is unsound. However, the framework already makes many 
other unsound assumptions in a similar spirit, so this one doesn't immediately 
strike me as one that needs to change. I'll defer to people with more context.

> - The current code might do a bit too much work. E.g. consider:
>
>   while (...) {
> inlinableCall();
>   }
>
> As far as I understand, the current approach would start the analysis of 
> `inlinableCall` from scratch in each iteration. I wonder if we actually want 
> to preserve the state between the iterations, so we do not always reevaluate 
> the call from scratch. Currently, it might not be a big deal as the 
> fixed-point iteration part is disabled. But this could be a perf problem in 
> the future, unless I miss something.

Agreed, this is somewhat wasteful. Note that not everything is thrown away, 
because the same `DataflowAnalysisContext` is reused when analyzing the callee. 
Still, we would like to handle this in a smarter way in the future, as you 
mention. For now, though, while just building up functionality behind a feature 
flag, we don't plan to worry as much 

[PATCH] D130305: [clang][dataflow] Refactor ApplyBuiltinTransfer field out into DataflowAnalysisOptions struct

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:66
   explicit DataflowAnalysis(ASTContext ) : Context(Context) {}
   explicit DataflowAnalysis(ASTContext , bool ApplyBuiltinTransfer)
   : TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}

sgatev wrote:
> samestep wrote:
> > gribozavr2 wrote:
> > > Will you remove this bool overload in a later patch?
> > I didn't have any plans to, but I'm fine with removing it in a later patch 
> > if people want to.
> I think it makes sense to remove it. Can you already document that it's 
> deprecated in this patch?
Sure, I can document that; what's the best way to do so? Is there a special way 
to say something is deprecated in a `///` comment?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130305/new/

https://reviews.llvm.org/D130305

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130306: [clang][dataflow] Analyze calls to in-TU functions

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446830.
samestep added a comment.

Update parent patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130306/new/

https://reviews.llvm.org/D130306

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -39,14 +39,14 @@
 
 template 
 void runDataflow(llvm::StringRef Code, Matcher Match,
-  LangStandard::Kind Std = LangStandard::lang_cxx17,
-  bool ApplyBuiltinTransfer = true,
-  llvm::StringRef TargetFun = "target") {
+ DataflowAnalysisOptions Options,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ llvm::StringRef TargetFun = "target") {
   ASSERT_THAT_ERROR(
   test::checkDataflow(
   Code, TargetFun,
-  [ApplyBuiltinTransfer](ASTContext , Environment &) {
-return NoopAnalysis(C, ApplyBuiltinTransfer);
+  [Options](ASTContext , Environment &) {
+return NoopAnalysis(C, Options);
   },
   [](
   llvm::ArrayRef<
@@ -54,12 +54,19 @@
   Results,
   ASTContext ) { Match(Results, ASTCtx); },
   {"-fsyntax-only", "-fno-delayed-template-parsing",
-"-std=" +
-std::string(
-LangStandard::getLangStandardForKind(Std).getName())}),
+   "-std=" + std::string(
+ LangStandard::getLangStandardForKind(Std).getName())}),
   llvm::Succeeded());
 }
 
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+ LangStandard::Kind Std = LangStandard::lang_cxx17,
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
+  runDataflow(Code, Match, {ApplyBuiltinTransfer}, Std, TargetFun);
+}
+
 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
@@ -3862,4 +3869,94 @@
   });
 }
 
+TEST(TransferTest, ContextSensitiveOptionDisabled) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
+}
+
+TEST(TransferTest, ContextSensitiveSetTrue) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = true; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment  = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+auto  =
+*cast(Env.getValue(*FooDecl, SkipPast::None));
+EXPECT_TRUE(Env.flowConditionImplies(FooVal));
+  },
+  {/*.ApplyBuiltinTransfer=*/true,
+   /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
+}
+
+TEST(TransferTest, ContextSensitiveSetFalse) {
+  std::string Code = R"(
+bool GiveBool();
+void SetBool(bool ) { Var = false; }
+
+void target() {
+  bool Foo = GiveBool();
+  SetBool(Foo);
+  // [[p]]
+}
+  )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext ) {
+ASSERT_THAT(Results, 

[PATCH] D130305: [clang][dataflow] Refactor ApplyBuiltinTransfer field out into DataflowAnalysisOptions struct

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 446829.
samestep added a comment.

Give a default value to ApplyBuiltinTransfer


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130305/new/

https://reviews.llvm.org/D130305

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h


Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -30,6 +30,14 @@
 namespace clang {
 namespace dataflow {
 
+struct DataflowAnalysisOptions {
+  /// Determines whether to apply the built-in transfer functions.
+  // FIXME: Remove this option once the framework supports composing analyses
+  // (at which point the built-in transfer functions can be simply a standalone
+  // analysis).
+  bool ApplyBuiltinTransfer = true;
+};
+
 /// Type-erased lattice element container.
 ///
 /// Requirements:
@@ -42,16 +50,14 @@
 
 /// Type-erased base class for dataflow analyses built on a single lattice 
type.
 class TypeErasedDataflowAnalysis : public Environment::ValueModel {
-  /// Determines whether to apply the built-in transfer functions.
-  // FIXME: Remove this option once the framework supports composing analyses
-  // (at which point the built-in transfer functions can be simply a standalone
-  // analysis).
-  bool ApplyBuiltinTransfer;
+  DataflowAnalysisOptions Options;
 
 public:
-  TypeErasedDataflowAnalysis() : ApplyBuiltinTransfer(true) {}
+  TypeErasedDataflowAnalysis() : Options({}) {}
   TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
-  : ApplyBuiltinTransfer(ApplyBuiltinTransfer) {}
+  : Options({ApplyBuiltinTransfer}) {}
+  TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
+  : Options(Options) {}
 
   virtual ~TypeErasedDataflowAnalysis() {}
 
@@ -80,7 +86,7 @@
 
   /// Determines whether to apply the built-in transfer functions, which model
   /// the heap and stack in the `Environment`.
-  bool applyBuiltinTransfer() const { return ApplyBuiltinTransfer; }
+  bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; }
 };
 
 /// Type-erased model of the program at a given program point.
Index: clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
@@ -32,6 +32,9 @@
   : DataflowAnalysis(Context,
 ApplyBuiltinTransfer) {}
 
+  NoopAnalysis(ASTContext , DataflowAnalysisOptions Options)
+  : DataflowAnalysis(Context, Options) {}
+
   static NoopLattice initialElement() { return {}; }
 
   void transfer(const Stmt *S, NoopLattice , Environment ) {}
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -65,6 +65,9 @@
   explicit DataflowAnalysis(ASTContext ) : Context(Context) {}
   explicit DataflowAnalysis(ASTContext , bool ApplyBuiltinTransfer)
   : TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
+  explicit DataflowAnalysis(ASTContext ,
+DataflowAnalysisOptions Options)
+  : TypeErasedDataflowAnalysis(Options), Context(Context) {}
 
   ASTContext () final { return Context; }
 


Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -30,6 +30,14 @@
 namespace clang {
 namespace dataflow {
 
+struct DataflowAnalysisOptions {
+  /// Determines whether to apply the built-in transfer functions.
+  // FIXME: Remove this option once the framework supports composing analyses
+  // (at which point the built-in transfer functions can be simply a standalone
+  // analysis).
+  bool ApplyBuiltinTransfer = true;
+};
+
 /// Type-erased lattice element container.
 ///
 /// Requirements:
@@ -42,16 +50,14 @@
 
 /// Type-erased base class for dataflow analyses built on a single lattice type.
 class TypeErasedDataflowAnalysis : public Environment::ValueModel {
-  /// Determines whether to apply the built-in transfer functions.
-  // FIXME: Remove this option once the framework supports composing analyses
-  // (at which point the built-in transfer functions can be simply a standalone
-  // analysis).
- 

[PATCH] D130305: [clang][dataflow] Refactor ApplyBuiltinTransfer field out into DataflowAnalysisOptions struct

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:66
   explicit DataflowAnalysis(ASTContext ) : Context(Context) {}
   explicit DataflowAnalysis(ASTContext , bool ApplyBuiltinTransfer)
   : TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}

gribozavr2 wrote:
> Will you remove this bool overload in a later patch?
I didn't have any plans to, but I'm fine with removing it in a later patch if 
people want to.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h:38
+  // analysis).
+  bool ApplyBuiltinTransfer;
+};

gribozavr2 wrote:
> xazax.hun wrote:
> > I think it might be better to have a default value.
> +1, uninitialized data is tricky to handle -- especially if we add more 
> options in future.
Makes sense, will do!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130305/new/

https://reviews.llvm.org/D130305

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
samestep added inline comments.



Comment at: 
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp:439
   Context.addFlowConditionConstraint(FC2, Y);
-  // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z
-  auto  = Context.joinFlowConditions(FC1, FC2);
+  // JoinedFC = ((!B && FC1) || (B && FC2)) && Z = ((!B && X) || (B && Y)) && Z
+  auto  = Context.createAtomicBoolValue();

ymandel wrote:
> I'm a bit concerned by the need to update this (essentially) unrelated test. 
> It implies the test is depending on implementation details that it shouldn't 
> be concerned with.
> 
> Not for this patch, but if you have thoughts on how to simplify this test to 
> do what it needs w/o being tied to the details of how joins work, that would 
> be appreciated. At least, it seems worth a FIXME.
> 
> thanks
Agreed, this test seems a bit awkward; in this patch I was just focusing on 
updating it instead of rethinking it.



Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:1202
+
+EXPECT_FALSE(Env.flowConditionImplies(FooVal));
+  });

ymandel wrote:
> should we also test the inverse?
> ```
> EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
> ```
> That is, I would think we want to show that neither is provable.
Sure, that makes sense; if I remember correctly, the inverse of `FooVal` is 
indeed not provable already. You're right that it would be good to test both 
here, though.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130270/new/

https://reviews.llvm.org/D130270

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130304: [clang][dataflow] Move NoopAnalysis from unittests to include

2022-07-22 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG32dcb759c300: [clang][dataflow] Move NoopAnalysis from 
unittests to include (authored by samestep).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130304/new/

https://reviews.llvm.org/D130304

Files:
  clang/docs/tools/clang-formatted-files.txt
  clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
  clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
  clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
  clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -6,7 +6,6 @@
 //
 //===--===//
 
-#include "NoopAnalysis.h"
 #include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
@@ -18,6 +17,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
 #include "clang/Tooling/Tooling.h"
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -6,13 +6,13 @@
 //
 //===--===//
 
-#include "NoopAnalysis.h"
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
Index: clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
@@ -1,8 +1,8 @@
 #include "TestingSupport.h"
-#include "NoopAnalysis.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gmock/gmock.h"
Index: clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -7,9 +7,9 @@
 //===--===//
 
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "NoopAnalysis.h"
 #include "TestingSupport.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
+#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
 #include "gmock/gmock.h"
Index: clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp
@@ -8,10 +8,10 @@
 // FIXME: Move this to clang/unittests/Analysis/FlowSensitive/Models.
 
 #include "clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h"
-#include "NoopAnalysis.h"
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringExtras.h"
Index: clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h
+++ 

  1   2   >