1 //===- unittests/AST/DataCollectionTest.cpp -------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains tests for the DataCollection module. 11 // 12 // They work by hashing the collected data of two nodes and asserting that the 13 // hash values are equal iff the nodes are considered equal. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "clang/AST/DataCollection.h" 18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/AST/StmtVisitor.h" 20 #include "clang/ASTMatchers/ASTMatchFinder.h" 21 #include "clang/Tooling/Tooling.h" 22 #include "gtest/gtest.h" 23 24 using namespace clang; 25 using namespace tooling; 26 using namespace ast_matchers; 27 28 namespace { 29 class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector> { 30 ASTContext &Context; 31 llvm::MD5 &DataConsumer; 32 33 template <class T> void addData(const T &Data) { 34 data_collection::addDataToConsumer(DataConsumer, Data); 35 } 36 37 public: 38 StmtDataCollector(const Stmt *S, ASTContext &Context, llvm::MD5 &DataConsumer) 39 : Context(Context), DataConsumer(DataConsumer) { 40 this->Visit(S); 41 } 42 43 #define DEF_ADD_DATA(CLASS, CODE) \ 44 template <class Dummy = void> Dummy Visit##CLASS(const CLASS *S) { \ 45 CODE; \ 46 ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \ 47 } 48 49 #include "../../lib/AST/StmtDataCollectors.inc" 50 }; 51 } // end anonymous namespace 52 53 namespace { 54 struct StmtHashMatch : public MatchFinder::MatchCallback { 55 unsigned NumFound; 56 llvm::MD5::MD5Result &Hash; 57 StmtHashMatch(llvm::MD5::MD5Result &Hash) : NumFound(0), Hash(Hash) {} 58 59 void run(const MatchFinder::MatchResult &Result) override { 60 const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id"); 61 if (!S) 62 return; 63 ++NumFound; 64 if (NumFound > 1) 65 return; 66 llvm::MD5 MD5; 67 StmtDataCollector(S, *Result.Context, MD5); 68 MD5.final(Hash); 69 } 70 }; 71 } // end anonymous namespace 72 73 static testing::AssertionResult hashStmt(llvm::MD5::MD5Result &Hash, 74 const StatementMatcher &StmtMatch, 75 StringRef Code) { 76 StmtHashMatch Hasher(Hash); 77 MatchFinder Finder; 78 Finder.addMatcher(StmtMatch, &Hasher); 79 std::unique_ptr<FrontendActionFactory> Factory( 80 newFrontendActionFactory(&Finder)); 81 if (!runToolOnCode(Factory->create(), Code)) 82 return testing::AssertionFailure() 83 << "Parsing error in \"" << Code.str() << "\""; 84 if (Hasher.NumFound == 0) 85 return testing::AssertionFailure() << "Matcher didn't find any statements"; 86 if (Hasher.NumFound > 1) 87 return testing::AssertionFailure() 88 << "Matcher should match only one statement " 89 "(found " 90 << Hasher.NumFound << ")"; 91 return testing::AssertionSuccess(); 92 } 93 94 static testing::AssertionResult 95 isStmtHashEqual(const StatementMatcher &StmtMatch, StringRef Code1, 96 StringRef Code2) { 97 llvm::MD5::MD5Result Hash1, Hash2; 98 testing::AssertionResult Result = hashStmt(Hash1, StmtMatch, Code1); 99 if (!Result) 100 return Result; 101 if (!(Result = hashStmt(Hash2, StmtMatch, Code2))) 102 return Result; 103 104 return testing::AssertionResult(Hash1 == Hash2); 105 } 106 107 TEST(StmtDataCollector, TestDeclRefExpr) { 108 ASSERT_TRUE(isStmtHashEqual(declRefExpr().bind("id"), "int x, r = x;", 109 "int x, r = x;")); 110 ASSERT_FALSE(isStmtHashEqual(declRefExpr().bind("id"), "int x, r = x;", 111 "int y, r = y;")); 112 ASSERT_FALSE(isStmtHashEqual(declRefExpr().bind("id"), "int x, r = x;", 113 "namespace n { int x, r = x; };")); 114 } 115 116 TEST(StmtDataCollector, TestMemberExpr) { 117 ASSERT_TRUE(isStmtHashEqual(memberExpr().bind("id"), 118 "struct { int x; } X; int r = X.x;", 119 "struct { int x; } X; int r = (&X)->x;")); 120 ASSERT_TRUE(isStmtHashEqual(memberExpr().bind("id"), 121 "struct { int x; } X; int r = X.x;", 122 "struct { int x; } Y; int r = Y.x;")); 123 ASSERT_TRUE(isStmtHashEqual(memberExpr().bind("id"), 124 "struct { int x; } X; int r = X.x;", 125 "struct C { int x; } X; int r = X.C::x;")); 126 ASSERT_FALSE(isStmtHashEqual(memberExpr().bind("id"), 127 "struct { int x; } X; int r = X.x;", 128 "struct { int y; } X; int r = X.y;")); 129 } 130 131 TEST(StmtDataCollector, TestIntegerLiteral) { 132 ASSERT_TRUE( 133 isStmtHashEqual(integerLiteral().bind("id"), "int x = 0;", "int x = 0;")); 134 ASSERT_TRUE( 135 isStmtHashEqual(integerLiteral().bind("id"), "int x = 0;", "int x =00;")); 136 ASSERT_FALSE( 137 isStmtHashEqual(integerLiteral().bind("id"), "int x = 0;", "int x = 1;")); 138 } 139 140 TEST(StmtDataCollector, TestFloatingLiteral) { 141 ASSERT_TRUE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .0;", 142 "double x = .0;")); 143 ASSERT_TRUE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .10;", 144 "double x = .1;")); 145 ASSERT_TRUE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .1;", 146 "double x = 1e-1;")); 147 ASSERT_FALSE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .0;", 148 "double x = .1;")); 149 } 150 151 TEST(StmtDataCollector, TestStringLiteral) { 152 ASSERT_TRUE(isStmtHashEqual(stringLiteral().bind("id"), R"(char x[] = "0";)", 153 R"(char x[] = "0";)")); 154 ASSERT_FALSE(isStmtHashEqual(stringLiteral().bind("id"), R"(char x[] = "0";)", 155 R"(char x[] = "1";)")); 156 } 157 158 TEST(StmtDataCollector, TestCXXBoolLiteral) { 159 ASSERT_TRUE(isStmtHashEqual(cxxBoolLiteral().bind("id"), "bool x = false;", 160 "bool x = false;")); 161 ASSERT_FALSE(isStmtHashEqual(cxxBoolLiteral().bind("id"), "bool x = false;", 162 "bool x = true;")); 163 } 164 165 TEST(StmtDataCollector, TestCharacterLiteral) { 166 ASSERT_TRUE(isStmtHashEqual(characterLiteral().bind("id"), "char x = '0';", 167 "char x = '0';")); 168 ASSERT_TRUE(isStmtHashEqual(characterLiteral().bind("id"), 169 R"(char x = '\0';)", 170 R"(char x = '\x00';)")); 171 ASSERT_FALSE(isStmtHashEqual(characterLiteral().bind("id"), "char x = '0';", 172 "char x = '1';")); 173 } 174