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