[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-19 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand closed https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-19 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/84499

>From 02381f2dbdcc569889ae55a2ca5d8698f74626d8 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH 1/2] [clang][dataflow] Refactor processing of terminator
 element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 126 +-
 1 file changed, 35 insertions(+), 91 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 721a11c2098530..be05ab5435e842 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -336,26 +273,33 @@ 

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-19 Thread via cfe-commits

https://github.com/martinboehme approved this pull request.

Thanks -- _so_ much better!

https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-18 Thread Yitzhak Mandelbaum via cfe-commits


@@ -337,26 +274,33 @@ computeBlockInputState(const CFGBlock , 
AnalysisContext ) {
 AC.BlockStates[Pred->getBlockID()];
 if (!MaybePredState)
   continue;
-
-if (AC.Analysis.builtinOptions()) {
-  if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
-// We have a terminator: we need to mutate an environment to describe
-// when the terminator is taken. Copy now.
+const TypeErasedDataflowAnalysisState  = *MaybePredState;
+
+if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {

ymand wrote:

Done

https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-18 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/84499

>From 3b20e1823753ab46e3e259d3d8c727dea91ce1d4 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH 1/2] [clang][dataflow] Refactor processing of terminator
 element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 126 +-
 1 file changed, 35 insertions(+), 91 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..2d745231fd0758 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -337,26 +274,33 @@ 

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-12 Thread via cfe-commits


@@ -337,26 +274,33 @@ computeBlockInputState(const CFGBlock , 
AnalysisContext ) {
 AC.BlockStates[Pred->getBlockID()];
 if (!MaybePredState)
   continue;
-
-if (AC.Analysis.builtinOptions()) {
-  if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
-// We have a terminator: we need to mutate an environment to describe
-// when the terminator is taken. Copy now.
+const TypeErasedDataflowAnalysisState  = *MaybePredState;
+
+if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {

martinboehme wrote:

To make this clearer, here's how the whole code block could be changed to make 
it (IMO) simpler (I can't do this as a suggested edit because I would have to 
include deleted lines in the block of code, and github doesn't allow me to do 
this):

```cxx
const Expr *TerminatorCond = 
getTerminatorCondition(Pred->getTerminatorStmt());
if (TerminatorCond == nullptr) {
  Builder.addUnowned(PredState);
  continue;
}

bool BranchVal = blockIndexInPredecessor(*Pred, Block) == 0;

// `transferBranch` may need to mutate the environment to describe the
// dynamic effect of the terminator for a given branch.  Copy now.
TypeErasedDataflowAnalysisState Copy = PredState.fork();
if (AC.Analysis.builtinOptions()) {
  auto *CondVal = Copy.Env.get(*TerminatorCond);
  // In transferCFGBlock(), we ensure that we always have a `Value`
  // for the terminator condition, so assert this. We consciously
  // assert ourselves instead of asserting via `cast()` so that we get
  // a more meaningful line number if the assertion fails.
  assert(CondVal != nullptr);
  BoolValue *AssertedVal =
  BranchVal ? CondVal : (*CondVal);
  Copy.Env.assume(AssertedVal->formula());
}
AC.Analysis.transferBranchTypeErased(BranchVal, TerminatorCond, 
Copy.Lattice,
 Copy.Env);
Builder.addOwned(std::move(Copy));
```

https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-12 Thread via cfe-commits


@@ -337,26 +274,33 @@ computeBlockInputState(const CFGBlock , 
AnalysisContext ) {
 AC.BlockStates[Pred->getBlockID()];
 if (!MaybePredState)
   continue;
-
-if (AC.Analysis.builtinOptions()) {
-  if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
-// We have a terminator: we need to mutate an environment to describe
-// when the terminator is taken. Copy now.
+const TypeErasedDataflowAnalysisState  = *MaybePredState;
+
+if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {

martinboehme wrote:

I'd suggest doing the shorter case first, so this longer case can be indented 
less:

```cxx
  const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt();
  if (PredTerminatorStmt == nullptr) {
Builder.addUnowned(PredState);
continue;
  }
```

Even better, introduce a short function `getTerminatorCondition()` that can 
handle a null argument:

```cxx
const Expr *getTerminatorCondition(const Stmt *TerminatorStmt) {
  if (TerminatorStmt == nullptr) return nullptr;
  return TerminatorVisitor().Visit(TerminatorStmt);
}
```

Then you can do this:

```cxx
  const Expr *TerminatorCond = 
getTerminatorCondition(Pred->getTerminatorStmt());
  if (TerminatorCond == nullptr) {
Builder.addUnowned(PredState);
continue;
  }
```

https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-12 Thread via cfe-commits


@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.

martinboehme wrote:

```suggestion
/// Extracts the terminator condition expression.
```

https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-12 Thread via cfe-commits


@@ -337,26 +274,33 @@ computeBlockInputState(const CFGBlock , 
AnalysisContext ) {
 AC.BlockStates[Pred->getBlockID()];
 if (!MaybePredState)
   continue;
-
-if (AC.Analysis.builtinOptions()) {
-  if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
-// We have a terminator: we need to mutate an environment to describe
-// when the terminator is taken. Copy now.
+const TypeErasedDataflowAnalysisState  = *MaybePredState;
+
+if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
+  bool BranchVal = blockIndexInPredecessor(*Pred, Block) == 0;

martinboehme wrote:

Move this down to the point where it's actually needed (this is included in the 
suggestion above).

https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-12 Thread via cfe-commits

https://github.com/martinboehme edited 
https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-12 Thread via cfe-commits

https://github.com/martinboehme requested changes to this pull request.


https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun approved this pull request.


https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/84499

>From 3b20e1823753ab46e3e259d3d8c727dea91ce1d4 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH] [clang][dataflow] Refactor processing of terminator element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 126 +-
 1 file changed, 35 insertions(+), 91 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..2d745231fd0758 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -337,26 +274,33 @@ 

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/84499

>From d1bedf3a9b1d0d4c2fbfc10509797b39eef3d592 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH] [clang][dataflow] Refactor processing of terminator element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 128 +-
 1 file changed, 36 insertions(+), 92 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..31682f93803003 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
-  }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
+return S->getLHS();
   }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -337,26 +274,33 @@ 

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/84499

>From b7887543320f8727545a7ce8e6d9e02b77604472 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH] [clang][dataflow] Refactor processing of terminator element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 128 +-
 1 file changed, 36 insertions(+), 92 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..e953271d54d30a 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
-  }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -337,26 +274,33 @@ 

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/84499

>From 81945389b60e95019ff916d356127119183e8198 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH] [clang][dataflow] Refactor processing of terminator element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 133 +-
 1 file changed, 39 insertions(+), 94 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..a1b73365b186b0 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
-  }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -337,26 +274,33 @@ 

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff cb6f657a70f7a8d6ecd4fcc2101550a7400f94a7 
210a2b83d3647c97ad4fc5eab9e0d9c68a5711a4 -- 
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 3acd6be874..c6522f1569 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -258,29 +258,29 @@ computeBlockInputState(const CFGBlock , 
AnalysisContext ) {
   continue;
 const TypeErasedDataflowAnalysisState  = *MaybePredState;
 
-  if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
-bool BranchVal = blockIndexInPredecessor(*Pred, Block) == 0;
-const Expr *Cond = TerminatorVisitor().Visit(PredTerminatorStmt);
-if (Cond != nullptr) {
-  // `transferBranch` may need to mutate the environment to describe 
the
-  // dynamic effect of the terminator for a given branch.  Copy now.
-  TypeErasedDataflowAnalysisState Copy = MaybePredState->fork();
-  if (AC.Analysis.builtinOptions()) {
-auto *CondVal = Copy.Env.get(*Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value`
-// for the terminator condition, so assert this. We consciously
-// assert ourselves instead of asserting via `cast()` so that we 
get
-// a more meaningful line number if the assertion fails.
-assert(CondVal != nullptr);
-BoolValue *AssertedVal =
-BranchVal ? CondVal : (*CondVal);
-Copy.Env.assume(AssertedVal->formula());
-  }
-  AC.Analysis.transferBranchTypeErased(BranchVal, Cond, Copy.Lattice,
-   Copy.Env);
-  Builder.addOwned(std::move(Copy));
-  continue;
+if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
+  bool BranchVal = blockIndexInPredecessor(*Pred, Block) == 0;
+  const Expr *Cond = TerminatorVisitor().Visit(PredTerminatorStmt);
+  if (Cond != nullptr) {
+// `transferBranch` may need to mutate the environment to describe the
+// dynamic effect of the terminator for a given branch.  Copy now.
+TypeErasedDataflowAnalysisState Copy = MaybePredState->fork();
+if (AC.Analysis.builtinOptions()) {
+  auto *CondVal = Copy.Env.get(*Cond);
+  // In transferCFGBlock(), we ensure that we always have a `Value`
+  // for the terminator condition, so assert this. We consciously
+  // assert ourselves instead of asserting via `cast()` so that we get
+  // a more meaningful line number if the assertion fails.
+  assert(CondVal != nullptr);
+  BoolValue *AssertedVal =
+  BranchVal ? CondVal : (*CondVal);
+  Copy.Env.assume(AssertedVal->formula());
 }
+AC.Analysis.transferBranchTypeErased(BranchVal, Cond, Copy.Lattice,
+ Copy.Env);
+Builder.addOwned(std::move(Copy));
+continue;
+  }
   }
   Builder.addUnowned(PredState);
   }

``




https://github.com/llvm/llvm-project/pull/84499
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-analysis

Author: Yitzhak Mandelbaum (ymand)


Changes

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.


---
Full diff: https://github.com/llvm/llvm-project/pull/84499.diff


1 Files Affected:

- (modified) clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
(+46-119) 


``diff
diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..3acd6be874a6b1 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-  ConditionValue = false;
-}
-
-Env.assume(Val->formula());
-return {, ConditionValue};
-  }
-
-  Environment 
-  int BlockSuccIdx;
 };
 
 /// Holds data structures required for running dataflow analysis.
@@ -221,7 +158,6 @@ class PrettyStackTraceCFGElement : public 
llvm::PrettyStackTraceEntry {
 // Avoids unneccesary copies of the environment.
 class JoinedStateBuilder {
  

[clang] [clang][dataflow] Refactor processing of terminator element (PR #84499)

2024-03-08 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand created https://github.com/llvm/llvm-project/pull/84499

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.


>From 210a2b83d3647c97ad4fc5eab9e0d9c68a5711a4 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum 
Date: Fri, 8 Mar 2024 15:19:14 +
Subject: [PATCH] [clang][dataflow] Refactor processing of terminator element

This patch vastly simplifies the code handling terminators, without changing any
behavior. Additionally, the simplification unblocks our ability to address a
(simple) FIXME in the code to invoke `transferBranch`, even when builtin options
are disabled.
---
 .../TypeErasedDataflowAnalysis.cpp| 165 +-
 1 file changed, 46 insertions(+), 119 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp 
b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 939247c047c66e..3acd6be874a6b1 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -11,7 +11,6 @@
 //
 
//===--===//
 
-#include 
 #include 
 #include 
 #include 
@@ -33,7 +32,6 @@
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 
@@ -64,88 +62,27 @@ static bool isBackedgeNode(const CFGBlock ) {
 
 namespace {
 
-// The return type of the visit functions in TerminatorVisitor. The first
-// element represents the terminator expression (that is the conditional
-// expression in case of a path split in the CFG). The second element
-// represents whether the condition was true or false.
-using TerminatorVisitorRetTy = std::pair;
-
-/// Extends the flow condition of an environment based on a terminator
-/// statement.
+/// Extracts the condition expression.
 class TerminatorVisitor
-: public ConstStmtVisitor {
+: public ConstStmtVisitor {
 public:
-  TerminatorVisitor(Environment , int BlockSuccIdx)
-  : Env(Env), BlockSuccIdx(BlockSuccIdx) {}
-
-  TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
-  }
-
-  TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) {
-auto *Cond = S->getCond();
-if (Cond != nullptr)
-  return extendFlowCondition(*Cond);
-return {nullptr, false};
-  }
-
-  TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) {
+  TerminatorVisitor() = default;
+  const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); }
+  const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); }
+  const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); }
+  const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); }
+  const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) {
 // Don't do anything special for CXXForRangeStmt, because the condition
 // (being implicitly generated) isn't visible from the loop body.
-return {nullptr, false};
+return nullptr;
   }
-
-  TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) {
+  const Expr *VisitBinaryOperator(const BinaryOperator *S) {
 assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
-auto *LHS = S->getLHS();
-assert(LHS != nullptr);
-return extendFlowCondition(*LHS);
+return S->getLHS();
   }
-
-  TerminatorVisitorRetTy
-  VisitConditionalOperator(const ConditionalOperator *S) {
-auto *Cond = S->getCond();
-assert(Cond != nullptr);
-return extendFlowCondition(*Cond);
+  const Expr *VisitConditionalOperator(const ConditionalOperator *S) {
+return S->getCond();
   }
-
-private:
-  TerminatorVisitorRetTy extendFlowCondition(const Expr ) {
-auto *Val = Env.get(Cond);
-// In transferCFGBlock(), we ensure that we always have a `Value` for the
-// terminator condition, so assert this.
-// We consciously assert ourselves instead of asserting via `cast()` so
-// that we get a more meaningful line number if the assertion fails.
-assert(Val != nullptr);
-
-bool ConditionValue = true;
-// The condition must be inverted for the successor that encompasses the
-// "else" branch, if such exists.
-if (BlockSuccIdx == 1) {
-  Val = (*Val);
-