[clang] 8dd14c4 - [clang][dataflow] Use `StringMap` for storing analysis states at annotated points instead of `vector<pair<string, StateT>>`.

Wei Yi Tee via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 1 07:10:31 PDT 2022


Author: Wei Yi Tee
Date: 2022-09-01T14:09:43Z
New Revision: 8dd14c427ae5c86cc2af4b8cac05b41bc4a49e86

URL: https://github.com/llvm/llvm-project/commit/8dd14c427ae5c86cc2af4b8cac05b41bc4a49e86
DIFF: https://github.com/llvm/llvm-project/commit/8dd14c427ae5c86cc2af4b8cac05b41bc4a49e86.diff

LOG: [clang][dataflow] Use `StringMap` for storing analysis states at annotated points instead of `vector<pair<string, StateT>>`.

Reviewed By: gribozavr2, sgatev, ymandel

Differential Revision: https://reviews.llvm.org/D132763

Added: 
    

Modified: 
    clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
    clang/unittests/Analysis/FlowSensitive/TestingSupport.h
    clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
    clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
index c0c05b0efdbb..dbb06c85814f 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Testing/Support/Annotations.h"
 #include <cassert>
@@ -72,6 +73,7 @@ llvm::Expected<llvm::DenseMap<const Stmt *, std::string>>
 test::buildStatementToAnnotationMapping(const FunctionDecl *Func,
                                         llvm::Annotations AnnotatedCode) {
   llvm::DenseMap<const Stmt *, std::string> Result;
+  llvm::StringSet<> ExistingAnnotations;
 
   auto StmtMatcher =
       findAll(stmt(unless(anyOf(hasParent(expr()), hasParent(returnStmt()))))
@@ -113,7 +115,14 @@ test::buildStatementToAnnotationMapping(const FunctionDecl *Func,
                 .data());
       }
 
-      Result[Stmt] = Code.slice(Range.Begin, Range.End).str();
+      auto Annotation = Code.slice(Range.Begin, Range.End).str();
+      if (!ExistingAnnotations.insert(Annotation).second) {
+        return llvm::createStringError(
+            std::make_error_code(std::errc::invalid_argument),
+            "Repeated use of annotation: %s", Annotation.data());
+      }
+      Result[Stmt] = std::move(Annotation);
+
       I++;
 
       if (I < Annotations.size() && Annotations[I].Begin >= Offset) {

diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 285c0c991d23..e3b68ca2976d 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -37,6 +37,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
@@ -284,13 +285,12 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
 ///
 ///   Annotations must not be repeated.
 template <typename AnalysisT>
-llvm::Error checkDataflow(
-    AnalysisInputs<AnalysisT> AI,
-    std::function<void(
-        llvm::ArrayRef<std::pair<
-            std::string, DataflowAnalysisState<typename AnalysisT::Lattice>>>,
-        const AnalysisOutputs &)>
-        VerifyResults) {
+llvm::Error
+checkDataflow(AnalysisInputs<AnalysisT> AI,
+              std::function<void(const llvm::StringMap<DataflowAnalysisState<
+                                     typename AnalysisT::Lattice>> &,
+                                 const AnalysisOutputs &)>
+                  VerifyResults) {
   // Compute mapping from nodes of annotated statements to the content in the
   // annotation.
   llvm::DenseMap<const Stmt *, std::string> StmtToAnnotations;
@@ -308,11 +308,9 @@ llvm::Error checkDataflow(
 
   using StateT = DataflowAnalysisState<typename AnalysisT::Lattice>;
 
-  // FIXME: Use a string map instead of a vector of pairs.
-  //
   // Save the states computed for program points immediately following annotated
   // statements. The saved states are keyed by the content of the annotation.
-  std::vector<std::pair<std::string, StateT>> AnnotationStates;
+  llvm::StringMap<StateT> AnnotationStates;
   auto PostVisitCFG = [&StmtToAnnotations, &AnnotationStates,
                        PrevPostVisitCFG = std::move(AI.PostVisitCFG)](
                           ASTContext &Ctx, const CFGElement &Elt,
@@ -329,7 +327,10 @@ llvm::Error checkDataflow(
       return;
     auto *Lattice =
         llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
-    AnnotationStates.emplace_back(It->second, StateT{*Lattice, State.Env});
+    auto [_, InsertSuccess] =
+        AnnotationStates.insert({It->second, StateT{*Lattice, State.Env}});
+    (void)InsertSuccess;
+    assert(InsertSuccess);
   };
   return checkDataflow<AnalysisT>(
       std::move(AI)
@@ -378,12 +379,20 @@ llvm::Error checkDataflow(
                                 std::move(MakeAnalysis))
           .withASTBuildArgs(std::move(Args))
           .withASTBuildVirtualMappedFiles(std::move(VirtualMappedFiles)),
-      [&VerifyResults](
-          llvm::ArrayRef<std::pair<
-              std::string, DataflowAnalysisState<typename AnalysisT::Lattice>>>
-              AnnotationStates,
-          const AnalysisOutputs &AO) {
-        VerifyResults(AnnotationStates, AO.ASTCtx);
+      [&VerifyResults](const llvm::StringMap<DataflowAnalysisState<
+                           typename AnalysisT::Lattice>> &AnnotationStates,
+                       const AnalysisOutputs &AO) {
+        std::vector<std::pair<
+            std::string, DataflowAnalysisState<typename AnalysisT::Lattice>>>
+            AnnotationStatesAsVector;
+        for (const auto &P : AnnotationStates) {
+          AnnotationStatesAsVector.push_back(
+              std::make_pair(P.first().str(), std::move(P.second)));
+        }
+        llvm::sort(AnnotationStatesAsVector,
+                   [](auto a, auto b) { return a.first < b.first; });
+
+        VerifyResults(AnnotationStatesAsVector, AO.ASTCtx);
       });
 }
 

diff  --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 7f055f3ad8b7..d08afd096bc3 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -649,8 +649,8 @@ TEST(TransferTest, JoinVarDecl) {
                            std::string, DataflowAnalysisState<NoopLattice>>>
                            Results,
                        ASTContext &ASTCtx) {
-    ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
-                                     Pair("p2", _), Pair("p1", _)));
+    ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _),
+                                     Pair("p3", _), Pair("p4", _)));
     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
     ASSERT_THAT(FooDecl, NotNull());
 
@@ -660,24 +660,24 @@ TEST(TransferTest, JoinVarDecl) {
     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
     ASSERT_THAT(BazDecl, NotNull());
 
-    const Environment &Env1 = Results[3].second.Env;
+    const Environment &Env1 = Results[0].second.Env;
     const StorageLocation *FooLoc =
         Env1.getStorageLocation(*FooDecl, SkipPast::None);
     EXPECT_THAT(FooLoc, NotNull());
     EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
     EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
 
-    const Environment &Env2 = Results[2].second.Env;
+    const Environment &Env2 = Results[1].second.Env;
     EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
     EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull());
     EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
 
-    const Environment &Env3 = Results[1].second.Env;
+    const Environment &Env3 = Results[2].second.Env;
     EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
     EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
     EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull());
 
-    const Environment &Env4 = Results[0].second.Env;
+    const Environment &Env4 = Results[3].second.Env;
     EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
     EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
     EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
@@ -3305,8 +3305,8 @@ TEST(TransferTest, CorrelatedBranches) {
         ASSERT_THAT(CDecl, NotNull());
 
         {
-          ASSERT_THAT(Results[2], Pair("p0", _));
-          const Environment &Env = Results[2].second.Env;
+          ASSERT_THAT(Results[0], Pair("p0", _));
+          const Environment &Env = Results[0].second.Env;
           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
           ASSERT_THAT(BDecl, NotNull());
           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
@@ -3322,8 +3322,8 @@ TEST(TransferTest, CorrelatedBranches) {
         }
 
         {
-          ASSERT_THAT(Results[0], Pair("p2", _));
-          const Environment &Env = Results[0].second.Env;
+          ASSERT_THAT(Results[2], Pair("p2", _));
+          const Environment &Env = Results[2].second.Env;
           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
           EXPECT_TRUE(Env.flowConditionImplies(CVal));
         }
@@ -3422,9 +3422,9 @@ TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
                    Results,
                ASTContext &ASTCtx) {
         ASSERT_THAT(Results,
-                    ElementsAre(Pair("p-outer", _), Pair("p-inner", _)));
-        const Environment &OuterEnv = Results[0].second.Env;
-        const Environment &InnerEnv = Results[1].second.Env;
+                    ElementsAre(Pair("p-inner", _), Pair("p-outer", _)));
+        const Environment &InnerEnv = Results[0].second.Env;
+        const Environment &OuterEnv = Results[1].second.Env;
 
         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
         ASSERT_THAT(ValDecl, NotNull());

diff  --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
index d308011047a0..0a87a7f02fa5 100644
--- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -426,12 +426,12 @@ TEST_F(JoinFlowConditionsTest, JoinDistinctButProvablyEquivalentValues) {
                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
                    Results,
                ASTContext &ASTCtx) {
-        ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
-                                         Pair("p2", _), Pair("p1", _)));
-        const Environment &Env1 = Results[3].second.Env;
-        const Environment &Env2 = Results[2].second.Env;
-        const Environment &Env3 = Results[1].second.Env;
-        const Environment &Env4 = Results[0].second.Env;
+        ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _),
+                                         Pair("p3", _), Pair("p4", _)));
+        const Environment &Env1 = Results[0].second.Env;
+        const Environment &Env2 = Results[1].second.Env;
+        const Environment &Env3 = Results[2].second.Env;
+        const Environment &Env4 = Results[3].second.Env;
 
         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
         ASSERT_THAT(FooDecl, NotNull());
@@ -579,10 +579,10 @@ TEST_F(WideningTest, JoinDistinctValuesWithDistinctProperties) {
                  Results,
              ASTContext &ASTCtx) {
         ASSERT_THAT(Results,
-                    ElementsAre(Pair("p3", _), Pair("p2", _), Pair("p1", _)));
-        const Environment &Env1 = Results[2].second.Env;
+                    ElementsAre(Pair("p1", _), Pair("p2", _), Pair("p3", _)));
+        const Environment &Env1 = Results[0].second.Env;
         const Environment &Env2 = Results[1].second.Env;
-        const Environment &Env3 = Results[0].second.Env;
+        const Environment &Env3 = Results[2].second.Env;
 
         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
         ASSERT_THAT(FooDecl, NotNull());
@@ -622,12 +622,12 @@ TEST_F(WideningTest, JoinDistinctValuesWithSameProperties) {
                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
                      Results,
                  ASTContext &ASTCtx) {
-                ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
-                                                 Pair("p2", _), Pair("p1", _)));
-                const Environment &Env1 = Results[3].second.Env;
-                const Environment &Env2 = Results[2].second.Env;
-                const Environment &Env3 = Results[1].second.Env;
-                const Environment &Env4 = Results[0].second.Env;
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _),
+                                                 Pair("p3", _), Pair("p4", _)));
+                const Environment &Env1 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
+                const Environment &Env3 = Results[2].second.Env;
+                const Environment &Env4 = Results[3].second.Env;
 
                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
                 ASSERT_THAT(FooDecl, NotNull());
@@ -751,14 +751,14 @@ TEST_F(FlowConditionTest, IfStmtSingleVar) {
                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
                 ASSERT_THAT(FooDecl, NotNull());
 
-                ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
 
-                const Environment &Env1 = Results[1].second.Env;
+                const Environment &Env1 = Results[0].second.Env;
                 auto *FooVal1 =
                     cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
                 EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
 
-                const Environment &Env2 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
                 auto *FooVal2 =
                     cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
                 EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
@@ -785,14 +785,14 @@ TEST_F(FlowConditionTest, IfStmtSingleNegatedVar) {
                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
                 ASSERT_THAT(FooDecl, NotNull());
 
-                ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
 
-                const Environment &Env1 = Results[1].second.Env;
+                const Environment &Env1 = Results[0].second.Env;
                 auto *FooVal1 =
                     cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
                 EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
 
-                const Environment &Env2 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
                 auto *FooVal2 =
                     cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
                 EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2));
@@ -847,9 +847,9 @@ TEST_F(FlowConditionTest, Conjunction) {
                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
                 ASSERT_THAT(BarDecl, NotNull());
 
-                ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
 
-                const Environment &Env1 = Results[1].second.Env;
+                const Environment &Env1 = Results[0].second.Env;
                 auto *FooVal1 =
                     cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal1 =
@@ -857,7 +857,7 @@ TEST_F(FlowConditionTest, Conjunction) {
                 EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
                 EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
 
-                const Environment &Env2 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
                 auto *FooVal2 =
                     cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal2 =
@@ -890,9 +890,9 @@ TEST_F(FlowConditionTest, Disjunction) {
                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
                 ASSERT_THAT(BarDecl, NotNull());
 
-                ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
 
-                const Environment &Env1 = Results[1].second.Env;
+                const Environment &Env1 = Results[0].second.Env;
                 auto *FooVal1 =
                     cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal1 =
@@ -900,7 +900,7 @@ TEST_F(FlowConditionTest, Disjunction) {
                 EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
                 EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
 
-                const Environment &Env2 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
                 auto *FooVal2 =
                     cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal2 =
@@ -933,9 +933,9 @@ TEST_F(FlowConditionTest, NegatedConjunction) {
                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
                 ASSERT_THAT(BarDecl, NotNull());
 
-                ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
 
-                const Environment &Env1 = Results[1].second.Env;
+                const Environment &Env1 = Results[0].second.Env;
                 auto *FooVal1 =
                     cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal1 =
@@ -943,7 +943,7 @@ TEST_F(FlowConditionTest, NegatedConjunction) {
                 EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
                 EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
 
-                const Environment &Env2 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
                 auto *FooVal2 =
                     cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal2 =
@@ -976,9 +976,9 @@ TEST_F(FlowConditionTest, DeMorgan) {
                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
                 ASSERT_THAT(BarDecl, NotNull());
 
-                ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+                ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
 
-                const Environment &Env1 = Results[1].second.Env;
+                const Environment &Env1 = Results[0].second.Env;
                 auto *FooVal1 =
                     cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal1 =
@@ -986,7 +986,7 @@ TEST_F(FlowConditionTest, DeMorgan) {
                 EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
                 EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
 
-                const Environment &Env2 = Results[0].second.Env;
+                const Environment &Env2 = Results[1].second.Env;
                 auto *FooVal2 =
                     cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
                 auto *BarVal2 =
@@ -1159,16 +1159,16 @@ TEST_F(FlowConditionTest, PointerToBoolImplicitCast) {
                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
                    Results,
                ASTContext &ASTCtx) {
-        ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+        ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
         ASSERT_THAT(FooDecl, NotNull());
 
-        const Environment &Env1 = Results[1].second.Env;
+        const Environment &Env1 = Results[0].second.Env;
         auto &FooVal1 =
             *cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::Reference));
         EXPECT_TRUE(Env1.flowConditionImplies(FooVal1));
 
-        const Environment &Env2 = Results[0].second.Env;
+        const Environment &Env2 = Results[1].second.Env;
         auto &FooVal2 =
             *cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::Reference));
         EXPECT_FALSE(Env2.flowConditionImplies(FooVal2));


        


More information about the cfe-commits mailing list