diff options
Diffstat (limited to 'clang/unittests/Analysis/FlowSensitive/TransferTest.cpp')
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 280 |
1 files changed, 1 insertions, 279 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 96e759e..214aaee 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -9,25 +9,17 @@ #include "TestingSupport.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/OperationKinds.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" -#include "clang/Analysis/FlowSensitive/NoopLattice.h" #include "clang/Analysis/FlowSensitive/RecordOps.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Basic/LangStandard.h" #include "clang/Testing/TestAST.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -35,7 +27,6 @@ #include <string> #include <string_view> #include <utility> -#include <vector> namespace clang { namespace dataflow { @@ -3550,7 +3541,7 @@ TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) { testFunction(Code, "noexceptTarget"); } -TEST(TransferTest, StaticCastNoOp) { +TEST(TransferTest, StaticCast) { std::string Code = R"( void target(int Foo) { int Bar = static_cast<int>(Foo); @@ -3570,13 +3561,6 @@ TEST(TransferTest, StaticCastNoOp) { const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); ASSERT_THAT(BarDecl, NotNull()); - const auto *Cast = ast_matchers::selectFirst<CXXStaticCastExpr>( - "cast", - ast_matchers::match(ast_matchers::cxxStaticCastExpr().bind("cast"), - ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_NoOp); - const auto *FooVal = Env.getValue(*FooDecl); const auto *BarVal = Env.getValue(*BarDecl); EXPECT_TRUE(isa<IntegerValue>(FooVal)); @@ -3585,268 +3569,6 @@ TEST(TransferTest, StaticCastNoOp) { }); } -TEST(TransferTest, StaticCastBaseToDerived) { - std::string Code = R"cc( - struct Base { - char C; - }; - struct Intermediate : public Base { - bool B; - }; - struct Derived : public Intermediate { - int I; - }; - Base& getBaseRef(); - void target(Base* BPtr) { - Derived* DPtr = static_cast<Derived*>(BPtr); - DPtr->C; - DPtr->B; - DPtr->I; - Derived& DRef = static_cast<Derived&>(*BPtr); - DRef.C; - DRef.B; - DRef.I; - Derived& DRefFromFunc = static_cast<Derived&>(getBaseRef()); - DRefFromFunc.C; - DRefFromFunc.B; - DRefFromFunc.I; - // [[p]] - } - )cc"; - runDataflow( - Code, - [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - - const ValueDecl *BPtrDecl = findValueDecl(ASTCtx, "BPtr"); - ASSERT_THAT(BPtrDecl, NotNull()); - - const ValueDecl *DPtrDecl = findValueDecl(ASTCtx, "DPtr"); - ASSERT_THAT(DPtrDecl, NotNull()); - - const ValueDecl *DRefDecl = findValueDecl(ASTCtx, "DRef"); - ASSERT_THAT(DRefDecl, NotNull()); - - const ValueDecl *DRefFromFuncDecl = - findValueDecl(ASTCtx, "DRefFromFunc"); - ASSERT_THAT(DRefFromFuncDecl, NotNull()); - - const auto *Cast = ast_matchers::selectFirst<CXXStaticCastExpr>( - "cast", - ast_matchers::match(ast_matchers::cxxStaticCastExpr().bind("cast"), - ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_BaseToDerived); - - EXPECT_EQ(Env.getValue(*BPtrDecl), Env.getValue(*DPtrDecl)); - EXPECT_EQ(&Env.get<PointerValue>(*BPtrDecl)->getPointeeLoc(), - Env.getStorageLocation(*DRefDecl)); - // For DRefFromFunc, not crashing when analyzing the field accesses is - // enough. - }); -} - -TEST(TransferTest, ExplicitDerivedToBaseCast) { - std::string Code = R"cc( - struct Base {}; - struct Derived : public Base {}; - void target(Derived D) { - (Base*)&D; - // [[p]] - } -)cc"; - runDataflow( - Code, - [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - - auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>( - "cast", ast_matchers::match( - ast_matchers::implicitCastExpr().bind("cast"), ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_DerivedToBase); - - auto *AddressOf = ast_matchers::selectFirst<UnaryOperator>( - "addressof", - ast_matchers::match(ast_matchers::unaryOperator().bind("addressof"), - ASTCtx)); - ASSERT_THAT(AddressOf, NotNull()); - ASSERT_EQ(AddressOf->getOpcode(), UO_AddrOf); - - EXPECT_EQ(Env.getValue(*Cast), Env.getValue(*AddressOf)); - }); -} - -TEST(TransferTest, ConstructorConversion) { - std::string Code = R"cc( - struct Base {}; - struct Derived : public Base {}; - void target(Derived D) { - Base B = (Base)D; - // [[p]] - } -)cc"; - runDataflow( - Code, - [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - - auto *Cast = ast_matchers::selectFirst<CStyleCastExpr>( - "cast", ast_matchers::match( - ast_matchers::cStyleCastExpr().bind("cast"), ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_ConstructorConversion); - - auto &DLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "D"); - auto &BLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "B"); - EXPECT_NE(&BLoc, &DLoc); - }); -} - -TEST(TransferTest, UserDefinedConversion) { - std::string Code = R"cc( - struct To {}; - struct From { - operator To(); - }; - void target(From F) { - To T = (To)F; - // [[p]] - } -)cc"; - runDataflow( - Code, - [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - - auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>( - "cast", ast_matchers::match( - ast_matchers::implicitCastExpr().bind("cast"), ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_UserDefinedConversion); - - auto &FLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "F"); - auto &TLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "T"); - EXPECT_NE(&TLoc, &FLoc); - }); -} - -TEST(TransferTest, ImplicitUncheckedDerivedToBaseCast) { - std::string Code = R"cc( - struct Base { - void method(); - }; - struct Derived : public Base {}; - void target(Derived D) { - D.method(); - // [[p]] - } -)cc"; - runDataflow( - Code, - [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - - auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>( - "cast", ast_matchers::match( - ast_matchers::implicitCastExpr().bind("cast"), ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_UncheckedDerivedToBase); - - auto &DLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "D"); - EXPECT_EQ(Env.getStorageLocation(*Cast), &DLoc); - }); -} - -TEST(TransferTest, ImplicitDerivedToBaseCast) { - std::string Code = R"cc( - struct Base {}; - struct Derived : public Base {}; - void target() { - Base* B = new Derived(); - // [[p]] - } -)cc"; - runDataflow( - Code, - [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - - auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>( - "cast", ast_matchers::match( - ast_matchers::implicitCastExpr().bind("cast"), ASTCtx)); - ASSERT_THAT(Cast, NotNull()); - ASSERT_EQ(Cast->getCastKind(), CK_DerivedToBase); - - auto *New = ast_matchers::selectFirst<CXXNewExpr>( - "new", ast_matchers::match(ast_matchers::cxxNewExpr().bind("new"), - ASTCtx)); - ASSERT_THAT(New, NotNull()); - - EXPECT_EQ(Env.getValue(*Cast), Env.getValue(*New)); - }); -} - -TEST(TransferTest, ReinterpretCast) { - std::string Code = R"cc( - struct S { - int I; - }; - - void target(unsigned char* Bytes) { - S& SRef = reinterpret_cast<S&>(Bytes); - SRef.I; - S* SPtr = reinterpret_cast<S*>(Bytes); - SPtr->I; - // [[p]] - } - )cc"; - runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> - &Results, - ASTContext &ASTCtx) { - ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); - const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); - const ValueDecl *I = findValueDecl(ASTCtx, "I"); - ASSERT_THAT(I, NotNull()); - - // No particular knowledge of I's value is modeled, but for both casts, - // the fields of S are modeled. - - { - auto &Loc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "SRef"); - std::vector<const ValueDecl *> Children; - for (const auto &Entry : Loc.children()) { - Children.push_back(Entry.getFirst()); - } - - EXPECT_THAT(Children, UnorderedElementsAre(I)); - } - - { - auto &Loc = cast<RecordStorageLocation>( - getValueForDecl<PointerValue>(ASTCtx, Env, "SPtr").getPointeeLoc()); - std::vector<const ValueDecl *> Children; - for (const auto &Entry : Loc.children()) { - Children.push_back(Entry.getFirst()); - } - - EXPECT_THAT(Children, UnorderedElementsAre(I)); - } - }); -} - TEST(TransferTest, IntegralCast) { std::string Code = R"( void target(int Foo) { |