[PATCH] D133865: [clang][dataflow] Replace usage of the deprecated overload of `checkDataflow`.

2022-09-15 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp:83-88
+AnalysisInputs(
+Code, hasName(Target),
+[](ASTContext &Context, Environment &) {
+  return NoopAnalysis(
+  Context, /*ApplyBuiltinTransfer=*/false);
+}),

Do we need `.withASTBuildArgs({"-fsyntax-only", "-std=c++17"})` here?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133865

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


[PATCH] D133930: [clang][dataflow] Replace `transfer(const Stmt *, ...)` with `transfer(const CFGElement *, ...)` in `Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel`.

2022-09-15 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h:75
+  std::vector
+  diagnose(ASTContext &Context, const CFGElement *Elt, const Environment &Env);
 

Why not `Ctx` like above?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133930

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


[PATCH] D133933: [clang][dataflow] Modify `transfer` in `DataflowModel` to take `CFGElement` as input instead of `Stmt`.

2022-09-15 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:235
+  /// Return value indicates whether the model processed the `Element`.
+  virtual bool transfer(const CFGElement *Elt, Environment &Env) = 0;
 };

In `DataflowAnalysis` we use the name `Element`. Can we use the same here too?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133933

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


[PATCH] D133935: [clang][dataflow] Refactor `clang/Analysis/FlowSensitive/MatchSwitchTest.cpp`.

2022-09-15 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp:139
 TEST(MatchSwitchTest, ReturnNonVoid) {
   using namespace ast_matchers;
 

Let's move this below line 27 and remove it from the other tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133935

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


[PATCH] D127898: [clang][dataflow] Add API to separate analysis from diagnosis

2022-06-28 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp:401
+   const TypeErasedDataflowAnalysisState &State) {
+PostVisitStmt(Stmt.getStmt(), State);
+  });

Let's harmonize the arguments to `transferBlock` and 
`runTypeErasedDataflowAnalysis`. I think in both cases we only need access to 
the internal `Stmt` so there's no need to pass `CFGStmt` to `transferBlock`. 
This way we can pass `PostVisitStmt` directly here without having to wrap it in 
a lambda.



Comment at: clang/unittests/Analysis/FlowSensitive/TestingSupport.h:87-89
+std::function(ASTContext &)>
+MakePostVisitStmt,

Why is this a function that returns a function? Couldn't it be simply a void 
function, like `VerifyResults`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

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


[PATCH] D128352: [clang][dataflow] Use diagnosis API in optional checker

2022-06-28 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:126-129
+auto *Lattice =
+llvm::any_cast(&State.Lattice.Value);
+PostVisitStmt(Stmt, DataflowAnalysisState{
+*Lattice, State.Env});




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128352

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


[PATCH] D128833: [clang][dataflow] Handle `for` statements without conditions

2022-06-29 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: martong, tschuett, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Handle `for` statements without conditions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128833

Files:
  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
@@ -3827,4 +3827,30 @@
   });
 }
 
+TEST_F(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
+  std::string Code = R"(
+void target(bool Foo) {
+  for (;;) {
+(void)0;
+// [[loop_body]]
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _)));
+const Environment &LoopBodyEnv = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+BoolValue &LoopBodyFooVal =
+*cast(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
+  });
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -97,8 +97,8 @@
 
   void VisitForStmt(const ForStmt *S) {
 auto *Cond = S->getCond();
-assert(Cond != nullptr);
-extendFlowCondition(*Cond);
+if (Cond != nullptr)
+  extendFlowCondition(*Cond);
   }
 
   void VisitBinaryOperator(const BinaryOperator *S) {


Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3827,4 +3827,30 @@
   });
 }
 
+TEST_F(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
+  std::string Code = R"(
+void target(bool Foo) {
+  for (;;) {
+(void)0;
+// [[loop_body]]
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _)));
+const Environment &LoopBodyEnv = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+BoolValue &LoopBodyFooVal =
+*cast(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
+  });
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -97,8 +97,8 @@
 
   void VisitForStmt(const ForStmt *S) {
 auto *Cond = S->getCond();
-assert(Cond != nullptr);
-extendFlowCondition(*Cond);
+if (Cond != nullptr)
+  extendFlowCondition(*Cond);
   }
 
   void VisitBinaryOperator(const BinaryOperator *S) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128833: [clang][dataflow] Handle `for` statements without conditions

2022-06-30 Thread Stanislav Gatev via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8207c2a66030: [clang][dataflow] Handle `for` statements 
without conditions (authored by sgatev).
Herald added a reviewer: NoQ.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128833

Files:
  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
@@ -3827,4 +3827,30 @@
   });
 }
 
+TEST_F(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
+  std::string Code = R"(
+void target(bool Foo) {
+  for (;;) {
+(void)0;
+// [[loop_body]]
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _)));
+const Environment &LoopBodyEnv = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+BoolValue &LoopBodyFooVal =
+*cast(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
+  });
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -97,8 +97,8 @@
 
   void VisitForStmt(const ForStmt *S) {
 auto *Cond = S->getCond();
-assert(Cond != nullptr);
-extendFlowCondition(*Cond);
+if (Cond != nullptr)
+  extendFlowCondition(*Cond);
   }
 
   void VisitBinaryOperator(const BinaryOperator *S) {


Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3827,4 +3827,30 @@
   });
 }
 
+TEST_F(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
+  std::string Code = R"(
+void target(bool Foo) {
+  for (;;) {
+(void)0;
+// [[loop_body]]
+  }
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _)));
+const Environment &LoopBodyEnv = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+BoolValue &LoopBodyFooVal =
+*cast(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
+EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
+  });
+}
+
 } // namespace
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -97,8 +97,8 @@
 
   void VisitForStmt(const ForStmt *S) {
 auto *Cond = S->getCond();
-assert(Cond != nullptr);
-extendFlowCondition(*Cond);
+if (Cond != nullptr)
+  extendFlowCondition(*Cond);
   }
 
   void VisitBinaryOperator(const BinaryOperator *S) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128924: [clang][dataflow] Replace TEST_F with TEST where possible

2022-06-30 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added a comment.

Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128924

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


[PATCH] D129180: [clang][dataflow] Return a solution from the solver when `Constraints` are `Satisfiable`.

2022-07-06 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/Solver.h:45
+enum class Assignment : int8_t {
+  Unassigned = -1,
+  AssignedFalse = 0,

A solution consists of true/false assignments for all variables. Having an 
`Unassigned` option seems confusing. I suggest defining only two values in this 
enum and translating `WatchedLiteralsSolver`'s internal representation to 
`Solution` right before returning it, in `buildValAssignment`.



Comment at: clang/include/clang/Analysis/FlowSensitive/Solver.h:50-57
+static Result Unsatisfiable() { return Result(Status::Unsatisfiable, {}); }
+
+static Result TimedOut() { return Result(Status::TimedOut, {}); }
+
+static Result
+Satisfiable(llvm::DenseMap Solution) {
+  return Result(Status::Satisfiable, std::move(Solution));

Let's document these members.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129180

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


[PATCH] D129180: [clang][dataflow] Return a solution from the solver when `Constraints` are `Satisfiable`.

2022-07-07 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/Solver.h:78
+Status Status;
+std::optional> Solution;
   };

`#include "llvm/ADT/DenseMap.h"`



Comment at: clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp:200
 
   if (!SubValsToVar.try_emplace(Val, NextVar).second)
 continue;

Let's create a local `Var` variable initialized to `NextVar` and use that here 
and below, where `NextVar - 1` is currently used.



Comment at: clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp:471-472
 private:
+  // Returns a satisfying truth assignment to the atomic values in the boolean
+  // formula.
+  llvm::DenseMap




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129180

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


[PATCH] D122231: [clang][dataflow] Add support for `value_or` in a comparison.

2022-03-28 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:270
+  // needed.
+  BoolValue &ComparisonValue = MakeValue(Env, *HasValueVal);
+  auto *ComparisonExprLoc =

ymandel wrote:
> ymandel wrote:
> > xazax.hun wrote:
> > > xazax.hun wrote:
> > > > ymandel wrote:
> > > > > xazax.hun wrote:
> > > > > > Is this the right way to initialize `ComparisonValue`?
> > > > > > 
> > > > > > Considering the expression: `opt.value_or(nullptr) != nullptr`
> > > > > > * When `has_value == false`, `opt.value_or(nullptr)` will return 
> > > > > > `nullptr`, so `!=` evaluates to false. This case seems to check out.
> > > > > > * However, when `has_value == true`, `opt` might still hold an 
> > > > > > `nullptr` and `!=` could still evaluate to false. 
> > > > > Thanks for digging into this. I think it's correct, but helpful to 
> > > > > step through:
> > > > > 
> > > > > Its correctness depends on `MakeValue`, so I'll focus on that in 
> > > > > particular. For the `nullptr` case, we'll get:
> > > > > ```
> > > > > HasValueVal && ContentsNotEqX
> > > > > ```
> > > > > So, when `has_value == true`, this basically reduces to 
> > > > > `ContentsNotEqX`. Since that's an atom, the result is indeterminate, 
> > > > > which I believe is the desired outcome.
> > > > > 
> > > > > WDYT?  Also, even if I've convinced you, please let me know how i can 
> > > > > improve the comments. For that matter, would `MakeValue` be better 
> > > > > with a more specific name, like "MakePredicate" or somesuch?
> > > > I think what confuses me is that we do something different for the 3 
> > > > cases. You convinced me that `HasValueVal && ContentsNotEqX` is 
> > > > correct. But we only do this for one branch out of the 3.  What is the 
> > > > reason for that?
> > > Oh, never mind. Yeah, I think changing `MakeValue` to `MakePredicate` 
> > > would make this a bit clearer. After a second read now I understand 
> > > better what is going on.
> > Just to be clear: the three cases you mean are lines 273-283, or something 
> > else?
> and never mind my question, then (I rpelied before I saw your updated). I'll 
> change the name and add comments.
Can you elaborate on the three cases on lines 273-283? Why not simply do

```
auto &ComparisonExprLoc = Env.createStorageLocation(*ComparisonExpr);
Env.setStorageLocation(ComparisonExpr, ComparisonExprLoc);
Env.setValue(ComparisonExprLoc, ComparisonValue);
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122231

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


[PATCH] D122231: [clang][dataflow] Add support for `value_or` in a comparison.

2022-03-29 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:270
+  // needed.
+  BoolValue &ComparisonValue = MakeValue(Env, *HasValueVal);
+  auto *ComparisonExprLoc =

ymandel wrote:
> sgatev wrote:
> > ymandel wrote:
> > > ymandel wrote:
> > > > xazax.hun wrote:
> > > > > xazax.hun wrote:
> > > > > > ymandel wrote:
> > > > > > > xazax.hun wrote:
> > > > > > > > Is this the right way to initialize `ComparisonValue`?
> > > > > > > > 
> > > > > > > > Considering the expression: `opt.value_or(nullptr) != nullptr`
> > > > > > > > * When `has_value == false`, `opt.value_or(nullptr)` will 
> > > > > > > > return `nullptr`, so `!=` evaluates to false. This case seems 
> > > > > > > > to check out.
> > > > > > > > * However, when `has_value == true`, `opt` might still hold an 
> > > > > > > > `nullptr` and `!=` could still evaluate to false. 
> > > > > > > Thanks for digging into this. I think it's correct, but helpful 
> > > > > > > to step through:
> > > > > > > 
> > > > > > > Its correctness depends on `MakeValue`, so I'll focus on that in 
> > > > > > > particular. For the `nullptr` case, we'll get:
> > > > > > > ```
> > > > > > > HasValueVal && ContentsNotEqX
> > > > > > > ```
> > > > > > > So, when `has_value == true`, this basically reduces to 
> > > > > > > `ContentsNotEqX`. Since that's an atom, the result is 
> > > > > > > indeterminate, which I believe is the desired outcome.
> > > > > > > 
> > > > > > > WDYT?  Also, even if I've convinced you, please let me know how i 
> > > > > > > can improve the comments. For that matter, would `MakeValue` be 
> > > > > > > better with a more specific name, like "MakePredicate" or 
> > > > > > > somesuch?
> > > > > > I think what confuses me is that we do something different for the 
> > > > > > 3 cases. You convinced me that `HasValueVal && ContentsNotEqX` is 
> > > > > > correct. But we only do this for one branch out of the 3.  What is 
> > > > > > the reason for that?
> > > > > Oh, never mind. Yeah, I think changing `MakeValue` to `MakePredicate` 
> > > > > would make this a bit clearer. After a second read now I understand 
> > > > > better what is going on.
> > > > Just to be clear: the three cases you mean are lines 273-283, or 
> > > > something else?
> > > and never mind my question, then (I rpelied before I saw your updated). 
> > > I'll change the name and add comments.
> > Can you elaborate on the three cases on lines 273-283? Why not simply do
> > 
> > ```
> > auto &ComparisonExprLoc = Env.createStorageLocation(*ComparisonExpr);
> > Env.setStorageLocation(ComparisonExpr, ComparisonExprLoc);
> > Env.setValue(ComparisonExprLoc, ComparisonValue);
> > ```
> > Can you elaborate on the three cases on lines 273-283? Why not simply do
> > 
> > ```
> > auto &ComparisonExprLoc = Env.createStorageLocation(*ComparisonExpr);
> > Env.setStorageLocation(ComparisonExpr, ComparisonExprLoc);
> > Env.setValue(ComparisonExprLoc, ComparisonValue);
> > ```
> 
> for the second case: I think we should drop it -- I don't see a reason to 
> maintain the previous value (if there is any). It might be a good idea for 
> compositionality, but we're not doing that anywhere else, so it doesn't make 
> sense here.
> 
> for the first and third case: I assumed that if the expression already has a 
> location, we'd want to reuse it. But, based on your question, I take it 
> that's incorrect?
> 
Dropping the second case makes sense to me.

For the rest, `createStorageLocation` returns a stable storage location so the 
snippet above should be sufficient. However, `setStorageLocation` will fail if 
we try calling it again with the same expression, even if it's called with the 
same storage location. What do you think about making `setStorageLocation` not 
fail if it's called with the same arguments?



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:279
+ cast_or_null(Env.getValue(*ComparisonExprLoc))) {
+Env.setValue(*ComparisonExprLoc,
+ Env.makeAnd(*CurrentValue, ComparisonValue));

ymandel wrote:
> ymandel wrote:
> > xazax.hun wrote:
> > > I am still wondering a bit about this case. 
> > > 
> > > We generate: `HasValueVal and ContentsNotEqX and CurrentValue`.'
> > > I wonder if we want: `HasValueVal  and (ContentsNotEqX  <=> 
> > > CurrentValue)` instead?  Or even `HasValueVal  and CurrentValue`?
> > I don't think that the iff version is right, but `HasValueVal  and 
> > CurrentValue` could be. My concern is that we're not guaranteed that 
> > `CurrentValue` is populated. And, even if we were, it doesn't feel quite 
> > right. Assuming its a high fidelity model, we get (logically): 
> > `HasValue(opt) and Ne(ValueOr(opt,X),X)`. Then, when negated (say, on an 
> > else branch) we get `not(HasValue(opt)) or not(Ne(ValueOr(opt,X),X))` which 
> > is equivalent to `not(HasValue(opt)) or Eq(ValueOr

[PATCH] D122231: [clang][dataflow] Add support for `value_or` in a comparison.

2022-03-30 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:279
+ cast_or_null(Env.getValue(*ComparisonExprLoc))) {
+Env.setValue(*ComparisonExprLoc,
+ Env.makeAnd(*CurrentValue, ComparisonValue));

ymandel wrote:
> sgatev wrote:
> > ymandel wrote:
> > > ymandel wrote:
> > > > xazax.hun wrote:
> > > > > I am still wondering a bit about this case. 
> > > > > 
> > > > > We generate: `HasValueVal and ContentsNotEqX and CurrentValue`.'
> > > > > I wonder if we want: `HasValueVal  and (ContentsNotEqX  <=> 
> > > > > CurrentValue)` instead?  Or even `HasValueVal  and CurrentValue`?
> > > > I don't think that the iff version is right, but `HasValueVal  and 
> > > > CurrentValue` could be. My concern is that we're not guaranteed that 
> > > > `CurrentValue` is populated. And, even if we were, it doesn't feel 
> > > > quite right. Assuming its a high fidelity model, we get (logically): 
> > > > `HasValue(opt) and Ne(ValueOr(opt,X),X)`. Then, when negated (say, on 
> > > > an else branch) we get `not(HasValue(opt)) or 
> > > > not(Ne(ValueOr(opt,X),X))` which is equivalent to `not(HasValue(opt)) 
> > > > or Eq(ValueOr(opt,X),X)`. While  true, it seems redundant, since the 
> > > > first clause should be derivable from the second (assuming an 
> > > > interpretatable semantics to the `ValueOr` predicate).
> > > > 
> > > > Regardless, it might be better to step back and figure out how this 
> > > > should be done systematically. I'll try to come back with a proposal on 
> > > > that.
> > > > Regardless, it might be better to step back and figure out how this 
> > > > should be done systematically. I'll try to come back with a proposal on 
> > > > that.
> > > 
> > > Here's what I have: in general, we're aiming for all models to be a sound 
> > > (over) approximation of reality. That is what we're doing here as well. 
> > > Yet, that poses a problem for the interpretation of the boolean not 
> > > operator. If its operand is an overapproximation, then I believe the 
> > > naive approach gives you an under approximation. That's the problem we're 
> > > hitting when reasoning about the negation.
> > > 
> > > I'm not sure how to handle this. Stanislav -- have we dealt with this 
> > > issue before?
> > > 
> > > That said, if we go back to the previous approach, of adding the 
> > > information to the path condition, I think we avoid this problem, since 
> > > the path conditions don't get negated.  To Gabor's earlier point:
> > > > There is an implication in the reverse direction as well. In case we 
> > > > know the optional is empty, we can prune one of the branches from the 
> > > > analysis. Is it possible to implement that with the current status of 
> > > > the framework?
> > > I think is covered by the condition we're adding. Namely:
> > > ```
> > > ExprValue => has_value
> > > ```
> > > where `ExprValue` is the truth value of the boolean expression.
> > > 
> > > So, the implication in the reverse direction is:
> > > ```
> > > !has_value => !ExprValue
> > > ```
> > > that is, if we know the optional doesn't hold a value, then we know that 
> > > `opt.value_or(X) = X`
> > > 
> > > But, that implication is the contrapositive of our own, so I think it's 
> > > already implicitly covered by adding the single implication. Does that 
> > > sound right?
> > I'm not following where `Env.makeAnd(*CurrentValue, ComparisonValue)` comes 
> > from so I'd question whether it's sound or not. I would have expected to 
> > see something like `ExprValue => has_value` (which I believe was the case 
> > in the first iteration) and I see no issues with the contrapositive. If you 
> > have `x => y` and `not y` in the flow condition, you'll be able to infer 
> > that `not x` is true (assuming no other statements for `x`). How we use 
> > this to prune branches from the analysis is a question of its own.
> I think the new version resolves this?
Yes, modelling these using implications looks good to me!



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:275
+  State.Env.getValue(*ValueOrPredExpr, SkipPast::None));
+  if (ExprValue == nullptr) {
+auto &ExprLoc = State.Env.createStorageLocation(*ValueOrPredExpr);

Why do this conditionally? I think we should set a value regardless of whether 
another model has already done so.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:525
+  // opt.value_or(X) != X
+  .CaseOf(isValueOrCondition(), transferValueOrNotEqX)
+

Call this `isValueOrNotEqX` for consistency?



Comment at: 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp:1720
+void target() {
+  $ns::$optional opt;
+  if (opt.value_or(nullptr) != nullptr) {

I sug

[PATCH] D122231: [clang][dataflow] Add support for `value_or` in a comparison.

2022-03-31 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:275
+  State.Env.getValue(*ValueOrPredExpr, SkipPast::None));
+  if (ExprValue == nullptr) {
+auto &ExprLoc = State.Env.createStorageLocation(*ValueOrPredExpr);

ymandel wrote:
> sgatev wrote:
> > Why do this conditionally? I think we should set a value regardless of 
> > whether another model has already done so.
> Why? I figured we're agnostic to the underlying value, and only care about 
> relating it via the implication. We're setting it only so we have something 
> to anchor that implication on.  If we always set it, then we're erasing the 
> information from another model.
Nevermind. I probably didn't follow carefully around all the comment blocks and 
thought that `addToFlowCondition` also happens conditionally. The current 
approach looks good to me.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122231

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


[PATCH] D122273: [clang][dataflow] Fix handling of base-class fields

2022-03-31 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:168
+static void
+getFieldsFromClassHierarchy(QualType Type, bool IgnorePrivateFields,
+llvm::DenseSet &Fields) {

Let's add to the documentation of `AggregateStorageLocation` and `StructValue` 
that they implement a flat struct layout. I don't see an immediate reason to 
revisit this, but let's be explicit about it.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:182
+  if (auto *CXXRecord = Type->getAsCXXRecordDecl()) {
+for (const clang::CXXBaseSpecifier &Base : CXXRecord->bases()) {
+  // Ignore private fields (including default access in C++ classes) in

The `clang` namespace is unnecessary.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:1014
+  std::string Code = R"(
+struct A {
+  int Bar;

Add a similar test with `class` instead of `struct`?



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:1015
+struct A {
+  int Bar;
+};

Let's also add private and protected members in `A` and a private member in `B`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122273

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


[PATCH] D122273: [clang][dataflow] Fix handling of base-class fields

2022-03-31 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/StorageLocation.h:59-60
 /// can be traced independently by abstract interpretation. For example: a
-/// struct with public members.
+/// struct with public members. Note that the corresponding `StructValue` has a
+/// flat layout that does not contain the child locations stored here.
 class AggregateStorageLocation final : public StorageLocation {

I find this a bit confusing. `StructValue` does not contain storage locations 
in general. I think we should make it clear that the layout of 
`AggregateStorageLocation` is flat, i.e. if it's used for a `struct` or `class` 
type it will contain child storage locations for all accessible members of base 
`struct` and `class` types.



Comment at: clang/include/clang/Analysis/FlowSensitive/Value.h:193-194
+/// Models a value of `struct` or `class` type. Implements a flat struct 
layout,
+/// where the child values are directly reachable from the struct value (rather
+/// than indirectly, through `StorageLocation`s).
 class StructValue final : public Value {

I'm not sure what's meant here by indirect reachability, but I suggest 
documenting that a `StructValue` that models a `struct` or `class` type 
contains child values for all accessible members of its base `struct` and 
`class` types. 



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:1097-1100
+const auto *FooLoc = cast(
+Env.getStorageLocation(*FooDecl, SkipPast::None));
+const auto &FooVal = *cast(Env.getValue(*FooLoc));
+EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());





Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:1102-
+// Base-class fields.
+EXPECT_THAT(FooVal.getChild(*ADefaultDecl), IsNull());
+EXPECT_THAT(FooVal.getChild(*APrivateDecl), IsNull());
+EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
+EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
+
+// Derived-class fields.

Let's also check `FooLoc`'s child storage locations. Same for the test below.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:1156-1159
+const auto *FooLoc = cast(
+Env.getStorageLocation(*FooDecl, SkipPast::None));
+const auto *FooVal = cast(Env.getValue(*FooLoc));
+EXPECT_THAT(FooVal->getChild(*BarDecl), NotNull());




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122273

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


[PATCH] D122830: [clang][dataflow] Add support for (built-in) (in)equality operators

2022-03-31 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:53
+  if (auto *LHSValue = dyn_cast_or_null(
+  Env.getValue(*LHSNorm, SkipPast::Reference)))
+if (auto *RHSValue = dyn_cast_or_null(

Do we need to skip past references here? If so, then let's add a test that 
fails if these are changed to `SkipPast::None`.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:109-113
+  auto &LHSAndRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env);
+  auto &Loc = Env.createStorageLocation(*S);
+  Env.setStorageLocation(*S, Loc);
+  Env.setValue(Loc, S->getOpcode() == BO_EQ ? LHSAndRHSValue
+: Env.makeNot(LHSAndRHSValue));





Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:2413
 
+TEST_F(TransferTest, Equality) {
+  std::string Code = R"(





Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:2448
+
+TEST_F(TransferTest, Inequality) {
+  std::string Code = R"(




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122830

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


[PATCH] D122838: [clang][dataflow] Add support for correlation of boolean (tracked) values

2022-04-01 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:79
+for (BoolValue *Constraint : Env1.getFlowConditionConstraints()) {
+  Expr1 = &Env1.makeAnd(*Expr1, *Constraint);
+}

xazax.hun wrote:
> Hmm, interesting.
> I think we view every boolean formula at a certain program point implicitly 
> as `FlowConditionAtThatPoint && Formula`. And the flow condition at a program 
> point should already be a disjunction of its predecessors.
> 
> So it would be interpreted as: `(FlowConditionPred1 || FlowConditionPred2) && 
> (FormulaAtPred1 || FormulaAtPred2)`.
> While this is great, this is not the strongest condition we could derive. 
> `(FlowConditionPred1 && FormulaAtPred1)  || (FormulaAtPred2 && 
> FlowConditionPred2)` created by this code snippet is stronger which is great.
> 
> My main concern is whether we would end up seeing an exponential explosion in 
> the size of these formulas in the number of branches following each other in 
> a sequence.
> 
Yeap, I agree this is suboptimal and I believe I'm the one to blame for 
introducing it downstream.

I wonder if we can represent the flow condition of each environment using a 
bool atom and have a mapping of bi-conditionals between flow condition atoms 
and flow condition constraints. Something like:

```
FC1 <=> C1 ^ C2
FC2 <=> C2 ^ C3 ^ C4
FC3 <=> (FC1 v FC2) ^ C5
... 
```

We can use that to simplify the formulas here and in `joinConstraints`. The 
mapping can be stored in `DataflowAnalysisContext`. We can track dependencies 
between flow conditions (e.g. above `FC3` depends on `FC1` and `FC2`) and 
modify `flowConditionImplies` to construct a formula that includes the 
bi-conditionals for all flow condition atoms in the transitive set before 
invoking the solver.

I suggest putting the optimization in its own patch. I'd love to look into it 
right after this patch is submitted if both of you think it makes sense on a 
high level.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122838

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


[PATCH] D123037: [clang][dataflow] Support integral casts

2022-04-05 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:206
+  // boolean.
+  auto &ExprLoc = Env.createStorageLocation(*S);
+  Env.setStorageLocation(*S, ExprLoc);

Nit: Just `Loc`? I believe that's what we use in other places in this file if 
it's a location for `S`.



Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:1904
-const auto *FooVal =
-cast(Env.getValue(*FooDecl, SkipPast::None));
-const auto *BarVal =

Why not assert the type of the value in this test and in `IntegralCast` below?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123037

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


[PATCH] D130522: [clang][dataflow] Fix SAT solver crashes on `X ^ X` and `X v X`

2022-07-25 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp:273
+
+// Visit a sub-value of `Val` (pick any, they are identical).
+  } else {

Let's visit `C->getLeftSubValue()` here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130522

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


[PATCH] D130519: [clang][dataflow] Add explicit "AST" nodes for implications and iff

2022-07-26 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/Value.h:40-41
 
 // Synthetic boolean values are either atomic values or composites that
 // represent conjunctions, disjunctions, and negations.
 AtomicBool,





Comment at: clang/lib/Analysis/FlowSensitive/DebugSupport.cpp:110
+  auto R = debugString(BV.getRightSubValue(), Depth + 1);
+  S = formatv("(=\n{0}\n{1})", L, R);
+  break;

I think `<=>` would be more natural.



Comment at: clang/unittests/Analysis/FlowSensitive/SolverTest.cpp:201
+
+  expectUnsatisfiable(solve({NotEquivalent}));
+}

Let's add a label: `!((X <=> Y) <=> ((X ^ Y) v (!X ^ !Y)))`



Comment at: clang/unittests/Analysis/FlowSensitive/SolverTest.cpp:303
+
+  expectUnsatisfiable(solve({NotEquivalent}));
+}

Let's add a label: `!((X => Y) <=> (!X v Y))`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130519

___
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 Stanislav Gatev via Phabricator via cfe-commits
sgatev 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;

Let's make this a FIXME to 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

___
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-28 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



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

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.`?



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;

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!


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] D130270: [clang][dataflow] Use a dedicated bool to encode which branch was taken

2022-07-28 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev 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;

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.


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] D131014: [clang][dataflow] Make the type of the post visit callback consistent

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2, samestep.
Herald added subscribers: martong, tschuett, rnkovacs.
Herald added a reviewer: NoQ.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Make the type of the post visit callback consistent.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131014

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.h
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -1245,9 +1245,10 @@
   return UncheckedOptionalAccessModel(Ctx, Options);
 },
 [&Diagnostics, Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
-ASTContext &Ctx, const Stmt *Stmt,
+ASTContext &Ctx, const CFGStmt &Stmt,
 const TypeErasedDataflowAnalysisState &State) mutable {
-  auto StmtDiagnostics = Diagnoser.diagnose(Ctx, Stmt, State.Env);
+  auto StmtDiagnostics =
+  Diagnoser.diagnose(Ctx, Stmt.getStmt(), State.Env);
   llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
 },
 [&Diagnostics](AnalysisData AnalysisData) {
Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -76,7 +76,7 @@
 llvm::StringRef Code,
 ast_matchers::internal::Matcher TargetFuncMatcher,
 std::function MakeAnalysis,
-std::function
 PostVisitStmt,
 std::function VerifyResults, ArrayRef Args,
@@ -112,11 +112,11 @@
   Environment Env(DACtx, *F);
   auto Analysis = MakeAnalysis(Context, Env);
 
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
 PostVisitStmtClosure = [&PostVisitStmt, &Context](
-   const Stmt *Stmt,
+   const CFGStmt &Stmt,
const TypeErasedDataflowAnalysisState &State) {
   PostVisitStmt(Context, Stmt, State);
 };
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -333,7 +333,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt) {
   PostOrderCFGView POV(&CFCtx.getCFG());
   ForwardDataflowWorklist Worklist(CFCtx.getCFG(), &POV);
@@ -398,12 +399,9 @@
   // Skip blocks that were not evaluated.
   if (!BlockStates[Block->getBlockID()])
 continue;
-  transferBlock(
-  CFCtx, BlockStates, *Block, InitEnv, Analysis,
-  [&PostVisitStmt](const clang::CFGStmt &Stmt,
-   const TypeErasedDataflowAnalysisState &State) {
-PostVisitStmt(Stmt.getStmt(), State);
-  });
+
+  transferBlock(CFCtx, BlockStates, *Block, InitEnv, Analysis,
+PostVisitStmt);
 }
   }
 
Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -138,7 +138,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt = nullptr);
 
 } // namespace dataflow
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -125,14 +125,14 @@
 runDataflowAnalysis(
 const ControlFlowContext &CFCtx, AnalysisT &Analysis,
 const Environment &InitEnv,
-std::function &)>
+std::function &)>
 PostVisitStmt = nullptr) {
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
  

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

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 449398.
sgatev added a comment.

Update commit message


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131014

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.h
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -1245,9 +1245,10 @@
   return UncheckedOptionalAccessModel(Ctx, Options);
 },
 [&Diagnostics, Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
-ASTContext &Ctx, const Stmt *Stmt,
+ASTContext &Ctx, const CFGStmt &Stmt,
 const TypeErasedDataflowAnalysisState &State) mutable {
-  auto StmtDiagnostics = Diagnoser.diagnose(Ctx, Stmt, State.Env);
+  auto StmtDiagnostics =
+  Diagnoser.diagnose(Ctx, Stmt.getStmt(), State.Env);
   llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
 },
 [&Diagnostics](AnalysisData AnalysisData) {
Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -76,7 +76,7 @@
 llvm::StringRef Code,
 ast_matchers::internal::Matcher TargetFuncMatcher,
 std::function MakeAnalysis,
-std::function
 PostVisitStmt,
 std::function VerifyResults, ArrayRef Args,
@@ -112,11 +112,11 @@
   Environment Env(DACtx, *F);
   auto Analysis = MakeAnalysis(Context, Env);
 
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
 PostVisitStmtClosure = [&PostVisitStmt, &Context](
-   const Stmt *Stmt,
+   const CFGStmt &Stmt,
const TypeErasedDataflowAnalysisState &State) {
   PostVisitStmt(Context, Stmt, State);
 };
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -333,7 +333,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt) {
   PostOrderCFGView POV(&CFCtx.getCFG());
   ForwardDataflowWorklist Worklist(CFCtx.getCFG(), &POV);
@@ -398,12 +399,9 @@
   // Skip blocks that were not evaluated.
   if (!BlockStates[Block->getBlockID()])
 continue;
-  transferBlock(
-  CFCtx, BlockStates, *Block, InitEnv, Analysis,
-  [&PostVisitStmt](const clang::CFGStmt &Stmt,
-   const TypeErasedDataflowAnalysisState &State) {
-PostVisitStmt(Stmt.getStmt(), State);
-  });
+
+  transferBlock(CFCtx, BlockStates, *Block, InitEnv, Analysis,
+PostVisitStmt);
 }
   }
 
Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -138,7 +138,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt = nullptr);
 
 } // namespace dataflow
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -125,14 +125,14 @@
 runDataflowAnalysis(
 const ControlFlowContext &CFCtx, AnalysisT &Analysis,
 const Environment &InitEnv,
-std::function &)>
+std::function &)>
 PostVisitStmt = nullptr) {
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
 PostVisitStmtClosure = [&PostVisitStmt](
-   const Stmt *Stmt,
+   const CFGStmt &Stmt,
   

[PATCH] D129097: [clang][dataflow] Handle null pointers of type std::nullptr_t

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:96
   ///
   ///  `Type` must not be null.
   StorageLocation &getStableStorageLocation(QualType Type);

This is inconsistent with the change introduced by this patch.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp:27
 DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
-  assert(!Type.isNull());
-  if (Type->isStructureOrClassType() || Type->isUnionType()) {
+  if (!Type.isNull() &&
+  (Type->isStructureOrClassType() || Type->isUnionType())) {

What does that mean? We are analyzing an incomplete translation unit? Why would 
the type ever be null here?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129097

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


[PATCH] D131021: [clang][dataflow] Rename member to make it clear that it isn't stable

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2, wyt.
Herald added subscribers: martong, tschuett, rnkovacs.
Herald added a reviewer: NoQ.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Rename `DataflowAnalysisContext::getStableStorageLocation(QualType)`
to `createStorageLocation, to make it clear that it doesn't return a
stable storage location.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131021

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


Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -337,7 +337,7 @@
 }
 
 StorageLocation &Environment::createStorageLocation(QualType Type) {
-  return DACtx->getStableStorageLocation(Type);
+  return DACtx->createStorageLocation(Type);
 }
 
 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -24,15 +24,14 @@
 namespace clang {
 namespace dataflow {
 
-StorageLocation &
-DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
+StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) 
{
   if (!Type.isNull() &&
   (Type->isStructureOrClassType() || Type->isUnionType())) {
 // FIXME: Explore options to avoid eager initialization of fields as some 
of
 // them might not be needed for a particular analysis.
 llvm::DenseMap FieldLocs;
 for (const FieldDecl *Field : getObjectFields(Type))
-  FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())});
+  FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
 return takeOwnership(
 std::make_unique(Type, 
std::move(FieldLocs)));
   }
@@ -43,7 +42,7 @@
 DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
   if (auto *Loc = getStorageLocation(D))
 return *Loc;
-  auto &Loc = getStableStorageLocation(D.getType());
+  auto &Loc = createStorageLocation(D.getType());
   setStorageLocation(D, Loc);
   return Loc;
 }
@@ -52,7 +51,7 @@
 DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
   if (auto *Loc = getStorageLocation(E))
 return *Loc;
-  auto &Loc = getStableStorageLocation(E.getType());
+  auto &Loc = createStorageLocation(E.getType());
   setStorageLocation(E, Loc);
   return Loc;
 }
@@ -63,7 +62,7 @@
   PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
   if (Res.second) {
-auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType);
+auto &PointeeLoc = createStorageLocation(CanonicalPointeeType);
 Res.first->second =
 &takeOwnership(std::make_unique(PointeeLoc));
   }
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -90,12 +90,12 @@
 return *cast(Vals.back().get());
   }
 
-  /// Returns a stable storage location appropriate for `Type`.
+  /// Returns a new storage location appropriate for `Type`.
   ///
   /// Requirements:
   ///
   ///  `Type` must not be null.
-  StorageLocation &getStableStorageLocation(QualType Type);
+  StorageLocation &createStorageLocation(QualType Type);
 
   /// Returns a stable storage location for `D`.
   StorageLocation &getStableStorageLocation(const VarDecl &D);


Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -337,7 +337,7 @@
 }
 
 StorageLocation &Environment::createStorageLocation(QualType Type) {
-  return DACtx->getStableStorageLocation(Type);
+  return DACtx->createStorageLocation(Type);
 }
 
 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -24,15 +24,14 @@
 namespace clang {
 namespace dataflow {
 
-StorageLocation &
-DataflowAnalysis

[PATCH] D131021: [clang][dataflow] Rename member to make it clear that it isn't stable

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 449436.
sgatev added a comment.

Update commit message


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131021

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


Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -337,7 +337,7 @@
 }
 
 StorageLocation &Environment::createStorageLocation(QualType Type) {
-  return DACtx->getStableStorageLocation(Type);
+  return DACtx->createStorageLocation(Type);
 }
 
 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -24,15 +24,14 @@
 namespace clang {
 namespace dataflow {
 
-StorageLocation &
-DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
+StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) 
{
   if (!Type.isNull() &&
   (Type->isStructureOrClassType() || Type->isUnionType())) {
 // FIXME: Explore options to avoid eager initialization of fields as some 
of
 // them might not be needed for a particular analysis.
 llvm::DenseMap FieldLocs;
 for (const FieldDecl *Field : getObjectFields(Type))
-  FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())});
+  FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
 return takeOwnership(
 std::make_unique(Type, 
std::move(FieldLocs)));
   }
@@ -43,7 +42,7 @@
 DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
   if (auto *Loc = getStorageLocation(D))
 return *Loc;
-  auto &Loc = getStableStorageLocation(D.getType());
+  auto &Loc = createStorageLocation(D.getType());
   setStorageLocation(D, Loc);
   return Loc;
 }
@@ -52,7 +51,7 @@
 DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
   if (auto *Loc = getStorageLocation(E))
 return *Loc;
-  auto &Loc = getStableStorageLocation(E.getType());
+  auto &Loc = createStorageLocation(E.getType());
   setStorageLocation(E, Loc);
   return Loc;
 }
@@ -63,7 +62,7 @@
   PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
   if (Res.second) {
-auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType);
+auto &PointeeLoc = createStorageLocation(CanonicalPointeeType);
 Res.first->second =
 &takeOwnership(std::make_unique(PointeeLoc));
   }
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -90,12 +90,12 @@
 return *cast(Vals.back().get());
   }
 
-  /// Returns a stable storage location appropriate for `Type`.
+  /// Returns a new storage location appropriate for `Type`.
   ///
   /// Requirements:
   ///
   ///  `Type` must not be null.
-  StorageLocation &getStableStorageLocation(QualType Type);
+  StorageLocation &createStorageLocation(QualType Type);
 
   /// Returns a stable storage location for `D`.
   StorageLocation &getStableStorageLocation(const VarDecl &D);


Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -337,7 +337,7 @@
 }
 
 StorageLocation &Environment::createStorageLocation(QualType Type) {
-  return DACtx->getStableStorageLocation(Type);
+  return DACtx->createStorageLocation(Type);
 }
 
 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -24,15 +24,14 @@
 namespace clang {
 namespace dataflow {
 
-StorageLocation &
-DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
+StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) {
   if (!Type.isNull() &&
   (Type->isStructureOrClassType() || Type->isUnionType())) {
 // FIXME: Explore options to avoid eager initializatio

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

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 449449.
sgatev added a comment.
Herald added a subscriber: carlosgalvezp.
Herald added a project: clang-tools-extra.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131014

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.h
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -1245,9 +1245,10 @@
   return UncheckedOptionalAccessModel(Ctx, Options);
 },
 [&Diagnostics, Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
-ASTContext &Ctx, const Stmt *Stmt,
+ASTContext &Ctx, const CFGStmt &Stmt,
 const TypeErasedDataflowAnalysisState &State) mutable {
-  auto StmtDiagnostics = Diagnoser.diagnose(Ctx, Stmt, State.Env);
+  auto StmtDiagnostics =
+  Diagnoser.diagnose(Ctx, Stmt.getStmt(), State.Env);
   llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
 },
 [&Diagnostics](AnalysisData AnalysisData) {
Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -76,7 +76,7 @@
 llvm::StringRef Code,
 ast_matchers::internal::Matcher TargetFuncMatcher,
 std::function MakeAnalysis,
-std::function
 PostVisitStmt,
 std::function VerifyResults, ArrayRef Args,
@@ -112,11 +112,11 @@
   Environment Env(DACtx, *F);
   auto Analysis = MakeAnalysis(Context, Env);
 
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
 PostVisitStmtClosure = [&PostVisitStmt, &Context](
-   const Stmt *Stmt,
+   const CFGStmt &Stmt,
const TypeErasedDataflowAnalysisState &State) {
   PostVisitStmt(Context, Stmt, State);
 };
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -333,7 +333,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt) {
   PostOrderCFGView POV(&CFCtx.getCFG());
   ForwardDataflowWorklist Worklist(CFCtx.getCFG(), &POV);
@@ -398,12 +399,9 @@
   // Skip blocks that were not evaluated.
   if (!BlockStates[Block->getBlockID()])
 continue;
-  transferBlock(
-  CFCtx, BlockStates, *Block, InitEnv, Analysis,
-  [&PostVisitStmt](const clang::CFGStmt &Stmt,
-   const TypeErasedDataflowAnalysisState &State) {
-PostVisitStmt(Stmt.getStmt(), State);
-  });
+
+  transferBlock(CFCtx, BlockStates, *Block, InitEnv, Analysis,
+PostVisitStmt);
 }
   }
 
Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -138,7 +138,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt = nullptr);
 
 } // namespace dataflow
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -125,14 +125,14 @@
 runDataflowAnalysis(
 const ControlFlowContext &CFCtx, AnalysisT &Analysis,
 const Environment &InitEnv,
-std::function &)>
+std::function &)>
 PostVisitStmt = nullptr) {
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
 PostVisitStmtClosure =

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

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added a comment.

In D131014#3694852 , @samestep wrote:

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

It does, thanks! Fixed.


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] D131039: [clang][dataflow] Add cache of `ControlFlowContext`s for function decls.

2022-08-02 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h:34
+  /// Builds a ControlFlowContext from an AST node. `D` is the function in 
which
+  /// `S` resides. All arguments must be non-null.
   static llvm::Expected build(const Decl *D, Stmt *S,

Can we make them references?



Comment at: clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h:50
 private:
-  ControlFlowContext(std::unique_ptr Cfg,
+  // `D` must not be null.
+  ControlFlowContext(const Decl *D, std::unique_ptr Cfg,

Can we make it a reference?



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:369
+
+  // Keyed on the function's fully qualified name. No leading "::".
+  llvm::StringMap FunctionModels;

Can we make the keys `FunctionDecl *` and use `FunctionDecl::getDefinition` in 
`getControlFlowContext` to obtain a canonical pointer?


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] D131014: [clang][dataflow] Make the type of the post visit callback consistent

2022-08-02 Thread Stanislav Gatev 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 rGc44c71843f3e: [clang][dataflow] Make the type of the post 
visit callback consistent (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131014

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.h
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -1245,9 +1245,10 @@
   return UncheckedOptionalAccessModel(Ctx, Options);
 },
 [&Diagnostics, Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
-ASTContext &Ctx, const Stmt *Stmt,
+ASTContext &Ctx, const CFGStmt &Stmt,
 const TypeErasedDataflowAnalysisState &State) mutable {
-  auto StmtDiagnostics = Diagnoser.diagnose(Ctx, Stmt, State.Env);
+  auto StmtDiagnostics =
+  Diagnoser.diagnose(Ctx, Stmt.getStmt(), State.Env);
   llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
 },
 [&Diagnostics](AnalysisData AnalysisData) {
Index: clang/unittests/Analysis/FlowSensitive/TestingSupport.h
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -76,7 +76,7 @@
 llvm::StringRef Code,
 ast_matchers::internal::Matcher TargetFuncMatcher,
 std::function MakeAnalysis,
-std::function
 PostVisitStmt,
 std::function VerifyResults, ArrayRef Args,
@@ -112,11 +112,11 @@
   Environment Env(DACtx, *F);
   auto Analysis = MakeAnalysis(Context, Env);
 
-  std::function
+  std::function
   PostVisitStmtClosure = nullptr;
   if (PostVisitStmt != nullptr) {
 PostVisitStmtClosure = [&PostVisitStmt, &Context](
-   const Stmt *Stmt,
+   const CFGStmt &Stmt,
const TypeErasedDataflowAnalysisState &State) {
   PostVisitStmt(Context, Stmt, State);
 };
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -333,7 +333,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt) {
   PostOrderCFGView POV(&CFCtx.getCFG());
   ForwardDataflowWorklist Worklist(CFCtx.getCFG(), &POV);
@@ -398,12 +399,9 @@
   // Skip blocks that were not evaluated.
   if (!BlockStates[Block->getBlockID()])
 continue;
-  transferBlock(
-  CFCtx, BlockStates, *Block, InitEnv, Analysis,
-  [&PostVisitStmt](const clang::CFGStmt &Stmt,
-   const TypeErasedDataflowAnalysisState &State) {
-PostVisitStmt(Stmt.getStmt(), State);
-  });
+
+  transferBlock(CFCtx, BlockStates, *Block, InitEnv, Analysis,
+PostVisitStmt);
 }
   }
 
Index: clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -138,7 +138,8 @@
 runTypeErasedDataflowAnalysis(
 const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
 const Environment &InitEnv,
-std::function
+std::function
 PostVisitStmt = nullptr);
 
 } // namespace dataflow
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -125,14 +125,14 @@
 runDataflowAnalysis(
 const ControlFlowContext &CFCtx, AnalysisT &Analysis,
 const Environment &InitEnv,
-std::function &)>
+std::function &)>
 PostVisitStmt = nullptr) {
-  std::function
+  std::function
   PostVisitSt

[PATCH] D131021: [clang][dataflow] Rename member to make it clear that it isn't stable

2022-08-02 Thread Stanislav Gatev 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 rG817dd5e3fd6b: [clang][dataflow] Rename member to make it 
clear that it isn't stable (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131021

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


Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -337,7 +337,7 @@
 }
 
 StorageLocation &Environment::createStorageLocation(QualType Type) {
-  return DACtx->getStableStorageLocation(Type);
+  return DACtx->createStorageLocation(Type);
 }
 
 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -24,15 +24,14 @@
 namespace clang {
 namespace dataflow {
 
-StorageLocation &
-DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
+StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) 
{
   if (!Type.isNull() &&
   (Type->isStructureOrClassType() || Type->isUnionType())) {
 // FIXME: Explore options to avoid eager initialization of fields as some 
of
 // them might not be needed for a particular analysis.
 llvm::DenseMap FieldLocs;
 for (const FieldDecl *Field : getObjectFields(Type))
-  FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())});
+  FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
 return takeOwnership(
 std::make_unique(Type, 
std::move(FieldLocs)));
   }
@@ -43,7 +42,7 @@
 DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
   if (auto *Loc = getStorageLocation(D))
 return *Loc;
-  auto &Loc = getStableStorageLocation(D.getType());
+  auto &Loc = createStorageLocation(D.getType());
   setStorageLocation(D, Loc);
   return Loc;
 }
@@ -52,7 +51,7 @@
 DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
   if (auto *Loc = getStorageLocation(E))
 return *Loc;
-  auto &Loc = getStableStorageLocation(E.getType());
+  auto &Loc = createStorageLocation(E.getType());
   setStorageLocation(E, Loc);
   return Loc;
 }
@@ -63,7 +62,7 @@
   PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
   if (Res.second) {
-auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType);
+auto &PointeeLoc = createStorageLocation(CanonicalPointeeType);
 Res.first->second =
 &takeOwnership(std::make_unique(PointeeLoc));
   }
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -90,12 +90,12 @@
 return *cast(Vals.back().get());
   }
 
-  /// Returns a stable storage location appropriate for `Type`.
+  /// Returns a new storage location appropriate for `Type`.
   ///
   /// Requirements:
   ///
   ///  `Type` must not be null.
-  StorageLocation &getStableStorageLocation(QualType Type);
+  StorageLocation &createStorageLocation(QualType Type);
 
   /// Returns a stable storage location for `D`.
   StorageLocation &getStableStorageLocation(const VarDecl &D);


Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -337,7 +337,7 @@
 }
 
 StorageLocation &Environment::createStorageLocation(QualType Type) {
-  return DACtx->getStableStorageLocation(Type);
+  return DACtx->createStorageLocation(Type);
 }
 
 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -24,15 +24,14 @@
 namespace clang {
 namespace dataflow {
 
-StorageLocation &
-DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
+StorageLocation &DataflowAnalysisContext::createStorageLocation(Qual

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

2022-08-03 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:170
 
+  /// Returns the `DeclCtx` of the block being analysed if provided, otherwise
+  /// returns nullptr.





Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:370
 
+  // `DeclCtx` of the block being analysed if provided.
+  const DeclContext *DeclCtx;





Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:170-172
+ const DeclContext &DeclCtxArg)
 : Environment(DACtx) {
+  DeclCtx = &DeclCtxArg;




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] D131039: [clang][dataflow] Add cache of `ControlFlowContext`s for function decls.

2022-08-03 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h:34
+  /// Builds a ControlFlowContext from an AST node. `D` is the function in 
which
+  /// `S` resides. All arguments must be non-null.
   static llvm::Expected build(const Decl *D, Stmt *S,

ymandel wrote:
> sgatev wrote:
> > Can we make them references?
> Turns out I was wrong - `D` can be null. Would that CFG has comments about 
> what its parameters do... We have a test that excercises this (though I can't 
> say why):
> 
> https://github.com/llvm/llvm-project/blob/9a976f36615dbe15e76c12b22f711b2e597a8e51/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp#L70
> 
> The other two -- yes -- but then we'd have to update the various callers as 
> well. I'd rather not do that in this patch, but I'll add the new overload and 
> we can follow up with cleanups in another patch.
> 
> 
Weird. I think we should change the test to pass the decl.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:369
+
+  llvm::DenseMap FunctionModels;
 };

Perhaps `FunctionContexts`?



Comment at: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp:19
 #include "clang/Analysis/FlowSensitive/Value.h"
+#include "clang/Basic/IdentifierTable.h"
 #include "llvm/Support/Debug.h"

Is this still needed?


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] D131109: [clang][dataflow][NFC] Fix outdated comment on getStableStorageLocation

2022-08-03 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added a comment.

Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131109

___
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 Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



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

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



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

Let's do `if (Loc == nullptr) return;`



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

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`.


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] D130726: [clang][dataflow] Handle multiple context-sensitive calls to the same function

2022-08-03 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:250
+  // scope, we do not propagate the maps.
+  this->LocToVal = std::move(CalleeEnv.LocToVal);
+  this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct);

Does `std::move` help here? `CalleeEnv` is a const reference.


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] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



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

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.



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

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.


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] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev 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;
 

Let's add a brief comment explaining what this is and when it is expected to be 
non-null.



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

What if `Arg` is null?


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 Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



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

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.


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] D130600: [clang][dataflow] Handle return statements

2022-08-04 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:208
   Environment Env(*this);
+  Env.ReturnLoc = Env.getStorageLocation(*Call, SkipPast::Reference);
 

Let's add a FIXME to support references here.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:543-545
+  auto &ReturnLoc = Env.createStorageLocation(*S);
+  Env.setStorageLocation(*S, ReturnLoc);
   auto CalleeEnv = Env.pushCall(S);

Now there's a hidden connection - `ReturnLoc` gets assigned a value in `Env` 
because we implicitly use the same storage location in `Env.pushCall(S)`. I 
suggest adding a comment about 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] D131170: [clang][dataflow] Analyze method bodies

2022-08-04 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



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

samestep wrote:
> 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?
Ah, right. Well, I'm not familiar with the details, but apparently it returns 
null in some cases.


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] D131065: [clang][dataflow] Store DeclContext of block being analysed in Environment if available.

2022-08-05 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:537-539
+  auto *Caller = Env.getDeclCtx();
+  Env = Environment(ExitState->Env);
+  Env.setDeclCtx(Caller);

I believe you'll need to rebase because this has changed: 
https://github.com/llvm/llvm-project/blob/main/clang/lib/Analysis/FlowSensitive/Transfer.cpp#L567


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] D131280: [clang][dataflow] Parameterize analysis by explicit map of analyzable functions.

2022-08-08 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h:83
+/// overload sets. change the key to support uniqueness.
+llvm::Expected>
+buildFunctionMapFromAST(ASTUnit &Unit);

`#include "llvm/ADT/StringMap.h"`



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:27
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Compiler.h"

This should be `StringMap`.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:60
   ///
+  /// Paramter `AnalyzableFunctions` is a map of analyzable function bodies
+  /// (represented as `ControlFlowContext`s), keyed by the fully-qualified

How about `InlineableFunctions`?



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:60
   ///
+  /// Paramter `AnalyzableFunctions` is a map of analyzable function bodies
+  /// (represented as `ControlFlowContext`s), keyed by the fully-qualified

sgatev wrote:
> How about `InlineableFunctions`?




Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:549
 
-  // 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 &ReturnLoc = Env.createStorageLocation(*S);
-  Env.setStorageLocation(*S, ReturnLoc);
-  auto CalleeEnv = Env.pushCall(S);
+  const FunctionDecl *FuncDecl = CFCtx->getDecl()->getAsFunction();
+  assert(FuncDecl != nullptr && "ControlFlowContexts in the environment "

How is that different from `F`? Why not let `Environment::pushCall` get this 
from the `CallExpr` argument?



Comment at: clang/unittests/Analysis/FlowSensitive/TestingSupport.h:74
 
+/// `Code` must be the source code from `ASTUnit` was built.
 template 




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 Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



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

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.


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-10 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev 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);

Let's add a note that unlike `pushCall`, this member is invoked on the 
environment of the callee.



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

`#include "llvm/ADT/ArrayRef.h"`



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




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] D121197: [clang][dataflow] Add analysis that detects unsafe accesses to optionals

2022-03-09 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 414029.
sgatev marked 2 inline comments as done.
sgatev added a comment.

Address reviewers' comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121197

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/TestingSupport.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/Models/CMakeLists.txt
  
clang/unittests/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModelTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.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
@@ -7,7 +7,6 @@
 //===--===//
 
 #include "NoopAnalysis.h"
-#include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -17,6 +16,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.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
@@ -7,13 +7,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/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/ArrayRef.h"
Index: clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
@@ -1,4 +1,4 @@
-#include "TestingSupport.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.h"
 #include "NoopAnalysis.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
Index: clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
@@ -12,7 +12,6 @@
 //
 //===--===//
 
-#include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
@@ -22,6 +21,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
Index: clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
@@ -12,7 +12,6 @@
 //
 //===

[PATCH] D121197: [clang][dataflow] Add analysis that detects unsafe accesses to optionals

2022-03-09 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:115
+  // optional::has_value
+  .CaseOf(isOptionalMemberCallWithName("has_value"),
+  transferOptionalHasValueCall)

xazax.hun wrote:
> One very important omission seems to be `optional::operator bool`. This is a 
> widely used method and I'd love to see it supported.
> 
> Also would love to see FIXMEs for some of the most more frequently used 
> functions/methods:
> * make_optional makes a non-empty optional
> * swap (free function and method)
> * value_or returning its argument when the optional is known to be empty
> * Model the value semantics:  Copy ctor, assignment operator
> * Model the move semantics
> * Default constructed optional is empty
> * Invalidation: passing optional by non-const reference/pointer can 
> invalidate its state
> 
> 
Most of these will be implemented in follow up patches soon and you can already 
find the list in the FIXME in UncheckedOptionalAccessModelTest.cpp. I added to 
it invalidation so that it covers all features you mentioned here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121197

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


[PATCH] D121197: [clang][dataflow] Add analysis that detects unsafe accesses to optionals

2022-03-09 Thread Stanislav Gatev 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 rGce205cffdfa0: [clang][dataflow] Add analysis that detects 
unsafe accesses to optionals (authored by sgatev).

Changed prior to commit:
  https://reviews.llvm.org/D121197?vs=414029&id=414037#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121197

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/TestingSupport.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/Models/CMakeLists.txt
  
clang/unittests/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModelTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.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
@@ -7,7 +7,6 @@
 //===--===//
 
 #include "NoopAnalysis.h"
-#include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -17,6 +16,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.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
@@ -7,13 +7,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/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/ArrayRef.h"
Index: clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TestingSupportTest.cpp
@@ -1,4 +1,4 @@
-#include "TestingSupport.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.h"
 #include "NoopAnalysis.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
Index: clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
@@ -12,7 +12,6 @@
 //
 //===--===//
 
-#include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
@@ -22,6 +21,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/TestingSupport.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
Index: clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
==

[PATCH] D121285: [clang][dataflow] Move dataflow testing support out of unittests

2022-03-09 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs, mgorny.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added a subscriber: sstefan1.
Herald added a project: clang.

This enables tests out of clang/unittests/Analysis/FlowSensitive to
use the testing support utilities.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121285

Files:
  clang/include/clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/DataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.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
@@ -7,7 +7,6 @@
 //===--===//
 
 #include "NoopAnalysis.h"
-#include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -17,6 +16,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.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
@@ -7,13 +7,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/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/ArrayRef.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
@@ -1,4 +1,13 @@
-#include "TestingSupport.h"
+//===- unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
+//---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Testing/DataflowChecker.h"
 #include "NoopAnalysis.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
===
--- /dev/null
+++ clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+  FrontendOpenMP
+  Support
+  )
+
+add_clang_unittest(ClangAnalysisFlowSensitiveTestingTests
+  DataflowCheckerTest.cpp
+  )
+
+clang_target_link_libraries(ClangAnalysisFlowSensitiveTestingTests
+  PRIVATE
+  clangAnalysis
+  clangAnalysisFlowSensitive
+  clangAnalysisFlowSensitiveTesting
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangLex
+  clangSerialization
+  clangTesting
+  clangTooli

[PATCH] D121285: [clang][dataflow] Move dataflow testing support out of unittests

2022-03-09 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 414074.
sgatev added a comment.

Update top level comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121285

Files:
  clang/include/clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/DataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.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
@@ -7,7 +7,6 @@
 //===--===//
 
 #include "NoopAnalysis.h"
-#include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -17,6 +16,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.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
@@ -7,13 +7,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/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/ArrayRef.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
@@ -1,4 +1,12 @@
-#include "TestingSupport.h"
+//===- DataflowAnalysisTest.cpp ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Analysis/FlowSensitive/Testing/DataflowChecker.h"
 #include "NoopAnalysis.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
===
--- /dev/null
+++ clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+  FrontendOpenMP
+  Support
+  )
+
+add_clang_unittest(ClangAnalysisFlowSensitiveTestingTests
+  DataflowCheckerTest.cpp
+  )
+
+clang_target_link_libraries(ClangAnalysisFlowSensitiveTestingTests
+  PRIVATE
+  clangAnalysis
+  clangAnalysisFlowSensitive
+  clangAnalysisFlowSensitiveTesting
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangLex
+  clangSerialization
+  clangTesting
+  clangTooling
+  )
+
+target_link_libraries(ClangAnalysisFlowSensitiveTestingTests
+  PRIVATE
+  LLVMTestingSupport
+  )
Index: clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
===
--- clang/un

[PATCH] D121285: [clang][dataflow] Move dataflow testing support out of unittests

2022-03-09 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 414094.
sgatev added a comment.

Move NoopAnalysis.h to clang/include/clang/Analysis/FlowSensitive/Testing.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121285

Files:
  clang/include/clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/Testing/NoopAnalysis.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/DataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.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,8 +6,6 @@
 //
 //===--===//
 
-#include "NoopAnalysis.h"
-#include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -17,6 +15,8 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/Testing/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,14 +6,14 @@
 //
 //===--===//
 
-#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/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/Testing/NoopAnalysis.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/ArrayRef.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
@@ -1,8 +1,16 @@
-#include "TestingSupport.h"
-#include "NoopAnalysis.h"
+//===- DataflowAnalysisTest.cpp ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/Testing/NoopAnalysis.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gmock/gmock.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
===
--- /dev/null
+++ clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+  FrontendOpenMP
+  Support
+  )
+
+add_clang_unittest(ClangAnalysisFlowSensitiveTestingTests
+  DataflowCheckerTest.cpp
+  )
+
+clang_target_link_libraries(ClangAnalysi

[PATCH] D121285: [clang][dataflow] Move dataflow testing support out of unittests

2022-03-09 Thread Stanislav Gatev 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 rG26bbde2612b2: [clang][dataflow] Move dataflow testing 
support out of unittests (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121285

Files:
  clang/include/clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h
  clang/include/clang/Analysis/FlowSensitive/Testing/NoopAnalysis.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/Testing/DataflowAnalysis.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupport.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,8 +6,6 @@
 //
 //===--===//
 
-#include "NoopAnalysis.h"
-#include "TestingSupport.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -17,6 +15,8 @@
 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/Testing/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,14 +6,14 @@
 //
 //===--===//
 
-#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/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/Testing/NoopAnalysis.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/ArrayRef.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/Testing/DataflowCheckerTest.cpp
@@ -1,8 +1,16 @@
-#include "TestingSupport.h"
-#include "NoopAnalysis.h"
+//===- DataflowAnalysisTest.cpp ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/FlowSensitive/Testing/DataflowAnalysis.h"
+#include "clang/Analysis/FlowSensitive/Testing/NoopAnalysis.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gmock/gmock.h"
Index: clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
===
--- /dev/null
+++ clang/unittests/Analysis/FlowSensitive/Testing/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+  FrontendOpenMP
+  Support
+  )
+
+add_clang_unittest(ClangAnal

[PATCH] D121378: [clang][dataflow] Model the behavior of various optional members

2022-03-10 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Model `make_optional`, optional's default constructor, `emplace`,
`reset`, and `operator bool` members.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121378

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -30,8 +30,21 @@
 using ::testing::UnorderedElementsAre;
 
 static constexpr char StdTypeTraitsHeader[] = R"(
+#ifndef TYPE_TRAITS_H
+#define TYPE_TRAITS_H
+
 namespace std {
 
+typedef decltype(sizeof(char)) size_t;
+
+template 
+struct integral_constant {
+  static constexpr T value = V;
+};
+
+using true_type = integral_constant;
+using false_type = integral_constant;
+
 template< class T > struct remove_reference  {typedef T type;};
 template< class T > struct remove_reference  {typedef T type;};
 template< class T > struct remove_reference {typedef T type;};
@@ -39,21 +52,135 @@
 template 
   using remove_reference_t = typename remove_reference::type;
 
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct is_array : false_type {};
+
+template 
+struct is_array : true_type {};
+
+template 
+struct is_array : true_type {};
+
+template 
+struct is_function : false_type {};
+
+template 
+struct is_function : true_type {};
+
+namespace detail {
+
+template 
+struct type_identity {
+  using type = T;
+};  // or use type_identity (since C++20)
+
+template 
+auto try_add_pointer(int) -> type_identity::type*>;
+template 
+auto try_add_pointer(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_pointer : decltype(detail::try_add_pointer(0)) {};
+
+template 
+struct conditional {
+  typedef T type;
+};
+
+template 
+struct conditional {
+  typedef F type;
+};
+
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+
+template 
+struct decay {
+ private:
+  typedef typename remove_reference::type U;
+
+ public:
+  typedef typename conditional<
+  is_array::value, typename remove_extent::type*,
+  typename conditional::value, typename add_pointer::type,
+   typename remove_cv::type>::type>::type type;
+};
+
 } // namespace std
+
+#endif // TYPE_TRAITS_H
 )";
 
 static constexpr char StdUtilityHeader[] = R"(
+#ifndef UTILITY_H
+#define UTILITY_H
+
 #include "std_type_traits.h"
 
 namespace std {
 
 template 
-constexpr std::remove_reference_t&& move(T&& x);
+constexpr remove_reference_t&& move(T&& x);
 
 } // namespace std
+
+#endif // UTILITY_H
+)";
+
+static constexpr char StdInitializerListHeader[] = R"(
+#ifndef INITIALIZER_LIST_H
+#define INITIALIZER_LIST_H
+
+namespace std {
+
+template 
+class initializer_list {
+ public:
+  initializer_list() noexcept;
+};
+
+} // namespace std
+
+#endif // INITIALIZER_LIST_H
 )";
 
 static constexpr char StdOptionalHeader[] = R"(
+#include "std_type_traits.h"
+#include "std_utility.h"
+#include "std_initializer_list.h"
+
 namespace std {
 
 template 
@@ -74,13 +201,41 @@
   const T&& value() const&&;
   T&& value() &&;
 
+  template 
+  constexpr T value_or(U&& v) const&;
+  template 
+  T value_or(U&& v) &&;
+
+  template 
+  T& emplace(Args&&... args);
+
+  template 
+  T& emplace(std::initializer_list ilist, Args&&... args);
+
+  void reset() noexcept;
+
+  constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
 };
 
+template 
+constexpr optional::type> make_optional(T&& v);
+
+template 
+constexpr optional make_optional(Args&&... args);
+
+template 
+constexpr optional make_optional(std::initializer_list il,
+Args&&... args);
+
 } // namespace std
 )";
 
 static constexpr char AbslOptionalHeader[] = R"(
+#include "std_type_traits.h"
+#include "std_utility.h"
+#include "std_initializer_list.h"
+
 namespace absl {
 
 template 
@@ -101,13 +256,41 @@
   const T&& value() const&&;
   T&& value() &&;
 
+  template 
+  constexpr T value_or(U&& v) const&;
+  template 
+  T value_or(U&& v) &&;
+
+  template 
+  T& emplace(Args&&... args);
+
+  template 
+  T& emplace(std::initializer_list ilist, Args&&... args);
+
+  void reset() noexcept;
+
+  constexpr explic

[PATCH] D121378: [clang][dataflow] Model the behavior of various optional members

2022-03-10 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 414396.
sgatev marked an inline comment as done.
sgatev added a comment.

Address reviewers' comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121378

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -29,9 +29,23 @@
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
+// FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
+#ifndef TYPE_TRAITS_H
+#define TYPE_TRAITS_H
+
 namespace std {
 
+typedef decltype(sizeof(char)) size_t;
+
+template 
+struct integral_constant {
+  static constexpr T value = V;
+};
+
+using true_type = integral_constant;
+using false_type = integral_constant;
+
 template< class T > struct remove_reference  {typedef T type;};
 template< class T > struct remove_reference  {typedef T type;};
 template< class T > struct remove_reference {typedef T type;};
@@ -39,21 +53,135 @@
 template 
   using remove_reference_t = typename remove_reference::type;
 
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct is_array : false_type {};
+
+template 
+struct is_array : true_type {};
+
+template 
+struct is_array : true_type {};
+
+template 
+struct is_function : false_type {};
+
+template 
+struct is_function : true_type {};
+
+namespace detail {
+
+template 
+struct type_identity {
+  using type = T;
+};  // or use type_identity (since C++20)
+
+template 
+auto try_add_pointer(int) -> type_identity::type*>;
+template 
+auto try_add_pointer(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_pointer : decltype(detail::try_add_pointer(0)) {};
+
+template 
+struct conditional {
+  typedef T type;
+};
+
+template 
+struct conditional {
+  typedef F type;
+};
+
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+
+template 
+struct decay {
+ private:
+  typedef typename remove_reference::type U;
+
+ public:
+  typedef typename conditional<
+  is_array::value, typename remove_extent::type*,
+  typename conditional::value, typename add_pointer::type,
+   typename remove_cv::type>::type>::type type;
+};
+
 } // namespace std
+
+#endif // TYPE_TRAITS_H
 )";
 
 static constexpr char StdUtilityHeader[] = R"(
+#ifndef UTILITY_H
+#define UTILITY_H
+
 #include "std_type_traits.h"
 
 namespace std {
 
 template 
-constexpr std::remove_reference_t&& move(T&& x);
+constexpr remove_reference_t&& move(T&& x);
+
+} // namespace std
+
+#endif // UTILITY_H
+)";
+
+static constexpr char StdInitializerListHeader[] = R"(
+#ifndef INITIALIZER_LIST_H
+#define INITIALIZER_LIST_H
+
+namespace std {
+
+template 
+class initializer_list {
+ public:
+  initializer_list() noexcept;
+};
 
 } // namespace std
+
+#endif // INITIALIZER_LIST_H
 )";
 
 static constexpr char StdOptionalHeader[] = R"(
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
 namespace std {
 
 template 
@@ -74,13 +202,41 @@
   const T&& value() const&&;
   T&& value() &&;
 
+  template 
+  constexpr T value_or(U&& v) const&;
+  template 
+  T value_or(U&& v) &&;
+
+  template 
+  T& emplace(Args&&... args);
+
+  template 
+  T& emplace(std::initializer_list ilist, Args&&... args);
+
+  void reset() noexcept;
+
+  constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
 };
 
+template 
+constexpr optional::type> make_optional(T&& v);
+
+template 
+constexpr optional make_optional(Args&&... args);
+
+template 
+constexpr optional make_optional(std::initializer_list il,
+Args&&... args);
+
 } // namespace std
 )";
 
 static constexpr char AbslOptionalHeader[] = R"(
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
 namespace absl {
 
 template 
@@ -101,13 +257,41 @@
   const T&& value() const&&;
   T&& value() &&;
 
+  template 
+  constexpr T value_or(U&& v) const&;
+  template 
+  T value_or(U&& v) &&;
+
+  template 
+  T& emplace(Args&&... args);
+
+  template 
+  T& emplace(std::initializer_list ilist, Args&&... args);
+
+  void reset() noexcept;
+
+  constexpr explicit operator bool() const noexcept;
   constexpr bool has_value

[PATCH] D121378: [clang][dataflow] Model the behavior of various optional members

2022-03-10 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev marked an inline comment as done.
sgatev added inline comments.



Comment at: 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp:33
 static constexpr char StdTypeTraitsHeader[] = R"(
+#ifndef TYPE_TRAITS_H
+#define TYPE_TRAITS_H

xazax.hun wrote:
> I wonder if it is more sustainable in the long term to have these headers in 
> a separate file and `#include` them here (and build the raw string literal 
> with a macro if that is possible at all).
Yeap, I agree that would be better. I'll consider some options and send a patch 
to move them out of here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121378

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


[PATCH] D121455: [clang][dataflow] Add support for nested composite bool expressions

2022-03-11 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

This is part of the implementation of the dataflow analysis framework.
See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121455

Files:
  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
@@ -2060,86 +2060,109 @@
   });
 }
 
-TEST_F(TransferTest, AssignFromBoolConjunction) {
-  std::string Code = R"(
-void target(bool Foo, bool Bar) {
-  bool Baz = (Foo) && (Bar);
+TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
+  {
+std::string Code = R"(
+void target(bool Foo, bool Bar, bool Qux) {
+  bool Baz = (Foo) && (Bar || Qux);
   // [[p]]
 }
   )";
-  runDataflow(
-  Code, [](llvm::ArrayRef<
-   std::pair>>
-   Results,
-   ASTContext &ASTCtx) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment &Env = Results[0].second.Env;
+runDataflow(
+Code, [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+  ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+  const Environment &Env = Results[0].second.Env;
 
-const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
-ASSERT_THAT(FooDecl, NotNull());
+  const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+  ASSERT_THAT(FooDecl, NotNull());
 
-const auto *FooVal =
-dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
-ASSERT_THAT(FooVal, NotNull());
+  const auto *FooVal = dyn_cast_or_null(
+  Env.getValue(*FooDecl, SkipPast::None));
+  ASSERT_THAT(FooVal, NotNull());
 
-const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
-ASSERT_THAT(BarDecl, NotNull());
+  const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+  ASSERT_THAT(BarDecl, NotNull());
 
-const auto *BarVal =
-dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
-ASSERT_THAT(BarVal, NotNull());
+  const auto *BarVal = dyn_cast_or_null(
+  Env.getValue(*BarDecl, SkipPast::None));
+  ASSERT_THAT(BarVal, NotNull());
 
-const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
-ASSERT_THAT(BazDecl, NotNull());
+  const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
+  ASSERT_THAT(QuxDecl, NotNull());
 
-const auto *BazVal = dyn_cast_or_null(
-Env.getValue(*BazDecl, SkipPast::None));
-ASSERT_THAT(BazVal, NotNull());
+  const auto *QuxVal = dyn_cast_or_null(
+  Env.getValue(*QuxDecl, SkipPast::None));
+  ASSERT_THAT(QuxVal, NotNull());
 
-EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
-EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
-  });
-}
+  const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+  ASSERT_THAT(BazDecl, NotNull());
 
-TEST_F(TransferTest, AssignFromBoolDisjunction) {
-  std::string Code = R"(
-void target(bool Foo, bool Bar) {
-  bool Baz = (Foo) || (Bar);
+  const auto *BazVal = dyn_cast_or_null(
+  Env.getValue(*BazDecl, SkipPast::None));
+  ASSERT_THAT(BazVal, NotNull());
+  EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+
+  const auto *BazRightSubValVal =
+  cast(&BazVal->getRightSubValue());
+  EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
+  EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
+});
+  }
+
+  {
+std::string Code = R"(
+void target(bool Foo, bool Bar, bool Qux) {
+  bool Baz = (Foo && Qux) || (Bar);
   // [[p]]
 }
   )";
-  runDataflow(
-  Code, [](llvm::ArrayRef<
-   std::pair>>
-   Results,
-   ASTContext &ASTCtx) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment &Env = Results[0].second.Env;
+runDataflow(
+Code, [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+  ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+  const Environment &Env = Results[0].second.Env;
 
-const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
-ASSERT_THAT(FooDecl, NotNull());
+  const ValueDec

[PATCH] D121378: [clang][dataflow] Model the behavior of various optional members

2022-03-13 Thread Stanislav Gatev via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
sgatev marked an inline comment as done.
Closed by commit rG9e0fc6768378: [clang][dataflow] Model the behavior of 
various optional members (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121378

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -29,9 +29,23 @@
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
+// FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
+#ifndef TYPE_TRAITS_H
+#define TYPE_TRAITS_H
+
 namespace std {
 
+typedef decltype(sizeof(char)) size_t;
+
+template 
+struct integral_constant {
+  static constexpr T value = V;
+};
+
+using true_type = integral_constant;
+using false_type = integral_constant;
+
 template< class T > struct remove_reference  {typedef T type;};
 template< class T > struct remove_reference  {typedef T type;};
 template< class T > struct remove_reference {typedef T type;};
@@ -39,21 +53,135 @@
 template 
   using remove_reference_t = typename remove_reference::type;
 
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct remove_extent {
+  typedef T type;
+};
+
+template 
+struct is_array : false_type {};
+
+template 
+struct is_array : true_type {};
+
+template 
+struct is_array : true_type {};
+
+template 
+struct is_function : false_type {};
+
+template 
+struct is_function : true_type {};
+
+namespace detail {
+
+template 
+struct type_identity {
+  using type = T;
+};  // or use type_identity (since C++20)
+
+template 
+auto try_add_pointer(int) -> type_identity::type*>;
+template 
+auto try_add_pointer(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_pointer : decltype(detail::try_add_pointer(0)) {};
+
+template 
+struct conditional {
+  typedef T type;
+};
+
+template 
+struct conditional {
+  typedef F type;
+};
+
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+template 
+struct remove_cv {
+  typedef T type;
+};
+
+template 
+struct decay {
+ private:
+  typedef typename remove_reference::type U;
+
+ public:
+  typedef typename conditional<
+  is_array::value, typename remove_extent::type*,
+  typename conditional::value, typename add_pointer::type,
+   typename remove_cv::type>::type>::type type;
+};
+
 } // namespace std
+
+#endif // TYPE_TRAITS_H
 )";
 
 static constexpr char StdUtilityHeader[] = R"(
+#ifndef UTILITY_H
+#define UTILITY_H
+
 #include "std_type_traits.h"
 
 namespace std {
 
 template 
-constexpr std::remove_reference_t&& move(T&& x);
+constexpr remove_reference_t&& move(T&& x);
+
+} // namespace std
+
+#endif // UTILITY_H
+)";
+
+static constexpr char StdInitializerListHeader[] = R"(
+#ifndef INITIALIZER_LIST_H
+#define INITIALIZER_LIST_H
+
+namespace std {
+
+template 
+class initializer_list {
+ public:
+  initializer_list() noexcept;
+};
 
 } // namespace std
+
+#endif // INITIALIZER_LIST_H
 )";
 
 static constexpr char StdOptionalHeader[] = R"(
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
 namespace std {
 
 template 
@@ -74,13 +202,41 @@
   const T&& value() const&&;
   T&& value() &&;
 
+  template 
+  constexpr T value_or(U&& v) const&;
+  template 
+  T value_or(U&& v) &&;
+
+  template 
+  T& emplace(Args&&... args);
+
+  template 
+  T& emplace(std::initializer_list ilist, Args&&... args);
+
+  void reset() noexcept;
+
+  constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
 };
 
+template 
+constexpr optional::type> make_optional(T&& v);
+
+template 
+constexpr optional make_optional(Args&&... args);
+
+template 
+constexpr optional make_optional(std::initializer_list il,
+Args&&... args);
+
 } // namespace std
 )";
 
 static constexpr char AbslOptionalHeader[] = R"(
+#include "std_initializer_list.h"
+#include "std_type_traits.h"
+#include "std_utility.h"
+
 namespace absl {
 
 template 
@@ -101,13 +257,41 @@
   const T&& value() const&&;
   T&& value() &&;
 
+  template 
+  constexpr T value_or(U&& v) const&;
+  template 
+  T value_or(U&& v) &&;
+
+  template 
+  T& emplace(Args&&... args);
+
+  template 
+  T& emplace(std::i

[PATCH] D121455: [clang][dataflow] Add support for nested composite bool expressions

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 415021.
sgatev marked an inline comment as done.
sgatev added a comment.

Address reviewers' comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121455

Files:
  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
@@ -2060,86 +2060,109 @@
   });
 }
 
-TEST_F(TransferTest, AssignFromBoolConjunction) {
-  std::string Code = R"(
-void target(bool Foo, bool Bar) {
-  bool Baz = (Foo) && (Bar);
+TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
+  {
+std::string Code = R"(
+void target(bool Foo, bool Bar, bool Qux) {
+  bool Baz = (Foo) && (Bar || Qux);
   // [[p]]
 }
   )";
-  runDataflow(
-  Code, [](llvm::ArrayRef<
-   std::pair>>
-   Results,
-   ASTContext &ASTCtx) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment &Env = Results[0].second.Env;
+runDataflow(
+Code, [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+  ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+  const Environment &Env = Results[0].second.Env;
 
-const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
-ASSERT_THAT(FooDecl, NotNull());
+  const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+  ASSERT_THAT(FooDecl, NotNull());
 
-const auto *FooVal =
-dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
-ASSERT_THAT(FooVal, NotNull());
+  const auto *FooVal = dyn_cast_or_null(
+  Env.getValue(*FooDecl, SkipPast::None));
+  ASSERT_THAT(FooVal, NotNull());
 
-const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
-ASSERT_THAT(BarDecl, NotNull());
+  const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+  ASSERT_THAT(BarDecl, NotNull());
 
-const auto *BarVal =
-dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
-ASSERT_THAT(BarVal, NotNull());
+  const auto *BarVal = dyn_cast_or_null(
+  Env.getValue(*BarDecl, SkipPast::None));
+  ASSERT_THAT(BarVal, NotNull());
 
-const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
-ASSERT_THAT(BazDecl, NotNull());
+  const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
+  ASSERT_THAT(QuxDecl, NotNull());
 
-const auto *BazVal = dyn_cast_or_null(
-Env.getValue(*BazDecl, SkipPast::None));
-ASSERT_THAT(BazVal, NotNull());
+  const auto *QuxVal = dyn_cast_or_null(
+  Env.getValue(*QuxDecl, SkipPast::None));
+  ASSERT_THAT(QuxVal, NotNull());
 
-EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
-EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
-  });
-}
+  const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+  ASSERT_THAT(BazDecl, NotNull());
 
-TEST_F(TransferTest, AssignFromBoolDisjunction) {
-  std::string Code = R"(
-void target(bool Foo, bool Bar) {
-  bool Baz = (Foo) || (Bar);
+  const auto *BazVal = dyn_cast_or_null(
+  Env.getValue(*BazDecl, SkipPast::None));
+  ASSERT_THAT(BazVal, NotNull());
+  EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+
+  const auto *BazRightSubValVal =
+  cast(&BazVal->getRightSubValue());
+  EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
+  EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
+});
+  }
+
+  {
+std::string Code = R"(
+void target(bool Foo, bool Bar, bool Qux) {
+  bool Baz = (Foo && Qux) || (Bar);
   // [[p]]
 }
   )";
-  runDataflow(
-  Code, [](llvm::ArrayRef<
-   std::pair>>
-   Results,
-   ASTContext &ASTCtx) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment &Env = Results[0].second.Env;
+runDataflow(
+Code, [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+  ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+  const Environment &Env = Results[0].second.Env;
 
-const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
-ASSERT_THAT(FooDecl, NotNull());
+  const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+  ASSERT_THAT(FooDecl, NotNull());
 
-const auto *FooVal =
-dyn_cast_or_null(Env.getValue(*FooDecl, SkipP

[PATCH] D121455: [clang][dataflow] Add support for nested composite bool expressions

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:516
+// assigned to it.
+Visit(&SubExpr);
+if (auto *Val = dyn_cast_or_null(

xazax.hun wrote:
> Could you elaborate on when would this happen? I'd expect the traversal to 
> always visit the predecessor basic blocks first and within a basic block 
> always visit subexpressions first. So I'd be quite surprised if there is a 
> subexpression we did not visit.
From what I've seen, logic operators influence the structure of the CFG through 
additional basic blocks and terminators, but their sub-expression operators are 
not added directly in the basic blocks.

For example:
```
void test(bool a, bool b, bool c) {
bool d = a && (b || c);
}
```

results in:
```

void test(bool a, bool b, bool c)
 [B5 (ENTRY)]
   Succs (1): B4

 [B1]
   1: [B4.2] && ([B3.2] || [B2.2])
   2: bool d = a && (b || c);
   Preds (3): B2 B3 B4
   Succs (1): B0

 [B2]
   1: c
   2: [B2.1] (ImplicitCastExpr, LValueToRValue, _Bool)
   Preds (1): B3
   Succs (1): B1

 [B3]
   1: b
   2: [B3.1] (ImplicitCastExpr, LValueToRValue, _Bool)
   T: [B3.2] || ...
   Preds (1): B4
   Succs (2): B1 B2

 [B4]
   1: a
   2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
   T: [B4.2] && ...
   Preds (1): B5
   Succs (2): B3 B1

 [B0 (EXIT)]
   Preds (1): B1
```

So, when we evaluate `a && (b || c)` in `B1`, the sub-expression `b || c` has 
not been evaluated yet. I updated the comment in the code to make that more 
clear.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121455

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


[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Model nullopt, inplace, value, and conversion constructors.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121602

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -31,8 +31,8 @@
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
-#ifndef TYPE_TRAITS_H
-#define TYPE_TRAITS_H
+#ifndef STD_TYPE_TRAITS_H
+#define STD_TYPE_TRAITS_H
 
 namespace std {
 
@@ -127,6 +127,9 @@
   typedef T type;
 };
 
+template 
+using remove_cv_t = typename remove_cv::type;
+
 template 
 struct decay {
  private:
@@ -139,9 +142,196 @@
typename remove_cv::type>::type>::type type;
 };
 
+template 
+struct enable_if {};
+
+template 
+struct enable_if {
+  typedef T type;
+};
+
+template 
+using enable_if_t = typename enable_if::type;
+
+template 
+struct is_same : false_type {};
+
+template 
+struct is_same : true_type {};
+
+template 
+struct is_void : is_same::type> {};
+
+namespace detail {
+
+template 
+auto try_add_rvalue_reference(int) -> type_identity;
+template 
+auto try_add_rvalue_reference(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {
+};
+
+template 
+typename add_rvalue_reference::type declval() noexcept;
+
+namespace detail {
+
+template 
+auto test_returnable(int)
+-> decltype(void(static_cast(nullptr)), true_type{});
+template 
+auto test_returnable(...) -> false_type;
+
+template 
+auto test_implicitly_convertible(int)
+-> decltype(void(declval()(declval())), true_type{});
+template 
+auto test_implicitly_convertible(...) -> false_type;
+
+}  // namespace detail
+
+template 
+struct is_convertible
+: integral_constant(0))::value &&
+ decltype(detail::test_implicitly_convertible(
+ 0))::value) ||
+(is_void::value && is_void::value)> {};
+
+template 
+inline constexpr bool is_convertible_v = is_convertible::value;
+
+template 
+using void_t = void;
+
+template 
+struct is_constructible_ : false_type {};
+
+template 
+struct is_constructible_()...))>, T, Args...>
+: true_type {};
+
+template 
+using is_constructible = is_constructible_, T, Args...>;
+
+template 
+inline constexpr bool is_constructible_v = is_constructible::value;
+
+template 
+struct __uncvref {
+  typedef typename remove_cv::type>::type type;
+};
+
+template 
+using __uncvref_t = typename __uncvref<_Tp>::type;
+
+template 
+using _BoolConstant = integral_constant;
+
+template 
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+template 
+using _IsNotSame = _BoolConstant;
+
+template 
+struct _MetaBase;
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Tp;
+  template  class _FirstFn, template  class,
+class... _Args>
+  using _SelectApplyImpl = _FirstFn<_Args...>;
+  template 
+  using _FirstImpl = _First;
+  template 
+  using _SecondImpl = _Second;
+  template 
+  using _OrImpl =
+  typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+  template _OrImpl<_First, _Rest...>;
+};
+
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Up;
+  template  class, template  class _SecondFn,
+class... _Args>
+  using _SelectApplyImpl = _SecondFn<_Args...>;
+  template 
+  using _OrImpl = _Result;
+};
+
+template 
+using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+template 
+using _Or = typename _MetaBase::template _OrImpl;
+
+template 
+using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+template 
+using __expand_to_true = true_type;
+template 
+__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+template 
+false_type __and_helper(...);
+template 
+using _And = decltype(__and_helper<_Pred...>(0));
+
+struct __check_tuple_constructor_fail {
+  static constexpr bool __enable_explicit_default() { return false; }
+  static constexpr bool __enable_implicit_default() { return false; }
+  template 
+  static constexpr bool __enable_explicit() {
+return false;
+  }
+  template 
+  static constexpr bool

[PATCH] D121455: [clang][dataflow] Add support for nested composite bool expressions

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:516
+// assigned to it.
+Visit(&SubExpr);
+if (auto *Val = dyn_cast_or_null(

xazax.hun wrote:
> sgatev wrote:
> > xazax.hun wrote:
> > > Could you elaborate on when would this happen? I'd expect the traversal 
> > > to always visit the predecessor basic blocks first and within a basic 
> > > block always visit subexpressions first. So I'd be quite surprised if 
> > > there is a subexpression we did not visit.
> > From what I've seen, logic operators influence the structure of the CFG 
> > through additional basic blocks and terminators, but their sub-expression 
> > operators are not added directly in the basic blocks.
> > 
> > For example:
> > ```
> > void test(bool a, bool b, bool c) {
> > bool d = a && (b || c);
> > }
> > ```
> > 
> > results in:
> > ```
> > 
> > void test(bool a, bool b, bool c)
> >  [B5 (ENTRY)]
> >Succs (1): B4
> > 
> >  [B1]
> >1: [B4.2] && ([B3.2] || [B2.2])
> >2: bool d = a && (b || c);
> >Preds (3): B2 B3 B4
> >Succs (1): B0
> > 
> >  [B2]
> >1: c
> >2: [B2.1] (ImplicitCastExpr, LValueToRValue, _Bool)
> >Preds (1): B3
> >Succs (1): B1
> > 
> >  [B3]
> >1: b
> >2: [B3.1] (ImplicitCastExpr, LValueToRValue, _Bool)
> >T: [B3.2] || ...
> >Preds (1): B4
> >Succs (2): B1 B2
> > 
> >  [B4]
> >1: a
> >2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
> >T: [B4.2] && ...
> >Preds (1): B5
> >Succs (2): B3 B1
> > 
> >  [B0 (EXIT)]
> >Preds (1): B1
> > ```
> > 
> > So, when we evaluate `a && (b || c)` in `B1`, the sub-expression `b || c` 
> > has not been evaluated yet. I updated the comment in the code to make that 
> > more clear.
> I understand the structure of the CFG and also understand that certain 
> subexpressions are in different basic blocks. But I still don't understand 
> why would `b || c` be not evaluated when we evaluate `a && (b || c)`.
> 
> The operator `&&` in your example is evaluated in `B1`. The operator `||` is 
> evaluated in `B3`. `B3` is a predecessor of `B1`, so if we process the CFG in 
> reverse-post order, we should visit `B3` before `B1`. 
> 
> I am pretty sure if the traversal is well-written we should have the `||` 
> evaluated before we visit `B1`.
> 
> I suspect that something different might be going on. Is it possible that you 
> want to evaluate the `&&` in `B4`?
> 
> Note that `&&` is a terminator there because of the short-circuiting. So at 
> that point we should NOT ask for the value of `||`.
> The operator `||` is evaluated in `B3`.

I don't think that's the case.  Similar to your observation about `&&` being a 
terminator in `B4`, I believe that `||` is a terminator in `B3`.

I interpret `B3` as the "`a` is true" branch. It still doesn't contain 
information about `b` and `c` which might be subject to short-circuiting.

Does that make sense?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121455

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


[PATCH] D121455: [clang][dataflow] Add support for nested composite bool expressions

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcf63e9d4cacc: [clang][dataflow] Add support for nested 
composite bool expressions (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121455

Files:
  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
@@ -2060,86 +2060,109 @@
   });
 }
 
-TEST_F(TransferTest, AssignFromBoolConjunction) {
-  std::string Code = R"(
-void target(bool Foo, bool Bar) {
-  bool Baz = (Foo) && (Bar);
+TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
+  {
+std::string Code = R"(
+void target(bool Foo, bool Bar, bool Qux) {
+  bool Baz = (Foo) && (Bar || Qux);
   // [[p]]
 }
   )";
-  runDataflow(
-  Code, [](llvm::ArrayRef<
-   std::pair>>
-   Results,
-   ASTContext &ASTCtx) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment &Env = Results[0].second.Env;
+runDataflow(
+Code, [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+  ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+  const Environment &Env = Results[0].second.Env;
 
-const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
-ASSERT_THAT(FooDecl, NotNull());
+  const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+  ASSERT_THAT(FooDecl, NotNull());
 
-const auto *FooVal =
-dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
-ASSERT_THAT(FooVal, NotNull());
+  const auto *FooVal = dyn_cast_or_null(
+  Env.getValue(*FooDecl, SkipPast::None));
+  ASSERT_THAT(FooVal, NotNull());
 
-const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
-ASSERT_THAT(BarDecl, NotNull());
+  const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+  ASSERT_THAT(BarDecl, NotNull());
 
-const auto *BarVal =
-dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
-ASSERT_THAT(BarVal, NotNull());
+  const auto *BarVal = dyn_cast_or_null(
+  Env.getValue(*BarDecl, SkipPast::None));
+  ASSERT_THAT(BarVal, NotNull());
 
-const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
-ASSERT_THAT(BazDecl, NotNull());
+  const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
+  ASSERT_THAT(QuxDecl, NotNull());
 
-const auto *BazVal = dyn_cast_or_null(
-Env.getValue(*BazDecl, SkipPast::None));
-ASSERT_THAT(BazVal, NotNull());
+  const auto *QuxVal = dyn_cast_or_null(
+  Env.getValue(*QuxDecl, SkipPast::None));
+  ASSERT_THAT(QuxVal, NotNull());
 
-EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
-EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
-  });
-}
+  const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+  ASSERT_THAT(BazDecl, NotNull());
 
-TEST_F(TransferTest, AssignFromBoolDisjunction) {
-  std::string Code = R"(
-void target(bool Foo, bool Bar) {
-  bool Baz = (Foo) || (Bar);
+  const auto *BazVal = dyn_cast_or_null(
+  Env.getValue(*BazDecl, SkipPast::None));
+  ASSERT_THAT(BazVal, NotNull());
+  EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+
+  const auto *BazRightSubValVal =
+  cast(&BazVal->getRightSubValue());
+  EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
+  EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
+});
+  }
+
+  {
+std::string Code = R"(
+void target(bool Foo, bool Bar, bool Qux) {
+  bool Baz = (Foo && Qux) || (Bar);
   // [[p]]
 }
   )";
-  runDataflow(
-  Code, [](llvm::ArrayRef<
-   std::pair>>
-   Results,
-   ASTContext &ASTCtx) {
-ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
-const Environment &Env = Results[0].second.Env;
+runDataflow(
+Code, [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+  ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+  const Environment &Env = Results[0].second.Env;
 
-const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
-ASSERT_THAT(FooDecl, NotNull());
+  const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+  ASSERT_THAT(FooDecl, NotNull());
 
-const auto *FooVal =
-

[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 415177.
sgatev marked 2 inline comments as done.
sgatev added a comment.

Address reviewers' comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121602

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -31,8 +31,8 @@
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
-#ifndef TYPE_TRAITS_H
-#define TYPE_TRAITS_H
+#ifndef STD_TYPE_TRAITS_H
+#define STD_TYPE_TRAITS_H
 
 namespace std {
 
@@ -127,6 +127,9 @@
   typedef T type;
 };
 
+template 
+using remove_cv_t = typename remove_cv::type;
+
 template 
 struct decay {
  private:
@@ -139,9 +142,196 @@
typename remove_cv::type>::type>::type type;
 };
 
+template 
+struct enable_if {};
+
+template 
+struct enable_if {
+  typedef T type;
+};
+
+template 
+using enable_if_t = typename enable_if::type;
+
+template 
+struct is_same : false_type {};
+
+template 
+struct is_same : true_type {};
+
+template 
+struct is_void : is_same::type> {};
+
+namespace detail {
+
+template 
+auto try_add_rvalue_reference(int) -> type_identity;
+template 
+auto try_add_rvalue_reference(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {
+};
+
+template 
+typename add_rvalue_reference::type declval() noexcept;
+
+namespace detail {
+
+template 
+auto test_returnable(int)
+-> decltype(void(static_cast(nullptr)), true_type{});
+template 
+auto test_returnable(...) -> false_type;
+
+template 
+auto test_implicitly_convertible(int)
+-> decltype(void(declval()(declval())), true_type{});
+template 
+auto test_implicitly_convertible(...) -> false_type;
+
+}  // namespace detail
+
+template 
+struct is_convertible
+: integral_constant(0))::value &&
+ decltype(detail::test_implicitly_convertible(
+ 0))::value) ||
+(is_void::value && is_void::value)> {};
+
+template 
+inline constexpr bool is_convertible_v = is_convertible::value;
+
+template 
+using void_t = void;
+
+template 
+struct is_constructible_ : false_type {};
+
+template 
+struct is_constructible_()...))>, T, Args...>
+: true_type {};
+
+template 
+using is_constructible = is_constructible_, T, Args...>;
+
+template 
+inline constexpr bool is_constructible_v = is_constructible::value;
+
+template 
+struct __uncvref {
+  typedef typename remove_cv::type>::type type;
+};
+
+template 
+using __uncvref_t = typename __uncvref<_Tp>::type;
+
+template 
+using _BoolConstant = integral_constant;
+
+template 
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+template 
+using _IsNotSame = _BoolConstant;
+
+template 
+struct _MetaBase;
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Tp;
+  template  class _FirstFn, template  class,
+class... _Args>
+  using _SelectApplyImpl = _FirstFn<_Args...>;
+  template 
+  using _FirstImpl = _First;
+  template 
+  using _SecondImpl = _Second;
+  template 
+  using _OrImpl =
+  typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+  template _OrImpl<_First, _Rest...>;
+};
+
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Up;
+  template  class, template  class _SecondFn,
+class... _Args>
+  using _SelectApplyImpl = _SecondFn<_Args...>;
+  template 
+  using _OrImpl = _Result;
+};
+
+template 
+using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+template 
+using _Or = typename _MetaBase::template _OrImpl;
+
+template 
+using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+template 
+using __expand_to_true = true_type;
+template 
+__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+template 
+false_type __and_helper(...);
+template 
+using _And = decltype(__and_helper<_Pred...>(0));
+
+struct __check_tuple_constructor_fail {
+  static constexpr bool __enable_explicit_default() { return false; }
+  static constexpr bool __enable_implicit_default() { return false; }
+  template 
+  static constexpr bool __enable_explicit() {
+return false;
+  }
+  template 
+  static constexpr bool __enable_implicit() {
+return false;
+  }
+};
+
 } // namespace std
 
-#endif // TYPE_TRAITS_

[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 415178.
sgatev marked 2 inline comments as done.
sgatev added a comment.

Add a FIXME.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121602

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -31,8 +31,8 @@
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
-#ifndef TYPE_TRAITS_H
-#define TYPE_TRAITS_H
+#ifndef STD_TYPE_TRAITS_H
+#define STD_TYPE_TRAITS_H
 
 namespace std {
 
@@ -127,6 +127,9 @@
   typedef T type;
 };
 
+template 
+using remove_cv_t = typename remove_cv::type;
+
 template 
 struct decay {
  private:
@@ -139,9 +142,196 @@
typename remove_cv::type>::type>::type type;
 };
 
+template 
+struct enable_if {};
+
+template 
+struct enable_if {
+  typedef T type;
+};
+
+template 
+using enable_if_t = typename enable_if::type;
+
+template 
+struct is_same : false_type {};
+
+template 
+struct is_same : true_type {};
+
+template 
+struct is_void : is_same::type> {};
+
+namespace detail {
+
+template 
+auto try_add_rvalue_reference(int) -> type_identity;
+template 
+auto try_add_rvalue_reference(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {
+};
+
+template 
+typename add_rvalue_reference::type declval() noexcept;
+
+namespace detail {
+
+template 
+auto test_returnable(int)
+-> decltype(void(static_cast(nullptr)), true_type{});
+template 
+auto test_returnable(...) -> false_type;
+
+template 
+auto test_implicitly_convertible(int)
+-> decltype(void(declval()(declval())), true_type{});
+template 
+auto test_implicitly_convertible(...) -> false_type;
+
+}  // namespace detail
+
+template 
+struct is_convertible
+: integral_constant(0))::value &&
+ decltype(detail::test_implicitly_convertible(
+ 0))::value) ||
+(is_void::value && is_void::value)> {};
+
+template 
+inline constexpr bool is_convertible_v = is_convertible::value;
+
+template 
+using void_t = void;
+
+template 
+struct is_constructible_ : false_type {};
+
+template 
+struct is_constructible_()...))>, T, Args...>
+: true_type {};
+
+template 
+using is_constructible = is_constructible_, T, Args...>;
+
+template 
+inline constexpr bool is_constructible_v = is_constructible::value;
+
+template 
+struct __uncvref {
+  typedef typename remove_cv::type>::type type;
+};
+
+template 
+using __uncvref_t = typename __uncvref<_Tp>::type;
+
+template 
+using _BoolConstant = integral_constant;
+
+template 
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+template 
+using _IsNotSame = _BoolConstant;
+
+template 
+struct _MetaBase;
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Tp;
+  template  class _FirstFn, template  class,
+class... _Args>
+  using _SelectApplyImpl = _FirstFn<_Args...>;
+  template 
+  using _FirstImpl = _First;
+  template 
+  using _SecondImpl = _Second;
+  template 
+  using _OrImpl =
+  typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+  template _OrImpl<_First, _Rest...>;
+};
+
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Up;
+  template  class, template  class _SecondFn,
+class... _Args>
+  using _SelectApplyImpl = _SecondFn<_Args...>;
+  template 
+  using _OrImpl = _Result;
+};
+
+template 
+using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+template 
+using _Or = typename _MetaBase::template _OrImpl;
+
+template 
+using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+template 
+using __expand_to_true = true_type;
+template 
+__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+template 
+false_type __and_helper(...);
+template 
+using _And = decltype(__and_helper<_Pred...>(0));
+
+struct __check_tuple_constructor_fail {
+  static constexpr bool __enable_explicit_default() { return false; }
+  static constexpr bool __enable_implicit_default() { return false; }
+  template 
+  static constexpr bool __enable_explicit() {
+return false;
+  }
+  template 
+  static constexpr bool __enable_implicit() {
+return false;
+  }
+};
+
 } // namespace std
 
-#endif // TYPE_TRAITS_H
+#endif // STD

[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-14 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev marked 2 inline comments as done.
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:264
+  +[](const CXXMemberCallExpr *E, LatticeTransferState &State) {
+assignOptionalValue(*E->getImplicitObjectArgument(), State,
+State.Env.getBoolLiteralValue(true));

ymandel wrote:
> I realize this is consistent with the previous version, but just noticed this 
> issue. By using `assignOptionalValue` for `emplace` (and `reset`), does that 
> break the following case?
> 
> ```
> optional opt;
> if (p) opt.emplace(3);
> someCode();
> if (p) use(*opt);
> ```
This isn't supported yet. Still, I don't think `assignOptionalValue` breaks it 
because this seems more related to the way information from different branches 
is joined than the way values are initialized. I'll add this case (and others) 
in a following patch that adds support for joining.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121602

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


[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-15 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 415349.
sgatev marked 3 inline comments as done.
sgatev added a comment.

Address reviewers' comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121602

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -31,8 +31,8 @@
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
-#ifndef TYPE_TRAITS_H
-#define TYPE_TRAITS_H
+#ifndef STD_TYPE_TRAITS_H
+#define STD_TYPE_TRAITS_H
 
 namespace std {
 
@@ -127,6 +127,9 @@
   typedef T type;
 };
 
+template 
+using remove_cv_t = typename remove_cv::type;
+
 template 
 struct decay {
  private:
@@ -139,9 +142,196 @@
typename remove_cv::type>::type>::type type;
 };
 
+template 
+struct enable_if {};
+
+template 
+struct enable_if {
+  typedef T type;
+};
+
+template 
+using enable_if_t = typename enable_if::type;
+
+template 
+struct is_same : false_type {};
+
+template 
+struct is_same : true_type {};
+
+template 
+struct is_void : is_same::type> {};
+
+namespace detail {
+
+template 
+auto try_add_rvalue_reference(int) -> type_identity;
+template 
+auto try_add_rvalue_reference(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {
+};
+
+template 
+typename add_rvalue_reference::type declval() noexcept;
+
+namespace detail {
+
+template 
+auto test_returnable(int)
+-> decltype(void(static_cast(nullptr)), true_type{});
+template 
+auto test_returnable(...) -> false_type;
+
+template 
+auto test_implicitly_convertible(int)
+-> decltype(void(declval()(declval())), true_type{});
+template 
+auto test_implicitly_convertible(...) -> false_type;
+
+}  // namespace detail
+
+template 
+struct is_convertible
+: integral_constant(0))::value &&
+ decltype(detail::test_implicitly_convertible(
+ 0))::value) ||
+(is_void::value && is_void::value)> {};
+
+template 
+inline constexpr bool is_convertible_v = is_convertible::value;
+
+template 
+using void_t = void;
+
+template 
+struct is_constructible_ : false_type {};
+
+template 
+struct is_constructible_()...))>, T, Args...>
+: true_type {};
+
+template 
+using is_constructible = is_constructible_, T, Args...>;
+
+template 
+inline constexpr bool is_constructible_v = is_constructible::value;
+
+template 
+struct __uncvref {
+  typedef typename remove_cv::type>::type type;
+};
+
+template 
+using __uncvref_t = typename __uncvref<_Tp>::type;
+
+template 
+using _BoolConstant = integral_constant;
+
+template 
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+template 
+using _IsNotSame = _BoolConstant;
+
+template 
+struct _MetaBase;
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Tp;
+  template  class _FirstFn, template  class,
+class... _Args>
+  using _SelectApplyImpl = _FirstFn<_Args...>;
+  template 
+  using _FirstImpl = _First;
+  template 
+  using _SecondImpl = _Second;
+  template 
+  using _OrImpl =
+  typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+  template _OrImpl<_First, _Rest...>;
+};
+
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Up;
+  template  class, template  class _SecondFn,
+class... _Args>
+  using _SelectApplyImpl = _SecondFn<_Args...>;
+  template 
+  using _OrImpl = _Result;
+};
+
+template 
+using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+template 
+using _Or = typename _MetaBase::template _OrImpl;
+
+template 
+using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+template 
+using __expand_to_true = true_type;
+template 
+__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+template 
+false_type __and_helper(...);
+template 
+using _And = decltype(__and_helper<_Pred...>(0));
+
+struct __check_tuple_constructor_fail {
+  static constexpr bool __enable_explicit_default() { return false; }
+  static constexpr bool __enable_implicit_default() { return false; }
+  template 
+  static constexpr bool __enable_explicit() {
+return false;
+  }
+  template 
+  static constexpr bool __enable_implicit() {
+return false;
+  }
+};
+
 } // namespace std
 
-#endif // TYPE_TRAITS_

[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-15 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h:146
+  std::vector>
+  Actions;

xazax.hun wrote:
> Nit: looks like we need to repeat the action type. Should we restore the 
> using above?
It's not the same. The one above is a template - it accepts an arbitrary `Node` 
instead of a `Stmt`.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:118
+/// function will be 2.
+int countOptionalWrappers(const ASTContext &ASTCtx, QualType Type) {
+  if (!IsOptionalType(Type))

xazax.hun wrote:
> Nit: some of these functions are static and some not. Should we have one big 
> anonymous namespace instead?
We already have an anonymous namespace so I'll make the functions inside 
non-static.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121602

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


[PATCH] D121602: [clang][dataflow] Model the behavior of non-standard optional constructors

2022-03-15 Thread Stanislav Gatev 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 rG092a530ca187: [clang][dataflow] Model the behavior of 
non-standard optional constructors (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121602

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -31,8 +31,8 @@
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char StdTypeTraitsHeader[] = R"(
-#ifndef TYPE_TRAITS_H
-#define TYPE_TRAITS_H
+#ifndef STD_TYPE_TRAITS_H
+#define STD_TYPE_TRAITS_H
 
 namespace std {
 
@@ -127,6 +127,9 @@
   typedef T type;
 };
 
+template 
+using remove_cv_t = typename remove_cv::type;
+
 template 
 struct decay {
  private:
@@ -139,9 +142,196 @@
typename remove_cv::type>::type>::type type;
 };
 
+template 
+struct enable_if {};
+
+template 
+struct enable_if {
+  typedef T type;
+};
+
+template 
+using enable_if_t = typename enable_if::type;
+
+template 
+struct is_same : false_type {};
+
+template 
+struct is_same : true_type {};
+
+template 
+struct is_void : is_same::type> {};
+
+namespace detail {
+
+template 
+auto try_add_rvalue_reference(int) -> type_identity;
+template 
+auto try_add_rvalue_reference(...) -> type_identity;
+
+}  // namespace detail
+
+template 
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {
+};
+
+template 
+typename add_rvalue_reference::type declval() noexcept;
+
+namespace detail {
+
+template 
+auto test_returnable(int)
+-> decltype(void(static_cast(nullptr)), true_type{});
+template 
+auto test_returnable(...) -> false_type;
+
+template 
+auto test_implicitly_convertible(int)
+-> decltype(void(declval()(declval())), true_type{});
+template 
+auto test_implicitly_convertible(...) -> false_type;
+
+}  // namespace detail
+
+template 
+struct is_convertible
+: integral_constant(0))::value &&
+ decltype(detail::test_implicitly_convertible(
+ 0))::value) ||
+(is_void::value && is_void::value)> {};
+
+template 
+inline constexpr bool is_convertible_v = is_convertible::value;
+
+template 
+using void_t = void;
+
+template 
+struct is_constructible_ : false_type {};
+
+template 
+struct is_constructible_()...))>, T, Args...>
+: true_type {};
+
+template 
+using is_constructible = is_constructible_, T, Args...>;
+
+template 
+inline constexpr bool is_constructible_v = is_constructible::value;
+
+template 
+struct __uncvref {
+  typedef typename remove_cv::type>::type type;
+};
+
+template 
+using __uncvref_t = typename __uncvref<_Tp>::type;
+
+template 
+using _BoolConstant = integral_constant;
+
+template 
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+
+template 
+using _IsNotSame = _BoolConstant;
+
+template 
+struct _MetaBase;
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Tp;
+  template  class _FirstFn, template  class,
+class... _Args>
+  using _SelectApplyImpl = _FirstFn<_Args...>;
+  template 
+  using _FirstImpl = _First;
+  template 
+  using _SecondImpl = _Second;
+  template 
+  using _OrImpl =
+  typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::
+  template _OrImpl<_First, _Rest...>;
+};
+
+template <>
+struct _MetaBase {
+  template 
+  using _SelectImpl = _Up;
+  template  class, template  class _SecondFn,
+class... _Args>
+  using _SelectApplyImpl = _SecondFn<_Args...>;
+  template 
+  using _OrImpl = _Result;
+};
+
+template 
+using _If = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>;
+
+template 
+using _Or = typename _MetaBase::template _OrImpl;
+
+template 
+using __enable_if_t = typename enable_if<_Bp, _Tp>::type;
+
+template 
+using __expand_to_true = true_type;
+template 
+__expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
+template 
+false_type __and_helper(...);
+template 
+using _And = decltype(__and_helper<_Pred...>(0));
+
+struct __check_tuple_constructor_fail {
+  static constexpr bool __enable_explicit_default() { return false; }
+  static constexpr bool __enable_implicit_default() { return false; }
+  template 
+  static constexpr bool __enable_explicit() {
+return false;
+  }
+  template 
+ 

[PATCH] D121197: [clang][dataflow] Add analysis that detects unsafe accesses to optionals

2022-03-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added a comment.

In D121197#3385669 , @Szelethus wrote:

> Seems like all new files are missing the header blurb about the licence.

Thanks for spotting that! I'll prepare a patch to fix it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121197

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


[PATCH] D121796: [clang][dataflow] Add an API for dataflow "models" -- reusable analysis components.

2022-03-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:148-149
+/// b) Models should focus on _modeling_ a particular aspect of program
+///semantics -- for example, a type and its related functions, and should 
be
+///composable with other models over the same lattice.
+///

Do we want to compose models that have different lattice types? Do we want to 
have models with no lattices that only use `Environment`? If we don't know this 
yet, I suggest replacing this with a FIXME to explore model composability at a 
later point when we have answers to these questions.



Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:153
+///the analysis.
+template 
+class DataflowModel : public Environment::ValueModel {

`LatticeT` for consistency with the code above.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121796

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


[PATCH] D121863: [clang][dataflow] Model the behavior of non-standard optional assignment

2022-03-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Model nullopt, value, and conversion assignment operators.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121863

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -30,13 +30,28 @@
 using ::testing::UnorderedElementsAre;
 
 // FIXME: Move header definitions in separate file(s).
+static constexpr char CSDtdDefHeader[] = R"(
+#ifndef CSTDDEF_H
+#define CSTDDEF_H
+
+namespace std {
+
+typedef decltype(sizeof(char)) size_t;
+
+using nullptr_t = decltype(nullptr);
+
+} // namespace std
+
+#endif // CSTDDEF_H
+)";
+
 static constexpr char StdTypeTraitsHeader[] = R"(
 #ifndef STD_TYPE_TRAITS_H
 #define STD_TYPE_TRAITS_H
 
-namespace std {
+#include "cstddef.h"
 
-typedef decltype(sizeof(char)) size_t;
+namespace std {
 
 template 
 struct integral_constant {
@@ -287,6 +302,9 @@
 template 
 using _And = decltype(__and_helper<_Pred...>(0));
 
+template 
+struct _Not : _BoolConstant {};
+
 struct __check_tuple_constructor_fail {
   static constexpr bool __enable_explicit_default() { return false; }
   static constexpr bool __enable_implicit_default() { return false; }
@@ -300,6 +318,150 @@
   }
 };
 
+template 
+struct __select_2nd {
+  typedef _Tp type;
+};
+template 
+typename __select_2nd() = declval<_Arg>())),
+  true_type>::type
+__is_assignable_test(int);
+template 
+false_type __is_assignable_test(...);
+template ::value || is_void<_Arg>::value>
+struct __is_assignable_imp
+: public decltype((__is_assignable_test<_Tp, _Arg>(0))) {};
+template 
+struct __is_assignable_imp<_Tp, _Arg, true> : public false_type {};
+template 
+struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {};
+
+template 
+struct __libcpp_is_integral : public false_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>// NOLINTNEXTLINE
+struct __libcpp_is_integral : public true_type {};
+template 
+struct is_integral
+: public __libcpp_is_integral::type> {};
+
+template 
+struct __libcpp_is_floating_point : public false_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template 
+struct is_floating_point
+: public __libcpp_is_floating_point::type> {};
+
+template 
+struct is_arithmetic
+: public integral_constant::value ||
+ is_floating_point<_Tp>::value> {};
+
+template 
+struct __libcpp_is_pointer : public false_type {};
+template 
+struct __libcpp_is_pointer<_Tp*> : public true_type {};
+template 
+struct is_pointer : public __libcpp_is_pointer::type> {
+};
+
+template 
+struct __libcpp_is_member_pointer : public false_type {};
+template 
+struct __libcpp_is_member_pointer<_Tp _Up::*> : public true_type {};
+template 
+struct is_member_pointer
+: public __libcpp_is_member_pointer::type> {};
+
+template 
+struct __libcpp_union : public false_type {};
+template 
+struct is_union : public __libcpp_union::type> {};
+
+template 
+struct is_reference : false_type {};
+template 
+struct is_reference : true_type {};
+template 
+struct is_reference : true_type {};
+
+template 
+inline constexpr bool is_reference_v = is_reference::value;
+
+struct __two {
+  char __lx[2];
+};
+
+namespace __is_class_imp {
+template 
+char __test(int _Tp::*);
+template 
+__two __test(...);
+}  // namespace __is_class_imp
+template 
+struct is_class
+: public integral_constant(0)) == 1 &&
+ 

[PATCH] D121863: [clang][dataflow] Model the behavior of non-standard optional assignment

2022-03-17 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 416132.
sgatev marked 3 inline comments as done.
sgatev added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121863

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -30,13 +30,28 @@
 using ::testing::UnorderedElementsAre;
 
 // FIXME: Move header definitions in separate file(s).
+static constexpr char CSDtdDefHeader[] = R"(
+#ifndef CSTDDEF_H
+#define CSTDDEF_H
+
+namespace std {
+
+typedef decltype(sizeof(char)) size_t;
+
+using nullptr_t = decltype(nullptr);
+
+} // namespace std
+
+#endif // CSTDDEF_H
+)";
+
 static constexpr char StdTypeTraitsHeader[] = R"(
 #ifndef STD_TYPE_TRAITS_H
 #define STD_TYPE_TRAITS_H
 
-namespace std {
+#include "cstddef.h"
 
-typedef decltype(sizeof(char)) size_t;
+namespace std {
 
 template 
 struct integral_constant {
@@ -287,6 +302,9 @@
 template 
 using _And = decltype(__and_helper<_Pred...>(0));
 
+template 
+struct _Not : _BoolConstant {};
+
 struct __check_tuple_constructor_fail {
   static constexpr bool __enable_explicit_default() { return false; }
   static constexpr bool __enable_implicit_default() { return false; }
@@ -300,6 +318,150 @@
   }
 };
 
+template 
+struct __select_2nd {
+  typedef _Tp type;
+};
+template 
+typename __select_2nd() = declval<_Arg>())),
+  true_type>::type
+__is_assignable_test(int);
+template 
+false_type __is_assignable_test(...);
+template ::value || is_void<_Arg>::value>
+struct __is_assignable_imp
+: public decltype((__is_assignable_test<_Tp, _Arg>(0))) {};
+template 
+struct __is_assignable_imp<_Tp, _Arg, true> : public false_type {};
+template 
+struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {};
+
+template 
+struct __libcpp_is_integral : public false_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>// NOLINTNEXTLINE
+struct __libcpp_is_integral : public true_type {};
+template 
+struct is_integral
+: public __libcpp_is_integral::type> {};
+
+template 
+struct __libcpp_is_floating_point : public false_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template 
+struct is_floating_point
+: public __libcpp_is_floating_point::type> {};
+
+template 
+struct is_arithmetic
+: public integral_constant::value ||
+ is_floating_point<_Tp>::value> {};
+
+template 
+struct __libcpp_is_pointer : public false_type {};
+template 
+struct __libcpp_is_pointer<_Tp*> : public true_type {};
+template 
+struct is_pointer : public __libcpp_is_pointer::type> {
+};
+
+template 
+struct __libcpp_is_member_pointer : public false_type {};
+template 
+struct __libcpp_is_member_pointer<_Tp _Up::*> : public true_type {};
+template 
+struct is_member_pointer
+: public __libcpp_is_member_pointer::type> {};
+
+template 
+struct __libcpp_union : public false_type {};
+template 
+struct is_union : public __libcpp_union::type> {};
+
+template 
+struct is_reference : false_type {};
+template 
+struct is_reference : true_type {};
+template 
+struct is_reference : true_type {};
+
+template 
+inline constexpr bool is_reference_v = is_reference::value;
+
+struct __two {
+  char __lx[2];
+};
+
+namespace __is_class_imp {
+template 
+char __test(int _Tp::*);
+template 
+__two __test(...);
+}  // namespace __is_c

[PATCH] D121863: [clang][dataflow] Model the behavior of non-standard optional assignment

2022-03-17 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:81
 
+auto isOptionalValueOrConversionAssignment() {
+  return cxxOperatorCallExpr(

xazax.hun wrote:
> While really like the convenience matchers will give us building data flow 
> analyses, I wonder whether a lot of duplicated work is happening in the 
> background. E.g. will we end up string comparing the class name of the parent 
> of the method in the matcher built by `optionalClass` whenever we process an 
> overloaded `operator=`?
> 
> In a handwritten implementation we would only do this once, store the address 
> of the canonical declaration somewhere and subsequent checks would only look 
> up the canonical declaration of the called method and do a pointer 
> comparison. 
> 
> In case this matcher approach is not that efficient, I wonder if it would be 
> possible to come up with some APIs where the matching is only done once and 
> subsequent transfer functions would only use the cached pointers to 
> declarations/types. In case the matchers are already doing something smart in 
> the background feel free to ignore this comment. 
That's a great point! Unfortunately, I'm not familiar with the implementation 
of matchers so I'll need to take a closer look/ask around to understand if such 
an optimization is already in place. Let me take a note of this for now. I 
suggest revising the APIs once we know more about the internals of matchers.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121863

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


[PATCH] D121863: [clang][dataflow] Model the behavior of non-standard optional assignment

2022-03-17 Thread Stanislav Gatev via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb000b7705ad8: [clang][dataflow] Model the behavior of 
non-standard optional assignment (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121863

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -30,13 +30,28 @@
 using ::testing::UnorderedElementsAre;
 
 // FIXME: Move header definitions in separate file(s).
+static constexpr char CSDtdDefHeader[] = R"(
+#ifndef CSTDDEF_H
+#define CSTDDEF_H
+
+namespace std {
+
+typedef decltype(sizeof(char)) size_t;
+
+using nullptr_t = decltype(nullptr);
+
+} // namespace std
+
+#endif // CSTDDEF_H
+)";
+
 static constexpr char StdTypeTraitsHeader[] = R"(
 #ifndef STD_TYPE_TRAITS_H
 #define STD_TYPE_TRAITS_H
 
-namespace std {
+#include "cstddef.h"
 
-typedef decltype(sizeof(char)) size_t;
+namespace std {
 
 template 
 struct integral_constant {
@@ -287,6 +302,9 @@
 template 
 using _And = decltype(__and_helper<_Pred...>(0));
 
+template 
+struct _Not : _BoolConstant {};
+
 struct __check_tuple_constructor_fail {
   static constexpr bool __enable_explicit_default() { return false; }
   static constexpr bool __enable_implicit_default() { return false; }
@@ -300,6 +318,150 @@
   }
 };
 
+template 
+struct __select_2nd {
+  typedef _Tp type;
+};
+template 
+typename __select_2nd() = declval<_Arg>())),
+  true_type>::type
+__is_assignable_test(int);
+template 
+false_type __is_assignable_test(...);
+template ::value || is_void<_Arg>::value>
+struct __is_assignable_imp
+: public decltype((__is_assignable_test<_Tp, _Arg>(0))) {};
+template 
+struct __is_assignable_imp<_Tp, _Arg, true> : public false_type {};
+template 
+struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {};
+
+template 
+struct __libcpp_is_integral : public false_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>
+struct __libcpp_is_integral : public true_type {};  // NOLINT
+template <>// NOLINTNEXTLINE
+struct __libcpp_is_integral : public true_type {};
+template 
+struct is_integral
+: public __libcpp_is_integral::type> {};
+
+template 
+struct __libcpp_is_floating_point : public false_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template <>
+struct __libcpp_is_floating_point : public true_type {};
+template 
+struct is_floating_point
+: public __libcpp_is_floating_point::type> {};
+
+template 
+struct is_arithmetic
+: public integral_constant::value ||
+ is_floating_point<_Tp>::value> {};
+
+template 
+struct __libcpp_is_pointer : public false_type {};
+template 
+struct __libcpp_is_pointer<_Tp*> : public true_type {};
+template 
+struct is_pointer : public __libcpp_is_pointer::type> {
+};
+
+template 
+struct __libcpp_is_member_pointer : public false_type {};
+template 
+struct __libcpp_is_member_pointer<_Tp _Up::*> : public true_type {};
+template 
+struct is_member_pointer
+: public __libcpp_is_member_pointer::type> {};
+
+template 
+struct __libcpp_union : public false_type {};
+template 
+struct is_union : public __libcpp_union::type> {};
+
+template 
+struct is_reference : false_type {};
+template 
+struct is_reference : true_type {};
+template 
+struct is_reference : true_type {};
+
+template 
+inline constexpr bool is_reference_v = is_reference::value;
+
+struct __two {
+  char __lx[2];
+};
+
+namespace __is_class_imp {
+template 
+char _

[PATCH] D121797: [clang][dataflow] Add modeling of Chromium's CHECK functionality

2022-03-18 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h:15
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"

This is unnecessary.



Comment at: clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp:49-55
+  if (const auto *Call = dyn_cast(Stmt))
+if (const auto *M = dyn_cast(Call->getDirectCallee()))
+  if (M->isStatic() && isCheckLikeMethod(CheckDecls, *M)) {
+// Logically, mark this branch as unreachable.
+Env.addToFlowCondition(Env.getBoolLiteralValue(false));
+return true;
+  }





Comment at: clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp:51
+if (const auto *M = dyn_cast(Call->getDirectCallee()))
+  if (M->isStatic() && isCheckLikeMethod(CheckDecls, *M)) {
+// Logically, mark this branch as unreachable.

Shouldn't this be part of `isCheckLikeMethod`?



Comment at: clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp:52
+  if (M->isStatic() && isCheckLikeMethod(CheckDecls, *M)) {
+// Logically, mark this branch as unreachable.
+Env.addToFlowCondition(Env.getBoolLiteralValue(false));





Comment at: clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp:57
+  return false;
+}
+} // namespace dataflow





Comment at: clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp:90
+
+static constexpr char BadChromiumCheckHeader[] = R"(
+namespace other {

Perhaps "Incorrect" instead of "Bad" and comment on what makes it incorrect?



Comment at: 
clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp:133
+  void runDataflow(llvm::StringRef Code, Matcher Match,
+   LangStandard::Kind Std = LangStandard::lang_cxx17) {
+const tooling::FileContentMappings FileContents = {

We're not testing with other standards so remove this?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D121797

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


[PATCH] D122121: [clang][dataflow] Add action caching support to MatchSwitch

2022-03-21 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Enable default caching of actionsin `MatchSwitch` so that for each
unique statement matchers are invoked at most once.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122121

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
@@ -100,19 +100,26 @@
 }
 
 class TestAnalysis : public DataflowAnalysis {
+  bool CacheMatchSwitchActions;
   MatchSwitch> TransferSwitch;
 
 public:
+  TestAnalysis(ASTContext &ASTCtx, bool CacheMatchSwitchActions)
+  : DataflowAnalysis(ASTCtx),
+CacheMatchSwitchActions(CacheMatchSwitchActions) {}
+
   explicit TestAnalysis(ASTContext &Context)
   : DataflowAnalysis(Context) {
 using namespace ast_matchers;
+MatchSwitchBuildOptions BuildOptions;
+BuildOptions.CacheActions = CacheMatchSwitchActions;
 TransferSwitch =
 MatchSwitchBuilder>()
 .CaseOf(declRefExpr(to(varDecl(hasName("X",
  TransferSetTrue)
 .CaseOf(callExpr(callee(functionDecl(hasName("Foo",
   TransferSetFalse)
-.Build();
+.Build(std::move(BuildOptions));
   }
 
   static BooleanLattice initialElement() { return BooleanLattice::bottom(); }
@@ -123,7 +130,7 @@
   }
 };
 
-class MatchSwitchTest : public ::testing::Test {
+class MatchSwitchTest : public ::testing::TestWithParam {
 protected:
   template 
   void RunDataflow(llvm::StringRef Code, Matcher Expectations) {
@@ -141,7 +148,10 @@
   }
 };
 
-TEST_F(MatchSwitchTest, JustX) {
+INSTANTIATE_TEST_SUITE_P(MatchSwitchTestInst, MatchSwitchTest,
+ ::testing::Bool());
+
+TEST_P(MatchSwitchTest, JustX) {
   std::string Code = R"(
 void fun() {
   int X = 1;
@@ -153,7 +163,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(true);
 }
 
-TEST_F(MatchSwitchTest, JustFoo) {
+TEST_P(MatchSwitchTest, JustFoo) {
   std::string Code = R"(
 void Foo();
 void fun() {
@@ -165,7 +175,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(false);
 }
 
-TEST_F(MatchSwitchTest, XThenFoo) {
+TEST_P(MatchSwitchTest, XThenFoo) {
   std::string Code = R"(
 void Foo();
 void fun() {
@@ -179,7 +189,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(false);
 }
 
-TEST_F(MatchSwitchTest, FooThenX) {
+TEST_P(MatchSwitchTest, FooThenX) {
   std::string Code = R"(
 void Foo();
 void fun() {
@@ -193,7 +203,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(true);
 }
 
-TEST_F(MatchSwitchTest, Neither) {
+TEST_P(MatchSwitchTest, Neither) {
   std::string Code = R"(
 void Bar();
 void fun(bool b) {
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -284,9 +284,6 @@
 }
 
 auto buildTransferMatchSwitch() {
-  // FIXME: Evaluate the efficiency of matchers. If using matchers results in a
-  // lot of duplicated work (e.g. string comparisons), consider providing APIs
-  // that avoid it through memoization.
   return MatchSwitchBuilder()
   // Attach a symbolic "has_value" state to optional values that we see for
   // the first time.
Index: clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
===
--- clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
+++ clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
@@ -25,7 +25,9 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
 #include 
 #include 
@@ -49,6 +51,16 @@
 template 
 using MatchSwitch = std::function;
 
+/// Options that determine the behavior of a `MatchSwitchBuilder` instance.
+struct MatchSwitchBuildOptions {
+  /// If true, caches the action of a match for a given statement. As a result,
+  /// matchers will be invoked at most once for each unique statement.
+  ///
+  /// Note: This assumes that all invocations of `MatchSwitch

[PATCH] D122129: [clang][dataflow] Model the behavior of optional and std swap

2022-03-21 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
Herald added a project: All.
sgatev requested review of this revision.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122129

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -507,6 +507,9 @@
 template 
 constexpr remove_reference_t&& move(T&& x);
 
+template 
+void swap(T& a, T& b) noexcept;
+
 } // namespace std
 
 #endif // UTILITY_H
@@ -718,6 +721,8 @@
 
   constexpr explicit operator bool() const noexcept;
   using __base::has_value;
+
+  constexpr void swap(optional& __opt) noexcept;
 };
 
 template 
@@ -938,6 +943,8 @@
 
   constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
+
+  void swap(optional& rhs) noexcept;
 };
 
 template 
@@ -1129,6 +1136,8 @@
 
   constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
+
+  void swap(Optional& other);
 };
 
 template 
@@ -1911,10 +1920,93 @@
   UnorderedElementsAre(Pair("check", "unsafe: input.cc:6:7")));
 }
 
+TEST_P(UncheckedOptionalAccessTest, OptionalSwap) {
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  opt1.swap(opt2);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  opt2.swap(opt1);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+}
+
+TEST_P(UncheckedOptionalAccessTest, StdSwap) {
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  std::swap(opt1, opt2);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  std::swap(opt2, opt1);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+}
+
 // FIXME: Add support for:
 // - constructors (copy, move)
 // - assignment operators (default, copy, move)
-// - swap
 // - invalidation (passing optional by non-const reference/pointer)
 // - `value_or(nullptr) != nullptr`, `value_or(0) != 0`, `value_or("").empty()`
 // - nested `optional` values
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -107,6 +107,12 @@
  hasArgument(1, hasNulloptType()));
 }
 
+auto isStdSwapCall() {
+  return callExpr(callee(functionDecl(hasName("std::swap"))),
+  argumentCountIs(2), hasArgument(0, hasOptionalType()),
+  hasArgument(1, hasOptionalType()));
+}
+
 /// Creates a symbolic value for an `optional` value using `HasValueVal` as the
 /// symbolic value of its "has_value" property.
 StructValue &createOptionalValue(Environment &Env, BoolValue &HasValueVal) {
@@ -283,6 +289,50 @@
   transferAssignment(E, State.Env.getBoolLiteralValue(false), State);
 }
 
+void transferSwap(const StorageLocation &OptionalLoc1,
+  const StorageLocation &OptionalLoc2,
+  LatticeTransferState &State) {
+  auto *OptionalVal1 = State.Env.getValue(OptionalLoc1);
+  assert(OptionalVal1 != nullptr);
+
+  auto *OptionalVal2 = State.Env.getValue(Op

[PATCH] D122121: [clang][dataflow] Add action caching support to MatchSwitch

2022-03-21 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 416906.
sgatev added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122121

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
@@ -100,19 +100,26 @@
 }
 
 class TestAnalysis : public DataflowAnalysis {
+  bool CacheMatchSwitchActions;
   MatchSwitch> TransferSwitch;
 
 public:
+  TestAnalysis(ASTContext &ASTCtx, bool CacheMatchSwitchActions)
+  : DataflowAnalysis(ASTCtx),
+CacheMatchSwitchActions(CacheMatchSwitchActions) {}
+
   explicit TestAnalysis(ASTContext &Context)
   : DataflowAnalysis(Context) {
 using namespace ast_matchers;
+MatchSwitchBuildOptions BuildOptions;
+BuildOptions.CacheActions = CacheMatchSwitchActions;
 TransferSwitch =
 MatchSwitchBuilder>()
 .CaseOf(declRefExpr(to(varDecl(hasName("X",
  TransferSetTrue)
 .CaseOf(callExpr(callee(functionDecl(hasName("Foo",
   TransferSetFalse)
-.Build();
+.Build(std::move(BuildOptions));
   }
 
   static BooleanLattice initialElement() { return BooleanLattice::bottom(); }
@@ -123,7 +130,7 @@
   }
 };
 
-class MatchSwitchTest : public ::testing::Test {
+class MatchSwitchTest : public ::testing::TestWithParam {
 protected:
   template 
   void RunDataflow(llvm::StringRef Code, Matcher Expectations) {
@@ -141,7 +148,10 @@
   }
 };
 
-TEST_F(MatchSwitchTest, JustX) {
+INSTANTIATE_TEST_SUITE_P(MatchSwitchTestInst, MatchSwitchTest,
+ ::testing::Bool());
+
+TEST_P(MatchSwitchTest, JustX) {
   std::string Code = R"(
 void fun() {
   int X = 1;
@@ -153,7 +163,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(true);
 }
 
-TEST_F(MatchSwitchTest, JustFoo) {
+TEST_P(MatchSwitchTest, JustFoo) {
   std::string Code = R"(
 void Foo();
 void fun() {
@@ -165,7 +175,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(false);
 }
 
-TEST_F(MatchSwitchTest, XThenFoo) {
+TEST_P(MatchSwitchTest, XThenFoo) {
   std::string Code = R"(
 void Foo();
 void fun() {
@@ -179,7 +189,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(false);
 }
 
-TEST_F(MatchSwitchTest, FooThenX) {
+TEST_P(MatchSwitchTest, FooThenX) {
   std::string Code = R"(
 void Foo();
 void fun() {
@@ -193,7 +203,7 @@
   UnorderedElementsAre(Pair("p", Holds(BooleanLattice(true);
 }
 
-TEST_F(MatchSwitchTest, Neither) {
+TEST_P(MatchSwitchTest, Neither) {
   std::string Code = R"(
 void Bar();
 void fun(bool b) {
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -284,9 +284,6 @@
 }
 
 auto buildTransferMatchSwitch() {
-  // FIXME: Evaluate the efficiency of matchers. If using matchers results in a
-  // lot of duplicated work (e.g. string comparisons), consider providing APIs
-  // that avoid it through memoization.
   return MatchSwitchBuilder()
   // Attach a symbolic "has_value" state to optional values that we see for
   // the first time.
Index: clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
===
--- clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
+++ clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
@@ -25,7 +25,9 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
 #include 
 #include 
@@ -49,6 +51,16 @@
 template 
 using MatchSwitch = std::function;
 
+/// Options that determine the behavior of a `MatchSwitchBuilder` instance.
+struct MatchSwitchBuildOptions {
+  /// If true, caches the action of a match for a given statement. As a result,
+  /// matchers will be invoked at most once for each unique statement.
+  ///
+  /// Note: This assumes that all invocations of `MatchSwitch` for a given
+  /// `Stmt` use the same `ASTContext`.
+  bool CacheActions = true;
+};
+
 /// Collects cases of a "match switch": a collection of matchers paired with
 /// callbacks, which together define a s

[PATCH] D122121: [clang][dataflow] Add action caching support to MatchSwitch

2022-03-21 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev marked an inline comment as done.
sgatev added a comment.

In D122121#3396022 , @ymandel wrote:

> What is the motivation for stashing the results of a match on a statement? Do 
> we expect to encounter the same statement often?

The matcher is evaluated for each fixpoint iteration so I expect that we'll 
encounter the same statement as many times as there are iterations over the 
same basic block. Does that make sense?

> I thought the concern was more specific to re-matching particular types, like 
> `std::optional`. For that, we could lazily store the declaration nodes (like 
> we do in 
> https://github.com/llvm/llvm-project/blob/main/clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp
>  with `CheckDecls`).  But, I'm less clear on the impact of storing the result 
> of the match itself.

I was thinking that maybe we can split the problem in two:

1. duplicated work across `matchDynamic` calls, and
2. duplicated work within a single `matchDynamic` call.

This patch addresses 1. as I see it as responsibility of `MatchSwitch`. Your 
comment seems to be about 2., if I'm reading it correctly. Do you think it's 
possible and makes sense to solve it in the AST matcher framework? Would that 
address your concerns?




Comment at: clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h:159
+  static std::function
+  BuildMatcherForStmt(const ast_matchers::internal::DynTypedMatcher &Matcher,
+  const std::vector &Actions, const Stmt &Stmt,

ymandel wrote:
> What is this function doing?  Please add a comment. Also, I don't understand 
> how it compiles -- the return type is `std::function` but it 
> returns a lambda of type `(State &S) -> std::function`?
The outer lambda was a leftover. I removed it and added a comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122121

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


[PATCH] D122129: [clang][dataflow] Model the behavior of optional and std swap

2022-03-21 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 416953.
sgatev added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122129

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -507,6 +507,9 @@
 template 
 constexpr remove_reference_t&& move(T&& x);
 
+template 
+void swap(T& a, T& b) noexcept;
+
 } // namespace std
 
 #endif // UTILITY_H
@@ -718,6 +721,8 @@
 
   constexpr explicit operator bool() const noexcept;
   using __base::has_value;
+
+  constexpr void swap(optional& __opt) noexcept;
 };
 
 template 
@@ -938,6 +943,8 @@
 
   constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
+
+  void swap(optional& rhs) noexcept;
 };
 
 template 
@@ -1129,6 +1136,8 @@
 
   constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
+
+  void swap(Optional& other);
 };
 
 template 
@@ -1911,10 +1920,93 @@
   UnorderedElementsAre(Pair("check", "unsafe: input.cc:6:7")));
 }
 
+TEST_P(UncheckedOptionalAccessTest, OptionalSwap) {
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  opt1.swap(opt2);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  opt2.swap(opt1);
+
+  opt1.value();
+  /*[[check-3]]*/
+
+  opt2.value();
+  /*[[check-4]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-3", "safe"),
+   Pair("check-4", "unsafe: input.cc:13:7")));
+}
+
+TEST_P(UncheckedOptionalAccessTest, StdSwap) {
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  std::swap(opt1, opt2);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  std::swap(opt2, opt1);
+
+  opt1.value();
+  /*[[check-3]]*/
+
+  opt2.value();
+  /*[[check-4]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-3", "safe"),
+   Pair("check-4", "unsafe: input.cc:13:7")));
+}
+
 // FIXME: Add support for:
 // - constructors (copy, move)
 // - assignment operators (default, copy, move)
-// - swap
 // - invalidation (passing optional by non-const reference/pointer)
 // - `value_or(nullptr) != nullptr`, `value_or(0) != 0`, `value_or("").empty()`
 // - nested `optional` values
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -107,6 +107,12 @@
  hasArgument(1, hasNulloptType()));
 }
 
+auto isStdSwapCall() {
+  return callExpr(callee(functionDecl(hasName("std::swap"))),
+  argumentCountIs(2), hasArgument(0, hasOptionalType()),
+  hasArgument(1, hasOptionalType()));
+}
+
 /// Creates a symbolic value for an `optional` value using `HasValueVal` as the
 /// symbolic value of its "has_value" property.
 StructValue &createOptionalValue(Environment &Env, BoolValue &HasValueVal) {
@@ -283,6 +289,50 @@
   transferAssignment(E, State.Env.getBoolLiteralValue(false), State);
 }
 
+void transferSwap(const StorageLocation &OptionalLoc1,
+  const StorageLocation &OptionalLoc2,
+  LatticeTransferState &State) {
+  auto *OptionalVal1 = State.Env.getValue(OptionalLoc1);
+  assert(OptionalVal1 != nullptr);
+
+  auto *OptionalVal2 = State.Env.getValue(OptionalLoc2);
+  assert(OptionalVal2 != nullptr);
+
+  State.Env.setValue(OptionalLoc1, *

[PATCH] D122129: [clang][dataflow] Model the behavior of optional and std swap

2022-03-22 Thread Stanislav Gatev via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2ddd57ae1ec4: [clang][dataflow] Model the behavior of 
optional and std swap (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122129

Files:
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -507,6 +507,9 @@
 template 
 constexpr remove_reference_t&& move(T&& x);
 
+template 
+void swap(T& a, T& b) noexcept;
+
 } // namespace std
 
 #endif // UTILITY_H
@@ -718,6 +721,8 @@
 
   constexpr explicit operator bool() const noexcept;
   using __base::has_value;
+
+  constexpr void swap(optional& __opt) noexcept;
 };
 
 template 
@@ -938,6 +943,8 @@
 
   constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
+
+  void swap(optional& rhs) noexcept;
 };
 
 template 
@@ -1129,6 +1136,8 @@
 
   constexpr explicit operator bool() const noexcept;
   constexpr bool has_value() const noexcept;
+
+  void swap(Optional& other);
 };
 
 template 
@@ -1911,10 +1920,93 @@
   UnorderedElementsAre(Pair("check", "unsafe: input.cc:6:7")));
 }
 
+TEST_P(UncheckedOptionalAccessTest, OptionalSwap) {
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  opt1.swap(opt2);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  opt2.swap(opt1);
+
+  opt1.value();
+  /*[[check-3]]*/
+
+  opt2.value();
+  /*[[check-4]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-3", "safe"),
+   Pair("check-4", "unsafe: input.cc:13:7")));
+}
+
+TEST_P(UncheckedOptionalAccessTest, StdSwap) {
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  std::swap(opt1, opt2);
+
+  opt1.value();
+  /*[[check-1]]*/
+
+  opt2.value();
+  /*[[check-2]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-1", "safe"),
+   Pair("check-2", "unsafe: input.cc:13:7")));
+
+  ExpectLatticeChecksFor(
+  R"(
+#include "unchecked_optional_access_test.h"
+
+void target() {
+  $ns::$optional opt1 = $ns::nullopt;
+  $ns::$optional opt2 = 3;
+
+  std::swap(opt2, opt1);
+
+  opt1.value();
+  /*[[check-3]]*/
+
+  opt2.value();
+  /*[[check-4]]*/
+}
+  )",
+  UnorderedElementsAre(Pair("check-3", "safe"),
+   Pair("check-4", "unsafe: input.cc:13:7")));
+}
+
 // FIXME: Add support for:
 // - constructors (copy, move)
 // - assignment operators (default, copy, move)
-// - swap
 // - invalidation (passing optional by non-const reference/pointer)
 // - `value_or(nullptr) != nullptr`, `value_or(0) != 0`, `value_or("").empty()`
 // - nested `optional` values
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -107,6 +107,12 @@
  hasArgument(1, hasNulloptType()));
 }
 
+auto isStdSwapCall() {
+  return callExpr(callee(functionDecl(hasName("std::swap"))),
+  argumentCountIs(2), hasArgument(0, hasOptionalType()),
+  hasArgument(1, hasOptionalType()));
+}
+
 /// Creates a symbolic value for an `optional` value using `HasValueVal` as the
 /// symbolic value of its "has_value" property.
 StructValue &createOptionalValue(Environment &Env, BoolValue &HasValueVal) {
@@ -283,6 +289,50 @@
   transferAssignment(E, State.Env.getBoolLiteralValue(false), State);
 }
 
+void transferSwap(const StorageLocation &OptionalLoc1,
+  const StorageLocation &OptionalLoc2,
+  LatticeTransferState &State) {
+  auto *OptionalVal1 = State.Env.getValue(OptionalLoc1);
+  assert(OptionalVal1 != nullptr);
+
+  auto *OptionalVal2 = State.

[PATCH] D122143: [clang][dataflow] Add support for disabling warnings on smart pointers.

2022-03-22 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.
This revision is now accepted and ready to land.



Comment at: 
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h:31
+struct UncheckedOptionalAccessModelOptions {
+  /// Ignore optionals reachable by derefencing a smart pointer (other than
+  /// optional itself). The analysis does not track smart-pointer pointees, so

Can you clarify what "smart pointer" refers to? It's not only standard types 
like `unique_ptr`, `shared_ptr`, and `weak_ptr`, right?



Comment at: 
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h:32
+  /// Ignore optionals reachable by derefencing a smart pointer (other than
+  /// optional itself). The analysis does not track smart-pointer pointees, so
+  /// it can't identify when optionals resulting from dereferencing such





Comment at: 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp:1923-1927
+template 
+struct unique_ptr {
+  T& operator*() &;
+  T* operator->();
+};

Let's add this to a `memory.h` header.



Comment at: 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp:1929
+
+struct Member {
+  $ns::$optional opt;

Why `Member`? I suggest either using one of the generic names that we use above 
or maybe something more descriptive.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122143

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


[PATCH] D122231: [clang][dataflow] Add support for `value_or` in a comparison.

2022-03-23 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:119
+  auto NonEmptyStringOptional = unaryOperator(
+  hasOperatorName("!"),
+  hasUnaryOperand(cxxMemberCallExpr(

Why handle negation here? Would it work for `if (opt.value_or("").empty()) { 
... } else { opt.value(); }`?



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:148
+anyOf(ComparesToSame(cxxNullPtrLiteralExpr()),
+  
ComparesToSame(integerLiteral(equals(0)));
+}

Why `0`? How about `opt_p->value_or(21) != 21`?



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:480
 
+  // opt.value_or(X) != X, !opt.value_or("").empty():
+  .CaseOf(

Extreme nit for consistency with all comments above.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:482
+  .CaseOf(
+  isValueOrCondition("ValueOrCall"),
+  [](const clang::Expr *E, const MatchFinder::MatchResult &Result,

Why not hard-code this in the `isValueOrCondition` matcher?



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:483
+  isValueOrCondition("ValueOrCall"),
+  [](const clang::Expr *E, const MatchFinder::MatchResult &Result,
+ LatticeTransferState &State) {

The `clang` namespace can be removed. Same comment for other instances in the 
patch.



Comment at: 
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp:485
+ LatticeTransferState &State) {
+transferOptionalValueOrCall(
+E,

Why not pass `transferOptionalValueOrCall` as argument instead of wrapping it 
in a lambda? The function can take the "ValueOrCall" node from the 
`MatchResult`.



Comment at: 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp:1722
+  if (opt.value_or(nullptr) != nullptr) {
+return *opt;
+/*[[check-ptrs-1]]*/

Is the `return` important? I think having `void` return type would be simpler. 
Same comment for the cases below.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122231

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


[PATCH] D123961: [clang][dataflow] Do not crash on missing `Value` for struct-typed variable init.

2022-04-19 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:184-186
-  // FIXME: The initializer expression must always be assigned a value.
-  // Replace this with an assert when we have sufficient coverage of
-  // language features.

The patch makes sense to me in the current state, but it's unclear why is this 
not something that we'd like to do in the long term.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123961

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


[PATCH] D123858: [clang][dataflow] Ensure well-formed flow conditions.

2022-04-19 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: 
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp:112-113
 cast_or_null(Env.getValue(Cond, SkipPast::Reference));
-if (Val == nullptr)
-  return;
+// Value merging depends on flow conditions from different environments
+// being mutually exclusive. So, we need *some* value for the condition
+// expression, even if just an atom.

What does it mean for flow conditions to be mutually exclusive? Why is this a 
requirement?



Comment at: 
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp:123-136
+  } else if (auto *CondVal = cast_or_null(
+ Env.getValue(Cond, SkipPast::None))) {
+Env.setValue(CondVal->getPointeeLoc(), *Val);
+  } else {
+QualType PointeeType = Type->castAs()->getPointeeType();
+StorageLocation &PointeeLoc = Env.createStorageLocation(PointeeType);
+Env.setValue(PointeeLoc, *Val);

Let's also add tests for these two paths.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123858

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


[PATCH] D123961: [clang][dataflow] Do not crash on missing `Value` for struct-typed variable init.

2022-04-19 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:184-186
-  // FIXME: The initializer expression must always be assigned a value.
-  // Replace this with an assert when we have sufficient coverage of
-  // language features.

xazax.hun wrote:
> ymandel wrote:
> > sgatev wrote:
> > > The patch makes sense to me in the current state, but it's unclear why is 
> > > this not something that we'd like to do in the long term.
> > Because of uninterpreted fields. If we consider those a temporary fix, then 
> > I agree about the long term. I'd thought those were here to stay.  That 
> > said, if we find a way to either interperet fields lazily or only interpret 
> > those needed in the current function scope, we may be able to avoid 
> > uninterpreted expressions.
> > 
> > This also begs the question as to why we insist on initializing the 
> > variable. Arguably, if the expresssion is uninterpreted, so should be the 
> > variable. So, we should at least explain why we're distinguishing. Thoughts 
> > on my adding a comment to that effect?
> >Because of uninterpreted fields.
> 
> Could you elaborate on this? Do you mean fields being uninterpreted due to 
> hitting a depth limit or being recursive? Or is this something else?
Not initializing the variable in such cases also makes sense to me. I'd very 
much appreciate a comment. I suggest also keeping the FIXME as interpreting 
fields lazily (and thus relying that all fields that are accessed are 
initialized) is still an option.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123961

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


[PATCH] D123858: [clang][dataflow] Ensure well-formed flow conditions.

2022-04-20 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:884
+//
+// Note: currently, abstract function calls are uninterpreted, so the test
+// exercises this case. If and when we change that, this test will not add to

What does "abstract" mean here? Perhaps "arbitrary"?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123858

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


[PATCH] D119447: [clang][dataflow] Include terminator statements in buildStmtToBasicBlockMap

2022-02-10 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
sgatev requested review of this revision.
Herald added a project: clang.

This will be necessary later when we add support for evaluating logic
expressions such as && and ||.

This is part of the implementation of the dataflow analysis framework.
See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119447

Files:
  clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp


Index: clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -38,6 +38,8 @@
 
   StmtToBlock[Stmt.getValue().getStmt()] = Block;
 }
+if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
+  StmtToBlock[TerminatorStmt] = Block;
   }
   return StmtToBlock;
 }


Index: clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -38,6 +38,8 @@
 
   StmtToBlock[Stmt.getValue().getStmt()] = Block;
 }
+if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
+  StmtToBlock[TerminatorStmt] = Block;
   }
   return StmtToBlock;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119447: [clang][dataflow] Include terminator statements in buildStmtToBasicBlockMap

2022-02-11 Thread Stanislav Gatev 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 rG87c32be023d2: [clang][dataflow] Include terminator 
statements in buildStmtToBasicBlockMap (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119447

Files:
  clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp


Index: clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -38,6 +38,8 @@
 
   StmtToBlock[Stmt.getValue().getStmt()] = Block;
 }
+if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
+  StmtToBlock[TerminatorStmt] = Block;
   }
   return StmtToBlock;
 }


Index: clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
===
--- clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -38,6 +38,8 @@
 
   StmtToBlock[Stmt.getValue().getStmt()] = Block;
 }
+if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
+  StmtToBlock[TerminatorStmt] = Block;
   }
   return StmtToBlock;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119953: [clang][dataflow] Add transfer functions for logical and, or, not.

2022-02-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev created this revision.
sgatev added reviewers: ymandel, xazax.hun, gribozavr2.
Herald added subscribers: tschuett, steakhal, rnkovacs.
sgatev requested review of this revision.
Herald added a project: clang.

This is part of the implementation of the dataflow analysis framework.
See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119953

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/Value.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.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
@@ -387,7 +387,8 @@
 Code, "target",
 [this](ASTContext &Context, Environment &Env) {
   assert(HasValueTop == nullptr);
-  HasValueTop = &Env.takeOwnership(std::make_unique());
+  HasValueTop =
+  &Env.takeOwnership(std::make_unique());
   return OptionalIntAnalysis(Context, *HasValueTop);
 },
 [&Match](
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2006,6 +2006,42 @@
   // [[p]]
 }
   )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal = dyn_cast_or_null(
+Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal = dyn_cast_or_null(
+Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
+EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+  });
+}
+
+TEST_F(TransferTest, AssignFromBoolConjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = Foo && Bar;
+  // [[p]]
+}
+  )";
   runDataflow(
   Code, [](llvm::ArrayRef<
std::pair>>
@@ -2028,9 +2064,93 @@
 dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
 ASSERT_THAT(BarVal, NotNull());
 
-EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
-EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+const auto *BazVal = dyn_cast_or_null(
+Env.getValue(*BazDecl, SkipPast::None));
+ASSERT_THAT(BazVal, NotNull());
+
+EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
   });
 }
 
+TEST_F(TransferTest, AssignFromBoolDisjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = Foo || Bar;
+  // [[p]]
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal =
+dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal =
+dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(B

[PATCH] D119953: [clang][dataflow] Add transfer functions for logical and, or, not.

2022-02-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 409296.
sgatev added a comment.

Remove unnecessary IgnoreParens calls.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119953

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/Value.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.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
@@ -387,7 +387,8 @@
 Code, "target",
 [this](ASTContext &Context, Environment &Env) {
   assert(HasValueTop == nullptr);
-  HasValueTop = &Env.takeOwnership(std::make_unique());
+  HasValueTop =
+  &Env.takeOwnership(std::make_unique());
   return OptionalIntAnalysis(Context, *HasValueTop);
 },
 [&Match](
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2006,6 +2006,42 @@
   // [[p]]
 }
   )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal = dyn_cast_or_null(
+Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal = dyn_cast_or_null(
+Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
+EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+  });
+}
+
+TEST_F(TransferTest, AssignFromBoolConjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = (Foo) && (Bar);
+  // [[p]]
+}
+  )";
   runDataflow(
   Code, [](llvm::ArrayRef<
std::pair>>
@@ -2028,9 +2064,93 @@
 dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
 ASSERT_THAT(BarVal, NotNull());
 
-EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
-EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+const auto *BazVal = dyn_cast_or_null(
+Env.getValue(*BazDecl, SkipPast::None));
+ASSERT_THAT(BazVal, NotNull());
+
+EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
   });
 }
 
+TEST_F(TransferTest, AssignFromBoolDisjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = (Foo) || (Bar);
+  // [[p]]
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal =
+dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal =
+dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+const auto *BazVal = dyn_cast_or_null(
+Env.getValue(*BazDecl, SkipPast::None));
+ASSERT_THAT(BazVal, NotNull());
+
+   

[PATCH] D119953: [clang][dataflow] Add transfer functions for logical and, or, not.

2022-02-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev updated this revision to Diff 409330.
sgatev marked 5 inline comments as done.
sgatev added a comment.

Address reviewers' comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119953

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/Value.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.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
@@ -387,7 +387,8 @@
 Code, "target",
 [this](ASTContext &Context, Environment &Env) {
   assert(HasValueTop == nullptr);
-  HasValueTop = &Env.takeOwnership(std::make_unique());
+  HasValueTop =
+  &Env.takeOwnership(std::make_unique());
   return OptionalIntAnalysis(Context, *HasValueTop);
 },
 [&Match](
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2006,6 +2006,42 @@
   // [[p]]
 }
   )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal = dyn_cast_or_null(
+Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal = dyn_cast_or_null(
+Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
+EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+  });
+}
+
+TEST_F(TransferTest, AssignFromBoolConjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = (Foo) && (Bar);
+  // [[p]]
+}
+  )";
   runDataflow(
   Code, [](llvm::ArrayRef<
std::pair>>
@@ -2028,9 +2064,93 @@
 dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
 ASSERT_THAT(BarVal, NotNull());
 
-EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
-EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+const auto *BazVal = dyn_cast_or_null(
+Env.getValue(*BazDecl, SkipPast::None));
+ASSERT_THAT(BazVal, NotNull());
+
+EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
   });
 }
 
+TEST_F(TransferTest, AssignFromBoolDisjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = (Foo) || (Bar);
+  // [[p]]
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal =
+dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal =
+dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+const auto *BazVal = dyn_cast_or_null(
+Env.getValue(*BazDecl, SkipPast::None));
+ASSERT_

[PATCH] D119953: [clang][dataflow] Add transfer functions for logical and, or, not.

2022-02-16 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev added inline comments.



Comment at: clang/include/clang/Analysis/FlowSensitive/Value.h:39
+// represent conjunctions, disjunctions, and negations.
+AtomicBoolValue,
+BoolConjunctionValue,

xazax.hun wrote:
> Do we need `Value` in the `Kind` if we are already in the class `Value`?
> Also, do we need prefix `Conjunction` and `Disjunction` with `Bool`? Will 
> there be a `Conjunction` with other types?
We don't need the `Value` suffix in `Kind` and we don't expect other 
conjunctions, disjunctions, and negations for now so I simplified the names.



Comment at: clang/include/clang/Analysis/FlowSensitive/Value.h:79
+/// Models a boolean conjunction.
+class BoolConjunctionValue : public BoolValue {
+public:

xazax.hun wrote:
> Do we want to have a separate class for every binary/unary operator? 
> Alternatively, we could follow what the AST is already doing. Having 
> BinaryOperator and UnaryOperator classes with a kind. I guess the current 
> approach is not too bad for booleans, but if we want to support all integer 
> operators as well in the future I wonder if that would end up with too much 
> boilerplate.
Great point! Right now we have this subdivision only for booleans and, as you 
mentioned, it's not too bad. Definitely worth considering the alternative 
design going forward. If you don't mind, I suggest starting with the current 
setup, with a FIXME to remind us of the other option. I'd be happy to revisit 
this after the next couple of patches.



Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:98
+
+  // Create fresh values for unknown boolean expressions.
+  if (LHSVal == nullptr)

xazax.hun wrote:
> I wonder if this `GetOrCreateFresh` style operations will be common enough to 
> have a helper for this purpose.
That, or we can ensure that each expression gets assigned a value. Added a 
FIXME for now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119953

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


[PATCH] D119953: [clang][dataflow] Add transfer functions for logical and, or, not.

2022-02-17 Thread Stanislav Gatev 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 rGdd4dde8d39a9: [clang][dataflow] Add transfer functions for 
logical and, or, not. (authored by sgatev).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119953

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
  clang/include/clang/Analysis/FlowSensitive/Transfer.h
  clang/include/clang/Analysis/FlowSensitive/Value.h
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.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
@@ -387,7 +387,8 @@
 Code, "target",
 [this](ASTContext &Context, Environment &Env) {
   assert(HasValueTop == nullptr);
-  HasValueTop = &Env.takeOwnership(std::make_unique());
+  HasValueTop =
+  &Env.takeOwnership(std::make_unique());
   return OptionalIntAnalysis(Context, *HasValueTop);
 },
 [&Match](
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2006,6 +2006,42 @@
   // [[p]]
 }
   )";
+  runDataflow(Code,
+  [](llvm::ArrayRef<
+ std::pair>>
+ Results,
+ ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal = dyn_cast_or_null(
+Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal = dyn_cast_or_null(
+Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
+EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+  });
+}
+
+TEST_F(TransferTest, AssignFromBoolConjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = (Foo) && (Bar);
+  // [[p]]
+}
+  )";
   runDataflow(
   Code, [](llvm::ArrayRef<
std::pair>>
@@ -2028,9 +2064,93 @@
 dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
 ASSERT_THAT(BarVal, NotNull());
 
-EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
-EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+const auto *BazVal = dyn_cast_or_null(
+Env.getValue(*BazDecl, SkipPast::None));
+ASSERT_THAT(BazVal, NotNull());
+
+EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
+EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
   });
 }
 
+TEST_F(TransferTest, AssignFromBoolDisjunction) {
+  std::string Code = R"(
+void target() {
+  bool Foo = true;
+  bool Bar = true;
+  bool Baz = (Foo) || (Bar);
+  // [[p]]
+}
+  )";
+  runDataflow(
+  Code, [](llvm::ArrayRef<
+   std::pair>>
+   Results,
+   ASTContext &ASTCtx) {
+ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+const Environment &Env = Results[0].second.Env;
+
+const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ASSERT_THAT(FooDecl, NotNull());
+
+const auto *FooVal =
+dyn_cast_or_null(Env.getValue(*FooDecl, SkipPast::None));
+ASSERT_THAT(FooVal, NotNull());
+
+const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ASSERT_THAT(BarDecl, NotNull());
+
+const auto *BarVal =
+dyn_cast_or_null(Env.getValue(*BarDecl, SkipPast::None));
+ASSERT_THAT(BarVal, NotNull());
+
+const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
+ASSERT_THAT(BazDecl, NotNull());
+
+ 

[PATCH] D124104: [clang][dataflow] Fix `Environment::join`'s handling of flow condition merging

2022-04-24 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:339-341
   // Move `LocToVal` so that `Environment::ValueModel::merge` can safely assign
   // values to storage locations while this code iterates over the current
   // assignments.

This comment is no longer relevant, right?



Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:299
 
+// Models an analysis that uses the flow conditions.
+class SpecialBoolAnalysis





Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:340-344
+if (!Type->isRecordType())
+  return false;
+const auto *Decl = Type->getAsCXXRecordDecl();
+if (Decl->getIdentifier() == nullptr || Decl->getName() != "SpecialBool")
+  return false;





Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:356
+
+return V1 == V2 ||
+   Env1.flowConditionImplies(*V1) == Env2.flowConditionImplies(*V2);

That's guaranteed to be false in `compareEquivalent`.



Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:364-368
+if (!Type->isRecordType())
+  return true;
+const auto *Decl = Type->getAsCXXRecordDecl();
+if (Decl->getIdentifier() == nullptr || Decl->getName() != "SpecialBool")
+  return true;





Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:414
+  void set();
+};
+void target(bool Cond) {





Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:422
+  } else {
+Foo.set();
+  }

Add `/*[[p3]]*/` after this statement and ensure that the value is implied in 
the "else" branch.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D124104

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


[PATCH] D124104: [clang][dataflow] Fix `Environment::join`'s handling of flow condition merging

2022-04-25 Thread Stanislav Gatev via Phabricator via cfe-commits
sgatev accepted this revision.
sgatev added inline comments.



Comment at: 
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:356
+
+return V1 == V2 ||
+   Env1.flowConditionImplies(*V1) == Env2.flowConditionImplies(*V2);

ymandel wrote:
> sgatev wrote:
> > That's guaranteed to be false in `compareEquivalent`.
> I thought just `Val1 == Val2` was guaranteed false? Also, I see that the 
> variable naming could be confusing, so I've renamed.
Right. I think I misread it. Having `IsSet1 == IsSet2` here makes sense to me. 
Though, if the test only needs the second part, I suggest removing this to 
simplify the setup.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D124104

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


  1   2   3   4   >