xref: /llvm-project/clang/unittests/AST/DataCollectionTest.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
11a267692SJohannes Altmanninger //===- unittests/AST/DataCollectionTest.cpp -------------------------------===//
21a267692SJohannes Altmanninger //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61a267692SJohannes Altmanninger //
71a267692SJohannes Altmanninger //===----------------------------------------------------------------------===//
81a267692SJohannes Altmanninger //
91a267692SJohannes Altmanninger // This file contains tests for the DataCollection module.
101a267692SJohannes Altmanninger //
111a267692SJohannes Altmanninger // They work by hashing the collected data of two nodes and asserting that the
121a267692SJohannes Altmanninger // hash values are equal iff the nodes are considered equal.
131a267692SJohannes Altmanninger //
141a267692SJohannes Altmanninger //===----------------------------------------------------------------------===//
151a267692SJohannes Altmanninger 
161a267692SJohannes Altmanninger #include "clang/AST/DataCollection.h"
171a267692SJohannes Altmanninger #include "clang/AST/DeclTemplate.h"
181a267692SJohannes Altmanninger #include "clang/AST/StmtVisitor.h"
191a267692SJohannes Altmanninger #include "clang/ASTMatchers/ASTMatchFinder.h"
201a267692SJohannes Altmanninger #include "clang/Tooling/Tooling.h"
211a267692SJohannes Altmanninger #include "gtest/gtest.h"
221a267692SJohannes Altmanninger 
231a267692SJohannes Altmanninger using namespace clang;
241a267692SJohannes Altmanninger using namespace tooling;
251a267692SJohannes Altmanninger using namespace ast_matchers;
261a267692SJohannes Altmanninger 
271a267692SJohannes Altmanninger namespace {
281a267692SJohannes Altmanninger class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector> {
291a267692SJohannes Altmanninger   ASTContext &Context;
301a267692SJohannes Altmanninger   llvm::MD5 &DataConsumer;
311a267692SJohannes Altmanninger 
addData(const T & Data)321a267692SJohannes Altmanninger   template <class T> void addData(const T &Data) {
331a267692SJohannes Altmanninger     data_collection::addDataToConsumer(DataConsumer, Data);
341a267692SJohannes Altmanninger   }
351a267692SJohannes Altmanninger 
361a267692SJohannes Altmanninger public:
StmtDataCollector(const Stmt * S,ASTContext & Context,llvm::MD5 & DataConsumer)371a267692SJohannes Altmanninger   StmtDataCollector(const Stmt *S, ASTContext &Context, llvm::MD5 &DataConsumer)
381a267692SJohannes Altmanninger       : Context(Context), DataConsumer(DataConsumer) {
391a267692SJohannes Altmanninger     this->Visit(S);
401a267692SJohannes Altmanninger   }
411a267692SJohannes Altmanninger 
421a267692SJohannes Altmanninger #define DEF_ADD_DATA(CLASS, CODE)                                              \
431a267692SJohannes Altmanninger   template <class Dummy = void> Dummy Visit##CLASS(const CLASS *S) {           \
441a267692SJohannes Altmanninger     CODE;                                                                      \
451a267692SJohannes Altmanninger     ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S);                      \
461a267692SJohannes Altmanninger   }
471a267692SJohannes Altmanninger 
481509da08SJohannes Altmanninger #include "clang/AST/StmtDataCollectors.inc"
491a267692SJohannes Altmanninger };
501a267692SJohannes Altmanninger } // end anonymous namespace
511a267692SJohannes Altmanninger 
521a267692SJohannes Altmanninger namespace {
531a267692SJohannes Altmanninger struct StmtHashMatch : public MatchFinder::MatchCallback {
541a267692SJohannes Altmanninger   unsigned NumFound;
551a267692SJohannes Altmanninger   llvm::MD5::MD5Result &Hash;
StmtHashMatch__anonc11d63060211::StmtHashMatch561a267692SJohannes Altmanninger   StmtHashMatch(llvm::MD5::MD5Result &Hash) : NumFound(0), Hash(Hash) {}
571a267692SJohannes Altmanninger 
run__anonc11d63060211::StmtHashMatch581a267692SJohannes Altmanninger   void run(const MatchFinder::MatchResult &Result) override {
591a267692SJohannes Altmanninger     const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id");
601a267692SJohannes Altmanninger     if (!S)
611a267692SJohannes Altmanninger       return;
621a267692SJohannes Altmanninger     ++NumFound;
631a267692SJohannes Altmanninger     if (NumFound > 1)
641a267692SJohannes Altmanninger       return;
651a267692SJohannes Altmanninger     llvm::MD5 MD5;
661a267692SJohannes Altmanninger     StmtDataCollector(S, *Result.Context, MD5);
671a267692SJohannes Altmanninger     MD5.final(Hash);
681a267692SJohannes Altmanninger   }
691a267692SJohannes Altmanninger };
701a267692SJohannes Altmanninger } // end anonymous namespace
711a267692SJohannes Altmanninger 
hashStmt(llvm::MD5::MD5Result & Hash,const StatementMatcher & StmtMatch,StringRef Code)721a267692SJohannes Altmanninger static testing::AssertionResult hashStmt(llvm::MD5::MD5Result &Hash,
731a267692SJohannes Altmanninger                                          const StatementMatcher &StmtMatch,
741a267692SJohannes Altmanninger                                          StringRef Code) {
751a267692SJohannes Altmanninger   StmtHashMatch Hasher(Hash);
761a267692SJohannes Altmanninger   MatchFinder Finder;
771a267692SJohannes Altmanninger   Finder.addMatcher(StmtMatch, &Hasher);
781a267692SJohannes Altmanninger   std::unique_ptr<FrontendActionFactory> Factory(
791a267692SJohannes Altmanninger       newFrontendActionFactory(&Finder));
801a267692SJohannes Altmanninger   if (!runToolOnCode(Factory->create(), Code))
811a267692SJohannes Altmanninger     return testing::AssertionFailure()
821a267692SJohannes Altmanninger            << "Parsing error in \"" << Code.str() << "\"";
831a267692SJohannes Altmanninger   if (Hasher.NumFound == 0)
841a267692SJohannes Altmanninger     return testing::AssertionFailure() << "Matcher didn't find any statements";
851a267692SJohannes Altmanninger   if (Hasher.NumFound > 1)
861a267692SJohannes Altmanninger     return testing::AssertionFailure()
871a267692SJohannes Altmanninger            << "Matcher should match only one statement "
881a267692SJohannes Altmanninger               "(found "
891a267692SJohannes Altmanninger            << Hasher.NumFound << ")";
901a267692SJohannes Altmanninger   return testing::AssertionSuccess();
911a267692SJohannes Altmanninger }
921a267692SJohannes Altmanninger 
931a267692SJohannes Altmanninger static testing::AssertionResult
isStmtHashEqual(const StatementMatcher & StmtMatch,StringRef Code1,StringRef Code2)941a267692SJohannes Altmanninger isStmtHashEqual(const StatementMatcher &StmtMatch, StringRef Code1,
951a267692SJohannes Altmanninger                 StringRef Code2) {
961a267692SJohannes Altmanninger   llvm::MD5::MD5Result Hash1, Hash2;
971a267692SJohannes Altmanninger   testing::AssertionResult Result = hashStmt(Hash1, StmtMatch, Code1);
981a267692SJohannes Altmanninger   if (!Result)
991a267692SJohannes Altmanninger     return Result;
1001a267692SJohannes Altmanninger   if (!(Result = hashStmt(Hash2, StmtMatch, Code2)))
1011a267692SJohannes Altmanninger     return Result;
1021a267692SJohannes Altmanninger 
1031a267692SJohannes Altmanninger   return testing::AssertionResult(Hash1 == Hash2);
1041a267692SJohannes Altmanninger }
1051a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestDeclRefExpr)1061a267692SJohannes Altmanninger TEST(StmtDataCollector, TestDeclRefExpr) {
1071a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(declRefExpr().bind("id"), "int x, r = x;",
1081a267692SJohannes Altmanninger                               "int x, r = x;"));
1091a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(declRefExpr().bind("id"), "int x, r = x;",
1101a267692SJohannes Altmanninger                                "int y, r = y;"));
1111a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(declRefExpr().bind("id"), "int x, r = x;",
1121a267692SJohannes Altmanninger                                "namespace n { int x, r = x; };"));
1131a267692SJohannes Altmanninger }
1141a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestMemberExpr)1151a267692SJohannes Altmanninger TEST(StmtDataCollector, TestMemberExpr) {
1161a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(memberExpr().bind("id"),
1171a267692SJohannes Altmanninger                               "struct { int x; } X; int r = X.x;",
1181a267692SJohannes Altmanninger                               "struct { int x; } X; int r = (&X)->x;"));
1191a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(memberExpr().bind("id"),
1201a267692SJohannes Altmanninger                               "struct { int x; } X; int r = X.x;",
1211a267692SJohannes Altmanninger                               "struct { int x; } Y; int r = Y.x;"));
1221a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(memberExpr().bind("id"),
1231a267692SJohannes Altmanninger                               "struct { int x; } X; int r = X.x;",
1241a267692SJohannes Altmanninger                               "struct C { int x; } X; int r = X.C::x;"));
1251a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(memberExpr().bind("id"),
1261a267692SJohannes Altmanninger                                "struct { int x; } X; int r = X.x;",
1271a267692SJohannes Altmanninger                                "struct { int y; } X; int r = X.y;"));
1281a267692SJohannes Altmanninger }
1291a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestIntegerLiteral)1301a267692SJohannes Altmanninger TEST(StmtDataCollector, TestIntegerLiteral) {
1311a267692SJohannes Altmanninger   ASSERT_TRUE(
1321a267692SJohannes Altmanninger       isStmtHashEqual(integerLiteral().bind("id"), "int x = 0;", "int x = 0;"));
1331a267692SJohannes Altmanninger   ASSERT_TRUE(
1341a267692SJohannes Altmanninger       isStmtHashEqual(integerLiteral().bind("id"), "int x = 0;", "int x =00;"));
1351a267692SJohannes Altmanninger   ASSERT_FALSE(
1361a267692SJohannes Altmanninger       isStmtHashEqual(integerLiteral().bind("id"), "int x = 0;", "int x = 1;"));
1371a267692SJohannes Altmanninger }
1381a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestFloatingLiteral)1391a267692SJohannes Altmanninger TEST(StmtDataCollector, TestFloatingLiteral) {
1401a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .0;",
1411a267692SJohannes Altmanninger                               "double x = .0;"));
1421a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .10;",
1431a267692SJohannes Altmanninger                               "double x = .1;"));
1441a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .1;",
1451a267692SJohannes Altmanninger                               "double x = 1e-1;"));
1461a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(floatLiteral().bind("id"), "double x = .0;",
1471a267692SJohannes Altmanninger                                "double x = .1;"));
1481a267692SJohannes Altmanninger }
1491a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestStringLiteral)1501a267692SJohannes Altmanninger TEST(StmtDataCollector, TestStringLiteral) {
1511a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(stringLiteral().bind("id"), R"(char x[] = "0";)",
1521a267692SJohannes Altmanninger                               R"(char x[] = "0";)"));
1531a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(stringLiteral().bind("id"), R"(char x[] = "0";)",
1541a267692SJohannes Altmanninger                                R"(char x[] = "1";)"));
1551a267692SJohannes Altmanninger }
1561a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestCXXBoolLiteral)1571a267692SJohannes Altmanninger TEST(StmtDataCollector, TestCXXBoolLiteral) {
1581a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(cxxBoolLiteral().bind("id"), "bool x = false;",
1591a267692SJohannes Altmanninger                               "bool x = false;"));
1601a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(cxxBoolLiteral().bind("id"), "bool x = false;",
1611a267692SJohannes Altmanninger                                "bool x = true;"));
1621a267692SJohannes Altmanninger }
1631a267692SJohannes Altmanninger 
TEST(StmtDataCollector,TestCharacterLiteral)1641a267692SJohannes Altmanninger TEST(StmtDataCollector, TestCharacterLiteral) {
1651a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(characterLiteral().bind("id"), "char x = '0';",
1661a267692SJohannes Altmanninger                               "char x = '0';"));
1671a267692SJohannes Altmanninger   ASSERT_TRUE(isStmtHashEqual(characterLiteral().bind("id"),
1681a267692SJohannes Altmanninger                               R"(char x = '\0';)",
1691a267692SJohannes Altmanninger                               R"(char x = '\x00';)"));
1701a267692SJohannes Altmanninger   ASSERT_FALSE(isStmtHashEqual(characterLiteral().bind("id"), "char x = '0';",
1711a267692SJohannes Altmanninger                                "char x = '1';"));
1721a267692SJohannes Altmanninger }
173