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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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


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

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

- Merge branch 'main' into diagnose-api


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.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
@@ -11,9 +11,10 @@
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Error.h"
 #include "gmock/gmock.h"
@@ -26,8 +27,7 @@
 using namespace dataflow;
 using namespace test;
 
-using ::testing::Pair;
-using ::testing::UnorderedElementsAre;
+using ::testing::ContainerEq;
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char CSDtdDefHeader[] = R"(
@@ -1180,13 +1180,6 @@
 } // namespace base
 )";
 
-/// Converts `L` to string.
-static std::string ConvertToString(const SourceLocationsLattice &L,
-   const ASTContext &Ctx) {
-  return L.getSourceLocations().empty() ? "safe"
-: "unsafe: " + DebugString(L, Ctx);
-}
-
 /// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
 static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
   const std::string &Replacement) {
@@ -1207,18 +1200,14 @@
 class UncheckedOptionalAccessTest
 : public ::testing::TestWithParam {
 protected:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  LatticeChecksMatcher MatchesLatticeChecks) {
-ExpectLatticeChecksFor(SourceCode, ast_matchers::hasName("target"),
-   MatchesLatticeChecks);
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+ExpectDiagnosticsFor(SourceCode, ast_matchers::hasName("target"));
   }
 
 private:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  FuncDeclMatcher FuncMatcher,
-  LatticeChecksMatcher MatchesLatticeChecks) {
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode,
+FuncDeclMatcher FuncMatcher) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1245,29 +1234,51 @@
 )");
 const tooling::FileContentMappings FileContents(Headers.begin(),
 Headers.end());
-llvm::Error Error = checkDataflow(
-SourceCode, FuncMatcher,
-[](ASTContext &Ctx, Environment &) {
-  return UncheckedOptionalAccessModel(
-  Ctx, UncheckedOptionalAccessModelOptions{
-   /*IgnoreSmartPointerDereference=*/true});
-},
-[&MatchesLatticeChecks](
-llvm::ArrayRef>>
-CheckToLatticeMap,
-ASTContext &Ctx) {
-  // FIXME: Consider using a matcher instead of translating
-  // `CheckToLatticeMap` to `CheckToStringifiedLatticeMap`.
-  std::vector>
-  CheckToStringifiedLatticeMap;
-  for (const auto &E : CheckToLatticeMap) {
-CheckToStringifiedLatticeMap.emplace_back(
-E.first, ConvertToString(E.second.Lattice, Ctx));
-  }
-  EXPECT_THAT(CheckToStringifiedLatticeMap, MatchesLatticeChecks);
-},
-{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"}, FileContents);
+UncheckedOptionalAccessModelOptions Options{
+/*IgnoreSmartPointerDereference=*/true};
+llvm::Error Error =
+checkDataflowDiagnosis(
+SourceCode, FuncMatcher,
+[Options](ASTContext &Ctx, Environment &) {
+  return UncheckedOptionalAccessModel(Ctx, Options);
+},
+[Options](ASTContext &Ctx) {
+  UncheckedOptionalAccessDiagnosis Diagnosis(Ctx, Options);
+  return [Diagnosis = std::move(Diagnosis)](
+ const Stmt *Stmt,
+ const UncheckedOptionalAccessModel::Lattice &,
+ const Environment &Env) mutable {
+

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

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

- Bring back Diagnosis.h


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

Files:
  clang/docs/tools/clang-formatted-files.txt
  clang/include/clang/Analysis/FlowSensitive/Diagnosis.h
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.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
@@ -11,9 +11,10 @@
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Error.h"
 #include "gmock/gmock.h"
@@ -26,8 +27,7 @@
 using namespace dataflow;
 using namespace test;
 
-using ::testing::Pair;
-using ::testing::UnorderedElementsAre;
+using ::testing::ContainerEq;
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char CSDtdDefHeader[] = R"(
@@ -1180,13 +1180,6 @@
 } // namespace base
 )";
 
-/// Converts `L` to string.
-static std::string ConvertToString(const SourceLocationsLattice &L,
-   const ASTContext &Ctx) {
-  return L.getSourceLocations().empty() ? "safe"
-: "unsafe: " + DebugString(L, Ctx);
-}
-
 /// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
 static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
   const std::string &Replacement) {
@@ -1207,18 +1200,14 @@
 class UncheckedOptionalAccessTest
 : public ::testing::TestWithParam {
 protected:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  LatticeChecksMatcher MatchesLatticeChecks) {
-ExpectLatticeChecksFor(SourceCode, ast_matchers::hasName("target"),
-   MatchesLatticeChecks);
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+ExpectDiagnosticsFor(SourceCode, ast_matchers::hasName("target"));
   }
 
 private:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  FuncDeclMatcher FuncMatcher,
-  LatticeChecksMatcher MatchesLatticeChecks) {
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode,
+FuncDeclMatcher FuncMatcher) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1245,29 +1234,51 @@
 )");
 const tooling::FileContentMappings FileContents(Headers.begin(),
 Headers.end());
-llvm::Error Error = checkDataflow(
-SourceCode, FuncMatcher,
-[](ASTContext &Ctx, Environment &) {
-  return UncheckedOptionalAccessModel(
-  Ctx, UncheckedOptionalAccessModelOptions{
-   /*IgnoreSmartPointerDereference=*/true});
-},
-[&MatchesLatticeChecks](
-llvm::ArrayRef>>
-CheckToLatticeMap,
-ASTContext &Ctx) {
-  // FIXME: Consider using a matcher instead of translating
-  // `CheckToLatticeMap` to `CheckToStringifiedLatticeMap`.
-  std::vector>
-  CheckToStringifiedLatticeMap;
-  for (const auto &E : CheckToLatticeMap) {
-CheckToStringifiedLatticeMap.emplace_back(
-E.first, ConvertToString(E.second.Lattice, Ctx));
-  }
-  EXPECT_THAT(CheckToStringifiedLatticeMap, MatchesLatticeChecks);
-},
-{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"}, FileContents);
+UncheckedOptionalAccessModelOptions Options{
+/*IgnoreSmartPointerDereference=*/true};
+llvm::Error Error =
+checkDataflowDiagnosis(
+SourceCode, FuncMatcher,
+[Options](ASTContext &Ctx, Environment &) {
+  return UncheckedOptionalAccessModel(Ctx, Options);
+},
+[Options](ASTContext &Ctx) {
+  UncheckedOptionalAccessDiagnosis Diagnosis(Ctx, Options);
+  return [Diagnosis = std::move(Diagnosis)](
+ const Stmt *Stmt,
+ const UncheckedOptionalAccess

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

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

- Implement Gábor's suggestion
- Merge branch 'main' into diagnose-api


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  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
@@ -11,9 +11,11 @@
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Error.h"
 #include "gmock/gmock.h"
@@ -26,8 +28,7 @@
 using namespace dataflow;
 using namespace test;
 
-using ::testing::Pair;
-using ::testing::UnorderedElementsAre;
+using ::testing::ContainerEq;
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char CSDtdDefHeader[] = R"(
@@ -1180,13 +1181,6 @@
 } // namespace base
 )";
 
-/// Converts `L` to string.
-static std::string ConvertToString(const SourceLocationsLattice &L,
-   const ASTContext &Ctx) {
-  return L.getSourceLocations().empty() ? "safe"
-: "unsafe: " + DebugString(L, Ctx);
-}
-
 /// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
 static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
   const std::string &Replacement) {
@@ -1207,18 +1201,14 @@
 class UncheckedOptionalAccessTest
 : public ::testing::TestWithParam {
 protected:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  LatticeChecksMatcher MatchesLatticeChecks) {
-ExpectLatticeChecksFor(SourceCode, ast_matchers::hasName("target"),
-   MatchesLatticeChecks);
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+ExpectDiagnosticsFor(SourceCode, ast_matchers::hasName("target"));
   }
 
 private:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  FuncDeclMatcher FuncMatcher,
-  LatticeChecksMatcher MatchesLatticeChecks) {
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode,
+FuncDeclMatcher FuncMatcher) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1245,27 +1235,48 @@
 )");
 const tooling::FileContentMappings FileContents(Headers.begin(),
 Headers.end());
+UncheckedOptionalAccessModelOptions Options{
+/*IgnoreSmartPointerDereference=*/true};
+std::vector Diagnostics;
 llvm::Error Error = checkDataflow(
 SourceCode, FuncMatcher,
-[](ASTContext &Ctx, Environment &) {
-  return UncheckedOptionalAccessModel(
-  Ctx, UncheckedOptionalAccessModelOptions{
-   /*IgnoreSmartPointerDereference=*/true});
+[Options](ASTContext &Ctx, Environment &) {
+  return UncheckedOptionalAccessModel(Ctx, Options);
+},
+[Options, &Diagnostics](ASTContext &Ctx) {
+  UncheckedOptionalAccessDiagnosis Diagnosis(Ctx, Options);
+  return [&Diagnostics, Diagnosis = std::move(Diagnosis)](
+ const Stmt *Stmt,
+ const TypeErasedDataflowAnalysisState &State) mutable {
+auto StmtDiagnostics = Diagnosis.diagnose(Stmt, State.Env);
+std::move(StmtDiagnostics.begin(), StmtDiagnostics.end(),
+  std::back_inserter(Diagnostics));
+  };
 },
-[&MatchesLatticeChecks](
-llvm::ArrayRef>>
-CheckToLatticeMap,
-ASTContext &Ctx) {
-  // FIXME: Consider using a matcher instead of translating
-  // `CheckToLatticeMap` to `CheckToStringifiedLatticeMap`.
-  std::vector>
-  CheckToStringifiedLatticeMap;
-  for (const auto &E : C

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

2022-06-28 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 440702.
samestep added a comment.
Herald added a project: clang.

- Merge branch 'diagnose-api' into optional-check-diagnose
- Use the updated API


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128352

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h


Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -113,10 +113,21 @@
 template 
 llvm::Expected>>>
-runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
-const Environment &InitEnv) {
-  auto TypeErasedBlockStates =
-  runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv);
+runDataflowAnalysis(
+const ControlFlowContext &CFCtx, AnalysisT &Analysis,
+const Environment &InitEnv,
+std::function &)>
+PostVisitStmt = nullptr) {
+  auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
+  CFCtx, Analysis, InitEnv,
+  [&PostVisitStmt](const Stmt *Stmt,
+   const TypeErasedDataflowAnalysisState &State) {
+auto *Lattice =
+llvm::any_cast(&State.Lattice.Value);
+PostVisitStmt(Stmt, DataflowAnalysisState{
+*Lattice, State.Env});
+  });
   if (!TypeErasedBlockStates)
 return TypeErasedBlockStates.takeError();
 
Index: clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
@@ -32,12 +32,13 @@
 namespace bugprone {
 using ast_matchers::MatchFinder;
 using dataflow::SourceLocationsLattice;
+using dataflow::UncheckedOptionalAccessDiagnosis;
 using dataflow::UncheckedOptionalAccessModel;
 using llvm::Optional;
 
 static constexpr llvm::StringLiteral FuncID("fun");
 
-static Optional
+static Optional>
 analyzeFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx) {
   using dataflow::ControlFlowContext;
   using dataflow::DataflowAnalysisState;
@@ -52,23 +53,23 @@
   std::make_unique());
   dataflow::Environment Env(AnalysisContext, FuncDecl);
   UncheckedOptionalAccessModel Analysis(ASTCtx);
+  UncheckedOptionalAccessDiagnosis Diagnosis(ASTCtx);
+  std::vector Diagnostics;
   
Expected>>>
-  BlockToOutputState =
-  dataflow::runDataflowAnalysis(*Context, Analysis, Env);
+  BlockToOutputState = dataflow::runDataflowAnalysis(
+  *Context, Analysis, Env,
+  [&Diagnosis,
+   &Diagnostics](const Stmt *Stmt,
+ const DataflowAnalysisState
+ &State) mutable {
+auto StmtDiagnostics = Diagnosis.diagnose(Stmt, State.Env);
+std::move(StmtDiagnostics.begin(), StmtDiagnostics.end(),
+  std::back_inserter(Diagnostics));
+  });
   if (!BlockToOutputState)
 return llvm::None;
-  assert(Context->getCFG().getExit().getBlockID() < 
BlockToOutputState->size());
 
-  const Optional>
-  &ExitBlockState =
-  (*BlockToOutputState)[Context->getCFG().getExit().getBlockID()];
-  // `runDataflowAnalysis` doesn't guarantee that the exit block is visited;
-  // for example, when it is unreachable.
-  // FIXME: Diagnose violations even when the exit block is unreachable.
-  if (!ExitBlockState)
-return llvm::None;
-
-  return std::move(ExitBlockState->Lattice);
+  return Diagnostics;
 }
 
 void UncheckedOptionalAccessCheck::registerMatchers(MatchFinder *Finder) {
@@ -97,9 +98,9 @@
   if (FuncDecl->isTemplated())
 return;
 
-  if (Optional Errors =
+  if (Optional> Errors =
   analyzeFunction(*FuncDecl, *Result.Context))
-for (const SourceLocation &Loc : Errors->getSourceLocations())
+for (const SourceLocation &Loc : *Errors)
   diag(Loc, "unchecked access to optional value");
 }
 


Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -113,10 +113,21 @@
 template 
 llvm::Expected>>>
-runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
-const Environment &InitEnv) {
-  auto TypeErasedBlockStates =
-  runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv);
+runDataflowAnalysis(
+const ControlFlowContext &CFCtx, AnalysisT &Analysis,
+const Environment &InitEnv,
+std::function &)>
+PostVisitStmt = nullptr) {

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

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
samestep marked 9 inline comments as done.
samestep added a comment.

Fixed all the minor nits and responded to some comments.




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

sgatev wrote:
> 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.
Makes sense to me; should I do that in a followup?



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

sgatev wrote:
> Why is this a function that returns a function? Couldn't it be simply a void 
> function, like `VerifyResults`?
It needs to take in the `ASTContext`, and it needs to be able to close over 
state; see the one we pass from `UncheckedOptionalAccessModelTest.cpp`.



Comment at: clang/unittests/Analysis/FlowSensitive/TestingSupport.h:172-191
+std::vector> Results;
+for (const CFGBlock *Block : AnalysisResults.CFCtx.getCFG()) {
+  // Skip blocks that were not evaluated.
+  if (!AnalysisResults.BlockStates[Block->getBlockID()])
+continue;
+
+  transferBlock(

ymandel wrote:
> any chance that this could be folded into `MakePostVisitStmt`?
Looking into this now.



Comment at: 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp:2338
   //   if (opt1.has_value()) {
   // opt2.value();
   //   }

gribozavr2 wrote:
> 
I don't think this is correct, is it?


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] D127898: [clang][dataflow] Add API to separate analysis from diagnosis

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

- Merge branch 'main' into diagnose-api
- Fix minor nits


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  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
@@ -11,9 +11,11 @@
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Error.h"
 #include "gmock/gmock.h"
@@ -26,8 +28,7 @@
 using namespace dataflow;
 using namespace test;
 
-using ::testing::Pair;
-using ::testing::UnorderedElementsAre;
+using ::testing::ContainerEq;
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char CSDtdDefHeader[] = R"(
@@ -1180,13 +1181,6 @@
 } // namespace base
 )";
 
-/// Converts `L` to string.
-static std::string ConvertToString(const SourceLocationsLattice &L,
-   const ASTContext &Ctx) {
-  return L.getSourceLocations().empty() ? "safe"
-: "unsafe: " + DebugString(L, Ctx);
-}
-
 /// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
 static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
   const std::string &Replacement) {
@@ -1207,18 +1201,14 @@
 class UncheckedOptionalAccessTest
 : public ::testing::TestWithParam {
 protected:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  LatticeChecksMatcher MatchesLatticeChecks) {
-ExpectLatticeChecksFor(SourceCode, ast_matchers::hasName("target"),
-   MatchesLatticeChecks);
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+ExpectDiagnosticsFor(SourceCode, ast_matchers::hasName("target"));
   }
 
 private:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  FuncDeclMatcher FuncMatcher,
-  LatticeChecksMatcher MatchesLatticeChecks) {
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode,
+FuncDeclMatcher FuncMatcher) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1245,27 +1235,48 @@
 )");
 const tooling::FileContentMappings FileContents(Headers.begin(),
 Headers.end());
+UncheckedOptionalAccessModelOptions Options{
+/*IgnoreSmartPointerDereference=*/true};
+std::vector Diagnostics;
 llvm::Error Error = checkDataflow(
 SourceCode, FuncMatcher,
-[](ASTContext &Ctx, Environment &) {
-  return UncheckedOptionalAccessModel(
-  Ctx, UncheckedOptionalAccessModelOptions{
-   /*IgnoreSmartPointerDereference=*/true});
+[Options](ASTContext &Ctx, Environment &) {
+  return UncheckedOptionalAccessModel(Ctx, Options);
+},
+[Options, &Diagnostics](ASTContext &Ctx) {
+  return [&Diagnostics,
+  Diagnosis = UncheckedOptionalAccessDiagnoser(Ctx, Options)](
+ const Stmt *Stmt,
+ const TypeErasedDataflowAnalysisState &State) mutable {
+auto StmtDiagnostics = Diagnosis.diagnose(Stmt, State.Env);
+std::move(StmtDiagnostics.begin(), StmtDiagnostics.end(),
+  std::back_inserter(Diagnostics));
+  };
 },
-[&MatchesLatticeChecks](
-llvm::ArrayRef>>
-CheckToLatticeMap,
-ASTContext &Ctx) {
-  // FIXME: Consider using a matcher instead of translating
-  // `CheckToLatticeMap` to `CheckToStringifiedLatticeMap`.
-  std::vector>
-  CheckToStringifiedLatticeMap;
-  for (const auto &E : CheckToLatticeMap) {
-Check

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

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

- Tidy AnalysisData struct and PostVisitStmt param


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  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
@@ -11,9 +11,12 @@
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Error.h"
 #include "gmock/gmock.h"
@@ -26,8 +29,7 @@
 using namespace dataflow;
 using namespace test;
 
-using ::testing::Pair;
-using ::testing::UnorderedElementsAre;
+using ::testing::ContainerEq;
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char CSDtdDefHeader[] = R"(
@@ -1180,13 +1182,6 @@
 } // namespace base
 )";
 
-/// Converts `L` to string.
-static std::string ConvertToString(const SourceLocationsLattice &L,
-   const ASTContext &Ctx) {
-  return L.getSourceLocations().empty() ? "safe"
-: "unsafe: " + DebugString(L, Ctx);
-}
-
 /// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
 static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
   const std::string &Replacement) {
@@ -1207,18 +1202,14 @@
 class UncheckedOptionalAccessTest
 : public ::testing::TestWithParam {
 protected:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  LatticeChecksMatcher MatchesLatticeChecks) {
-ExpectLatticeChecksFor(SourceCode, ast_matchers::hasName("target"),
-   MatchesLatticeChecks);
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+ExpectDiagnosticsFor(SourceCode, ast_matchers::hasName("target"));
   }
 
 private:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  FuncDeclMatcher FuncMatcher,
-  LatticeChecksMatcher MatchesLatticeChecks) {
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode,
+FuncDeclMatcher FuncMatcher) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1245,27 +1236,44 @@
 )");
 const tooling::FileContentMappings FileContents(Headers.begin(),
 Headers.end());
+UncheckedOptionalAccessModelOptions Options{
+/*IgnoreSmartPointerDereference=*/true};
+std::vector Diagnostics;
 llvm::Error Error = checkDataflow(
 SourceCode, FuncMatcher,
-[](ASTContext &Ctx, Environment &) {
-  return UncheckedOptionalAccessModel(
-  Ctx, UncheckedOptionalAccessModelOptions{
-   /*IgnoreSmartPointerDereference=*/true});
+[Options](ASTContext &Ctx, Environment &) {
+  return UncheckedOptionalAccessModel(Ctx, Options);
+},
+[&Diagnostics, Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
+ASTContext &Ctx, const Stmt *Stmt,
+const TypeErasedDataflowAnalysisState &State) mutable {
+  auto StmtDiagnostics = Diagnoser.diagnose(Ctx, Stmt, State.Env);
+  llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
 },
-[&MatchesLatticeChecks](
-llvm::ArrayRef>>
-CheckToLatticeMap,
-ASTContext &Ctx) {
-  // FIXME: Consider using a matcher instead of translating
-  // `CheckToLatticeMap` to `CheckToStringifiedLatticeMap`.
-  std::vector>
-  CheckToStringifiedLatticeMap;
-  for (const auto &E : CheckToLatticeMap) {
-CheckToStringifiedLatticeMap.emplace_back(
-E.first, ConvertToString(E.second.Lattice, Ctx));
+[&Diagnosti

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

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
samestep marked an inline comment as done.
samestep 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});

sgatev wrote:
> 
I tried this but it doesn't seem to work; I get this error:

```
llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h:130:13:
 error: non-const lvalue reference to type 
'clang::dataflow::SourceLocationsLattice' cannot bind to a temporary of type 
'clang::dataflow::SourceLocationsLattice'
  auto &Lattice =
```


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] D128352: [clang][dataflow] Use diagnosis API in optional checker

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

- Merge branch 'diagnose-api' into optional-check-diagnose
- Update using review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128352

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h

Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -109,14 +109,33 @@
 /// dataflow analysis states that model the respective basic blocks. The
 /// returned vector, if any, will have the same size as the number of CFG
 /// blocks, with indices corresponding to basic block IDs. Returns an error if
-/// the dataflow analysis cannot be performed successfully.
+/// the dataflow analysis cannot be performed successfully. Otherwise, calls
+/// `PostVisitStmt` on each statement with the final analysis results at that
+/// program point.
 template 
 llvm::Expected>>>
-runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
-const Environment &InitEnv) {
-  auto TypeErasedBlockStates =
-  runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv);
+runDataflowAnalysis(
+const ControlFlowContext &CFCtx, AnalysisT &Analysis,
+const Environment &InitEnv,
+std::function &)>
+PostVisitStmt = nullptr) {
+  std::function
+  PostVisitStmtClosure = nullptr;
+  if (PostVisitStmt != nullptr) {
+PostVisitStmtClosure = [&PostVisitStmt](
+   const Stmt *Stmt,
+   const TypeErasedDataflowAnalysisState &State) {
+  auto *Lattice =
+  llvm::any_cast(&State.Lattice.Value);
+  PostVisitStmt(Stmt, DataflowAnalysisState{
+  *Lattice, State.Env});
+};
+  }
+
+  auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
+  CFCtx, Analysis, InitEnv, PostVisitStmtClosure);
   if (!TypeErasedBlockStates)
 return TypeErasedBlockStates.takeError();
 
Index: clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
@@ -23,6 +23,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/Any.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Error.h"
 #include 
 #include 
@@ -32,12 +33,13 @@
 namespace bugprone {
 using ast_matchers::MatchFinder;
 using dataflow::SourceLocationsLattice;
+using dataflow::UncheckedOptionalAccessDiagnoser;
 using dataflow::UncheckedOptionalAccessModel;
 using llvm::Optional;
 
 static constexpr llvm::StringLiteral FuncID("fun");
 
-static Optional
+static Optional>
 analyzeFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx) {
   using dataflow::ControlFlowContext;
   using dataflow::DataflowAnalysisState;
@@ -52,23 +54,22 @@
   std::make_unique());
   dataflow::Environment Env(AnalysisContext, FuncDecl);
   UncheckedOptionalAccessModel Analysis(ASTCtx);
+  UncheckedOptionalAccessDiagnoser Diagnoser;
+  std::vector Diagnostics;
   Expected>>>
-  BlockToOutputState =
-  dataflow::runDataflowAnalysis(*Context, Analysis, Env);
+  BlockToOutputState = dataflow::runDataflowAnalysis(
+  *Context, Analysis, Env,
+  [&ASTCtx, &Diagnoser,
+   &Diagnostics](const Stmt *Stmt,
+ const DataflowAnalysisState
+ &State) mutable {
+auto StmtDiagnostics = Diagnoser.diagnose(ASTCtx, Stmt, State.Env);
+llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
+  });
   if (!BlockToOutputState)
 return llvm::None;
-  assert(Context->getCFG().getExit().getBlockID() < BlockToOutputState->size());
 
-  const Optional>
-  &ExitBlockState =
-  (*BlockToOutputState)[Context->getCFG().getExit().getBlockID()];
-  // `runDataflowAnalysis` doesn't guarantee that the exit block is visited;
-  // for example, when it is unreachable.
-  // FIXME: Diagnose violations even when the exit block is unreachable.
-  if (!ExitBlockState)
-return llvm::None;
-
-  return std::move(ExitBlockState->Lattice);
+  return Diagnostics;
 }
 
 void UncheckedOptionalAccessCheck::registerMatchers(MatchFinder *Finder) {
@@ -97,9 +98,9 @@
   if (FuncDecl->isTemplated())
 return;
 
-  if (Optional Errors =
+  if (Optional> Errors =
   analyzeFunction(*FuncDecl, *Result.Context))
-for (const SourceLocation &Loc : Errors->getSourceLocations())
+for (const SourceLocation &Loc : *Errors)
   

[PATCH] D128356: [clang][dataflow] Use NoopLattice in optional model

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

- Merge branch 'optional-check-diagnose' into optional-model-noop-lattice


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128356

Files:
  clang/docs/tools/clang-formatted-files.txt
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h

Index: clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
@@ -18,25 +18,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include 
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 
 namespace clang {
 namespace dataflow {
 
-class NoopLattice {
-public:
-  bool operator==(const NoopLattice &) const { return true; }
-
-  LatticeJoinEffect join(const NoopLattice &) {
-return LatticeJoinEffect::Unchanged;
-  }
-};
-
-inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) {
-  return OS << "noop";
-}
-
 class NoopAnalysis : public DataflowAnalysis {
 public:
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -20,7 +20,7 @@
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
@@ -35,7 +35,7 @@
 namespace {
 
 using namespace ::clang::ast_matchers;
-using LatticeTransferState = TransferState;
+using LatticeTransferState = TransferState;
 
 DeclarationMatcher optionalClass() {
   return classTemplateSpecializationDecl(
@@ -312,18 +312,7 @@
   if (auto *Loc = maybeInitializeOptionalValueMember(
   UnwrapExpr->getType(), *OptionalVal, State.Env))
 State.Env.setStorageLocation(*UnwrapExpr, *Loc);
-
-auto *Prop = OptionalVal->getProperty("has_value");
-if (auto *HasValueVal = cast_or_null(Prop)) {
-  if (State.Env.flowConditionImplies(*HasValueVal))
-return;
-}
   }
-
-  // Record that this unwrap is *not* provably safe.
-  // FIXME: include either the name of the optional (if applicable) or a source
-  // range of the access for easier interpretation of the result.
-  State.Lattice.getSourceLocations().insert(ObjectExpr->getBeginLoc());
 }
 
 void transferMakeOptionalCall(const CallExpr *E,
@@ -716,12 +705,10 @@
 
 UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(
 ASTContext &Ctx, UncheckedOptionalAccessModelOptions Options)
-: DataflowAnalysis(
-  Ctx),
+: DataflowAnalysis(Ctx),
   TransferMatchSwitch(buildTransferMatchSwitch(Options)) {}
 
-void UncheckedOptionalAccessModel::transfer(const Stmt *S,
-SourceLocationsLattice &L,
+void UncheckedOptionalAccessModel::transfer(const Stmt *S, NoopLattice &L,
 Environment &Env) {
   LatticeTransferState State(L, Env);
   TransferMatchSwitch(*S, getASTContext(), State);
Index: clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
===
--- /dev/null
+++ clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
@@ -0,0 +1,41 @@
+//===-- NoopLattice.h ---*- C++ -*-===//
+//
+// 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
+//
+//===--===//
+//
+//  This file defines the lattice with exactly one element.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include 
+
+namespace clang {
+namespace dataflow {
+
+/// Trivial lattic

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

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG58fe7f9683a0: [clang][dataflow] Add API to separate analysis 
from diagnosis (authored by samestep).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127898

Files:
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  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
@@ -11,9 +11,12 @@
 #include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Error.h"
 #include "gmock/gmock.h"
@@ -26,8 +29,7 @@
 using namespace dataflow;
 using namespace test;
 
-using ::testing::Pair;
-using ::testing::UnorderedElementsAre;
+using ::testing::ContainerEq;
 
 // FIXME: Move header definitions in separate file(s).
 static constexpr char CSDtdDefHeader[] = R"(
@@ -1180,13 +1182,6 @@
 } // namespace base
 )";
 
-/// Converts `L` to string.
-static std::string ConvertToString(const SourceLocationsLattice &L,
-   const ASTContext &Ctx) {
-  return L.getSourceLocations().empty() ? "safe"
-: "unsafe: " + DebugString(L, Ctx);
-}
-
 /// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
 static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
   const std::string &Replacement) {
@@ -1207,18 +1202,14 @@
 class UncheckedOptionalAccessTest
 : public ::testing::TestWithParam {
 protected:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  LatticeChecksMatcher MatchesLatticeChecks) {
-ExpectLatticeChecksFor(SourceCode, ast_matchers::hasName("target"),
-   MatchesLatticeChecks);
+  void ExpectDiagnosticsFor(std::string SourceCode) {
+ExpectDiagnosticsFor(SourceCode, ast_matchers::hasName("target"));
   }
 
 private:
-  template 
-  void ExpectLatticeChecksFor(std::string SourceCode,
-  FuncDeclMatcher FuncMatcher,
-  LatticeChecksMatcher MatchesLatticeChecks) {
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode,
+FuncDeclMatcher FuncMatcher) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1245,27 +1236,44 @@
 )");
 const tooling::FileContentMappings FileContents(Headers.begin(),
 Headers.end());
+UncheckedOptionalAccessModelOptions Options{
+/*IgnoreSmartPointerDereference=*/true};
+std::vector Diagnostics;
 llvm::Error Error = checkDataflow(
 SourceCode, FuncMatcher,
-[](ASTContext &Ctx, Environment &) {
-  return UncheckedOptionalAccessModel(
-  Ctx, UncheckedOptionalAccessModelOptions{
-   /*IgnoreSmartPointerDereference=*/true});
+[Options](ASTContext &Ctx, Environment &) {
+  return UncheckedOptionalAccessModel(Ctx, Options);
+},
+[&Diagnostics, Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
+ASTContext &Ctx, const Stmt *Stmt,
+const TypeErasedDataflowAnalysisState &State) mutable {
+  auto StmtDiagnostics = Diagnoser.diagnose(Ctx, Stmt, State.Env);
+  llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
 },
-[&MatchesLatticeChecks](
-llvm::ArrayRef>>
-CheckToLatticeMap,
-ASTContext &Ctx) {
-  // FIXME: Consider using a matcher instead of translating
-  // `CheckToLatticeMap` to `CheckToStringifiedLatticeMap`.
-  std::vector>
-  CheckToStringifiedLatticeMap;
-  for (const auto &E : CheckToLatticeMap) {
-CheckT

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

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcafb8b4ff2c3: [clang][dataflow] Use diagnosis API in 
optional checker (authored by samestep).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128352

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h

Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
===
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -109,14 +109,33 @@
 /// dataflow analysis states that model the respective basic blocks. The
 /// returned vector, if any, will have the same size as the number of CFG
 /// blocks, with indices corresponding to basic block IDs. Returns an error if
-/// the dataflow analysis cannot be performed successfully.
+/// the dataflow analysis cannot be performed successfully. Otherwise, calls
+/// `PostVisitStmt` on each statement with the final analysis results at that
+/// program point.
 template 
 llvm::Expected>>>
-runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
-const Environment &InitEnv) {
-  auto TypeErasedBlockStates =
-  runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv);
+runDataflowAnalysis(
+const ControlFlowContext &CFCtx, AnalysisT &Analysis,
+const Environment &InitEnv,
+std::function &)>
+PostVisitStmt = nullptr) {
+  std::function
+  PostVisitStmtClosure = nullptr;
+  if (PostVisitStmt != nullptr) {
+PostVisitStmtClosure = [&PostVisitStmt](
+   const Stmt *Stmt,
+   const TypeErasedDataflowAnalysisState &State) {
+  auto *Lattice =
+  llvm::any_cast(&State.Lattice.Value);
+  PostVisitStmt(Stmt, DataflowAnalysisState{
+  *Lattice, State.Env});
+};
+  }
+
+  auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
+  CFCtx, Analysis, InitEnv, PostVisitStmtClosure);
   if (!TypeErasedBlockStates)
 return TypeErasedBlockStates.takeError();
 
Index: clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
@@ -23,6 +23,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/Any.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Error.h"
 #include 
 #include 
@@ -32,12 +33,13 @@
 namespace bugprone {
 using ast_matchers::MatchFinder;
 using dataflow::SourceLocationsLattice;
+using dataflow::UncheckedOptionalAccessDiagnoser;
 using dataflow::UncheckedOptionalAccessModel;
 using llvm::Optional;
 
 static constexpr llvm::StringLiteral FuncID("fun");
 
-static Optional
+static Optional>
 analyzeFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx) {
   using dataflow::ControlFlowContext;
   using dataflow::DataflowAnalysisState;
@@ -52,23 +54,22 @@
   std::make_unique());
   dataflow::Environment Env(AnalysisContext, FuncDecl);
   UncheckedOptionalAccessModel Analysis(ASTCtx);
+  UncheckedOptionalAccessDiagnoser Diagnoser;
+  std::vector Diagnostics;
   Expected>>>
-  BlockToOutputState =
-  dataflow::runDataflowAnalysis(*Context, Analysis, Env);
+  BlockToOutputState = dataflow::runDataflowAnalysis(
+  *Context, Analysis, Env,
+  [&ASTCtx, &Diagnoser,
+   &Diagnostics](const Stmt *Stmt,
+ const DataflowAnalysisState
+ &State) mutable {
+auto StmtDiagnostics = Diagnoser.diagnose(ASTCtx, Stmt, State.Env);
+llvm::move(StmtDiagnostics, std::back_inserter(Diagnostics));
+  });
   if (!BlockToOutputState)
 return llvm::None;
-  assert(Context->getCFG().getExit().getBlockID() < BlockToOutputState->size());
 
-  const Optional>
-  &ExitBlockState =
-  (*BlockToOutputState)[Context->getCFG().getExit().getBlockID()];
-  // `runDataflowAnalysis` doesn't guarantee that the exit block is visited;
-  // for example, when it is unreachable.
-  // FIXME: Diagnose violations even when the exit block is unreachable.
-  if (!ExitBlockState)
-return llvm::None;
-
-  return std::move(ExitBlockState->Lattice);
+  return Diagnostics;
 }
 
 void UncheckedOptionalAccessCheck::registerMatchers(MatchFinder *Finder) {
@@ -97,9 +98,9 @@
   if (FuncDecl->isTemplated())
 return;
 
-  if (Optional Errors =
+  if (Optional> Errors =
   analyzeFunction(*FuncDecl, *Result.Context))
-for (const SourceLocation &Loc : E

[PATCH] D128356: [clang][dataflow] Use NoopLattice in optional model

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG335c05f5d19f: [clang][dataflow] Use NoopLattice in optional 
model (authored by samestep).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128356

Files:
  clang/docs/tools/clang-formatted-files.txt
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h

Index: clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
@@ -18,25 +18,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include 
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 
 namespace clang {
 namespace dataflow {
 
-class NoopLattice {
-public:
-  bool operator==(const NoopLattice &) const { return true; }
-
-  LatticeJoinEffect join(const NoopLattice &) {
-return LatticeJoinEffect::Unchanged;
-  }
-};
-
-inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) {
-  return OS << "noop";
-}
-
 class NoopAnalysis : public DataflowAnalysis {
 public:
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -20,7 +20,7 @@
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
@@ -35,7 +35,7 @@
 namespace {
 
 using namespace ::clang::ast_matchers;
-using LatticeTransferState = TransferState;
+using LatticeTransferState = TransferState;
 
 DeclarationMatcher optionalClass() {
   return classTemplateSpecializationDecl(
@@ -312,18 +312,7 @@
   if (auto *Loc = maybeInitializeOptionalValueMember(
   UnwrapExpr->getType(), *OptionalVal, State.Env))
 State.Env.setStorageLocation(*UnwrapExpr, *Loc);
-
-auto *Prop = OptionalVal->getProperty("has_value");
-if (auto *HasValueVal = cast_or_null(Prop)) {
-  if (State.Env.flowConditionImplies(*HasValueVal))
-return;
-}
   }
-
-  // Record that this unwrap is *not* provably safe.
-  // FIXME: include either the name of the optional (if applicable) or a source
-  // range of the access for easier interpretation of the result.
-  State.Lattice.getSourceLocations().insert(ObjectExpr->getBeginLoc());
 }
 
 void transferMakeOptionalCall(const CallExpr *E,
@@ -716,12 +705,10 @@
 
 UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(
 ASTContext &Ctx, UncheckedOptionalAccessModelOptions Options)
-: DataflowAnalysis(
-  Ctx),
+: DataflowAnalysis(Ctx),
   TransferMatchSwitch(buildTransferMatchSwitch(Options)) {}
 
-void UncheckedOptionalAccessModel::transfer(const Stmt *S,
-SourceLocationsLattice &L,
+void UncheckedOptionalAccessModel::transfer(const Stmt *S, NoopLattice &L,
 Environment &Env) {
   LatticeTransferState State(L, Env);
   TransferMatchSwitch(*S, getASTContext(), State);
Index: clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
===
--- /dev/null
+++ clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
@@ -0,0 +1,41 @@
+//===-- NoopLattice.h ---*- C++ -*-===//
+//
+// 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
+//
+//===--===//
+//
+//  This file defines the lattice with exactly one element.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+
+#include "clang/Analysis/FlowSensitive/Dat

[PATCH] D128851: [clang][dataflow] Use NoopLattice in optional model

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
samestep created this revision.
Herald added subscribers: martong, tschuett, carlosgalvezp, xazax.hun.
Herald added a project: All.
samestep requested review of this revision.
Herald added projects: clang, clang-tools-extra.
Herald added a subscriber: cfe-commits.

Reland of D128356 . I meant to include these 
changes in the original patch, but somehow failed to properly update it before 
landing.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128851

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/docs/tools/clang-formatted-files.txt
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h

Index: clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
@@ -18,25 +18,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include 
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 
 namespace clang {
 namespace dataflow {
 
-class NoopLattice {
-public:
-  bool operator==(const NoopLattice &) const { return true; }
-
-  LatticeJoinEffect join(const NoopLattice &) {
-return LatticeJoinEffect::Unchanged;
-  }
-};
-
-inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) {
-  return OS << "noop";
-}
-
 class NoopAnalysis : public DataflowAnalysis {
 public:
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -20,7 +20,7 @@
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
@@ -35,7 +35,7 @@
 namespace {
 
 using namespace ::clang::ast_matchers;
-using LatticeTransferState = TransferState;
+using LatticeTransferState = TransferState;
 
 DeclarationMatcher optionalClass() {
   return classTemplateSpecializationDecl(
@@ -312,18 +312,7 @@
   if (auto *Loc = maybeInitializeOptionalValueMember(
   UnwrapExpr->getType(), *OptionalVal, State.Env))
 State.Env.setStorageLocation(*UnwrapExpr, *Loc);
-
-auto *Prop = OptionalVal->getProperty("has_value");
-if (auto *HasValueVal = cast_or_null(Prop)) {
-  if (State.Env.flowConditionImplies(*HasValueVal))
-return;
-}
   }
-
-  // Record that this unwrap is *not* provably safe.
-  // FIXME: include either the name of the optional (if applicable) or a source
-  // range of the access for easier interpretation of the result.
-  State.Lattice.getSourceLocations().insert(ObjectExpr->getBeginLoc());
 }
 
 void transferMakeOptionalCall(const CallExpr *E,
@@ -716,12 +705,10 @@
 
 UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(
 ASTContext &Ctx, UncheckedOptionalAccessModelOptions Options)
-: DataflowAnalysis(
-  Ctx),
+: DataflowAnalysis(Ctx),
   TransferMatchSwitch(buildTransferMatchSwitch(Options)) {}
 
-void UncheckedOptionalAccessModel::transfer(const Stmt *S,
-SourceLocationsLattice &L,
+void UncheckedOptionalAccessModel::transfer(const Stmt *S, NoopLattice &L,
 Environment &Env) {
   LatticeTransferState State(L, Env);
   TransferMatchSwitch(*S, getASTContext(), State);
Index: clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
===
--- /dev/null
+++ clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
@@ -0,0 +1,41 @@
+//===-- NoopLattice.h ---*- C++ -*-===//
+//
+// 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
+//
+//===--===//
+//
+//  This file defines the lattice with exactly one element.
+//
+//===-

[PATCH] D128356: [clang][dataflow] Use NoopLattice in optional model

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
samestep updated this revision to Diff 441142.
samestep added a comment.
Herald added a subscriber: carlosgalvezp.
Herald added a project: clang-tools-extra.

Update UncheckedOptionalAccessCheck.cpp


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128356

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/docs/tools/clang-formatted-files.txt
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h

Index: clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
@@ -18,25 +18,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include 
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 
 namespace clang {
 namespace dataflow {
 
-class NoopLattice {
-public:
-  bool operator==(const NoopLattice &) const { return true; }
-
-  LatticeJoinEffect join(const NoopLattice &) {
-return LatticeJoinEffect::Unchanged;
-  }
-};
-
-inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) {
-  return OS << "noop";
-}
-
 class NoopAnalysis : public DataflowAnalysis {
 public:
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -20,7 +20,7 @@
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
@@ -35,7 +35,7 @@
 namespace {
 
 using namespace ::clang::ast_matchers;
-using LatticeTransferState = TransferState;
+using LatticeTransferState = TransferState;
 
 DeclarationMatcher optionalClass() {
   return classTemplateSpecializationDecl(
@@ -312,18 +312,7 @@
   if (auto *Loc = maybeInitializeOptionalValueMember(
   UnwrapExpr->getType(), *OptionalVal, State.Env))
 State.Env.setStorageLocation(*UnwrapExpr, *Loc);
-
-auto *Prop = OptionalVal->getProperty("has_value");
-if (auto *HasValueVal = cast_or_null(Prop)) {
-  if (State.Env.flowConditionImplies(*HasValueVal))
-return;
-}
   }
-
-  // Record that this unwrap is *not* provably safe.
-  // FIXME: include either the name of the optional (if applicable) or a source
-  // range of the access for easier interpretation of the result.
-  State.Lattice.getSourceLocations().insert(ObjectExpr->getBeginLoc());
 }
 
 void transferMakeOptionalCall(const CallExpr *E,
@@ -716,12 +705,10 @@
 
 UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(
 ASTContext &Ctx, UncheckedOptionalAccessModelOptions Options)
-: DataflowAnalysis(
-  Ctx),
+: DataflowAnalysis(Ctx),
   TransferMatchSwitch(buildTransferMatchSwitch(Options)) {}
 
-void UncheckedOptionalAccessModel::transfer(const Stmt *S,
-SourceLocationsLattice &L,
+void UncheckedOptionalAccessModel::transfer(const Stmt *S, NoopLattice &L,
 Environment &Env) {
   LatticeTransferState State(L, Env);
   TransferMatchSwitch(*S, getASTContext(), State);
Index: clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
===
--- /dev/null
+++ clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
@@ -0,0 +1,41 @@
+//===-- NoopLattice.h ---*- C++ -*-===//
+//
+// 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
+//
+//===--===//
+//
+//  This file defines the lattice with exactly one element.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+
+#include 

[PATCH] D128356: [clang][dataflow] Use NoopLattice in optional model

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcf1f978d319b: [clang][dataflow] Use NoopLattice in optional 
model (authored by samestep).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128356

Files:
  clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.cpp
  clang/docs/tools/clang-formatted-files.txt
  
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
  clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h

Index: clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
===
--- clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
+++ clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
@@ -18,25 +18,11 @@
 #include "clang/AST/Stmt.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include 
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 
 namespace clang {
 namespace dataflow {
 
-class NoopLattice {
-public:
-  bool operator==(const NoopLattice &) const { return true; }
-
-  LatticeJoinEffect join(const NoopLattice &) {
-return LatticeJoinEffect::Unchanged;
-  }
-};
-
-inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) {
-  return OS << "noop";
-}
-
 class NoopAnalysis : public DataflowAnalysis {
 public:
   /// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -20,7 +20,7 @@
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
-#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/Analysis/FlowSensitive/NoopLattice.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
@@ -35,7 +35,7 @@
 namespace {
 
 using namespace ::clang::ast_matchers;
-using LatticeTransferState = TransferState;
+using LatticeTransferState = TransferState;
 
 DeclarationMatcher optionalClass() {
   return classTemplateSpecializationDecl(
@@ -312,18 +312,7 @@
   if (auto *Loc = maybeInitializeOptionalValueMember(
   UnwrapExpr->getType(), *OptionalVal, State.Env))
 State.Env.setStorageLocation(*UnwrapExpr, *Loc);
-
-auto *Prop = OptionalVal->getProperty("has_value");
-if (auto *HasValueVal = cast_or_null(Prop)) {
-  if (State.Env.flowConditionImplies(*HasValueVal))
-return;
-}
   }
-
-  // Record that this unwrap is *not* provably safe.
-  // FIXME: include either the name of the optional (if applicable) or a source
-  // range of the access for easier interpretation of the result.
-  State.Lattice.getSourceLocations().insert(ObjectExpr->getBeginLoc());
 }
 
 void transferMakeOptionalCall(const CallExpr *E,
@@ -716,12 +705,10 @@
 
 UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(
 ASTContext &Ctx, UncheckedOptionalAccessModelOptions Options)
-: DataflowAnalysis(
-  Ctx),
+: DataflowAnalysis(Ctx),
   TransferMatchSwitch(buildTransferMatchSwitch(Options)) {}
 
-void UncheckedOptionalAccessModel::transfer(const Stmt *S,
-SourceLocationsLattice &L,
+void UncheckedOptionalAccessModel::transfer(const Stmt *S, NoopLattice &L,
 Environment &Env) {
   LatticeTransferState State(L, Env);
   TransferMatchSwitch(*S, getASTContext(), State);
Index: clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
===
--- /dev/null
+++ clang/include/clang/Analysis/FlowSensitive/NoopLattice.h
@@ -0,0 +1,41 @@
+//===-- NoopLattice.h ---*- C++ -*-===//
+//
+// 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
+//
+//===--===//
+//
+//  This file defines the lattice with exactly one element.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
+#define LLVM_CLANG_ANALYSIS_F

[PATCH] D128448: [clang][dataflow] Delete SourceLocationsLattice

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

Update from main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128448

Files:
  clang/docs/tools/clang-formatted-files.txt
  clang/include/clang/Analysis/FlowSensitive/SourceLocationsLattice.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
  llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
  llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn

Index: llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
===
--- llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
+++ llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
@@ -25,7 +25,6 @@
 "MultiVarConstantPropagationTest.cpp",
 "SingleVarConstantPropagationTest.cpp",
 "SolverTest.cpp",
-"SourceLocationsLatticeTest.cpp",
 "TestingSupport.cpp",
 "TestingSupportTest.cpp",
 "TransferTest.cpp",
Index: llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
===
--- llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
+++ llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
@@ -9,7 +9,6 @@
 "ControlFlowContext.cpp",
 "DataflowAnalysisContext.cpp",
 "DataflowEnvironment.cpp",
-"SourceLocationsLattice.cpp",
 "Transfer.cpp",
 "TypeErasedDataflowAnalysis.cpp",
 "WatchedLiteralsSolver.cpp",
Index: clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.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/SourceLocationsLattice.h"
-
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include "clang/Basic/SourceLocation.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace dataflow {
-namespace {
-
-TEST(SourceLocationsLatticeTest, Comparison) {
-  const SourceLocationsLattice Bottom;
-  const SourceLocationsLattice NonBottom(
-  {SourceLocation::getFromRawEncoding(0)});
-
-  EXPECT_TRUE(Bottom == Bottom);
-  EXPECT_FALSE(Bottom == NonBottom);
-  EXPECT_FALSE(NonBottom == Bottom);
-  EXPECT_TRUE(NonBottom == NonBottom);
-
-  EXPECT_FALSE(Bottom != Bottom);
-  EXPECT_TRUE(Bottom != NonBottom);
-  EXPECT_TRUE(NonBottom != Bottom);
-  EXPECT_FALSE(NonBottom != NonBottom);
-}
-
-TEST(SourceLocationsLatticeTest, Join) {
-  const SourceLocationsLattice Bottom;
-  const SourceLocationsLattice NonBottom(
-  {SourceLocation::getFromRawEncoding(0)});
-  {
-SourceLocationsLattice LHS = Bottom;
-const SourceLocationsLattice RHS = Bottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
-EXPECT_EQ(LHS, Bottom);
-  }
-  {
-SourceLocationsLattice LHS = NonBottom;
-const SourceLocationsLattice RHS = Bottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
-EXPECT_EQ(LHS, NonBottom);
-  }
-  {
-SourceLocationsLattice LHS = Bottom;
-const SourceLocationsLattice RHS = NonBottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Changed);
-EXPECT_EQ(LHS, NonBottom);
-  }
-  {
-SourceLocationsLattice LHS = NonBottom;
-const SourceLocationsLattice RHS = NonBottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
-EXPECT_EQ(LHS, NonBottom);
-  }
-}
-
-} // namespace
-} // namespace dataflow
-} // namespace clang
Index: clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
===
--- clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
+++ clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
@@ -11,7 +11,6 @@
   MatchSwitchTest.cpp
   MultiVarConstantPropagationTest.cpp
   SingleVarConstantPropagationTest.cpp
-  SourceLocationsLatticeTest.cpp
   TestingSupport.cpp
   TestingSupportTest.cpp
   TransferTest.cpp
Index: clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
===
--- clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- SourceLocationsLattice.cpp -

[PATCH] D128448: [clang][dataflow] Delete SourceLocationsLattice

2022-06-29 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6a97be27a1de: [clang][dataflow] Delete 
SourceLocationsLattice (authored by samestep).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128448

Files:
  clang/docs/tools/clang-formatted-files.txt
  clang/include/clang/Analysis/FlowSensitive/SourceLocationsLattice.h
  clang/lib/Analysis/FlowSensitive/CMakeLists.txt
  clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
  clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
  clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
  llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
  llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn

Index: llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
===
--- llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
+++ llvm/utils/gn/secondary/clang/unittests/Analysis/FlowSensitive/BUILD.gn
@@ -25,7 +25,6 @@
 "MultiVarConstantPropagationTest.cpp",
 "SingleVarConstantPropagationTest.cpp",
 "SolverTest.cpp",
-"SourceLocationsLatticeTest.cpp",
 "TestingSupport.cpp",
 "TestingSupportTest.cpp",
 "TransferTest.cpp",
Index: llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
===
--- llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
+++ llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn
@@ -9,7 +9,6 @@
 "ControlFlowContext.cpp",
 "DataflowAnalysisContext.cpp",
 "DataflowEnvironment.cpp",
-"SourceLocationsLattice.cpp",
 "Transfer.cpp",
 "TypeErasedDataflowAnalysis.cpp",
 "WatchedLiteralsSolver.cpp",
Index: clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
===
--- clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.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/SourceLocationsLattice.h"
-
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include "clang/Basic/SourceLocation.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace dataflow {
-namespace {
-
-TEST(SourceLocationsLatticeTest, Comparison) {
-  const SourceLocationsLattice Bottom;
-  const SourceLocationsLattice NonBottom(
-  {SourceLocation::getFromRawEncoding(0)});
-
-  EXPECT_TRUE(Bottom == Bottom);
-  EXPECT_FALSE(Bottom == NonBottom);
-  EXPECT_FALSE(NonBottom == Bottom);
-  EXPECT_TRUE(NonBottom == NonBottom);
-
-  EXPECT_FALSE(Bottom != Bottom);
-  EXPECT_TRUE(Bottom != NonBottom);
-  EXPECT_TRUE(NonBottom != Bottom);
-  EXPECT_FALSE(NonBottom != NonBottom);
-}
-
-TEST(SourceLocationsLatticeTest, Join) {
-  const SourceLocationsLattice Bottom;
-  const SourceLocationsLattice NonBottom(
-  {SourceLocation::getFromRawEncoding(0)});
-  {
-SourceLocationsLattice LHS = Bottom;
-const SourceLocationsLattice RHS = Bottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
-EXPECT_EQ(LHS, Bottom);
-  }
-  {
-SourceLocationsLattice LHS = NonBottom;
-const SourceLocationsLattice RHS = Bottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
-EXPECT_EQ(LHS, NonBottom);
-  }
-  {
-SourceLocationsLattice LHS = Bottom;
-const SourceLocationsLattice RHS = NonBottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Changed);
-EXPECT_EQ(LHS, NonBottom);
-  }
-  {
-SourceLocationsLattice LHS = NonBottom;
-const SourceLocationsLattice RHS = NonBottom;
-EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
-EXPECT_EQ(LHS, NonBottom);
-  }
-}
-
-} // namespace
-} // namespace dataflow
-} // namespace clang
Index: clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
===
--- clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
+++ clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
@@ -11,7 +11,6 @@
   MatchSwitchTest.cpp
   MultiVarConstantPropagationTest.cpp
   SingleVarConstantPropagationTest.cpp
-  SourceLocationsLatticeTest.cpp
   TestingSupport.cpp
   TestingSupportTest.cpp
   TransferTest.cpp
Index: clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
===
--- clang/lib/Analysis/

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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128924

Files:
  clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupportTest.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
@@ -37,33 +37,30 @@
 using ::testing::Pair;
 using ::testing::SizeIs;
 
-class TransferTest : public ::testing::Test {
-protected:
-  template 
-  void runDataflow(llvm::StringRef Code, Matcher Match,
-   LangStandard::Kind Std = LangStandard::lang_cxx17,
-   bool ApplyBuiltinTransfer = true,
-   llvm::StringRef TargetFun = "target") {
-ASSERT_THAT_ERROR(
-test::checkDataflow(
-Code, TargetFun,
-[ApplyBuiltinTransfer](ASTContext &C, Environment &) {
-  return NoopAnalysis(C, ApplyBuiltinTransfer);
-},
-[&Match](
-llvm::ArrayRef<
-std::pair>>
-Results,
-ASTContext &ASTCtx) { Match(Results, ASTCtx); },
-{"-fsyntax-only", "-fno-delayed-template-parsing",
- "-std=" +
- std::string(
- LangStandard::getLangStandardForKind(Std).getName())}),
-llvm::Succeeded());
-  }
-};
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+  LangStandard::Kind Std = LangStandard::lang_cxx17,
+  bool ApplyBuiltinTransfer = true,
+  llvm::StringRef TargetFun = "target") {
+  ASSERT_THAT_ERROR(
+  test::checkDataflow(
+  Code, TargetFun,
+  [ApplyBuiltinTransfer](ASTContext &C, Environment &) {
+return NoopAnalysis(C, ApplyBuiltinTransfer);
+  },
+  [&Match](
+  llvm::ArrayRef<
+  std::pair>>
+  Results,
+  ASTContext &ASTCtx) { Match(Results, ASTCtx); },
+  {"-fsyntax-only", "-fno-delayed-template-parsing",
+"-std=" +
+std::string(
+LangStandard::getLangStandardForKind(Std).getName())}),
+  llvm::Succeeded());
+}
 
-TEST_F(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
+TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
   int Foo;
@@ -88,7 +85,7 @@
   /*ApplyBuiltinTransfer=*/false);
 }
 
-TEST_F(TransferTest, BoolVarDecl) {
+TEST(TransferTest, BoolVarDecl) {
   std::string Code = R"(
 void target() {
   bool Foo;
@@ -115,7 +112,7 @@
   });
 }
 
-TEST_F(TransferTest, IntVarDecl) {
+TEST(TransferTest, IntVarDecl) {
   std::string Code = R"(
 void target() {
   int Foo;
@@ -142,7 +139,7 @@
   });
 }
 
-TEST_F(TransferTest, StructVarDecl) {
+TEST(TransferTest, StructVarDecl) {
   std::string Code = R"(
 struct A {
   int Bar;
@@ -188,7 +185,7 @@
   });
 }
 
-TEST_F(TransferTest, StructVarDeclWithInit) {
+TEST(TransferTest, StructVarDeclWithInit) {
   std::string Code = R"(
 struct A {
   int Bar;
@@ -236,7 +233,7 @@
   });
 }
 
-TEST_F(TransferTest, ClassVarDecl) {
+TEST(TransferTest, ClassVarDecl) {
   std::string Code = R"(
 class A {
   int Bar;
@@ -282,7 +279,7 @@
   });
 }
 
-TEST_F(TransferTest, ReferenceVarDecl) {
+TEST(TransferTest, ReferenceVarDecl) {
   std::string Code = R"(
 struct A {};
 
@@ -318,7 +315,7 @@
   });
 }
 
-TEST_F(TransferTest, SelfReferentialReferenceVarDecl) {
+TEST(TransferTest, SelfReferentialReferenceVarDecl) {
   std::string Code = R"(
 struct A;
 
@@ -427,7 +424,7 @@
   });
 }
 
-TEST_F(TransferTest, PointerVarDecl) {
+TEST(TransferTest, PointerVarDecl) {
   std::string Code = R"(
 struct A {};
 
@@ -462,7 +459,7 @@
   });
 }
 
-TEST_F(TransferTest, SelfReferentialPointerVarDecl) {
+TEST(TransferTest, SelfReferentialPointerVarDecl) {
   std::string Code = R"(
 struct A;
 
@@ -584,7 +581,7 @@
   });
 }
 
-TEST_F(TransferTest, MultipleVarsDecl) {
+TEST(TransferTest, MultipleVarsDecl) {
   std::string Code = R"(
 void target() {
   int Foo, Bar;
@@ -622,7 +619,7 @@
   });
 }
 
-TEST_F(TransferTest, JoinVarDecl) {
+TEST(TransferTest, JoinVarDecl) {
   std::string Code = R"(
   

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

2022-06-30 Thread Sam Estep via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1d83a16bd3fa: [clang][dataflow] Replace TEST_F with TEST 
where possible (authored by samestep).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128924

Files:
  clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
  clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
  clang/unittests/Analysis/FlowSensitive/TestingSupportTest.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
@@ -37,33 +37,30 @@
 using ::testing::Pair;
 using ::testing::SizeIs;
 
-class TransferTest : public ::testing::Test {
-protected:
-  template 
-  void runDataflow(llvm::StringRef Code, Matcher Match,
-   LangStandard::Kind Std = LangStandard::lang_cxx17,
-   bool ApplyBuiltinTransfer = true,
-   llvm::StringRef TargetFun = "target") {
-ASSERT_THAT_ERROR(
-test::checkDataflow(
-Code, TargetFun,
-[ApplyBuiltinTransfer](ASTContext &C, Environment &) {
-  return NoopAnalysis(C, ApplyBuiltinTransfer);
-},
-[&Match](
-llvm::ArrayRef<
-std::pair>>
-Results,
-ASTContext &ASTCtx) { Match(Results, ASTCtx); },
-{"-fsyntax-only", "-fno-delayed-template-parsing",
- "-std=" +
- std::string(
- LangStandard::getLangStandardForKind(Std).getName())}),
-llvm::Succeeded());
-  }
-};
+template 
+void runDataflow(llvm::StringRef Code, Matcher Match,
+  LangStandard::Kind Std = LangStandard::lang_cxx17,
+  bool ApplyBuiltinTransfer = true,
+  llvm::StringRef TargetFun = "target") {
+  ASSERT_THAT_ERROR(
+  test::checkDataflow(
+  Code, TargetFun,
+  [ApplyBuiltinTransfer](ASTContext &C, Environment &) {
+return NoopAnalysis(C, ApplyBuiltinTransfer);
+  },
+  [&Match](
+  llvm::ArrayRef<
+  std::pair>>
+  Results,
+  ASTContext &ASTCtx) { Match(Results, ASTCtx); },
+  {"-fsyntax-only", "-fno-delayed-template-parsing",
+"-std=" +
+std::string(
+LangStandard::getLangStandardForKind(Std).getName())}),
+  llvm::Succeeded());
+}
 
-TEST_F(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
+TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
   std::string Code = R"(
 void target() {
   int Foo;
@@ -88,7 +85,7 @@
   /*ApplyBuiltinTransfer=*/false);
 }
 
-TEST_F(TransferTest, BoolVarDecl) {
+TEST(TransferTest, BoolVarDecl) {
   std::string Code = R"(
 void target() {
   bool Foo;
@@ -115,7 +112,7 @@
   });
 }
 
-TEST_F(TransferTest, IntVarDecl) {
+TEST(TransferTest, IntVarDecl) {
   std::string Code = R"(
 void target() {
   int Foo;
@@ -142,7 +139,7 @@
   });
 }
 
-TEST_F(TransferTest, StructVarDecl) {
+TEST(TransferTest, StructVarDecl) {
   std::string Code = R"(
 struct A {
   int Bar;
@@ -188,7 +185,7 @@
   });
 }
 
-TEST_F(TransferTest, StructVarDeclWithInit) {
+TEST(TransferTest, StructVarDeclWithInit) {
   std::string Code = R"(
 struct A {
   int Bar;
@@ -236,7 +233,7 @@
   });
 }
 
-TEST_F(TransferTest, ClassVarDecl) {
+TEST(TransferTest, ClassVarDecl) {
   std::string Code = R"(
 class A {
   int Bar;
@@ -282,7 +279,7 @@
   });
 }
 
-TEST_F(TransferTest, ReferenceVarDecl) {
+TEST(TransferTest, ReferenceVarDecl) {
   std::string Code = R"(
 struct A {};
 
@@ -318,7 +315,7 @@
   });
 }
 
-TEST_F(TransferTest, SelfReferentialReferenceVarDecl) {
+TEST(TransferTest, SelfReferentialReferenceVarDecl) {
   std::string Code = R"(
 struct A;
 
@@ -427,7 +424,7 @@
   });
 }
 
-TEST_F(TransferTest, PointerVarDecl) {
+TEST(TransferTest, PointerVarDecl) {
   std::string Code = R"(
 struct A {};
 
@@ -462,7 +459,7 @@
   });
 }
 
-TEST_F(TransferTest, SelfReferentialPointerVarDecl) {
+TEST(TransferTest, SelfReferentialPointerVarDecl) {
   std::string Code = R"(
 struct A;
 
@@ -584,7 +581,7 @@
   });
 }
 
-TEST_F(TransferTest, MultipleVarsDecl) {
+TEST(TransferTest, MultipleVarsDecl) {
   std::string Code = R"(
 void target() {
   int Foo, Bar;
@@ -622,7 +619,7 @@
   });
 }
 
-TEST_F(TransferTest

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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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


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

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

Rebase and add Yitzie's assertion


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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

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

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

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

In D130270#3679273 , @gribozavr2 
wrote:

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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


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

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

Be explicit when constructing TransferOptions


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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

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

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

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

Use different name for TransferOptions field


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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

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

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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130593

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

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

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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130593

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

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

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

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

Depends On D130593 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130600

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

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

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

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

In D130306#3680942 , @chapuni wrote:

> A few variables cause warinings in -Asserts.

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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


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

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

Address Dmitri's review


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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



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

gribozavr2 wrote:
> 
Done.



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

gribozavr2 wrote:
> 
Done.



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

gribozavr2 wrote:
> 
Done.



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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


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

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

In D130593#3681126 , @xazax.hun wrote:

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130593

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


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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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


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

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

Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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

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

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

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

@gribozavr2 I rebased again, should work now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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


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

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

Set a storage location for the outermost context too


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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



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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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


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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130593

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


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

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



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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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


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

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

Add FIXME about passing `TookSecondBranch` to `merge`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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

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

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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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


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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130726

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

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

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

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

Here is the new patch: D130726 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130593

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


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

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



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

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



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

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



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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130726

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


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

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

Address some of Yitzie's comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130726

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

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

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

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



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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130726

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


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

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

Add more comments and tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130726

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

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130726

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

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

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

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131014

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


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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131065

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


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

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

Looks awesome, thanks @ymandel!




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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131039

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


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

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

Rebase and address all comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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

Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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



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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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


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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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


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

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

Don't assert returns to not be references


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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

Use CallExpr location for ReturnLoc


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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

Revert an unnecessary little change


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131170

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

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

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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131170

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


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

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

Address Stanislav's comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131170

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

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

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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131170

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


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

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

Add Stanislav's suggested comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130600

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131170

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

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

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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131438

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

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

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

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

Tweaks


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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

Fix bug


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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



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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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


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

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

Address Yitzie's comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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

Narrow public signature of pushCall


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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



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




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131280

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


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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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


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

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

In D131438#3710697 , @xazax.hun wrote:

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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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


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

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

Use ArrayRef


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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


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

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

Pull type-specific logic into overloads


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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

Remove Call parameter from pushCallInternal method


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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


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

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



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

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



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

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



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

sgatev wrote:
> 
👍


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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


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

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

Address Stanislav's comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131438

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

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

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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131600

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


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


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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131600

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


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


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

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

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

This is a continuation of https://reviews.llvm.org/D129289 using @sgatev's 
feedback.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130270

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

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

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

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130304

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

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

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

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

Depends On D130304 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130305

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


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


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

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

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

Depends On D130305 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130306

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

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

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

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

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130304

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

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

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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130270

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


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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130305

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


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

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

Give a default value to ApplyBuiltinTransfer


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130305

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


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


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

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

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

Update parent patch


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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

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

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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130305

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


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

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

In D130306#3670259 , @xazax.hun wrote:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



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

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



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

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



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

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



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

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



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

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130306

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


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

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

Mark bool constructors as deprecated


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130305

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


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


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

  1   2   >