diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h --- 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 @@ /// /// Annotations must not be repeated. template -llvm::Error checkDataflow( - AnalysisInputs AI, - std::function>>, - const AnalysisOutputs &)> - VerifyResults) { +llvm::Error +checkDataflow(AnalysisInputs AI, + std::function> &, + const AnalysisOutputs &)> + VerifyResults) { // Compute mapping from nodes of annotated statements to the content in the // annotation. llvm::DenseMap StmtToAnnotations; @@ -308,11 +308,9 @@ using StateT = DataflowAnalysisState; - // 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> AnnotationStates; + llvm::StringMap AnnotationStates; auto PostVisitCFG = [&StmtToAnnotations, &AnnotationStates, PrevPostVisitCFG = std::move(AI.PostVisitCFG)]( ASTContext &Ctx, const CFGElement &Elt, @@ -329,7 +327,10 @@ return; auto *Lattice = llvm::any_cast(&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( std::move(AI) @@ -378,12 +379,20 @@ std::move(MakeAnalysis)) .withASTBuildArgs(std::move(Args)) .withASTBuildVirtualMappedFiles(std::move(VirtualMappedFiles)), - [&VerifyResults]( - llvm::ArrayRef>> - AnnotationStates, - const AnalysisOutputs &AO) { - VerifyResults(AnnotationStates, AO.ASTCtx); + [&VerifyResults](const llvm::StringMap> &AnnotationStates, + const AnalysisOutputs &AO) { + std::vector>> + 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/TestingSupport.cpp b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp --- 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 @@ -72,6 +73,7 @@ test::buildStatementToAnnotationMapping(const FunctionDecl *Func, llvm::Annotations AnnotatedCode) { llvm::DenseMap Result; + llvm::StringSet<> ExistingAnnotations; auto StmtMatcher = findAll(stmt(unless(anyOf(hasParent(expr()), hasParent(returnStmt())))) @@ -113,7 +115,14 @@ .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/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -649,8 +649,8 @@ std::string, DataflowAnalysisState>> 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 @@ 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 @@ 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(Env.getValue(*BDecl, SkipPast::None)); @@ -3322,8 +3322,8 @@ } { - 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(Env.getValue(*CDecl, SkipPast::None)); EXPECT_TRUE(Env.flowConditionImplies(CVal)); } @@ -3422,9 +3422,9 @@ 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 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -426,12 +426,12 @@ std::pair>> 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 @@ 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 @@ std::pair>> 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 @@ 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(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(Env2.getValue(*FooDecl, SkipPast::None)); EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2)); @@ -785,14 +785,14 @@ 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(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(Env2.getValue(*FooDecl, SkipPast::None)); EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2)); @@ -847,9 +847,9 @@ 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(Env1.getValue(*FooDecl, SkipPast::None)); auto *BarVal1 = @@ -857,7 +857,7 @@ 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(Env2.getValue(*FooDecl, SkipPast::None)); auto *BarVal2 = @@ -890,9 +890,9 @@ 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(Env1.getValue(*FooDecl, SkipPast::None)); auto *BarVal1 = @@ -900,7 +900,7 @@ 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(Env2.getValue(*FooDecl, SkipPast::None)); auto *BarVal2 = @@ -933,9 +933,9 @@ 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(Env1.getValue(*FooDecl, SkipPast::None)); auto *BarVal1 = @@ -943,7 +943,7 @@ 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(Env2.getValue(*FooDecl, SkipPast::None)); auto *BarVal2 = @@ -976,9 +976,9 @@ 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(Env1.getValue(*FooDecl, SkipPast::None)); auto *BarVal1 = @@ -986,7 +986,7 @@ 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(Env2.getValue(*FooDecl, SkipPast::None)); auto *BarVal2 = @@ -1159,16 +1159,16 @@ std::pair>> 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(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(Env2.getValue(*FooDecl, SkipPast::Reference)); EXPECT_FALSE(Env2.flowConditionImplies(FooVal2));