14da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek//===- unittest/Tooling/ASTMatchersTest.h - Matcher tests helpers ------===// 24da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// 34da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// The LLVM Compiler Infrastructure 44da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// 54da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// This file is distributed under the University of Illinois Open Source 64da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// License. See LICENSE.TXT for details. 74da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// 84da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek//===----------------------------------------------------------------------===// 94da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 104da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek#ifndef LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H 114da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek#define LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H 124da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 134da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek#include "clang/ASTMatchers/ASTMatchFinder.h" 1451fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne#include "clang/Frontend/ASTUnit.h" 154da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek#include "clang/Tooling/Tooling.h" 164da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek#include "gtest/gtest.h" 174da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 184da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimeknamespace clang { 194da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimeknamespace ast_matchers { 204da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 2151fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourneusing clang::tooling::buildASTFromCodeWithArgs; 224da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekusing clang::tooling::newFrontendActionFactory; 2350f88b99c60c2ed31b339cd8bd484766cc9e916bNico Weberusing clang::tooling::runToolOnCodeWithArgs; 244da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekusing clang::tooling::FrontendActionFactory; 254da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 264da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekclass BoundNodesCallback { 274da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekpublic: 284da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek virtual ~BoundNodesCallback() {} 29452abbc76b775169dc01c359e94a7f666ebc8692Daniel Jasper virtual bool run(const BoundNodes *BoundNodes) = 0; 30452abbc76b775169dc01c359e94a7f666ebc8692Daniel Jasper virtual bool run(const BoundNodes *BoundNodes, ASTContext *Context) = 0; 31d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne virtual void onEndOfTranslationUnit() {} 324da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek}; 334da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 344da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// If 'FindResultVerifier' is not NULL, sets *Verified to the result of 354da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// running 'FindResultVerifier' with the bound nodes as argument. 364da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// If 'FindResultVerifier' is NULL, sets *Verified to true when Run is called. 374da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekclass VerifyMatch : public MatchFinder::MatchCallback { 384da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekpublic: 394da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek VerifyMatch(BoundNodesCallback *FindResultVerifier, bool *Verified) 404da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek : Verified(Verified), FindResultReviewer(FindResultVerifier) {} 414da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 424da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek virtual void run(const MatchFinder::MatchResult &Result) { 43ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (FindResultReviewer != nullptr) { 4411c98771ba5d7fb1ec5707f9e1c77a6cf65bbc59Daniel Jasper *Verified |= FindResultReviewer->run(&Result.Nodes, Result.Context); 454da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } else { 464da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek *Verified = true; 474da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } 484da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } 494da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 50651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void onEndOfTranslationUnit() override { 51d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne if (FindResultReviewer) 52d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne FindResultReviewer->onEndOfTranslationUnit(); 53d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne } 54d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne 554da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimekprivate: 564da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek bool *const Verified; 574da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek BoundNodesCallback *const FindResultReviewer; 584da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek}; 594da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 604da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektemplate <typename T> 614da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektesting::AssertionResult matchesConditionally(const std::string &Code, 624da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek const T &AMatcher, 6331f7c08a0d2b140bf31a08894d1948649de53c15Daniel Jasper bool ExpectMatch, 6431f7c08a0d2b140bf31a08894d1948649de53c15Daniel Jasper llvm::StringRef CompileArg) { 65d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne bool Found = false, DynamicFound = false; 664da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek MatchFinder Finder; 67ef8225444452a1486bd721f3285301fe84643b00Stephen Hines VerifyMatch VerifyFound(nullptr, &Found); 686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Finder.addMatcher(AMatcher, &VerifyFound); 69ef8225444452a1486bd721f3285301fe84643b00Stephen Hines VerifyMatch VerifyDynamicFound(nullptr, &DynamicFound); 706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Finder.addDynamicMatcher(AMatcher, &VerifyDynamicFound)) 71d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne return testing::AssertionFailure() << "Could not add dynamic matcher"; 72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<FrontendActionFactory> Factory( 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines newFrontendActionFactory(&Finder)); 7450f88b99c60c2ed31b339cd8bd484766cc9e916bNico Weber // Some tests use typeof, which is a gnu extension. 7531f7c08a0d2b140bf31a08894d1948649de53c15Daniel Jasper std::vector<std::string> Args(1, CompileArg); 7650f88b99c60c2ed31b339cd8bd484766cc9e916bNico Weber if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) { 774da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; 784da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } 79d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne if (Found != DynamicFound) { 80d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne return testing::AssertionFailure() << "Dynamic match result (" 81d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne << DynamicFound 82d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne << ") does not match static result (" 83d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne << Found << ")"; 84d2bd58907f77e1c1b68a6fa8fc72e1c5b057a5b1Peter Collingbourne } 854da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek if (!Found && ExpectMatch) { 864da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionFailure() 874da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek << "Could not find match in \"" << Code << "\""; 884da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } else if (Found && !ExpectMatch) { 894da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionFailure() 904da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek << "Found unexpected match in \"" << Code << "\""; 914da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } 924da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionSuccess(); 934da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} 944da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 954da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektemplate <typename T> 964da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektesting::AssertionResult matches(const std::string &Code, const T &AMatcher) { 9731f7c08a0d2b140bf31a08894d1948649de53c15Daniel Jasper return matchesConditionally(Code, AMatcher, true, "-std=c++11"); 984da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} 994da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 1004da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektemplate <typename T> 1014da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektesting::AssertionResult notMatches(const std::string &Code, 1024da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek const T &AMatcher) { 10331f7c08a0d2b140bf31a08894d1948649de53c15Daniel Jasper return matchesConditionally(Code, AMatcher, false, "-std=c++11"); 1044da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} 1054da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 1064da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektemplate <typename T> 1074da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektesting::AssertionResult 1084da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel KlimekmatchAndVerifyResultConditionally(const std::string &Code, const T &AMatcher, 1094da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek BoundNodesCallback *FindResultVerifier, 1104da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek bool ExpectResult) { 111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<BoundNodesCallback> ScopedVerifier(FindResultVerifier); 1124da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek bool VerifiedResult = false; 1134da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek MatchFinder Finder; 1146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VerifyMatch VerifyVerifiedResult(FindResultVerifier, &VerifiedResult); 1156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Finder.addMatcher(AMatcher, &VerifyVerifiedResult); 116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<FrontendActionFactory> Factory( 117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines newFrontendActionFactory(&Finder)); 11850f88b99c60c2ed31b339cd8bd484766cc9e916bNico Weber // Some tests use typeof, which is a gnu extension. 11950f88b99c60c2ed31b339cd8bd484766cc9e916bNico Weber std::vector<std::string> Args(1, "-std=gnu++98"); 12050f88b99c60c2ed31b339cd8bd484766cc9e916bNico Weber if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) { 1214da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; 1224da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } 1234da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek if (!VerifiedResult && ExpectResult) { 1244da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionFailure() 1254da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek << "Could not verify result in \"" << Code << "\""; 1264da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } else if (VerifiedResult && !ExpectResult) { 1274da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionFailure() 1284da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek << "Verified unexpected result in \"" << Code << "\""; 1294da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek } 13051fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne 13151fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne VerifiedResult = false; 132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ASTUnit> AST(buildASTFromCodeWithArgs(Code, Args)); 13351fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne if (!AST.get()) 13451fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne return testing::AssertionFailure() << "Parsing error in \"" << Code 13551fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne << "\" while building AST"; 13651fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne Finder.matchAST(AST->getASTContext()); 13751fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne if (!VerifiedResult && ExpectResult) { 13851fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne return testing::AssertionFailure() 13951fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne << "Could not verify result in \"" << Code << "\" with AST"; 14051fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne } else if (VerifiedResult && !ExpectResult) { 14151fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne return testing::AssertionFailure() 14251fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne << "Verified unexpected result in \"" << Code << "\" with AST"; 14351fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne } 14451fcdf84a794a01601c7c78889efa21fbfc1db08Peter Collingbourne 1454da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return testing::AssertionSuccess(); 1464da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} 1474da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 1484da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// FIXME: Find better names for these functions (or document what they 1494da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek// do more precisely). 1504da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektemplate <typename T> 1514da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektesting::AssertionResult 1524da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel KlimekmatchAndVerifyResultTrue(const std::string &Code, const T &AMatcher, 1534da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek BoundNodesCallback *FindResultVerifier) { 1544da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return matchAndVerifyResultConditionally( 1554da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek Code, AMatcher, FindResultVerifier, true); 1564da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} 1574da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 1584da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektemplate <typename T> 1594da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimektesting::AssertionResult 1604da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel KlimekmatchAndVerifyResultFalse(const std::string &Code, const T &AMatcher, 1614da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek BoundNodesCallback *FindResultVerifier) { 1624da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek return matchAndVerifyResultConditionally( 1634da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek Code, AMatcher, FindResultVerifier, false); 1644da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} 1654da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 1664da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} // end namespace ast_matchers 1674da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek} // end namespace clang 1684da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek 1694da216637fa1ad4bdfd31bc265edb57ca35c2c12Manuel Klimek#endif // LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H 170