diff options
author | Manuel Klimek <klimek@google.com> | 2011-06-02 16:58:33 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2011-06-02 16:58:33 +0000 |
commit | 16f213142f8f8f5410672205a19f79ed3c232929 (patch) | |
tree | a11e620036d64fa4f97884a4ea22c26c06ee3b24 | |
parent | fb3f4aad0436a9c40e9130598162150890c405b5 (diff) |
Reverts the Tooling changes as requested by Chris.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132462 91177308-0d34-0410-b5e6-96231b3b80d8
25 files changed, 2 insertions, 7037 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8e16ef1c6c..317bc81637 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,3 +1,2 @@ add_subdirectory(clang-interpreter) add_subdirectory(PrintFunctionNames) -add_subdirectory(Tooling) diff --git a/examples/Makefile b/examples/Makefile index 9f1615c2f0..8cb431d739 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -9,6 +9,6 @@ CLANG_LEVEL := .. -PARALLEL_DIRS := clang-interpreter PrintFunctionNames Tooling +PARALLEL_DIRS := clang-interpreter PrintFunctionNames include $(CLANG_LEVEL)/Makefile diff --git a/examples/Tooling/CMakeLists.txt b/examples/Tooling/CMakeLists.txt deleted file mode 100644 index 01132b858a..0000000000 --- a/examples/Tooling/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(LLVM_USED_LIBS clangTooling clangBasic) - -add_clang_executable(clang-check - ClangCheck.cpp - ) - -add_subdirectory(RemoveCStrCalls) diff --git a/examples/Tooling/ClangCheck.cpp b/examples/Tooling/ClangCheck.cpp deleted file mode 100644 index ad88e023ca..0000000000 --- a/examples/Tooling/ClangCheck.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===- examples/Tooling/ClangCheck.cpp - Clang check tool -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a clang-check tool that runs the -// clang::SyntaxOnlyAction over a number of translation units. -// -// Usage: -// clang-check <cmake-output-dir> <file1> <file2> ... -// -// Where <cmake-output-dir> is a CMake build directory in which a file named -// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in -// CMake to get this output). -// -// <file1> ... specify the paths of files in the CMake source tree. This path -// is looked up in the compile command database. If the path of a file is -// absolute, it needs to point into CMake's source tree. If the path is -// relative, the current working directory needs to be in the CMake source -// tree and the file must be in a subdirectory of the current working -// directory. "./" prefixes in the relative files will be automatically -// removed, but the rest of a relative path must be a suffix of a path in -// the compile command line database. -// -// For example, to use clang-check on all files in a subtree of the source -// tree, use: -// -// /path/in/subtree $ find . -name '*.cpp'| xargs clang-check /path/to/source -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/FrontendActions.h" -#include "clang/Tooling/Tooling.h" - -class SyntaxOnlyActionFactory : public clang::tooling::FrontendActionFactory { - public: - virtual clang::FrontendAction *New() { return new clang::SyntaxOnlyAction; } -}; - -int main(int argc, char **argv) { - clang::tooling::ClangTool Tool(argc, argv); - return Tool.Run(new SyntaxOnlyActionFactory); -} diff --git a/examples/Tooling/Makefile b/examples/Tooling/Makefile deleted file mode 100644 index 4daa9c7f83..0000000000 --- a/examples/Tooling/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -##===- examples/Tooling/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -CLANG_LEVEL := ../.. - -TOOLNAME = clang-check -NO_INSTALL = 1 - -# No plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 - -LINK_COMPONENTS := support mc -USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \ - clangTooling.a clangParse.a clangSema.a clangAnalysis.a \ - clangAST.a clangLex.a clangBasic.a - -PARALLEL_DIRS := RemoveCStrCalls - -include $(CLANG_LEVEL)/Makefile - diff --git a/examples/Tooling/RemoveCStrCalls/CMakeLists.txt b/examples/Tooling/RemoveCStrCalls/CMakeLists.txt deleted file mode 100644 index 66debc9288..0000000000 --- a/examples/Tooling/RemoveCStrCalls/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(LLVM_USED_LIBS clangTooling clangBasic clangAST) - -add_clang_executable(remove-cstr-calls - RemoveCStrCalls.cpp - ) diff --git a/examples/Tooling/RemoveCStrCalls/Makefile b/examples/Tooling/RemoveCStrCalls/Makefile deleted file mode 100644 index 44de60ebe9..0000000000 --- a/examples/Tooling/RemoveCStrCalls/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -##===- examples/Tooling/RemoveCStrCalls/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -CLANG_LEVEL := ../../.. - -TOOLNAME = remove-cstr-calls -NO_INSTALL = 1 - -# No plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 - -LINK_COMPONENTS := support mc -USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ - clangParse.a clangSema.a clangAnalysis.a \ - clangAST.a clangLex.a clangBasic.a - -include $(CLANG_LEVEL)/Makefile diff --git a/examples/Tooling/RemoveCStrCalls/RemoveCStrCalls.cpp b/examples/Tooling/RemoveCStrCalls/RemoveCStrCalls.cpp deleted file mode 100644 index 6de9dd986a..0000000000 --- a/examples/Tooling/RemoveCStrCalls/RemoveCStrCalls.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//===- examples/Tooling/RemoveCStrCalls.cpp - Redundant c_str call removal ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a tool that prints replacements that remove redundant -// calls of c_str() on strings. -// -// Usage: -// remove-cstr-calls <cmake-output-dir> <file1> <file2> ... -// -// Where <cmake-output-dir> is a CMake build directory in which a file named -// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in -// CMake to get this output). -// -// <file1> ... specify the paths of files in the CMake source tree. This path -// is looked up in the compile command database. If the path of a file is -// absolute, it needs to point into CMake's source tree. If the path is -// relative, the current working directory needs to be in the CMake source -// tree and the file must be in a subdirectory of the current working -// directory. "./" prefixes in the relative files will be automatically -// removed, but the rest of a relative path must be a suffix of a path in -// the compile command line database. -// -// For example, to use remove-cstr-calls on all files in a subtree of the -// source tree, use: -// -// /path/in/subtree $ find . -name '*.cpp'| -// xargs remove-cstr-calls /path/to/source -// -//===----------------------------------------------------------------------===// - -#include "clang/Basic/SourceManager.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Lex/Lexer.h" -#include "clang/Tooling/ASTMatchers.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" - -using namespace clang::tooling::match; - -// FIXME: Pull out helper methods in here into more fitting places. - -// Returns the text that makes up 'node' in the source. -// Returns an empty string if the text cannot be found. -template <typename T> -std::string GetText(const clang::SourceManager &SourceManager, const T &Node) { - clang::SourceLocation StartSpellingLocatino = - SourceManager.getSpellingLoc(Node.getLocStart()); - clang::SourceLocation EndSpellingLocation = - SourceManager.getSpellingLoc(Node.getLocEnd()); - if (!StartSpellingLocatino.isValid() || !EndSpellingLocation.isValid()) { - return std::string(); - } - bool Invalid = true; - const char *Text = - SourceManager.getCharacterData(StartSpellingLocatino, &Invalid); - if (Invalid) { - return std::string(); - } - std::pair<clang::FileID, unsigned> Start = - SourceManager.getDecomposedLoc(StartSpellingLocatino); - std::pair<clang::FileID, unsigned> End = - SourceManager.getDecomposedLoc(clang::Lexer::getLocForEndOfToken( - EndSpellingLocation, 0, SourceManager, clang::LangOptions())); - if (Start.first != End.first) { - // Start and end are in different files. - return std::string(); - } - if (End.second < Start.second) { - // Shuffling text with macros may cause this. - return std::string(); - } - return std::string(Text, End.second - Start.second); -} - -// Returns the position of the spelling location of a node inside a file. -// The format is: -// "<start_line>:<start_column>:<end_line>:<end_column>" -template <typename T1> -void PrintPosition( - llvm::raw_ostream &OS, - const clang::SourceManager &SourceManager, const T1 &Node) { - clang::SourceLocation StartSpellingLocation = - SourceManager.getSpellingLoc(Node.getLocStart()); - clang::SourceLocation EndSpellingLocation = - SourceManager.getSpellingLoc(Node.getLocEnd()); - clang::PresumedLoc Start = - SourceManager.getPresumedLoc(StartSpellingLocation); - clang::SourceLocation EndToken = clang::Lexer::getLocForEndOfToken( - EndSpellingLocation, 1, SourceManager, clang::LangOptions()); - clang::PresumedLoc End = SourceManager.getPresumedLoc(EndToken); - OS << Start.getLine() << ":" << Start.getColumn() << ":" - << End.getLine() << ":" << End.getColumn(); -} - -class ReportPosition : public clang::tooling::MatchFinder::MatchCallback { - public: - virtual void Run(const clang::tooling::MatchFinder::MatchResult &Result) { - llvm::outs() << "Found!\n"; - } -}; - -// Return true if expr needs to be put in parens when it is an -// argument of a prefix unary operator, e.g. when it is a binary or -// ternary operator syntactically. -bool NeedParensAfterUnaryOperator(const clang::Expr &ExprNode) { - if (llvm::dyn_cast<clang::BinaryOperator>(&ExprNode) || - llvm::dyn_cast<clang::ConditionalOperator>(&ExprNode)) { - return true; - } - if (const clang::CXXOperatorCallExpr *op = - llvm::dyn_cast<clang::CXXOperatorCallExpr>(&ExprNode)) { - return op->getNumArgs() == 2 && - op->getOperator() != clang::OO_PlusPlus && - op->getOperator() != clang::OO_MinusMinus && - op->getOperator() != clang::OO_Call && - op->getOperator() != clang::OO_Subscript; - } - return false; -} - -// Format a pointer to an expression: prefix with '*' but simplify -// when it already begins with '&'. Return empty string on failure. -std::string FormatDereference(const clang::SourceManager &SourceManager, - const clang::Expr &ExprNode) { - if (const clang::UnaryOperator *Op = - llvm::dyn_cast<clang::UnaryOperator>(&ExprNode)) { - if (Op->getOpcode() == clang::UO_AddrOf) { - // Strip leading '&'. - return GetText(SourceManager, *Op->getSubExpr()->IgnoreParens()); - } - } - const std::string Text = GetText(SourceManager, ExprNode); - if (Text.empty()) return std::string(); - // Add leading '*'. - if (NeedParensAfterUnaryOperator(ExprNode)) { - return std::string("*(") + Text + ")"; - } - return std::string("*") + Text; -} - -class FixCStrCall : public clang::tooling::MatchFinder::MatchCallback { - public: - virtual void Run(const clang::tooling::MatchFinder::MatchResult &Result) { - const clang::CallExpr *Call = - Result.Nodes.GetStmtAs<clang::CallExpr>("call"); - const clang::Expr *Arg = - Result.Nodes.GetStmtAs<clang::Expr>("arg"); - const bool Arrow = - Result.Nodes.GetStmtAs<clang::MemberExpr>("member")->isArrow(); - // Replace the "call" node with the "arg" node, prefixed with '*' - // if the call was using '->' rather than '.'. - const std::string ArgText = Arrow ? - FormatDereference(*Result.SourceManager, *Arg) : - GetText(*Result.SourceManager, *Arg); - if (ArgText.empty()) return; - - llvm::outs() << - Result.SourceManager->getBufferName(Call->getLocStart(), NULL) << ":"; - PrintPosition(llvm::outs(), *Result.SourceManager, *Call); - llvm::outs() << ":" << ArgText << "\n"; - } -}; - -const char *StringConstructor = - "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >" - "::basic_string"; - -const char *StringCStrMethod = - "::std::basic_string<char, std::char_traits<char>, std::allocator<char> >" - "::c_str"; - -int main(int argc, char **argv) { - clang::tooling::ClangTool Tool(argc, argv); - clang::tooling::MatchFinder finder; - finder.AddMatcher( - ConstructorCall( - HasDeclaration(Method(HasName(StringConstructor))), - ArgumentCountIs(2), - // The first argument must have the form x.c_str() or p->c_str() - // where the method is string::c_str(). We can use the copy - // constructor of string instead (or the compiler might share - // the string object). - HasArgument( - 0, - Id("call", Call( - Callee(Id("member", MemberExpression())), - Callee(Method(HasName(StringCStrMethod))), - On(Id("arg", Expression()))))), - // The second argument is the alloc object which must not be - // present explicitly. - HasArgument( - 1, - DefaultArgument())), new FixCStrCall); - finder.AddMatcher( - ConstructorCall( - // Implicit constructors of these classes are overloaded - // wrt. string types and they internally make a StringRef - // referring to the argument. Passing a string directly to - // them is preferred to passing a char pointer. - HasDeclaration(Method(AnyOf( - HasName("::llvm::StringRef::StringRef"), - HasName("::llvm::Twine::Twine")))), - ArgumentCountIs(1), - // The only argument must have the form x.c_str() or p->c_str() - // where the method is string::c_str(). StringRef also has - // a constructor from string which is more efficient (avoids - // strlen), so we can construct StringRef from the string - // directly. - HasArgument( - 0, - Id("call", Call( - Callee(Id("member", MemberExpression())), - Callee(Method(HasName(StringCStrMethod))), - On(Id("arg", Expression())))))), - new FixCStrCall); - return Tool.Run(finder.NewFrontendActionFactory()); -} - diff --git a/examples/Tooling/replace.py b/examples/Tooling/replace.py deleted file mode 100755 index a738dea70c..0000000000 --- a/examples/Tooling/replace.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python - -#===- replace.py - Applying code rewrites --------------------*- python -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# -# This script applies the rewrites generated by replace-cstr-calls on a source -# tree. -# -# Usage: -# ./replace.py < /path/to/replace-cstr-calls-output -# -#===------------------------------------------------------------------------===# - -import fileinput -import re -import sys - -for line in sys.stdin.readlines(): - # The format is: - # <file>:<start_line>:<start_column>:<end_line>:<end_column>:<replacement> - # FIXME: This currently does not support files with colons, we'll need to - # figure out a format when we implement more refactoring support. - match = re.match(r'(.*):(\d+):(\d+):(\d+):(\d+):(.*)$', line) - if match is not None: - file_name = match.group(1) - start_line, start_column = int(match.group(2)), int(match.group(3)) - end_line, end_column = int(match.group(4)), int(match.group(5)) - replacement = match.group(6) - if start_line != end_line: - print ('Skipping match "%s": only single line ' + - 'replacements are supported') % line.strip() - continue - try: - replace_file = fileinput.input(file_name, inplace=1) - for replace_line in replace_file: - # FIXME: Looping over the file for each replacement is both inefficient - # and incorrect if replacements add or remove lines. - if replace_file.lineno() == start_line: - sys.stdout.write(replace_line[:start_column-1] + replacement + - replace_line[end_column:]) - else: - sys.stdout.write(replace_line) - except OSError, e: - print 'Cannot open %s for editing' % file_name diff --git a/include/clang/Tooling/ASTMatchers.h b/include/clang/Tooling/ASTMatchers.h deleted file mode 100644 index 74b94c967e..0000000000 --- a/include/clang/Tooling/ASTMatchers.h +++ /dev/null @@ -1,1735 +0,0 @@ -//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a framework of AST matchers that can be used to express -// structural queries on the AST representing C++ code. -// -// The general idea is to construct a matcher expression that describes a -// subtree match on the AST. Next, a callback that is executed every time the -// expression matches is registered, and the matcher is run over the AST of -// some code. Matched subexpressions can be bound to string IDs and easily -// be accessed from the registered callback. The callback can than use the -// AST nodes that the subexpressions matched on to output information about -// the match or construct changes that can be applied to the code. -// -// Example: -// class HandleMatch : public clang::tooling::MatchFinder::MatchCallback { -// public: -// virtual void Run(const clang::tooling::MatchFinder::MatchResult &Result) { -// const clang::CXXRecordDecl *Class = -// Result.Nodes.GetDeclAs<clang::CXXRecordDecl>("id"); -// ... -// } -// }; -// -// int main(int argc, char **argv) { -// ClangTool Tool(argc, argv); -// MatchFinder finder; -// finder.AddMatcher(Id("id", Class(HasName("::a_namespace::AClass"))), -// new HandleMatch); -// return Tool.Run(finder.NewFrontendActionFactory()); -// } -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_AST_MATCHERS_H -#define LLVM_CLANG_TOOLING_AST_MATCHERS_H - -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/Stmt.h" -#include "clang/Tooling/VariadicFunction.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/type_traits.h" -#include "llvm/Support/DataTypes.h" -#include <cassert> -#include <map> -#include <string> -#include <utility> -#include <vector> - -/// FIXME: Move into the llvm support library. -template <bool> struct CompileAssert {}; -#define COMPILE_ASSERT(Expr, Msg) \ - typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1] - -namespace clang { - -class FrontendAction; -class SourceManager; - -namespace tooling { - -class FrontendActionFactory; -class BoundNodesBuilder; - -/// Contains a mapping from IDs to nodes bound to those IDs and provides -/// convenient access to those nodes. -class BoundNodes { - public: - BoundNodes() {} - - /// Create BoundNodes from a pre-filled map of bindings. - BoundNodes(const std::map<std::string, const clang::Decl*> &DeclBindings, - const std::map<std::string, const clang::Stmt*> &StmtBindings) - : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {} - - /// Returns the node bound to the specified id if the id was bound to a node - /// and that node can be converted into the specified type. Returns NULL - /// otherwise. - /// FIXME: We'll need one of those for every base type. - template <typename T> - const T *GetDeclAs(const std::string &ID) const { - return GetNodeAs<T>(DeclBindings, ID); - } - template <typename T> - const T *GetStmtAs(const std::string &ID) const { - return GetNodeAs<T>(StmtBindings, ID); - } - - /// Adds all bound nodes to bound_nodes_builder. - void CopyTo(BoundNodesBuilder *CopyToBuilder) const; - - private: - template <typename T, typename MapT> - const T *GetNodeAs(const MapT &Bindings, const std::string &ID) const { - typename MapT::const_iterator It = Bindings.find(ID); - if (It == Bindings.end()) { - return NULL; - } - return llvm::dyn_cast<T>(It->second); - } - - std::map<std::string, const clang::Decl*> DeclBindings; - std::map<std::string, const clang::Stmt*> StmtBindings; -}; // class BoundNodes - -/// Creates BoundNodes objects. -class BoundNodesBuilder { - public: - BoundNodesBuilder() {} - - /// Add a binding from 'ID' to 'Node'. - /// FIXME: Add overloads for all AST base types. - void SetBinding(const std::string &ID, const clang::Decl *Node) { - DeclBindings[ID] = Node; - } - void SetBinding(const std::string &ID, const clang::Stmt *Node) { - StmtBindings[ID] = Node; - } - - /// Returns a BoundNodes object containing all current bindings. - BoundNodes Build() const { - return BoundNodes(DeclBindings, StmtBindings); - } - - private: - BoundNodesBuilder(const BoundNodesBuilder&); // DO NOT IMPLEMENT - void operator=(const BoundNodesBuilder&); // DO NOT IMPLEMENT - - std::map<std::string, const clang::Decl*> DeclBindings; - std::map<std::string, const clang::Stmt*> StmtBindings; -}; - -inline void BoundNodes::CopyTo(BoundNodesBuilder *CopyToBuilder) const { - for (std::map<std::string, const clang::Decl*>::const_iterator - It = DeclBindings.begin(), End = DeclBindings.end(); - It != End; ++It) { - CopyToBuilder->SetBinding(It->first, It->second); - } - /// FIXME: Pull out method. - for (std::map<std::string, const clang::Stmt*>::const_iterator - It = StmtBindings.begin(), End = StmtBindings.end(); - It != End; ++It) { - CopyToBuilder->SetBinding(It->first, It->second); - } -} - -class ASTMatchFinder; - -/// Generic interface for matchers on an AST node of type T. Implement -/// this if your matcher may need to inspect the children or -/// descendants of the node or bind matched nodes to names. If you are -/// writing a simple matcher that only inspects properties of the -/// current node and doesn't care about its children or descendants, -/// implement SingleNodeMatcherInterface instead. -template <typename T> -class MatcherInterface : public llvm::RefCountedBaseVPTR { - public: - virtual ~MatcherInterface() {} - - /// Returns true if 'Node' can be matched. - /// May bind 'Node' to an ID via 'Builder', or recurse into - /// the AST via 'Finder'. - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const = 0; -}; - -/// Interface for matchers that only evaluate properties on a single node. -template <typename T> -class SingleNodeMatcherInterface : public MatcherInterface<T> { - public: - /// Returns true if the matcher matches the provided node. A subclass - /// must implement this instead of Matches(). - virtual bool MatchesNode(const T &Node) const = 0; - - private: - /// Implements MatcherInterface::Matches. - virtual bool Matches(const T &Node, - ASTMatchFinder * /* Finder */, - BoundNodesBuilder * /* Builder */) const { - return MatchesNode(Node); - } -}; - -/// Wrapper of a MatcherInterface<T> *that allows copying. -/// -/// A Matcher<Base> can be used anywhere a Matcher<Derived> is -/// required. This establishes an is-a relationship which is reverse -/// to the AST hierarchy. In other words, Matcher<T> is contravariant -/// with respect to T. The relationship is built via a type conversion -/// operator rather than a type hierarchy to be able to templatize the -/// type hierarchy instead of spelling it out. -template <typename T> -class Matcher { - public: - /// Takes ownership of the provided implementation pointer. - explicit Matcher(MatcherInterface<T> *Implementation) - : Implementation(Implementation) {} - - /// Forwards the call to the underlying MatcherInterface<T> pointer. - bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return Implementation->Matches(Node, Finder, Builder); - } - - /// Implicitly converts this object to a Matcher<Derived>; requires - /// Derived to be derived from T. - template <typename Derived> - operator Matcher<Derived>() const { - return Matcher<Derived>(new ImplicitCastMatcher<Derived>(*this)); - } - - /// Returns an ID that uniquely identifies the matcher. - uint64_t GetID() const { - /// FIXME: Document the requirements this imposes on matcher - /// implementations (no new() implementation_ during a Matches()). - return reinterpret_cast<uint64_t>(Implementation.getPtr()); - } - - private: - /// Allows conversion from Matcher<T> to Matcher<Derived> if Derived - /// is derived from T. - template <typename Derived> - class ImplicitCastMatcher : public MatcherInterface<Derived> { - public: - explicit ImplicitCastMatcher(const Matcher<T> &From) - : From(From) {} - - virtual bool Matches( - const Derived &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return From.Matches(Node, Finder, Builder); - } - - private: - const Matcher<T> From; - }; - - llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; -}; // class Matcher - -/// A convenient helper for creating a Matcher<T> without specifying -/// the template type argument. -template <typename T> -inline Matcher<T> MakeMatcher(MatcherInterface<T> *Implementation) { - return Matcher<T>(Implementation); -} - -/// Matches declarations for QualType and CallExpr. Type argument -/// DeclMatcherT is required by PolymorphicMatcherWithParam1 but not -/// actually used. -template <typename T, typename DeclMatcherT> -class HasDeclarationMatcher : public MatcherInterface<T> { - COMPILE_ASSERT((llvm::is_same< DeclMatcherT, Matcher<clang::Decl> >::value), - instantiated_with_wrong_types); - public: - explicit HasDeclarationMatcher(const Matcher<clang::Decl> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return MatchesSpecialized(Node, Finder, Builder); - } - - private: - /// Extracts the CXXRecordDecl of a QualType and returns whether the inner - /// matcher matches on it. - bool MatchesSpecialized( - const clang::QualType &Node, ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - /// FIXME: Add other ways to convert... - clang::CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl(); - return NodeAsRecordDecl != NULL && - InnerMatcher.Matches(*NodeAsRecordDecl, Finder, Builder); - } - - /// Extracts the Decl of the callee of a CallExpr and returns whether the - /// inner matcher matches on it. - bool MatchesSpecialized( - const clang::CallExpr &Node, ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - const clang::Decl *NodeAsDecl = Node.getCalleeDecl(); - return NodeAsDecl != NULL && - InnerMatcher.Matches(*NodeAsDecl, Finder, Builder); - } - - /// Extracts the Decl of the constructor call and returns whether the inner - /// matcher matches on it. - bool MatchesSpecialized( - const clang::CXXConstructExpr &Node, ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - const clang::Decl *NodeAsDecl = Node.getConstructor(); - return NodeAsDecl != NULL && - InnerMatcher.Matches(*NodeAsDecl, Finder, Builder); - } - - const Matcher<clang::Decl> InnerMatcher; -}; - -/// IsBaseType<T>::value is true if T is a "base" type in the AST -/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). -template <typename T> -struct IsBaseType { - static const bool value = (llvm::is_same<T, clang::Decl>::value || - llvm::is_same<T, clang::Stmt>::value || - llvm::is_same<T, clang::QualType>::value); -}; -template <typename T> -const bool IsBaseType<T>::value; - -/// Interface that can match any AST base node type and contains default -/// implementations returning false. -class UntypedBaseMatcher { - public: - virtual ~UntypedBaseMatcher() {} - - virtual bool Matches( - const clang::Decl &DeclNode, ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return false; - } - virtual bool Matches( - const clang::QualType &TypeNode, ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return false; - } - virtual bool Matches( - const clang::Stmt &StmtNode, ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return false; - } - - /// Returns a unique ID for the matcher. - virtual uint64_t GetID() const = 0; -}; - -/// An UntypedBaseMatcher that overwrites the Matches(...) method for node -/// type T. T must be an AST base type. -template <typename T> -class TypedBaseMatcher : public UntypedBaseMatcher { - COMPILE_ASSERT(IsBaseType<T>::value, - typed_base_matcher_can_only_be_used_with_base_type); - public: - explicit TypedBaseMatcher(const Matcher<T> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - using UntypedBaseMatcher::Matches; - /// Implements UntypedBaseMatcher::Matches. Since T is guaranteed to - /// be a "base" AST node type, this method is guaranteed to override - /// one of the Matches() methods from UntypedBaseMatcher. - virtual bool Matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return InnerMatcher.Matches(Node, Finder, Builder); - } - - /// Implements UntypedBaseMatcher::GetID. - virtual uint64_t GetID() const { - return InnerMatcher.GetID(); - } - - private: - Matcher<T> InnerMatcher; -}; - -/// Interface that allows matchers to traverse the AST. -/// This provides two entry methods for each base node type in the AST: -/// - MatchesChildOf: -/// Matches a matcher on every child node of the given node. Returns true -/// if at least one child node could be matched. -/// - MatchesDescendantOf: -/// Matches a matcher on all descendant nodes of the given node. Returns true -/// if at least one descendant matched. -class ASTMatchFinder { - public: - /// Defines how we descend a level in the AST when we pass - /// through expressions. - enum TraversalMethod { - /// Will traverse any child nodes. - kAsIs, - /// Will not traverse implicit casts and parentheses. - kIgnoreImplicitCastsAndParentheses - }; - - virtual ~ASTMatchFinder() {} - - /// Returns true if the given class is directly or indirectly derived - /// from a base type with the given name. A class is considered to - /// be also derived from itself. - virtual bool ClassIsDerivedFrom(const clang::CXXRecordDecl *Declaration, - const std::string &BaseName) const = 0; - - // FIXME: Implement for other base nodes. - virtual bool MatchesChildOf(const clang::Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder, - TraversalMethod Traverse) = 0; - virtual bool MatchesChildOf(const clang::Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder, - TraversalMethod Traverse) = 0; - - virtual bool MatchesDescendantOf(const clang::Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder) = 0; - virtual bool MatchesDescendantOf(const clang::Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder) = 0; -}; - -/// Converts a Matcher<T> to a matcher of desired type To by "adapting" -/// a To into a T. The ArgumentAdapterT argument specifies how the -/// adaptation is done. For example: -/// -/// ArgumentAdaptingMatcher<DynCastMatcher, T>(InnerMatcher); -/// returns a matcher that can be used where a Matcher<To> is required, if -/// To and T are in the same type hierarchy, and thus dyn_cast can be -/// called to convert a To to a T. -/// -/// FIXME: Make sure all our applications of this class actually require -/// knowledge about the inner type. DynCastMatcher obviously does, but the -/// Has *matchers require the inner type solely for COMPILE_ASSERT purposes. -template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, - typename T> -class ArgumentAdaptingMatcher { - public: - explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - template <typename To> - operator Matcher<To>() const { - return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher)); - } - - private: - const Matcher<T> InnerMatcher; -}; - -/// A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be -/// created from N parameters p1, ..., pN (of type P1, ..., PN) and -/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN) -/// can be constructed. -/// -/// For example: -/// - PolymorphicMatcherWithParam0<IsDefinitionMatcher>() -/// creates an object that can be used as a Matcher<T> for any type T -/// where an IsDefinitionMatcher<T>() can be constructed. -/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42) -/// creates an object that can be used as a Matcher<T> for any type T -/// where a ValueEqualsMatcher<T, int>(42) can be constructed. -template <template <typename T> class MatcherT> -class PolymorphicMatcherWithParam0 { - public: - template <typename T> - operator Matcher<T>() const { - return Matcher<T>(new MatcherT<T>()); - } -}; - -template <template <typename T, typename P1> class MatcherT, - typename P1> -class PolymorphicMatcherWithParam1 { - public: - explicit PolymorphicMatcherWithParam1(const P1 &Param1) - : Param1(Param1) {} - - template <typename T> - operator Matcher<T>() const { - return Matcher<T>(new MatcherT<T, P1>(Param1)); - } - - private: - const P1 Param1; -}; - -template <template <typename T, typename P1, typename P2> class MatcherT, - typename P1, typename P2> -class PolymorphicMatcherWithParam2 { - public: - PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2) - : Param1(Param1), Param2(Param2) {} - - template <typename T> - operator Matcher<T>() const { - return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2)); - } - - private: - const P1 Param1; - const P2 Param2; -}; - -// FIXME: Alternatively we could also create a IsAMatcher or something -// that checks that a dyn_cast is possible. This is purely needed for the -// difference between calling for example: -// Class() -// and -// Class(SomeMatcher) -// In the second case we need the correct type we were dyn_cast'ed to in order -// to get the right type for the inner matcher. In the first case we don't need -// that, but we use the type conversion anyway and insert a TrueMatcher. -template <typename T> -class TrueMatcher : public SingleNodeMatcherInterface<T> { - public: - virtual bool MatchesNode(const T &Node) const { - return true; - } -}; - -/// Provides a MatcherInterface<T> for a Matcher<To> that matches if T is -/// dyn_cast'able into To and the given Matcher<To> matches on the dyn_cast'ed -/// node. -template <typename T, typename To> -class DynCastMatcher : public MatcherInterface<T> { - public: - explicit DynCastMatcher(const Matcher<To> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool Matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - const To *InnerMatchValue = llvm::dyn_cast<To>(&Node); - return InnerMatchValue != NULL && - InnerMatcher.Matches(*InnerMatchValue, Finder, Builder); - } - - private: - const Matcher<To> InnerMatcher; -}; - -/// Enables the user to pass a Matcher<clang::CXXMemberCallExpr> to Call(). -/// FIXME: Alternatives are using more specific methods than Call, like -/// MemberCall, or not using VariadicFunction for Call and overloading it. -template <> -template <> -inline Matcher<clang::CXXMemberCallExpr>:: -operator Matcher<clang::CallExpr>() const { - return MakeMatcher( - new DynCastMatcher<clang::CallExpr, clang::CXXMemberCallExpr>(*this)); -} - -/// Matcher<T> that wraps an inner Matcher<T> and binds the matched node to -/// an ID if the inner matcher matches on the node. -template <typename T> -class IdMatcher : public MatcherInterface<T> { - public: - /// Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches the node. - IdMatcher(const std::string &ID, const Matcher<T> &InnerMatcher) - : ID(ID), InnerMatcher(InnerMatcher) {} - - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - bool Result = InnerMatcher.Matches(Node, Finder, Builder); - if (Result) { - Builder->SetBinding(ID, &Node); - } - return Result; - } - - private: - const std::string ID; - const Matcher<T> InnerMatcher; -}; - -/// Matches nodes of type T that have child nodes of type ChildT for -/// which a specified child matcher matches. ChildT must be an AST base -/// type. -template <typename T, typename ChildT> -class HasMatcher : public MatcherInterface<T> { - COMPILE_ASSERT(IsBaseType<ChildT>::value, has_only_accepts_base_type_matcher); - public: - explicit HasMatcher(const Matcher<ChildT> &ChildMatcher) - : ChildMatcher(ChildMatcher) {} - - virtual bool Matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return Finder->MatchesChildOf( - Node, ChildMatcher, Builder, - ASTMatchFinder::kIgnoreImplicitCastsAndParentheses); - } - - private: - const TypedBaseMatcher<ChildT> ChildMatcher; -}; - -/// Matches nodes of type T if the given Matcher<T> does not match. -/// Type argument MatcherT is required by PolymorphicMatcherWithParam1 -/// but not actually used. It will always be instantiated with a type -/// convertible to Matcher<T>. -template <typename T, typename MatcherT> -class NotMatcher : public MatcherInterface<T> { - public: - explicit NotMatcher(const Matcher<T> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return !InnerMatcher.Matches(Node, Finder, Builder); - } - - private: - const Matcher<T> InnerMatcher; -}; - -/// Matches nodes of type T for which both provided matchers -/// match. Type arguments MatcherT1 and MatcherT2 are required by -/// PolymorphicMatcherWithParam2 but not actually used. They will -/// always be instantiated with types convertible to Matcher<T>. -template <typename T, typename MatcherT1, typename MatcherT2> -class AllOfMatcher : public MatcherInterface<T> { - public: - AllOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2) - : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {} - - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return InnerMatcher1.Matches(Node, Finder, Builder) && - InnerMatcher2.Matches(Node, Finder, Builder); - } - - private: - const Matcher<T> InnerMatcher1; - const Matcher<T> InnerMatcher2; -}; - -/// Matches nodes of type T for which at least one of the two provided -/// matchers matches. Type arguments MatcherT1 and MatcherT2 are -/// required by PolymorphicMatcherWithParam2 but not actually -/// used. They will always be instantiated with types convertible to -/// Matcher<T>. -template <typename T, typename MatcherT1, typename MatcherT2> -class AnyOfMatcher : public MatcherInterface<T> { - public: - AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2) - : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {} - - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return InnerMatcher1.Matches(Node, Finder, Builder) || - InnertMatcher2.Matches(Node, Finder, Builder); - } - - private: - const Matcher<T> InnerMatcher1; - const Matcher<T> InnertMatcher2; -}; - -/// Creates a Matcher<T> that matches if -/// T is dyn_cast'able into InnerT and all inner matchers match. -template<typename T, typename InnerT> -Matcher<T> MakeDynCastAllOfComposite( - const Matcher<InnerT> *const InnerMatchers[], int Count) { - if (Count == 0) { - return ArgumentAdaptingMatcher<DynCastMatcher, InnerT>( - MakeMatcher(new TrueMatcher<InnerT>)); - } - Matcher<InnerT> InnerMatcher = *InnerMatchers[Count-1]; - for (int I = Count-2; I >= 0; --I) { - InnerMatcher = MakeMatcher( - new AllOfMatcher<InnerT, Matcher<InnerT>, Matcher<InnerT> >( - *InnerMatchers[I], InnerMatcher)); - } - return ArgumentAdaptingMatcher<DynCastMatcher, InnerT>(InnerMatcher); -} - -/// Matches nodes of type T that have at least one descendant node of -/// type DescendantT for which the given inner matcher matches. -/// DescendantT must be an AST base type. -template <typename T, typename DescendantT> -class HasDescendantMatcher : public MatcherInterface<T> { - COMPILE_ASSERT(IsBaseType<DescendantT>::value, - has_descendant_only_accepts_base_type_matcher); - public: - explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher) - : DescendantMatcher(DescendantMatcher) {} - - virtual bool Matches( - const T &Node, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder) const { - return Finder->MatchesDescendantOf( - Node, DescendantMatcher, Builder); - } - - private: - const TypedBaseMatcher<DescendantT> DescendantMatcher; -}; - -/// Matches on nodes that have a getValue() method if getValue() equals the -/// value the ValueEqualsMatcher was constructed with. -template <typename T, typename ValueT> -class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> { - COMPILE_ASSERT((llvm::is_base_of<clang::CharacterLiteral, T>::value) || - (llvm::is_base_of<clang::CXXBoolLiteralExpr, T>::value) || - (llvm::is_base_of<clang::FloatingLiteral, T>::value) || - (llvm::is_base_of<clang::IntegerLiteral, T>::value), - the_node_must_have_a_getValue_method); - public: - explicit ValueEqualsMatcher(const ValueT &ExpectedValue) - : ExpectedValue(ExpectedValue) {} - - virtual bool MatchesNode(const T &Node) const { - return Node.getValue() == ExpectedValue; - } - - private: - const ValueT ExpectedValue; -}; - -template <typename T> -class IsDefinitionMatcher : public SingleNodeMatcherInterface<T> { - COMPILE_ASSERT((llvm::is_base_of<clang::TagDecl, T>::value) || - (llvm::is_base_of<clang::VarDecl, T>::value) || - (llvm::is_base_of<clang::FunctionDecl, T>::value), - is_definition_requires_isThisDeclarationADefinition_method); - public: - virtual bool MatchesNode(const T &Node) const { - return Node.isThisDeclarationADefinition(); - } -}; - -class IsArrowMatcher : public SingleNodeMatcherInterface<clang::MemberExpr> { - public: - virtual bool MatchesNode(const clang::MemberExpr &Node) const { - return Node.isArrow(); - } -}; - -/// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a -/// variadic functor that takes a list of Matcher<TargetT> and returns -/// a Matcher<SourceT> that dyn_casts its argument to TargetT. -template <typename SourceT, typename TargetT> -class VariadicDynCastAllOfMatcher - : public internal::VariadicFunction< - Matcher<SourceT>, Matcher<TargetT>, - MakeDynCastAllOfComposite<SourceT, TargetT> > { - public: - VariadicDynCastAllOfMatcher() {} -}; - -/// AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } -/// -/// defines a single-parameter function named DefineMatcher() that returns a -/// Matcher<Type> object. The code between the curly braces has access -/// to the following variables: -/// -/// Node: the AST node being matched; its type is Type. -/// Param: the parameter passed to the function; its type -/// is ParamType. -/// Finder: an ASTMatchFinder*. -/// Builder: a BoundNodesBuilder*. -/// -/// The code should return true if 'Node' matches. -#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \ - class matcher_internal_##DefineMatcher##Matcher \ - : public MatcherInterface<Type> { \ - public: \ - explicit matcher_internal_##DefineMatcher##Matcher( \ - const ParamType &A##Param) : Param(A##Param) {} \ - virtual bool Matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const; \ - private: \ - const ParamType Param; \ - }; \ - inline Matcher<Type> DefineMatcher(const ParamType &Param) { \ - return MakeMatcher(new matcher_internal_##DefineMatcher##Matcher(Param)); \ - } \ - inline bool matcher_internal_##DefineMatcher##Matcher::Matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const - -/// AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) -/// { ... } -/// -/// defines a two-parameter function named DefineMatcher() that returns a -/// Matcher<Type> object. The code between the curly braces has access -/// to the following variables: -/// -/// Node: the AST node being matched; its type is Type. -/// Param1, Param2: the parameters passed to the function; their types -/// are ParamType1 and ParamType2. -/// Finder: an ASTMatchFinder*. -/// Builder: a BoundNodesBuilder*. -/// -/// The code should return true if 'Node' matches. -#define AST_MATCHER_P2( \ - Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ - class matcher_internal_##DefineMatcher##Matcher \ - : public MatcherInterface<Type> { \ - public: \ - matcher_internal_##DefineMatcher##Matcher( \ - const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool Matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const; \ - private: \ - const ParamType1 Param1; \ - const ParamType2 Param2; \ - }; \ - inline Matcher<Type> DefineMatcher( \ - const ParamType1 &Param1, const ParamType2 &Param2) { \ - return MakeMatcher(new matcher_internal_##DefineMatcher##Matcher( \ - Param1, Param2)); \ - } \ - inline bool matcher_internal_##DefineMatcher##Matcher::Matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const - -/// AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } -/// -/// defines a single-parameter function named DefineMatcher() that is -/// polymorphic in the return type. The variables are the same as for -/// AST_MATCHER_P, with the addition of NodeType, which specifies the node type -/// of the matcher Matcher<NodeType> returned by the function matcher(). -/// -/// FIXME: Pull out common code with above macro? -#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \ - template <typename NodeType, typename ParamT> \ - class matcher_internal_##DefineMatcher##Matcher \ - : public MatcherInterface<NodeType> { \ - public: \ - explicit matcher_internal_##DefineMatcher##Matcher( \ - const ParamType &A##Param) : Param(A##Param) {} \ - virtual bool Matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const; \ - private: \ - const ParamType Param; \ - }; \ - inline PolymorphicMatcherWithParam1< \ - matcher_internal_##DefineMatcher##Matcher, \ - ParamType > \ - DefineMatcher(const ParamType &Param) { \ - return PolymorphicMatcherWithParam1< \ - matcher_internal_##DefineMatcher##Matcher, \ - ParamType >(Param); \ - } \ - template <typename NodeType, typename ParamT> \ - bool matcher_internal_##DefineMatcher##Matcher<NodeType, ParamT>::Matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const - -/// AST_POLYMORPHIC_MATCHER_P2( -/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } -/// -/// defines a two-parameter function named matcher() that is polymorphic in -/// the return type. The variables are the same as for AST_MATCHER_P2, with the -/// addition of NodeType, which specifies the node type of the matcher -/// Matcher<NodeType> returned by the function DefineMatcher(). -#define AST_POLYMORPHIC_MATCHER_P2( \ - DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ - template <typename NodeType, typename ParamT1, typename ParamT2> \ - class matcher_internal_##DefineMatcher##Matcher \ - : public MatcherInterface<NodeType> { \ - public: \ - matcher_internal_##DefineMatcher##Matcher( \ - const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool Matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const; \ - private: \ - const ParamType1 Param1; \ - const ParamType2 Param2; \ - }; \ - inline PolymorphicMatcherWithParam2< \ - matcher_internal_##DefineMatcher##Matcher, \ - ParamType1, ParamType2 > \ - DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ - return PolymorphicMatcherWithParam2< \ - matcher_internal_##DefineMatcher##Matcher, \ - ParamType1, ParamType2 >( \ - Param1, Param2); \ - } \ - template <typename NodeType, typename ParamT1, typename ParamT2> \ - bool matcher_internal_##DefineMatcher##Matcher< \ - NodeType, ParamT1, ParamT2>::Matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesBuilder *Builder) const - -namespace match { - -typedef Matcher<clang::Decl> DeclarationMatcher; -typedef Matcher<clang::QualType> TypeMatcher; -typedef Matcher<clang::Stmt> StatementMatcher; - -/// Matches C++ class declarations. -/// -/// Example matches X, Z -/// class X; -/// template<class T> class Z {}; -const VariadicDynCastAllOfMatcher<clang::Decl, clang::CXXRecordDecl> Class; - -/// Matches method declarations. -/// -/// Example matches y -/// class X { void y() }; -const VariadicDynCastAllOfMatcher<clang::Decl, clang::CXXMethodDecl> Method; - -/// Matches variable declarations. -/// -/// Example matches a -/// int a; -const VariadicDynCastAllOfMatcher<clang::Decl, clang::VarDecl> Variable; - -/// Matches member expressions. -/// -/// Given -/// class Y { -/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } -/// int a; static int b; -/// }; -/// MemberExpression() -/// matches this->x, x, y.x, a, this->b -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::MemberExpr> -MemberExpression; - -/// Matches call expressions. -/// -/// Example matches x.y() -/// X x; -/// x.y(); -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::CallExpr> Call; - -/// Matches constructor call expressions (including implicit ones). -/// -/// Example matches string(ptr, n) and ptr within arguments of f -/// (matcher = ConstructorCall()) -/// void f(const string &a, const string &b); -/// char *ptr; -/// int n; -/// f(string(ptr, n), ptr); -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::CXXConstructExpr> -ConstructorCall; - -/// Matches the value of a default argument at the call site. -/// -/// Example matches the CXXDefaultArgExpr placeholder inserted for the -/// default value of the second parameter in the call expression f(42) -/// (matcher = DefaultArgument()) -/// void f(int x, int y = 0); -/// f(42); -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::CXXDefaultArgExpr> -DefaultArgument; - -/// Matches overloaded operator calls. -/// Note that if an operator isn't overloaded, it won't match. Instead, use -/// BinaryOperator matcher. -/// Currently it does not match operators such as new delete. -/// FIXME: figure out why these do not match? -/// -/// Example matches both operator<<((o << b), c) and operator<<(o, b) -/// (matcher = OverloadedOperatorCall()) -/// ostream &operator<< (ostream &out, int i) { }; -/// ostream &o; int b = 1, c = 1; -/// o << b << c; -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::CXXOperatorCallExpr> -OverloadedOperatorCall; - -/// Matches expressions. -/// -/// Example matches x() -/// void f() { x(); } -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::Expr> Expression; - -/// Matches expressions that refer to declarations. -/// -/// Example matches x in if (x) -/// bool x; -/// if (x) {} -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::DeclRefExpr> -DeclarationReference; - -/// Matches if statements. -/// -/// Example matches 'if (x) {}' -/// if (x) {} -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::IfStmt> If; - -/// Matches for statements. -/// -/// Example matches 'for (;;) {}' -/// for (;;) {} -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::ForStmt> For; - -/// Matches compound statements. -/// -/// Example matches '{}' and '{{}}'in 'for (;;) {{}}' -/// for (;;) {{}} -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::CompoundStmt> -CompoundStatement; - -/// Matches bool literals. -/// -/// Example matches true -/// true -const VariadicDynCastAllOfMatcher<clang::Expr, clang::CXXBoolLiteralExpr> -BoolLiteral; - -/// Matches string literals (also matches wide string literals). -/// -/// Example matches "abcd", L"abcd" -/// char *s = "abcd"; wchar_t *ws = L"abcd" -const VariadicDynCastAllOfMatcher<clang::Expr, clang::StringLiteral> -StringLiteral; - -/// Matches character literals (also matches wchar_t). -/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral), -/// though. -/// -/// Example matches 'a', L'a' -/// char ch = 'a'; wchar_t chw = L'a'; -const VariadicDynCastAllOfMatcher<clang::Expr, clang::CharacterLiteral> -CharacterLiteral; - -/// Matches integer literals of all sizes / encodings. -/// Not matching character-encoded integers such as L'a'. -/// -/// Example matches 1, 1L, 0x1, 1U -const VariadicDynCastAllOfMatcher<clang::Expr, clang::IntegerLiteral> -IntegerLiteral; - -/// Matches binary operator expressions. -/// -/// Example matches a || b -/// !(a || b) -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::BinaryOperator> -BinaryOperator; - -/// Matches unary operator expressions. -/// -/// Example matches !a -/// !a || b -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::UnaryOperator> -UnaryOperator; - -/// Matches conditional operator expressions. -/// -/// Example matches a ? b : c -/// (a ? b : c) + 42 -const VariadicDynCastAllOfMatcher<clang::Stmt, clang::ConditionalOperator> -ConditionalOperator; - -template<typename C1, typename C2> -PolymorphicMatcherWithParam2<AnyOfMatcher, C1, C2> -AnyOf(const C1 &P1, const C2 &P2) { - return PolymorphicMatcherWithParam2< AnyOfMatcher, C1, C2 >(P1, P2); -} - -template<typename C1, typename C2, typename C3> -PolymorphicMatcherWithParam2<AnyOfMatcher, C1, - PolymorphicMatcherWithParam2<AnyOfMatcher, C2, C3> > -AnyOf(const C1 &P1, const C2 &P2, const C3 &P3) { - return AnyOf(P1, AnyOf(P2, P3)); -} - -template<typename C1, typename C2, typename C3, typename C4> -PolymorphicMatcherWithParam2<AnyOfMatcher, C1, - PolymorphicMatcherWithParam2<AnyOfMatcher, C2, - PolymorphicMatcherWithParam2<AnyOfMatcher, C3, C4> > > -AnyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { - return AnyOf(P1, AnyOf(P2, AnyOf(P3, P4))); -} - -template<typename C1, typename C2> -PolymorphicMatcherWithParam2<AllOfMatcher, C1, C2> -AllOf(const C1 &P1, const C2 &P2) { - return PolymorphicMatcherWithParam2<AllOfMatcher, C1, C2>(P1, P2); -} - -/// Matches NamedDecl nodes that have the specified name. Supports specifying -/// enclosing namespaces or classes by prefixing the name with '<enclosing>::'. -/// Does not match typedefs of an underlying type with the given name. -/// -/// Example matches X (name == "X") -/// class X; -/// -/// Example matches X (name is one of "::a::b::X", "a::b::X", "b::X", "X") -/// namespace a { namespace b { class X; } } -AST_MATCHER_P(clang::NamedDecl, HasName, std::string, Name) { - assert(!Name.empty()); - const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); - const llvm::StringRef FullName = FullNameString; - const llvm::StringRef Pattern = Name; - if (Pattern.startswith("::")) { - return FullName == Pattern; - } else { - return FullName.endswith(("::" + Pattern).str()); - } -} - -/// Matches overloaded operator name given in strings without the "operator" -/// prefix, such as "<<", for OverloadedOperatorCall's. -/// -/// Example matches a << b -/// (matcher == OverloadedOperatorCall(HasOverloadedOperatorName("<<"))) -/// a << b; -/// c && d; // assuming both operator<< -/// // and operator&& are overloaded somewhere. -AST_MATCHER_P(clang::CXXOperatorCallExpr, - HasOverloadedOperatorName, std::string, Name) { - return clang::getOperatorSpelling(Node.getOperator()) == Name; -} - -/// Matches C++ classes that are directly or indirectly derived from -/// the given base class. Note that a class is considered to be also -/// derived from itself. The parameter specified the name of the base -/// type (either a class or a typedef), and does not allow structural -/// matches for namespaces or template type parameters. -/// -/// Example matches X, Y, Z, C (base == "X") -/// class X; // A class is considered to be derived from itself. -/// class Y : public X {}; // directly derived -/// class Z : public Y {}; // indirectly derived -/// typedef X A; -/// typedef A B; -/// class C : public B {}; // derived from a typedef of X -/// -/// In the following example, Bar matches IsDerivedFrom("X"): -/// class Foo; -/// typedef Foo X; -/// class Bar : public Foo {}; // derived from a type that X is a typedef of -AST_MATCHER_P(clang::CXXRecordDecl, IsDerivedFrom, std::string, Base) { - assert(!Base.empty()); - return Finder->ClassIsDerivedFrom(&Node, Base); -} - -/// Matches AST nodes that have child AST nodes that match the provided matcher. -/// -/// Example matches X, Y (matcher = Class(Has(Class(HasName("X"))) -/// class X {}; // Matches X, because X::X is a class of name X inside X. -/// class Y { class X {}; }; -/// class Z { class Y { class X {}; }; }; // Does not match Z. -/// -/// ChildT must be an AST base type. -template <typename ChildT> -ArgumentAdaptingMatcher<HasMatcher, ChildT> Has( - const Matcher<ChildT> &ChildMatcher) { - return ArgumentAdaptingMatcher<HasMatcher, ChildT>(ChildMatcher); -} - -/// Matches AST nodes that have descendant AST nodes that match the provided -/// matcher. -/// -/// Example matches X, Y, Z (matcher = Class(HasDescendant(Class(HasName("X"))))) -/// class X {}; // Matches X, because X::X is a class of name X inside X. -/// class Y { class X {}; }; -/// class Z { class Y { class X {}; }; }; -/// -/// DescendantT must be an AST base type. -template <typename DescendantT> -ArgumentAdaptingMatcher<HasDescendantMatcher, DescendantT> HasDescendant( - const Matcher<DescendantT> &DescendantMatcher) { - return ArgumentAdaptingMatcher<HasDescendantMatcher, DescendantT>( - DescendantMatcher); -} - -/// Matches if the provided matcher does not match. -/// -/// Example matches Y (matcher = Class(Not(HasName("X")))) -/// class X {}; -/// class Y {}; -template <typename M> -PolymorphicMatcherWithParam1<NotMatcher, M> Not(const M &InnerMatcher) { - return PolymorphicMatcherWithParam1<NotMatcher, M>(InnerMatcher); -} - -/// If the provided matcher matches a node, binds the node to 'id'. -/// FIXME: Add example for accessing it. -template <typename T> -Matcher<T> Id(const std::string &ID, const Matcher<T> &InnerMatcher) { - return Matcher<T>(new IdMatcher<T>(ID, InnerMatcher)); -} - -/// Matches a type if the declaration of the type matches the given matcher. -inline PolymorphicMatcherWithParam1< HasDeclarationMatcher, - Matcher<clang::Decl> > - HasDeclaration(const Matcher<clang::Decl> &InnerMatcher) { - return PolymorphicMatcherWithParam1< HasDeclarationMatcher, - Matcher<clang::Decl> >(InnerMatcher); -} - -/// Matches on the implicit object argument of a member call expression. -/// -/// Example matches y.x() (matcher = Call(On(HasType(Class(HasName("Y")))))) -/// class Y { public: void x(); }; -/// void z() { Y y; y.x(); }", -/// -/// FIXME: Overload to allow directly matching types? -AST_MATCHER_P( - clang::CXXMemberCallExpr, On, Matcher<clang::Expr>, InnerMatcher) { - const clang::Expr *ExprNode = const_cast<clang::CXXMemberCallExpr&>(Node) - .getImplicitObjectArgument() - ->IgnoreParenImpCasts(); - return (ExprNode != NULL && - InnerMatcher.Matches(*ExprNode, Finder, Builder)); -} - -/// Matches if the call expression's callee expression matches. -/// -/// Given -/// class Y { void x() { this->x(); x(); Y y; y.x(); } }; -/// void f() { f(); } -/// Call(Callee(Expression())) -/// matches this->x(), x(), y.x(), f() -/// with Callee(...) -/// matching this->x, x, y.x, f respectively -/// -/// Note: Callee cannot take the more general Matcher<clang::Expr> because -/// this introduces ambiguous overloads with calls to Callee taking a -/// Matcher<clang::Decl>, as the matcher hierarchy is purely implemented in -/// terms of implicit casts. -AST_MATCHER_P(clang::CallExpr, Callee, Matcher<clang::Stmt>, InnerMatcher) { - const clang::Expr *ExprNode = Node.getCallee(); - return (ExprNode != NULL && - InnerMatcher.Matches(*ExprNode, Finder, Builder)); -} - -/// Matches if the call expression's callee's declaration matches the given -/// matcher. -/// -/// Example matches y.x() (matcher = Call(Callee(Method(HasName("x"))))) -/// class Y { public: void x(); }; -/// void z() { Y y; y.x(); -inline Matcher<clang::CallExpr> Callee( - const Matcher<clang::Decl> &InnerMatcher) { - return Matcher<clang::CallExpr>(HasDeclaration(InnerMatcher)); -} - -/// Matches if the expression's or declaration's type matches a type matcher. -/// -/// Example matches x (matcher = Expression(HasType( -/// HasDeclaration(Class(HasName("X")))))) -/// and z (matcher = Variable(HasType( -/// HasDeclaration(Class(HasName("X")))))) -/// class X {}; -/// void y(X &x) { x; X z; } -AST_POLYMORPHIC_MATCHER_P(HasType, Matcher<clang::QualType>, InnerMatcher) { - COMPILE_ASSERT((llvm::is_base_of<clang::Expr, NodeType>::value || - llvm::is_base_of<clang::ValueDecl, NodeType>::value), - instantiated_with_wrong_types); - return InnerMatcher.Matches(Node.getType(), Finder, Builder); -} - -/// Overloaded to match the declaration of the expression's or value -/// declaration's type. -/// In case of a value declaration (for example a variable declaration), -/// this resolves one layer of indirection. For example, in the value declaration -/// "X x;", Class(HasName("X")) matches the declaration of X, while -/// Variable(HasType(Class(HasName("X")))) matches the declaration of x." -/// -/// Example matches x (matcher = Expression(HasType(Class(HasName("X"))))) -/// and z (matcher = Variable(HasType(Class(HasName("X"))))) -/// class X {}; -/// void y(X &x) { x; X z; } -inline PolymorphicMatcherWithParam1<matcher_internal_HasTypeMatcher, - Matcher<clang::QualType> > -HasType(const Matcher<clang::Decl> &InnerMatcher) { - return HasType(Matcher<clang::QualType>(HasDeclaration(InnerMatcher))); -} - -/// Matches if the matched type is a pointer type and the pointee type matches -/// the specified matcher. -/// -/// Example matches y->x() -/// (matcher = Call(On(HasType(PointsTo(Class(HasName("Y"))))))) -/// class Y { public: void x(); }; -/// void z() { Y *y; y->x(); } -AST_MATCHER_P( - clang::QualType, PointsTo, Matcher<clang::QualType>, InnerMatcher) { - return (Node->isPointerType() && - InnerMatcher.Matches(Node->getPointeeType(), Finder, Builder)); -} - -/// Overloaded to match the pointee type's declaration. -inline Matcher<clang::QualType> PointsTo( - const Matcher<clang::Decl> &InnerMatcher) { - return PointsTo(Matcher<clang::QualType>(HasDeclaration(InnerMatcher))); -} - -/// Matches if the matched type is a reference type and the referenced type -/// matches the specified matcher. -/// -/// Example matches X &x and const X &y -/// (matcher = Variable(HasType(References(Class(HasName("X")))))) -/// class X { -/// void a(X b) { -/// X &x = b; -/// const X &y = b; -/// }; -AST_MATCHER_P( - clang::QualType, References, Matcher<clang::QualType>, InnerMatcher) { - return (Node->isReferenceType() && - InnerMatcher.Matches(Node->getPointeeType(), Finder, Builder)); -} - -/// Overloaded to match the referenced type's declaration. -inline Matcher<clang::QualType> References( - const Matcher<clang::Decl> &InnerMatcher) { - return References(Matcher<clang::QualType>(HasDeclaration(InnerMatcher))); -} - -AST_MATCHER_P(clang::CXXMemberCallExpr, OnImplicitObjectArgument, - Matcher<clang::Expr>, InnerMatcher) { - const clang::Expr *ExprNode = - const_cast<clang::CXXMemberCallExpr&>(Node).getImplicitObjectArgument(); - return (ExprNode != NULL && - InnerMatcher.Matches(*ExprNode, Finder, Builder)); -} - -/// Matches if the expression's type either matches the specified matcher, or -/// is a pointer to a type that matches the InnerMatcher. -inline Matcher<clang::CallExpr> ThisPointerType( - const Matcher<clang::QualType> &InnerMatcher) { - return OnImplicitObjectArgument( - AnyOf(HasType(InnerMatcher), HasType(PointsTo(InnerMatcher)))); -} - -/// Overloaded to match the type's declaration. -inline Matcher<clang::CallExpr> ThisPointerType( - const Matcher<clang::Decl> &InnerMatcher) { - return OnImplicitObjectArgument( - AnyOf(HasType(InnerMatcher), HasType(PointsTo(InnerMatcher)))); -} - -/// Matches a DeclRefExpr that refers to a declaration that matches the specified -/// matcher. -/// -/// Example matches x in if(x) -/// (matcher = DeclarationReference(To(Variable(HasName("x"))))) -/// bool x; -/// if (x) {} -AST_MATCHER_P(clang::DeclRefExpr, To, Matcher<clang::Decl>, InnerMatcher) { - const clang::Decl *DeclNode = Node.getDecl(); - return (DeclNode != NULL && - InnerMatcher.Matches(*DeclNode, Finder, Builder)); -} - -/// Matches a variable declaration that has an initializer expression that -/// matches the given matcher. -/// -/// Example matches x (matcher = Variable(HasInitializer(Call()))) -/// bool y() { return true; } -/// bool x = y(); -AST_MATCHER_P( - clang::VarDecl, HasInitializer, Matcher<clang::Expr>, InnerMatcher) { - const clang::Expr *Initializer = Node.getAnyInitializer(); - return (Initializer != NULL && - InnerMatcher.Matches(*Initializer, Finder, Builder)); -} - -/// Checks that a call expression or a constructor call expression has -/// a specific number of arguments (including absent default arguments). -/// -/// Example matches f(0, 0) (matcher = Call(ArgumentCountIs(2))) -/// void f(int x, int y); -/// f(0, 0); -AST_POLYMORPHIC_MATCHER_P(ArgumentCountIs, unsigned, N) { - COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr, NodeType>::value || - llvm::is_base_of<clang::CXXConstructExpr, NodeType>::value), - instantiated_with_wrong_types); - return Node.getNumArgs() == N; -} - -/// Matches the n'th argument of a call expression or a constructor -/// call expression. -/// -/// Example matches y in x(y) -/// (matcher = Call(HasArgument(0, DeclarationReference()))) -/// void x(int) { int y; x(y); } -AST_POLYMORPHIC_MATCHER_P2( - HasArgument, unsigned, N, Matcher<clang::Expr>, InnerMatcher) { - COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr, NodeType>::value || - llvm::is_base_of<clang::CXXConstructExpr, NodeType>::value), - instantiated_with_wrong_types); - assert(N >= 0); - return (N < Node.getNumArgs() && - InnerMatcher.Matches( - *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); -} - -/// Matches any argument of a call expression or a constructor call expression. -/// -/// Given -/// void x(int, int, int) { int y; x(1, y, 42); } -/// Call(HasAnyArgument(DeclarationReference())) -/// matches x(1, y, 42) -/// with HasAnyArgument(...) -/// matching y -AST_POLYMORPHIC_MATCHER_P(HasAnyArgument, Matcher<clang::Expr>, InnerMatcher) { - COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr, NodeType>::value || - llvm::is_base_of<clang::CXXConstructExpr, NodeType>::value), - instantiated_with_wrong_types); - for (unsigned I = 0; I < Node.getNumArgs(); ++I) { - if (InnerMatcher.Matches(*Node.getArg(I)->IgnoreParenImpCasts(), - Finder, Builder)) { - return true; - } - } - return false; -} - -/// Matches the n'th parameter of a function declaration. -/// -/// Given -/// class X { void f(int x) {} }; -/// Method(HasParameter(0, HasType(Variable()))) -/// matches f(int x) {} -/// with HasParameter(...) -/// matching int x -AST_MATCHER_P2(clang::FunctionDecl, HasParameter, - unsigned, N, Matcher<clang::ParmVarDecl>, InnerMatcher) { - return (N < Node.getNumParams() && - InnerMatcher.Matches( - *Node.getParamDecl(N), Finder, Builder)); -} - -/// Matches any parameter of a function declaration. -/// Does not match the 'this' parameter of a method. -/// -/// Given -/// class X { void f(int x, int y, int z) {} }; -/// Method(HasAnyParameter(HasName("y"))) -/// matches f(int x, int y, int z) {} -/// with HasAnyParameter(...) -/// matching int y -AST_MATCHER_P(clang::FunctionDecl, HasAnyParameter, - Matcher<clang::ParmVarDecl>, InnerMatcher) { - for (unsigned I = 0; I < Node.getNumParams(); ++I) { - if (InnerMatcher.Matches(*Node.getParamDecl(I), Finder, Builder)) { - return true; - } - } - return false; -} - -/// Matches the condition expression of an if statement or conditional operator. -/// -/// Example matches true (matcher = HasCondition(BoolLiteral(Equals(true)))) -/// if (true) {} -AST_POLYMORPHIC_MATCHER_P(HasCondition, Matcher<clang::Expr>, InnerMatcher) { - COMPILE_ASSERT((llvm::is_base_of<clang::IfStmt, NodeType>::value) || - (llvm::is_base_of<clang::ConditionalOperator, - NodeType>::value), - has_condition_requires_if_statement_or_conditional_operator); - const clang::Expr *const Condition = Node.getCond(); - return (Condition != NULL && - InnerMatcher.Matches(*Condition, Finder, Builder)); -} - -/// Matches a 'for' statement that has a given body. -/// -/// Given -/// for (;;) {} -/// HasBody(CompoundStatement()) -/// matches 'for (;;) {}' -/// with CompoundStatement() -/// matching '{}' -AST_MATCHER_P(clang::ForStmt, HasBody, Matcher<clang::Stmt>, InnerMatcher) { - const clang::Stmt *const Statement = Node.getBody(); - return (Statement != NULL && - InnerMatcher.Matches(*Statement, Finder, Builder)); -} - -/// Matches compound statements where at least one substatement matches a -/// given matcher. -/// -/// Given -/// { {}; 1+2; } -/// HasAnySubstatement(CompoundStatement()) -/// matches '{ {}; 1+2; }' -/// with CompoundStatement() -/// matching '{}' -AST_MATCHER_P(clang::CompoundStmt, HasAnySubstatement, - Matcher<clang::Stmt>, InnerMatcher) { - for (clang::CompoundStmt::const_body_iterator It = Node.body_begin(); - It != Node.body_end(); - ++It) { - if (InnerMatcher.Matches(**It, Finder, Builder)) return true; - } - return false; -} - -/// Checks that a compound statement contains a specific number of child -/// statements. -/// -/// Example: Given -/// { for (;;) {} } -/// CompoundStatement(StatementCountIs(0))) -/// matches '{}' -/// but does not match the outer compound statement. -AST_MATCHER_P(clang::CompoundStmt, StatementCountIs, unsigned, N) { - return Node.size() == N; -} - -/// Matches literals that are equal to the given value. -/// -/// Example matches true (matcher = BoolLiteral(Equals(true))) -/// true -template <typename ValueT> -PolymorphicMatcherWithParam1<ValueEqualsMatcher, ValueT> Equals( - const ValueT &Value) { - return PolymorphicMatcherWithParam1<ValueEqualsMatcher, ValueT>(Value); -} - -/// Matches the operator Name of operator expressions (binary or unary). -/// -/// Example matches a || b (matcher = BinaryOperator(HasOperatorName("||"))) -/// !(a || b) -AST_POLYMORPHIC_MATCHER_P(HasOperatorName, std::string, Name) { - COMPILE_ASSERT( - (llvm::is_base_of<clang::BinaryOperator, NodeType>::value) || - (llvm::is_base_of<clang::UnaryOperator, NodeType>::value), - has_condition_requires_if_statement_or_conditional_operator); - return Name == Node.getOpcodeStr(Node.getOpcode()); -} - -/// Matches the left hand side of binary operator expressions. -/// -/// Example matches a (matcher = BinaryOperator(HasLHS())) -/// a || b -AST_MATCHER_P(clang::BinaryOperator, HasLHS, - Matcher<clang::Expr>, InnerMatcher) { - clang::Expr *LeftHandSide = Node.getLHS(); - return (LeftHandSide != NULL && - InnerMatcher.Matches(*LeftHandSide, Finder, Builder)); -} - -/// Matches the right hand side of binary operator expressions. -/// -/// Example matches b (matcher = BinaryOperator(HasRHS())) -/// a || b -AST_MATCHER_P(clang::BinaryOperator, HasRHS, - Matcher<clang::Expr>, InnerMatcher) { - clang::Expr *RightHandSide = Node.getRHS(); - return (RightHandSide != NULL && - InnerMatcher.Matches(*RightHandSide, Finder, Builder)); -} - -/// Matches if either the left hand side or the right hand side of a binary -/// operator matches. -inline Matcher<clang::BinaryOperator> HasEitherOperand( - const Matcher<clang::Expr> &InnerMatcher) { - return AnyOf(HasLHS(InnerMatcher), HasRHS(InnerMatcher)); -} - -/// Matches if the operand of a unary operator matches. -/// -/// Example matches true (matcher = HasOperand(BoolLiteral(Equals(true)))) -/// !true -AST_MATCHER_P(clang::UnaryOperator, HasUnaryOperand, - Matcher<clang::Expr>, InnerMatcher) { - clang::Expr *Operand = Node.getSubExpr(); - return (Operand != NULL && - InnerMatcher.Matches(*Operand, Finder, Builder)); -} - -/// Matches the true branch expression of a conditional operator. -/// -/// Example matches a -/// condition ? a : b -AST_MATCHER_P(clang::ConditionalOperator, HasTrueExpression, - Matcher<clang::Expr>, InnerMatcher) { - clang::Expr *Expression = Node.getTrueExpr(); - return (Expression != NULL && - InnerMatcher.Matches(*Expression, Finder, Builder)); -} - -/// Matches the false branch expression of a conditional operator. -/// -/// Example matches b -/// condition ? a : b -AST_MATCHER_P(clang::ConditionalOperator, HasFalseExpression, - Matcher<clang::Expr>, InnerMatcher) { - clang::Expr *Expression = Node.getFalseExpr(); - return (Expression != NULL && - InnerMatcher.Matches(*Expression, Finder, Builder)); -} - -/// Matches if a declaration has a body attached. -/// -/// Example matches A, va, fa -/// class A {}; -/// class B; // Doesn't match, as it has no body. -/// int va; -/// extern int vb; // Doesn't match, as it doesn't define the variable. -/// void fa() {} -/// void fb(); // Doesn't match, as it has no body. -inline PolymorphicMatcherWithParam0<IsDefinitionMatcher> IsDefinition() { - return PolymorphicMatcherWithParam0<IsDefinitionMatcher>(); -} - -/// Matches the class declaration that the given method declaration belongs to. -/// TODO(qrczak): Generalize this for other kinds of declarations. -/// FIXME: What other kind of declarations would we need to generalize -/// this to? -/// -/// Example matches A() in the last line -/// (matcher = ConstructorCall(HasDeclaration(Method( -/// OfClass(HasName("A")))))) -/// class A { -/// public: -/// A(); -/// }; -/// A a = A(); -AST_MATCHER_P(clang::CXXMethodDecl, OfClass, - Matcher<clang::CXXRecordDecl>, InnerMatcher) { - const clang::CXXRecordDecl *Parent = Node.getParent(); - return (Parent != NULL && - InnerMatcher.Matches(*Parent, Finder, Builder)); -} - -/// Matches member expressions that are called with '->' as opposed to '.'. -/// Member calls on the implicit this pointer match as called with '->'. -/// -/// Given -/// class Y { -/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } -/// int a; -/// static int b; -/// }; -/// MemberExpression(IsArrow()) -/// matches this->x, x, y.x, a, this->b -inline Matcher<clang::MemberExpr> IsArrow() { - return MakeMatcher(new IsArrowMatcher()); -} - -} // namespace match - -/// Runs over an AST and finds matches. -/// FIXME: Define exactly what "one match" is. -/// -/// Not intended to be subclassed. -class MatchFinder { - public: - struct MatchResult { - BoundNodes Nodes; - - ///@{ - /// Utilities for interpreting the matched AST structures. - clang::ASTContext *Context; - clang::SourceManager *SourceManager; - ///@} - }; - - /// Called when the Match registered for it was successfully found in the AST. - class MatchCallback { - public: - virtual ~MatchCallback(); - virtual void Run(const MatchResult &Result) = 0; - }; - - /// Called when parsing is finished. Intended for testing only. - class ParsingDoneTestCallback { - public: - virtual ~ParsingDoneTestCallback(); - virtual void Run() = 0; - }; - - MatchFinder(); - ~MatchFinder(); - - /// Adds a NodeMatcher to match when running over the AST. - /// Calls action with the BoundNodes on every match. - /// Adding more than one InnerMatcher allows finding different matches in a - /// single pass over the AST. - void AddMatcher(const Matcher<clang::Decl> &NodeMatch, - MatchCallback *Action); - /// Adds a NodeMatcher to match when running over the AST. - /// Calls action with the BoundNodes on every match. - /// Adding more than one InnerMatcher allows finding different matches in a - /// single pass over the AST. - void AddMatcher(const Matcher<clang::QualType> &NodeMatch, - MatchCallback *Action); - /// Adds a NodeMatcher to match when running over the AST. - /// Calls action with the BoundNodes on every match. - /// Adding more than one InnerMatcher allows finding different matches in a - /// single pass over the AST. - void AddMatcher(const Matcher<clang::Stmt> &NodeMatch, - MatchCallback *Action); - - /// Finds all matches in the given code and runs the corresponding triggers. - /// Returns true if the code parsed correctly. - bool FindAll(const std::string &Code); - - /// Creates a clang FrontendAction factory that finds all matches. - FrontendActionFactory *NewFrontendActionFactory(); - - /// The provided closure is called after parsing is done, before the AST is - /// traversed. Useful for benchmarking. - /// Each call to FindAll(...) will call the closure once. - void RegisterTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); - - private: - clang::FrontendAction *NewVisitorAction(); - - /// The MatchCallback*'s will be called every time the UntypedBaseMatcher - /// matches on the AST. - std::vector< std::pair<const UntypedBaseMatcher*, MatchCallback*> > Triggers; - - /// Called when parsing is done. - ParsingDoneTestCallback *ParsingDone; - - friend class MatchFinderFrontendActionFactory; -}; - -} // end namespace tooling -} // end namespace clang - -#endif // LLVM_CLANG_TOOLING_AST_MATCHERS_H diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h deleted file mode 100644 index 63c8b6eb22..0000000000 --- a/include/clang/Tooling/Tooling.h +++ /dev/null @@ -1,142 +0,0 @@ -//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements functions to run clang tools standalone instead -// of running them as a plugin. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_TOOLING_H -#define LLVM_CLANG_TOOLING_TOOLING_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/MemoryBuffer.h" -#include <string> -#include <vector> - -namespace clang { - -class FrontendAction; - -namespace tooling { - -/// \brief Runs (and deletes) the tool on 'Code' with the -fsynatx-only flag. -/// -/// \param ToolAction The action to run over the code. -/// \param Code C++ code. -/// -/// \return - True if 'ToolAction' was successfully executed. -bool RunSyntaxOnlyToolOnCode( - clang::FrontendAction *ToolAction, llvm::StringRef Code); - -/// \brief Runs (and deletes) the tool with the given Clang flags. -/// -/// \param ToolAction The action to run over the code. -/// \param Argc The number of elements in Argv. -/// \param Argv The command line arguments, including the path the binary -/// was started with (Argv[0]). -bool RunToolWithFlags( - clang::FrontendAction *ToolAction, int Argc, char *Argv[]); - -/// \brief Converts a vector<string> into a vector<char*> suitable to pass -/// to main-style functions taking (int Argc, char *Argv[]). -std::vector<char*> CommandLineToArgv(const std::vector<std::string> *Command); - -/// \brief Specifies the working directory and command of a compilation. -struct CompileCommand { - /// \brief The working directory the command was executed from. - std::string Directory; - - /// \brief The command line that was executed. - std::vector<std::string> CommandLine; -}; - -/// \brief Looks up the compile command for 'FileName' in 'JsonDatabase'. -/// -/// \param FileName The path to an input file for which we want the compile -/// command line. If the 'JsonDatabase' was created by CMake, this must be -/// an absolute path inside the CMake source directory which does not have -/// symlinks resolved. -/// -/// \param JsonDatabase A JSON formatted list of compile commands. This lookup -/// command supports only a subset of the JSON standard as written by CMake. -/// -/// \param ErrorMessage If non-empty, an error occurred and 'ErrorMessage' will -/// be set to contain the error message. In this case CompileCommand will -/// contain an empty directory and command line. -/// -/// \see JsonCompileCommandLineDatabase -CompileCommand FindCompileArgsInJsonDatabase( - llvm::StringRef FileName, llvm::StringRef JsonDatabase, - std::string &ErrorMessage); - -// Interface to generate clang::FrontendActions. -class FrontendActionFactory { - public: - virtual ~FrontendActionFactory(); - - // Returns a new clang::FrontendAction. The caller takes ownership of the - // returned action. - virtual clang::FrontendAction* New() = 0; -}; - -/// \brief Utility to run a FrontendAction over a set of files. -/// -/// This class is written to be usable for command line utilities. -class ClangTool { - public: - /// \brief Construct a clang tool from a command line. - /// - /// This will parse the command line parameters and print an error message - /// and exit the program if the command line does not specify the required - /// parameters. - /// - /// Usage: - /// $ tool-name <cmake-output-dir> <file1> <file2> ... - /// - /// where <cmake-output-dir> is a CMake build directory in which a file named - /// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in - /// CMake to get this output). - /// - /// <file1> ... specify the paths of files in the CMake source tree. This - /// path is looked up in the compile command database. If the path of a file - /// is absolute, it needs to point into CMake's source tree. If the path is - /// relative, the current working directory needs to be in the CMake source - /// tree and the file must be in a subdirectory of the current working - /// directory. "./" prefixes in the relative files will be automatically - /// removed, but the rest of a relative path must be a suffix of a path in - /// the compile command line database. - /// - /// For example, to use a tool on all files in a subtree of the source - /// tree, use: - /// - /// /path/in/subtree $ find . -name '*.cpp' | - /// xargs tool-name /path/to/source - /// - /// \param argc The argc argument from main. - /// \param argv The argv argument from main. - ClangTool(int argc, char **argv); - - /// Runs a frontend action over all files specified in the command line. - /// - /// \param ActionFactory Factory generating the frontend actions. The function - /// takes ownership of this parameter. A new action is generated for every - /// processed translation unit. - int Run(FrontendActionFactory *ActionFactory); - - private: - std::vector<std::string> Files; - llvm::OwningPtr<llvm::MemoryBuffer> JsonDatabase; -}; - -} // end namespace tooling -} // end namespace clang - -#endif // LLVM_CLANG_TOOLING_TOOLING_H diff --git a/include/clang/Tooling/VariadicFunction.h b/include/clang/Tooling/VariadicFunction.h deleted file mode 100644 index 6c19d90615..0000000000 --- a/include/clang/Tooling/VariadicFunction.h +++ /dev/null @@ -1,1398 +0,0 @@ -//===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements compile-time type-safe variadic functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_VARIADIC_FUNCTION_H -#define LLVM_CLANG_TOOLING_VARIADIC_FUNCTION_H - -#include <stddef.h> // Defines NULL. - -namespace clang { -namespace tooling { -namespace internal { - -/// The VariadicFunction class template makes it easy to define -/// type-safe variadic functions where all arguments have the same -/// type. -/// -/// Suppose we need a variadic function like this: -/// -/// Result Foo(const Arg &a0, const Arg &a1, ..., const Arg &an); -/// -/// Instead of many overloads of Foo(), we only need to define a helper -/// function that takes an array of arguments: -/// -/// Result FooImpl(const Arg *const args[], int count) { -/// // 'count' is the number of values in the array; args[i] is a pointer -/// // to the i-th argument passed to Foo(). Therefore, write *args[i] -/// // to access the i-th argument. -/// ... -/// } -/// -/// and then define Foo() like this: -/// -/// const VariadicFunction<Result, Arg, FooImpl> Foo; -/// -/// VariadicFunction takes care of defining the overloads of Foo(). -/// -/// Actually, Foo is a function object (i.e. functor) instead of a plain -/// function. This object is stateless and its constructor/destructor -/// does nothing, so it's safe to call Foo(...) at any time. -/// -/// Sometimes we need a variadic function to have some fixed leading -/// arguments whose types may be different from that of the optional -/// arguments. For example: -/// -/// bool FullMatch(const StringRef &s, const RE ®ex, -/// const Arg &a0, ..., const Arg &an); -/// -/// VariadicFunctionN is for such cases, where N is the number of fixed -/// arguments. It is like VariadicFunction, except that it takes N more -/// template arguments for the types of the fixed arguments: -/// -/// bool FullMatchImpl(const StringRef &s, const RE ®ex, -/// const Arg *const args[], int count) { ... } -/// const VariadicFunction2<bool, const StringRef&, -/// const RE&, Arg, FullMatchImpl> -/// FullMatch; -/// -/// Currently VariadicFunction and friends support up-to 3 -/// fixed leading arguments and up-to 32 optional arguments. -template <typename Result, typename Arg, - Result (*Func)(const Arg *const [], int count)> -class VariadicFunction { - public: - VariadicFunction() {} - - Result operator()() const { - return Func(NULL, 0); - } - - Result operator()(const Arg &a0) const { - const Arg *const args[] = { &a0 }; - return Func(args, 1); - } - - Result operator()(const Arg &a0, const Arg &a1) const { - const Arg *const args[] = { &a0, &a1 }; - return Func(args, 2); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2) const { - const Arg *const args[] = { &a0, &a1, &a2 }; - return Func(args, 3); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3 }; - return Func(args, 4); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4 }; - return Func(args, 5); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5 }; - return Func(args, 6); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6 }; - return Func(args, 7); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; - return Func(args, 8); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; - return Func(args, 9); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9 }; - return Func(args, 10); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10 }; - return Func(args, 11); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11 }; - return Func(args, 12); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12 }; - return Func(args, 13); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13 }; - return Func(args, 14); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14 }; - return Func(args, 15); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15 }; - return Func(args, 16); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16 }; - return Func(args, 17); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17 }; - return Func(args, 18); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18 }; - return Func(args, 19); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19 }; - return Func(args, 20); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, - &a20 }; - return Func(args, 21); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21 }; - return Func(args, 22); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22 }; - return Func(args, 23); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23 }; - return Func(args, 24); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24 }; - return Func(args, 25); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25 }; - return Func(args, 26); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25, const Arg &a26) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26 }; - return Func(args, 27); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25, const Arg &a26, const Arg &a27) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27 }; - return Func(args, 28); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25, const Arg &a26, const Arg &a27, - const Arg &a28) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28 }; - return Func(args, 29); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25, const Arg &a26, const Arg &a27, - const Arg &a28, const Arg &a29) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29 }; - return Func(args, 30); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25, const Arg &a26, const Arg &a27, - const Arg &a28, const Arg &a29, const Arg &a30) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30 }; - return Func(args, 31); - } - - Result operator()(const Arg &a0, const Arg &a1, const Arg &a2, const Arg &a3, - const Arg &a4, const Arg &a5, const Arg &a6, const Arg &a7, - const Arg &a8, const Arg &a9, const Arg &a10, const Arg &a11, - const Arg &a12, const Arg &a13, const Arg &a14, const Arg &a15, - const Arg &a16, const Arg &a17, const Arg &a18, const Arg &a19, - const Arg &a20, const Arg &a21, const Arg &a22, const Arg &a23, - const Arg &a24, const Arg &a25, const Arg &a26, const Arg &a27, - const Arg &a28, const Arg &a29, const Arg &a30, const Arg &a31) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30, &a31 }; - return Func(args, 32); - } -}; - -template <typename Result, typename Param0, typename Arg, - Result (*Func)(Param0, const Arg *const [], int count)> -class VariadicFunction1 { - public: - VariadicFunction1() {} - - Result operator()(Param0 p0) const { - return Func(p0, NULL, 0); - } - - Result operator()(Param0 p0, const Arg &a0) const { - const Arg *const args[] = { &a0 }; - return Func(p0, args, 1); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1) const { - const Arg *const args[] = { &a0, &a1 }; - return Func(p0, args, 2); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, - const Arg &a2) const { - const Arg *const args[] = { &a0, &a1, &a2 }; - return Func(p0, args, 3); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3 }; - return Func(p0, args, 4); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4 }; - return Func(p0, args, 5); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5 }; - return Func(p0, args, 6); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6 }; - return Func(p0, args, 7); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; - return Func(p0, args, 8); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; - return Func(p0, args, 9); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9 }; - return Func(p0, args, 10); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10 }; - return Func(p0, args, 11); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11 }; - return Func(p0, args, 12); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12 }; - return Func(p0, args, 13); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13 }; - return Func(p0, args, 14); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14 }; - return Func(p0, args, 15); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15 }; - return Func(p0, args, 16); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16 }; - return Func(p0, args, 17); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17 }; - return Func(p0, args, 18); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18 }; - return Func(p0, args, 19); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19 }; - return Func(p0, args, 20); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, - &a20 }; - return Func(p0, args, 21); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21 }; - return Func(p0, args, 22); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22 }; - return Func(p0, args, 23); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23 }; - return Func(p0, args, 24); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24 }; - return Func(p0, args, 25); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25 }; - return Func(p0, args, 26); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25, const Arg &a26) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26 }; - return Func(p0, args, 27); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25, const Arg &a26, - const Arg &a27) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27 }; - return Func(p0, args, 28); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25, const Arg &a26, - const Arg &a27, const Arg &a28) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28 }; - return Func(p0, args, 29); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25, const Arg &a26, - const Arg &a27, const Arg &a28, const Arg &a29) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29 }; - return Func(p0, args, 30); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25, const Arg &a26, - const Arg &a27, const Arg &a28, const Arg &a29, const Arg &a30) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30 }; - return Func(p0, args, 31); - } - - Result operator()(Param0 p0, const Arg &a0, const Arg &a1, const Arg &a2, - const Arg &a3, const Arg &a4, const Arg &a5, const Arg &a6, - const Arg &a7, const Arg &a8, const Arg &a9, const Arg &a10, - const Arg &a11, const Arg &a12, const Arg &a13, const Arg &a14, - const Arg &a15, const Arg &a16, const Arg &a17, const Arg &a18, - const Arg &a19, const Arg &a20, const Arg &a21, const Arg &a22, - const Arg &a23, const Arg &a24, const Arg &a25, const Arg &a26, - const Arg &a27, const Arg &a28, const Arg &a29, const Arg &a30, - const Arg &a31) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30, &a31 }; - return Func(p0, args, 32); - } -}; - -template <typename Result, typename Param0, typename Param1, typename Arg, - Result (*Func)(Param0, Param1, const Arg *const [], int count)> -class VariadicFunction2 { - public: - VariadicFunction2() {} - - Result operator()(Param0 p0, Param1 p1) const { - return Func(p0, p1, NULL, 0); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0) const { - const Arg *const args[] = { &a0 }; - return Func(p0, p1, args, 1); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1) const { - const Arg *const args[] = { &a0, &a1 }; - return Func(p0, p1, args, 2); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2) const { - const Arg *const args[] = { &a0, &a1, &a2 }; - return Func(p0, p1, args, 3); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3 }; - return Func(p0, p1, args, 4); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4 }; - return Func(p0, p1, args, 5); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5 }; - return Func(p0, p1, args, 6); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6 }; - return Func(p0, p1, args, 7); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; - return Func(p0, p1, args, 8); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; - return Func(p0, p1, args, 9); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9 }; - return Func(p0, p1, args, 10); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10 }; - return Func(p0, p1, args, 11); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11 }; - return Func(p0, p1, args, 12); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12 }; - return Func(p0, p1, args, 13); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13 }; - return Func(p0, p1, args, 14); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14 }; - return Func(p0, p1, args, 15); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15 }; - return Func(p0, p1, args, 16); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16 }; - return Func(p0, p1, args, 17); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17 }; - return Func(p0, p1, args, 18); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18 }; - return Func(p0, p1, args, 19); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19 }; - return Func(p0, p1, args, 20); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, - &a20 }; - return Func(p0, p1, args, 21); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21 }; - return Func(p0, p1, args, 22); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22 }; - return Func(p0, p1, args, 23); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23 }; - return Func(p0, p1, args, 24); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24 }; - return Func(p0, p1, args, 25); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25 }; - return Func(p0, p1, args, 26); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25, - const Arg &a26) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26 }; - return Func(p0, p1, args, 27); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25, - const Arg &a26, const Arg &a27) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27 }; - return Func(p0, p1, args, 28); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25, - const Arg &a26, const Arg &a27, const Arg &a28) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28 }; - return Func(p0, p1, args, 29); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25, - const Arg &a26, const Arg &a27, const Arg &a28, const Arg &a29) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29 }; - return Func(p0, p1, args, 30); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25, - const Arg &a26, const Arg &a27, const Arg &a28, const Arg &a29, - const Arg &a30) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30 }; - return Func(p0, p1, args, 31); - } - - Result operator()(Param0 p0, Param1 p1, const Arg &a0, const Arg &a1, - const Arg &a2, const Arg &a3, const Arg &a4, const Arg &a5, - const Arg &a6, const Arg &a7, const Arg &a8, const Arg &a9, - const Arg &a10, const Arg &a11, const Arg &a12, const Arg &a13, - const Arg &a14, const Arg &a15, const Arg &a16, const Arg &a17, - const Arg &a18, const Arg &a19, const Arg &a20, const Arg &a21, - const Arg &a22, const Arg &a23, const Arg &a24, const Arg &a25, - const Arg &a26, const Arg &a27, const Arg &a28, const Arg &a29, - const Arg &a30, const Arg &a31) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30, &a31 }; - return Func(p0, p1, args, 32); - } -}; - -template <typename Result, typename Param0, typename Param1, typename Param2, - typename Arg, - Result (*Func)(Param0, Param1, Param2, const Arg *const [], - int count)> -class VariadicFunction3 { - public: - VariadicFunction3() {} - - Result operator()(Param0 p0, Param1 p1, Param2 p2) const { - return Func(p0, p1, p2, NULL, 0); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0) const { - const Arg *const args[] = { &a0 }; - return Func(p0, p1, p2, args, 1); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1) const { - const Arg *const args[] = { &a0, &a1 }; - return Func(p0, p1, p2, args, 2); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2) const { - const Arg *const args[] = { &a0, &a1, &a2 }; - return Func(p0, p1, p2, args, 3); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3 }; - return Func(p0, p1, p2, args, 4); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4 }; - return Func(p0, p1, p2, args, 5); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5 }; - return Func(p0, p1, p2, args, 6); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6 }; - return Func(p0, p1, p2, args, 7); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; - return Func(p0, p1, p2, args, 8); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; - return Func(p0, p1, p2, args, 9); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9 }; - return Func(p0, p1, p2, args, 10); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10 }; - return Func(p0, p1, p2, args, 11); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11 }; - return Func(p0, p1, p2, args, 12); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12 }; - return Func(p0, p1, p2, args, 13); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13 }; - return Func(p0, p1, p2, args, 14); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14 }; - return Func(p0, p1, p2, args, 15); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15 }; - return Func(p0, p1, p2, args, 16); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16 }; - return Func(p0, p1, p2, args, 17); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17 }; - return Func(p0, p1, p2, args, 18); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18 }; - return Func(p0, p1, p2, args, 19); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19 }; - return Func(p0, p1, p2, args, 20); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, - &a20 }; - return Func(p0, p1, p2, args, 21); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21 }; - return Func(p0, p1, p2, args, 22); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22 }; - return Func(p0, p1, p2, args, 23); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23 }; - return Func(p0, p1, p2, args, 24); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24 }; - return Func(p0, p1, p2, args, 25); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25 }; - return Func(p0, p1, p2, args, 26); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25, const Arg &a26) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26 }; - return Func(p0, p1, p2, args, 27); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25, const Arg &a26, const Arg &a27) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27 }; - return Func(p0, p1, p2, args, 28); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25, const Arg &a26, const Arg &a27, const Arg &a28) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28 }; - return Func(p0, p1, p2, args, 29); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25, const Arg &a26, const Arg &a27, const Arg &a28, - const Arg &a29) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29 }; - return Func(p0, p1, p2, args, 30); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25, const Arg &a26, const Arg &a27, const Arg &a28, - const Arg &a29, const Arg &a30) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30 }; - return Func(p0, p1, p2, args, 31); - } - - Result operator()(Param0 p0, Param1 p1, Param2 p2, const Arg &a0, - const Arg &a1, const Arg &a2, const Arg &a3, const Arg &a4, - const Arg &a5, const Arg &a6, const Arg &a7, const Arg &a8, - const Arg &a9, const Arg &a10, const Arg &a11, const Arg &a12, - const Arg &a13, const Arg &a14, const Arg &a15, const Arg &a16, - const Arg &a17, const Arg &a18, const Arg &a19, const Arg &a20, - const Arg &a21, const Arg &a22, const Arg &a23, const Arg &a24, - const Arg &a25, const Arg &a26, const Arg &a27, const Arg &a28, - const Arg &a29, const Arg &a30, const Arg &a31) const { - const Arg *const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, - &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, - &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30, &a31 }; - return Func(p0, p1, p2, args, 32); - } -}; - -} // end namespace internal -} // end namespace tooling -} // end namespace clang - -#endif // LLVM_CLANG_TOOLING_VARIADIC_FUNCTION_H diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 0943e2b1c7..b4574344bc 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -13,4 +13,3 @@ add_subdirectory(Frontend) add_subdirectory(FrontendTool) add_subdirectory(Index) add_subdirectory(StaticAnalyzer) -add_subdirectory(Tooling) diff --git a/lib/Makefile b/lib/Makefile index eda7017bb8..924819c818 100755 --- a/lib/Makefile +++ b/lib/Makefile @@ -10,7 +10,7 @@ CLANG_LEVEL := .. PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \ StaticAnalyzer Rewrite Serialization Frontend FrontendTool \ - Index Driver Tooling + Index Driver include $(CLANG_LEVEL)/Makefile diff --git a/lib/Tooling/ASTMatchers.cpp b/lib/Tooling/ASTMatchers.cpp deleted file mode 100644 index f03580ea34..0000000000 --- a/lib/Tooling/ASTMatchers.cpp +++ /dev/null @@ -1,564 +0,0 @@ -//===--- ASTMatchers.cpp - Structural query framework ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a framework of AST matchers that can be used to express -// structural queries on C++ code. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Tooling/ASTMatchers.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/ADT/DenseMap.h" -#include <assert.h> -#include <stddef.h> -#include <set> -#include <utility> - -namespace clang { -namespace tooling { - -// Returns the value that 'a_map' maps 'key' to, or NULL if 'key' is -// not in 'a_map'. -template <typename Map> -static const typename Map::mapped_type *Find( - const Map &AMap, const typename Map::key_type &Key) { - typename Map::const_iterator It = AMap.find(Key); - return It == AMap.end() ? NULL : &It->second; -} - -// We use memoization to avoid running the same matcher on the same -// AST node twice. This pair is the key for looking up match -// result. It consists of an ID of the MatcherInterface (for -// identifying the matcher) and a pointer to the AST node. -typedef std::pair<uint64_t, const void*> UntypedMatchInput; - -// Used to store the result of a match and possibly bound nodes. -struct MemoizedMatchResult { - bool ResultOfMatch; - BoundNodes Nodes; -}; - -// A RecursiveASTVisitor that traverses all children or all descendants of -// a node. -class MatchChildASTVisitor - : public clang::RecursiveASTVisitor<MatchChildASTVisitor> { - public: - typedef clang::RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase; - - // Creates an AST visitor that matches 'matcher' on all children or - // descendants of a traversed node. max_depth is the maximum depth - // to traverse: use 1 for matching the children and INT_MAX for - // matching the descendants. - MatchChildASTVisitor(const UntypedBaseMatcher *BaseMatcher, - ASTMatchFinder *Finder, - BoundNodesBuilder *Builder, - int MaxDepth, - ASTMatchFinder::TraversalMethod Traversal) - : BaseMatcher(BaseMatcher), - Finder(Finder), - Builder(Builder), - CurrentDepth(-1), - MaxDepth(MaxDepth), - Traversal(Traversal), - Matches(false) {} - - // Returns true if a match is found in the subtree rooted at the - // given AST node. This is done via a set of mutually recursive - // functions. Here's how the recursion is done (the *wildcard can - // actually be Decl, Stmt, or Type): - // - // - Traverse(node) calls BaseTraverse(node) when it needs - // to visit the descendants of node. - // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node)) - // Traverse*(c) for each child c of 'node'. - // - Traverse*(c) in turn calls Traverse(c), completing the - // recursion. - template <typename T> - bool FindMatch(const T &Node) { - Reset(); - Traverse(Node); - return Matches; - } - - // The following are overriding methods from the base visitor class. - // They are public only to allow CRTP to work. They are *not *part - // of the public API of this class. - bool TraverseDecl(clang::Decl *DeclNode) { - return (DeclNode == NULL) || Traverse(*DeclNode); - } - bool TraverseStmt(clang::Stmt *StmtNode) { - const clang::Stmt *StmtToTraverse = StmtNode; - if (Traversal == - ASTMatchFinder::kIgnoreImplicitCastsAndParentheses) { - const clang::Expr *ExprNode = dyn_cast_or_null<clang::Expr>(StmtNode); - if (ExprNode != NULL) { - StmtToTraverse = ExprNode->IgnoreParenImpCasts(); - } - } - return (StmtToTraverse == NULL) || Traverse(*StmtToTraverse); - } - bool TraverseType(clang::QualType TypeNode) { - return Traverse(TypeNode); - } - - bool shouldVisitTemplateInstantiations() const { return true; } - - private: - // Resets the state of this object. - void Reset() { - Matches = false; - CurrentDepth = -1; - } - - // Forwards the call to the corresponding Traverse*() method in the - // base visitor class. - bool BaseTraverse(const clang::Decl &DeclNode) { - return VisitorBase::TraverseDecl(const_cast<clang::Decl*>(&DeclNode)); - } - bool BaseTraverse(const clang::Stmt &StmtNode) { - return VisitorBase::TraverseStmt(const_cast<clang::Stmt*>(&StmtNode)); - } - bool BaseTraverse(clang::QualType TypeNode) { - return VisitorBase::TraverseType(TypeNode); - } - - // Traverses the subtree rooted at 'node'; returns true if the - // traversal should continue after this function returns; also sets - // matched_ to true if a match is found during the traversal. - template <typename T> - bool Traverse(const T &Node) { - COMPILE_ASSERT(IsBaseType<T>::value, - traverse_can_only_be_instantiated_with_base_type); - ++CurrentDepth; - bool ShouldContinue; - if (CurrentDepth == 0) { - // We don't want to match the root node, so just recurse. - ShouldContinue = BaseTraverse(Node); - } else if (BaseMatcher->Matches(Node, Finder, Builder)) { - Matches = true; - ShouldContinue = false; // Abort as soon as a match is found. - } else if (CurrentDepth < MaxDepth) { - // The current node doesn't match, and we haven't reached the - // maximum depth yet, so recurse. - ShouldContinue = BaseTraverse(Node); - } else { - // The current node doesn't match, and we have reached the - // maximum depth, so don't recurse (but continue the traversal - // such that other nodes at the current level can be visited). - ShouldContinue = true; - } - --CurrentDepth; - return ShouldContinue; - } - - const UntypedBaseMatcher *const BaseMatcher; - ASTMatchFinder *const Finder; - BoundNodesBuilder *const Builder; - int CurrentDepth; - const int MaxDepth; - const ASTMatchFinder::TraversalMethod Traversal; - bool Matches; -}; - -// Controls the outermost traversal of the AST and allows to match multiple -// matchers. -class MatchASTVisitor : public clang::RecursiveASTVisitor<MatchASTVisitor>, - public ASTMatchFinder { - public: - MatchASTVisitor(std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> > *Triggers, - clang::SourceManager *VisitorSourceManager, - clang::LangOptions *LanguageOptions) - : Triggers(Triggers), - VisitorSourceManager(VisitorSourceManager), - LanguageOptions(LanguageOptions), - ActiveASTContext(NULL) { - assert(VisitorSourceManager != NULL); - assert(LanguageOptions != NULL); - // FIXME: add rewriter_(*source_manager, *language_options) - } - - void set_active_ast_context(clang::ASTContext *NewActiveASTContext) { - ActiveASTContext = NewActiveASTContext; - } - - // The following Visit*() and Traverse*() functions "override" - // methods in RecursiveASTVisitor. - - bool VisitTypedefDecl(clang::TypedefDecl *DeclNode) { - // When we see 'typedef A B', we add name 'B' to the set of names - // A's canonical type maps to. This is necessary for implementing - // IsDerivedFrom(x) properly, where x can be the name of the base - // class or any of its aliases. - // - // In general, the is-alias-of (as defined by typedefs) relation - // is tree-shaped, as you can typedef a type more than once. For - // example, - // - // typedef A B; - // typedef A C; - // typedef C D; - // typedef C E; - // - // gives you - // - // A - // |- B - // `- C - // |- D - // `- E - // - // It is wrong to assume that the relation is a chain. A correct - // implementation of IsDerivedFrom() needs to recognize that B and - // E are aliases, even though neither is a typedef of the other. - // Therefore, we cannot simply walk through one typedef chain to - // find out whether the type name matches. - const clang::Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr(); - const clang::Type *CanonicalType = // root of the typedef tree - ActiveASTContext->getCanonicalType(TypeNode); - TypeToUnqualifiedAliases[CanonicalType].insert( - DeclNode->getName().str()); - return true; - } - - bool TraverseDecl(clang::Decl *DeclNode); - bool TraverseStmt(clang::Stmt *StmtNode); - bool TraverseType(clang::QualType TypeNode); - bool TraverseTypeLoc(clang::TypeLoc TypeNode); - - // Matches children or descendants of 'Node' with 'BaseMatcher'. - template <typename T> - bool MemoizedMatchesRecursively( - const T &Node, const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder, int MaxDepth, - TraversalMethod Traversal) { - COMPILE_ASSERT((llvm::is_same<T, clang::Decl>::value) || - (llvm::is_same<T, clang::Stmt>::value), - type_does_not_support_memoization); - const UntypedMatchInput input(BaseMatcher.GetID(), &Node); - std::pair <MemoizationMap::iterator, bool> - InsertResult = ResultCache.insert( - std::make_pair(input, MemoizedMatchResult())); - if (InsertResult.second) { - BoundNodesBuilder DescendantBoundNodesBuilder; - InsertResult.first->second.ResultOfMatch = - MatchesRecursively(Node, BaseMatcher, &DescendantBoundNodesBuilder, - MaxDepth, Traversal); - InsertResult.first->second.Nodes = - DescendantBoundNodesBuilder.Build(); - } - InsertResult.first->second.Nodes.CopyTo(Builder); - return InsertResult.first->second.ResultOfMatch; - } - - // Matches children or descendants of 'Node' with 'BaseMatcher'. - template <typename T> - bool MatchesRecursively( - const T &Node, const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder, int MaxDepth, - TraversalMethod Traversal) { - MatchChildASTVisitor Visitor( - &BaseMatcher, this, Builder, MaxDepth, Traversal); - return Visitor.FindMatch(Node); - } - - virtual bool ClassIsDerivedFrom(const clang::CXXRecordDecl *Declaration, - const std::string &BaseName) const; - - // Implements ASTMatchFinder::MatchesChildOf. - virtual bool MatchesChildOf(const clang::Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder, - TraversalMethod Traversal) { - return MatchesRecursively( - DeclNode, BaseMatcher, Builder, 1, Traversal); - } - virtual bool MatchesChildOf(const clang::Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder, - TraversalMethod Traversal) { - return MatchesRecursively( - StmtNode, BaseMatcher, Builder, 1, Traversal); - } - - // Implements ASTMatchFinder::MatchesDescendantOf. - virtual bool MatchesDescendantOf(const clang::Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder) { - return MemoizedMatchesRecursively( - DeclNode, BaseMatcher, Builder, INT_MAX, kAsIs); - } - virtual bool MatchesDescendantOf(const clang::Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesBuilder *Builder) { - return MemoizedMatchesRecursively( - StmtNode, BaseMatcher, Builder, INT_MAX, kAsIs); - } - - bool shouldVisitTemplateInstantiations() const { return true; } - - private: - // Returns true if 'TypeNode' is also known by the name 'Name'. In other - // words, there is a type (including typedef) with the name 'Name' - // that is equal to 'TypeNode'. - bool TypeHasAlias( - const clang::Type *TypeNode, const std::string &Name) const { - const clang::Type *const CanonicalType = - ActiveASTContext->getCanonicalType(TypeNode); - const std::set<std::string> *UnqualifiedAlias = - Find(TypeToUnqualifiedAliases, CanonicalType); - return UnqualifiedAlias != NULL && UnqualifiedAlias->count(Name) > 0; - } - - // Matches all registered matchers on the given node and calls the - // result callback for every node that matches. - template <typename T> - void Match(const T &node) { - for (std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> >::const_iterator - It = Triggers->begin(), End = Triggers->end(); - It != End; ++It) { - BoundNodesBuilder Builder; - if (It->first->Matches(node, this, &Builder)) { - MatchFinder::MatchResult Result; - Result.Nodes = Builder.Build(); - Result.Context = ActiveASTContext; - Result.SourceManager = VisitorSourceManager; - It->second->Run(Result); - } - } - } - - std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> > *const Triggers; - clang::SourceManager *const VisitorSourceManager; - clang::LangOptions *const LanguageOptions; - clang::ASTContext *ActiveASTContext; - - // Maps a canonical type to the names of its typedefs. - llvm::DenseMap<const clang::Type*, std::set<std::string> > - TypeToUnqualifiedAliases; - - // Maps (matcher, node) -> the match result for memoization. - typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap; - MemoizationMap ResultCache; -}; - -// Returns true if the given class is directly or indirectly derived -// from a base type with the given name. A class is considered to be -// also derived from itself. -bool MatchASTVisitor::ClassIsDerivedFrom( - const clang::CXXRecordDecl *Declaration, - const std::string &BaseName) const { - if (std::string(Declaration->getName()) == BaseName) { - return true; - } - if (!Declaration->hasDefinition()) { - return false; - } - typedef clang::CXXRecordDecl::base_class_const_iterator BaseIterator; - for (BaseIterator It = Declaration->bases_begin(), - End = Declaration->bases_end(); It != End; ++It) { - const clang::Type *TypeNode = It->getType().getTypePtr(); - - if (TypeHasAlias(TypeNode, BaseName)) - return true; - - // clang::Type::getAs<...>() drills through typedefs. - if (TypeNode->getAs<clang::DependentNameType>() != NULL || - TypeNode->getAs<clang::TemplateTypeParmType>() != NULL) { - // Dependent names and template TypeNode parameters will be matched when - // the template is instantiated. - continue; - } - clang::CXXRecordDecl *ClassDecl = NULL; - clang::TemplateSpecializationType const *TemplateType = - TypeNode->getAs<clang::TemplateSpecializationType>(); - if (TemplateType != NULL) { - if (TemplateType->getTemplateName().isDependent()) { - // Dependent template specializations will be matched when the - // template is instantiated. - continue; - } - // For template specialization types which are specializing a template - // declaration which is an explicit or partial specialization of another - // template declaration, getAsCXXRecordDecl() returns the corresponding - // ClassTemplateSpecializationDecl. - // - // For template specialization types which are specializing a template - // declaration which is neither an explicit nor partial specialization of - // another template declaration, getAsCXXRecordDecl() returns NULL and - // we get the CXXRecordDecl of the templated declaration. - clang::CXXRecordDecl *SpecializationDecl = - TemplateType->getAsCXXRecordDecl(); - if (SpecializationDecl != NULL) { - ClassDecl = SpecializationDecl; - } else { - ClassDecl = llvm::dyn_cast<clang::CXXRecordDecl>( - TemplateType->getTemplateName() - .getAsTemplateDecl()->getTemplatedDecl()); - } - } else { - ClassDecl = TypeNode->getAsCXXRecordDecl(); - } - assert(ClassDecl != NULL); - assert(ClassDecl != Declaration); - if (ClassIsDerivedFrom(ClassDecl, BaseName)) { - return true; - } - } - return false; -} - -bool MatchASTVisitor::TraverseDecl(clang::Decl *DeclNode) { - if (DeclNode == NULL) { - return true; - } - Match(*DeclNode); - return clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode); -} - -bool MatchASTVisitor::TraverseStmt(clang::Stmt *StmtNode) { - if (StmtNode == NULL) { - return true; - } - Match(*StmtNode); - return clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode); -} - -bool MatchASTVisitor::TraverseType(clang::QualType TypeNode) { - Match(TypeNode); - return clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode); -} - -bool MatchASTVisitor::TraverseTypeLoc(clang::TypeLoc TypeLoc) { - return clang::RecursiveASTVisitor<MatchASTVisitor>:: - TraverseType(TypeLoc.getType()); -} - -class MatchASTConsumer : public clang::ASTConsumer { - public: - MatchASTConsumer(std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> > *Triggers, - MatchFinder::ParsingDoneTestCallback *ParsingDone, - clang::SourceManager *ConsumerSourceManager, - clang::LangOptions *LanaguageOptions) - : Visitor(Triggers, ConsumerSourceManager, LanaguageOptions), - ParsingDone(ParsingDone) {} - - private: - virtual void HandleTranslationUnit( - clang::ASTContext &Context) { // NOLINT: external API uses refs - if (ParsingDone != NULL) { - ParsingDone->Run(); - } - Visitor.set_active_ast_context(&Context); - Visitor.TraverseDecl(Context.getTranslationUnitDecl()); - Visitor.set_active_ast_context(NULL); - } - - MatchASTVisitor Visitor; - MatchFinder::ParsingDoneTestCallback *ParsingDone; -}; - -class MatchASTAction : public clang::ASTFrontendAction { - public: - explicit MatchASTAction( - std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> > *Triggers, - MatchFinder::ParsingDoneTestCallback *ParsingDone) - : Triggers(Triggers), - ParsingDone(ParsingDone) {} - - private: - clang::ASTConsumer *CreateASTConsumer( - clang::CompilerInstance &Compiler, - llvm::StringRef) { - return new MatchASTConsumer(Triggers, - ParsingDone, - &Compiler.getSourceManager(), - &Compiler.getLangOpts()); - } - - std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> > *const Triggers; - MatchFinder::ParsingDoneTestCallback *ParsingDone; -}; - -MatchFinder::MatchCallback::~MatchCallback() {} -MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {} - -MatchFinder::MatchFinder() : ParsingDone(NULL) {} - -MatchFinder::~MatchFinder() { - for (std::vector< std::pair<const UntypedBaseMatcher*, - MatchFinder::MatchCallback*> >::const_iterator - It = Triggers.begin(), End = Triggers.end(); - It != End; ++It) { - delete It->first; - delete It->second; - } -} - -void MatchFinder::AddMatcher(const Matcher<clang::Decl> &NodeMatch, - MatchCallback *Action) { - Triggers.push_back(std::make_pair( - new TypedBaseMatcher<clang::Decl>(NodeMatch), Action)); -} - -void MatchFinder::AddMatcher(const Matcher<clang::QualType> &NodeMatch, - MatchCallback *Action) { - Triggers.push_back(std::make_pair( - new TypedBaseMatcher<clang::QualType>(NodeMatch), Action)); -} - -void MatchFinder::AddMatcher(const Matcher<clang::Stmt> &NodeMatch, - MatchCallback *Action) { - Triggers.push_back(std::make_pair( - new TypedBaseMatcher<clang::Stmt>(NodeMatch), Action)); -} - -bool MatchFinder::FindAll(const std::string &Code) { - return RunSyntaxOnlyToolOnCode( - new MatchASTAction(&Triggers, ParsingDone), Code); -} - -clang::FrontendAction *MatchFinder::NewVisitorAction() { - return new MatchASTAction(&Triggers, ParsingDone); -} - -class MatchFinderFrontendActionFactory : public FrontendActionFactory { - public: - explicit MatchFinderFrontendActionFactory(MatchFinder *Finder) - : Finder(Finder) {} - - virtual clang::FrontendAction *New() { - return Finder->NewVisitorAction(); - } - - private: - MatchFinder *const Finder; -}; - -FrontendActionFactory *MatchFinder::NewFrontendActionFactory() { - return new MatchFinderFrontendActionFactory(this); -} - -void MatchFinder::RegisterTestCallbackAfterParsing( - MatchFinder::ParsingDoneTestCallback *NewParsingDone) { - ParsingDone = NewParsingDone; -} - -} // end namespace tooling -} // end namespace clang diff --git a/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt deleted file mode 100644 index 0a0020a555..0000000000 --- a/lib/Tooling/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -SET(LLVM_USED_LIBS clangBasic clangFrontend clangAST) - -add_clang_library(clangTooling - ASTMatchers.cpp - JsonCompileCommandLineDatabase.cpp - Tooling.cpp - ) diff --git a/lib/Tooling/JsonCompileCommandLineDatabase.cpp b/lib/Tooling/JsonCompileCommandLineDatabase.cpp deleted file mode 100644 index 7f027cfbea..0000000000 --- a/lib/Tooling/JsonCompileCommandLineDatabase.cpp +++ /dev/null @@ -1,214 +0,0 @@ -//===--- JsonCompileCommandLineDatabase.cpp - Simple JSON database --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements reading a compile command line database, as written -// out for example by CMake. -// -//===----------------------------------------------------------------------===// - -#include "JsonCompileCommandLineDatabase.h" -#include "llvm/ADT/Twine.h" - -namespace clang { -namespace tooling { - -namespace { - -// A parser for JSON escaped strings of command line arguments with \-escaping -// for quoted arguments (see the documentation of UnescapeJsonCommandLine(...)). -class CommandLineArgumentParser { - public: - CommandLineArgumentParser(llvm::StringRef CommandLine) - : Input(CommandLine), Position(Input.begin()-1) {} - - std::vector<std::string> Parse() { - bool HasMoreInput = true; - while (HasMoreInput && NextNonWhitespace()) { - std::string Argument; - HasMoreInput = ParseStringInto(Argument); - CommandLine.push_back(Argument); - } - return CommandLine; - } - - private: - // All private methods return true if there is more input available. - - bool ParseStringInto(std::string &String) { - do { - if (*Position == '"') { - if (!ParseQuotedStringInto(String)) return false; - } else { - if (!ParseFreeStringInto(String)) return false; - } - } while (*Position != ' '); - return true; - } - - bool ParseQuotedStringInto(std::string &String) { - if (!Next()) return false; - while (*Position != '"') { - if (!SkipEscapeCharacter()) return false; - String.push_back(*Position); - if (!Next()) return false; - } - return Next(); - } - - bool ParseFreeStringInto(std::string &String) { - do { - if (!SkipEscapeCharacter()) return false; - String.push_back(*Position); - if (!Next()) return false; - } while (*Position != ' ' && *Position != '"'); - return true; - } - - bool SkipEscapeCharacter() { - if (*Position == '\\') { - return Next(); - } - return true; - } - - bool NextNonWhitespace() { - do { - if (!Next()) return false; - } while (*Position == ' '); - return true; - } - - bool Next() { - ++Position; - if (Position == Input.end()) return false; - // Remove the JSON escaping first. This is done unconditionally. - if (*Position == '\\') ++Position; - return Position != Input.end(); - } - - const llvm::StringRef Input; - llvm::StringRef::iterator Position; - std::vector<std::string> CommandLine; -}; - -} // end namespace - -std::vector<std::string> UnescapeJsonCommandLine( - llvm::StringRef JsonEscapedCommandLine) { - CommandLineArgumentParser parser(JsonEscapedCommandLine); - return parser.Parse(); -} - -JsonCompileCommandLineParser::JsonCompileCommandLineParser( - const llvm::StringRef Input, CompileCommandHandler *CommandHandler) - : Input(Input), Position(Input.begin()-1), CommandHandler(CommandHandler) {} - -bool JsonCompileCommandLineParser::Parse() { - NextNonWhitespace(); - return ParseTranslationUnits(); -} - -std::string JsonCompileCommandLineParser::GetErrorMessage() const { - return ErrorMessage; -} - -bool JsonCompileCommandLineParser::ParseTranslationUnits() { - if (!ConsumeOrError('[', "at start of compile command file")) return false; - if (!ParseTranslationUnit(/*First=*/true)) return false; - while (Consume(',')) { - if (!ParseTranslationUnit(/*First=*/false)) return false; - } - if (!ConsumeOrError(']', "at end of array")) return false; - if (CommandHandler != NULL) { - CommandHandler->EndTranslationUnits(); - } - return true; -} - -bool JsonCompileCommandLineParser::ParseTranslationUnit(bool First) { - if (First) { - if (!Consume('{')) return true; - } else { - if (!ConsumeOrError('{', "at start of object")) return false; - } - if (!Consume('}')) { - if (!ParseObjectKeyValuePairs()) return false; - if (!ConsumeOrError('}', "at end of object")) return false; - } - if (CommandHandler != NULL) { - CommandHandler->EndTranslationUnit(); - } - return true; -} - -bool JsonCompileCommandLineParser::ParseObjectKeyValuePairs() { - do { - llvm::StringRef Key; - if (!ParseString(Key)) return false; - if (!ConsumeOrError(':', "between name and value")) return false; - llvm::StringRef Value; - if (!ParseString(Value)) return false; - if (CommandHandler != NULL) { - CommandHandler->HandleKeyValue(Key, Value); - } - } while (Consume(',')); - return true; -} - -bool JsonCompileCommandLineParser::ParseString(llvm::StringRef &String) { - if (!ConsumeOrError('"', "at start of string")) return false; - llvm::StringRef::iterator First = Position; - llvm::StringRef::iterator Last = Position; - while (!Consume('"')) { - Consume('\\'); - ++Position; - // We need to store Position, as Consume will change Last before leaving - // the loop. - Last = Position; - } - String = llvm::StringRef(First, Last - First); - return true; -} - -bool JsonCompileCommandLineParser::Consume(char C) { - if (Position == Input.end()) return false; - if (*Position != C) return false; - NextNonWhitespace(); - return true; -} - -bool JsonCompileCommandLineParser::ConsumeOrError( - char C, llvm::StringRef Message) { - if (!Consume(C)) { - SetExpectError(C, Message); - return false; - } - return true; -} - -void JsonCompileCommandLineParser::SetExpectError( - char C, llvm::StringRef Message) { - ErrorMessage = (llvm::Twine("'") + llvm::StringRef(&C, 1) + - "' expected " + Message + ".").str(); -} - -void JsonCompileCommandLineParser::NextNonWhitespace() { - do { - ++Position; - } while (IsWhitespace()); -} - -bool JsonCompileCommandLineParser::IsWhitespace() { - if (Position == Input.end()) return false; - return (*Position == ' ' || *Position == '\t' || - *Position == '\n' || *Position == '\r'); -} - -} // end namespace tooling -} // end namespace clang diff --git a/lib/Tooling/JsonCompileCommandLineDatabase.h b/lib/Tooling/JsonCompileCommandLineDatabase.h deleted file mode 100644 index ea7cf0e6e1..0000000000 --- a/lib/Tooling/JsonCompileCommandLineDatabase.h +++ /dev/null @@ -1,107 +0,0 @@ -//===--- JsonCompileCommandLineDatabase - Simple JSON database --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements reading a compile command line database, as written -// out for example by CMake. It only supports the subset of the JSON standard -// that is needed to parse the CMake output. -// See http://www.json.org/ for the full standard. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_JSON_COMPILE_COMMAND_LINE_DATABASE_H -#define LLVM_CLANG_TOOLING_JSON_COMPILE_COMMAND_LINE_DATABASE_H - -#include "llvm/ADT/StringRef.h" -#include <string> -#include <vector> - -namespace clang { -namespace tooling { - -/// \brief Converts a JSON escaped command line to a vector of arguments. -/// -/// \param JsonEscapedCommandLine The escaped command line as a string. This -/// is assumed to be escaped as a JSON string (e.g. " and \ are escaped). -/// In addition, any arguments containing spaces are assumed to be \-escaped -/// -/// For example, the input (|| denoting non C-escaped strings): -/// |./call a \"b \\\" c \\\\ \" d| -/// would yield: -/// [ |./call|, |a|, |b " c \ |, |d| ]. -std::vector<std::string> UnescapeJsonCommandLine( - llvm::StringRef JsonEscapedCommandLine); - -/// \brief Interface for users of the JsonCompileCommandLineParser. -class CompileCommandHandler { - public: - virtual ~CompileCommandHandler() {} - - /// \brief Called after all translation units are parsed. - virtual void EndTranslationUnits() {} - - /// \brief Called at the end of a single translation unit. - virtual void EndTranslationUnit() {} - - /// \brief Called for every (Key, Value) pair in a translation unit - /// description. - virtual void HandleKeyValue(llvm::StringRef Key, llvm::StringRef Value) {} -}; - -/// \brief A JSON parser that supports the subset of JSON needed to parse -/// JSON compile command line databases as written out by CMake. -/// -/// The supported subset describes a list of compile command lines for -/// each processed translation unit. The translation units are stored in a -/// JSON array, where each translation unit is described by a JSON object -/// containing (Key, Value) pairs for the working directory the compile command -/// line was executed from, the main C/C++ input file of the translation unit -/// and the actual compile command line, for example: -/// [ -/// { -/// "file":"/file.cpp", -/// "directory":"/", -/// "command":"/cc /file.cpp" -/// } -/// ] -class JsonCompileCommandLineParser { - public: - /// \brief Create a parser on 'Input', calling 'CommandHandler' to handle the - /// parsed constructs. 'CommandHandler' may be NULL in order to just check - /// the validity of 'Input'. - JsonCompileCommandLineParser(const llvm::StringRef Input, - CompileCommandHandler *CommandHandler); - - /// \brief Parses the specified input. Returns true if no parsing errors were - /// found. - bool Parse(); - - /// \brief Returns an error message if Parse() returned false previously. - std::string GetErrorMessage() const; - - private: - bool ParseTranslationUnits(); - bool ParseTranslationUnit(bool First); - bool ParseObjectKeyValuePairs(); - bool ParseString(llvm::StringRef &String); - bool Consume(char C); - bool ConsumeOrError(char C, llvm::StringRef Message); - void NextNonWhitespace(); - bool IsWhitespace(); - void SetExpectError(char C, llvm::StringRef Message); - - const llvm::StringRef Input; - llvm::StringRef::iterator Position; - std::string ErrorMessage; - CompileCommandHandler * const CommandHandler; -}; - -} // end namespace tooling -} // end namespace clang - -#endif // LLVM_CLANG_TOOLING_JSON_COMPILE_COMMAND_LINE_DATABASE_H diff --git a/lib/Tooling/Makefile b/lib/Tooling/Makefile deleted file mode 100644 index 501a00c3f4..0000000000 --- a/lib/Tooling/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- clang/lib/Tooling/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -CLANG_LEVEL := ../.. -LIBRARYNAME := clangTooling - -include $(CLANG_LEVEL)/Makefile - - diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp deleted file mode 100644 index 97a9463852..0000000000 --- a/lib/Tooling/Tooling.cpp +++ /dev/null @@ -1,403 +0,0 @@ -//===--- Tooling.cpp - Running clang standalone tools ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements functions to run clang tools standalone instead -// of running them as a plugin. -// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/Tooling.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include "clang/Basic/DiagnosticIDs.h" -#include "clang/Driver/Compilation.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/Tool.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "JsonCompileCommandLineDatabase.h" -#include <map> -#include <cstdio> - -namespace clang { -namespace tooling { - -namespace { - -// Checks that the input conforms to the argv[] convention as in -// main(). Namely: -// - it must contain at least a program path, -// - argv[0], ..., and argv[argc - 1] mustn't be NULL, and -// - argv[argc] must be NULL. -void ValidateArgv(int argc, char *argv[]) { - if (argc < 1) { - fprintf(stderr, "ERROR: argc is %d. It must be >= 1.\n", argc); - abort(); - } - - for (int i = 0; i < argc; ++i) { - if (argv[i] == NULL) { - fprintf(stderr, "ERROR: argv[%d] is NULL.\n", i); - abort(); - } - } - - if (argv[argc] != NULL) { - fprintf(stderr, "ERROR: argv[argc] isn't NULL.\n"); - abort(); - } -} - -} // end namespace - -// FIXME: This file contains structural duplication with other parts of the -// code that sets up a compiler to run tools on it, and we should refactor -// it to be based on the same framework. - -static clang::Diagnostic *NewTextDiagnostics() { - llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs( - new clang::DiagnosticIDs()); - clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter( - llvm::errs(), clang::DiagnosticOptions()); - return new clang::Diagnostic(DiagIDs, DiagClient); -} - -// Exists solely for the purpose of lookup of the main executable. -static int StaticSymbol; - -/// \brief Builds a clang driver initialized for running clang tools. -static clang::driver::Driver *NewDriver(clang::Diagnostic *Diagnostics, - const char *BinaryName) { - // This just needs to be some symbol in the binary. - void *const SymbolAddr = &StaticSymbol; - const llvm::sys::Path ExePath = - llvm::sys::Path::GetMainExecutable(BinaryName, SymbolAddr); - - const std::string DefaultOutputName = "a.out"; - clang::driver::Driver *CompilerDriver = new clang::driver::Driver( - ExePath.str(), llvm::sys::getHostTriple(), - DefaultOutputName, false, false, *Diagnostics); - CompilerDriver->setTitle("clang_based_tool"); - return CompilerDriver; -} - -/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs. -/// Returns NULL on error. -static const clang::driver::ArgStringList *GetCC1Arguments( - clang::Diagnostic *Diagnostics, clang::driver::Compilation *Compilation) { - // We expect to get back exactly one Command job, if we didn't something - // failed. Extract that job from the Compilation. - const clang::driver::JobList &Jobs = Compilation->getJobs(); - if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) { - llvm::SmallString<256> error_msg; - llvm::raw_svector_ostream error_stream(error_msg); - Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true); - Diagnostics->Report(clang::diag::err_fe_expected_compiler_job) - << error_stream.str(); - return NULL; - } - - // The one job we find should be to invoke clang again. - const clang::driver::Command *Cmd = - cast<clang::driver::Command>(*Jobs.begin()); - if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { - Diagnostics->Report(clang::diag::err_fe_expected_clang_command); - return NULL; - } - - return &Cmd->getArguments(); -} - -/// \brief Returns a clang build invocation initialized from the CC1 flags. -static clang::CompilerInvocation *NewInvocation( - clang::Diagnostic *Diagnostics, - const clang::driver::ArgStringList &CC1Args) { - clang::CompilerInvocation *Invocation = new clang::CompilerInvocation; - clang::CompilerInvocation::CreateFromArgs( - *Invocation, CC1Args.data(), CC1Args.data() + CC1Args.size(), - *Diagnostics); - Invocation->getFrontendOpts().DisableFree = false; - return Invocation; -} - -/// \brief Runs the specified clang tool action and returns whether it executed -/// successfully. -static bool RunInvocation(const char *BinaryName, - clang::driver::Compilation *Compilation, - clang::CompilerInvocation *Invocation, - const clang::driver::ArgStringList &CC1Args, - clang::FrontendAction *ToolAction) { - llvm::OwningPtr<clang::FrontendAction> ScopedToolAction(ToolAction); - // Show the invocation, with -v. - if (Invocation->getHeaderSearchOpts().Verbose) { - llvm::errs() << "clang Invocation:\n"; - Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true); - llvm::errs() << "\n"; - } - - // Create a compiler instance to handle the actual work. - clang::CompilerInstance Compiler; - Compiler.setInvocation(Invocation); - - // Create the compilers actual diagnostics engine. - Compiler.createDiagnostics(CC1Args.size(), - const_cast<char**>(CC1Args.data())); - if (!Compiler.hasDiagnostics()) - return false; - - // Infer the builtin include path if unspecified. - if (Compiler.getHeaderSearchOpts().UseBuiltinIncludes && - Compiler.getHeaderSearchOpts().ResourceDir.empty()) { - // This just needs to be some symbol in the binary. - void *const SymbolAddr = &StaticSymbol; - Compiler.getHeaderSearchOpts().ResourceDir = - clang::CompilerInvocation::GetResourcesPath(BinaryName, SymbolAddr); - } - - const bool Success = Compiler.ExecuteAction(*ToolAction); - return Success; -} - -/// \brief Converts a string vector representing a Command line into a C -/// string vector representing the Argv (including the trailing NULL). -std::vector<char*> CommandLineToArgv(const std::vector<std::string> *Command) { - std::vector<char*> Result(Command->size() + 1); - for (std::vector<char*>::size_type I = 0; I < Command->size(); ++I) { - Result[I] = const_cast<char*>((*Command)[I].c_str()); - } - Result[Command->size()] = NULL; - return Result; -} - -bool RunToolWithFlags( - clang::FrontendAction *ToolAction, int Args, char *Argv[]) { - ValidateArgv(Args, Argv); - const llvm::OwningPtr<clang::Diagnostic> Diagnostics(NewTextDiagnostics()); - const llvm::OwningPtr<clang::driver::Driver> Driver( - NewDriver(Diagnostics.get(), Argv[0])); - const llvm::OwningPtr<clang::driver::Compilation> Compilation( - Driver->BuildCompilation(llvm::ArrayRef<const char*>(Argv, Args))); - const clang::driver::ArgStringList *const CC1Args = GetCC1Arguments( - Diagnostics.get(), Compilation.get()); - if (CC1Args == NULL) { - return false; - } - llvm::OwningPtr<clang::CompilerInvocation> Invocation( - NewInvocation(Diagnostics.get(), *CC1Args)); - return RunInvocation(Argv[0], Compilation.get(), Invocation.take(), - *CC1Args, ToolAction); -} - -/// \brief Runs 'ToolAction' on the code specified by 'FileContents'. -/// -/// \param FileContents A mapping from file name to source code. For each -/// entry a virtual file mapping will be created when running the tool. -bool RunToolWithFlagsOnCode( - const std::vector<std::string> &CommandLine, - const std::map<std::string, std::string> &FileContents, - clang::FrontendAction *ToolAction) { - const std::vector<char*> Argv = CommandLineToArgv(&CommandLine); - const char *const BinaryName = Argv[0]; - - const llvm::OwningPtr<clang::Diagnostic> Diagnostics(NewTextDiagnostics()); - const llvm::OwningPtr<clang::driver::Driver> Driver( - NewDriver(Diagnostics.get(), BinaryName)); - - // Since the Input is only virtual, don't check whether it exists. - Driver->setCheckInputsExist(false); - - const llvm::OwningPtr<clang::driver::Compilation> Compilation( - Driver->BuildCompilation(llvm::ArrayRef<const char*>(&Argv[0], - Argv.size() - 1))); - const clang::driver::ArgStringList *const CC1Args = GetCC1Arguments( - Diagnostics.get(), Compilation.get()); - if (CC1Args == NULL) { - return false; - } - llvm::OwningPtr<clang::CompilerInvocation> Invocation( - NewInvocation(Diagnostics.get(), *CC1Args)); - - for (std::map<std::string, std::string>::const_iterator - It = FileContents.begin(), End = FileContents.end(); - It != End; ++It) { - // Inject the code as the given file name into the preprocessor options. - const llvm::MemoryBuffer *Input = - llvm::MemoryBuffer::getMemBuffer(It->second.c_str()); - Invocation->getPreprocessorOpts().addRemappedFile(It->first.c_str(), Input); - } - - return RunInvocation(BinaryName, Compilation.get(), - Invocation.take(), *CC1Args, ToolAction); -} - -bool RunSyntaxOnlyToolOnCode( - clang::FrontendAction *ToolAction, llvm::StringRef Code) { - const char *const FileName = "input.cc"; - const char *const CommandLine[] = { - "clang-tool", "-fsyntax-only", FileName - }; - std::map<std::string, std::string> FileContents; - FileContents[FileName] = Code; - return RunToolWithFlagsOnCode( - std::vector<std::string>( - CommandLine, - CommandLine + sizeof(CommandLine)/sizeof(CommandLine[0])), - FileContents, ToolAction); -} - -namespace { - -// A CompileCommandHandler implementation that finds compile commands for a -// specific input file. -// -// FIXME: Implement early exit when JsonCompileCommandLineParser supports it. -class FindHandler : public clang::tooling::CompileCommandHandler { - public: - explicit FindHandler(llvm::StringRef File) - : FileToMatch(File), FoundMatchingCommand(false) {} - - virtual void EndTranslationUnits() { - if (!FoundMatchingCommand && ErrorMessage.empty()) { - ErrorMessage = "ERROR: No matching command found."; - } - } - - virtual void EndTranslationUnit() { - if (File == FileToMatch) { - FoundMatchingCommand = true; - MatchingCommand.Directory = Directory; - MatchingCommand.CommandLine = UnescapeJsonCommandLine(Command); - } - } - - virtual void HandleKeyValue(llvm::StringRef Key, llvm::StringRef Value) { - if (Key == "directory") { Directory = Value; } - else if (Key == "file") { File = Value; } - else if (Key == "command") { Command = Value; } - else { - ErrorMessage = (llvm::Twine("Unknown key: \"") + Key + "\"").str(); - } - } - - const llvm::StringRef FileToMatch; - bool FoundMatchingCommand; - CompileCommand MatchingCommand; - std::string ErrorMessage; - - llvm::StringRef Directory; - llvm::StringRef File; - llvm::StringRef Command; -}; - -} // end namespace - -CompileCommand FindCompileArgsInJsonDatabase( - llvm::StringRef FileName, llvm::StringRef JsonDatabase, - std::string &ErrorMessage) { - FindHandler find_handler(FileName); - JsonCompileCommandLineParser parser(JsonDatabase, &find_handler); - if (!parser.Parse()) { - ErrorMessage = parser.GetErrorMessage(); - return CompileCommand(); - } - return find_handler.MatchingCommand; -} - -/// \brief Returns the absolute path of 'File', by prepending it with -/// 'BaseDirectory' if 'File' is not absolute. Otherwise returns 'File'. -/// If 'File' starts with "./", the returned path will not contain the "./". -/// Otherwise, the returned path will contain the literal path-concatenation of -/// 'BaseDirectory' and 'File'. -/// -/// \param File Either an absolute or relative path. -/// \param BaseDirectory An absolute path. -static std::string GetAbsolutePath( - llvm::StringRef File, llvm::StringRef BaseDirectory) { - assert(llvm::sys::path::is_absolute(BaseDirectory)); - if (llvm::sys::path::is_absolute(File)) { - return File; - } - llvm::StringRef RelativePath(File); - if (RelativePath.startswith("./")) { - RelativePath = RelativePath.substr(strlen("./")); - } - llvm::SmallString<1024> AbsolutePath(BaseDirectory); - llvm::sys::path::append(AbsolutePath, RelativePath); - return AbsolutePath.str(); -} - -FrontendActionFactory::~FrontendActionFactory() {} - -ClangTool::ClangTool(int argc, char **argv) { - if (argc < 3) { - llvm::outs() << "Usage: " << argv[0] << " <cmake-output-dir> " - << "<file1> <file2> ...\n"; - exit(1); - } - llvm::SmallString<1024> JsonDatabasePath(argv[1]); - llvm::sys::path::append(JsonDatabasePath, "compile_commands.json"); - llvm::error_code Result = - llvm::MemoryBuffer::getFile(JsonDatabasePath, JsonDatabase); - if (Result != 0) { - llvm::outs() << "Error while opening JSON database: " << Result.message() - << "\n"; - exit(1); - } - Files = std::vector<std::string>(argv + 2, argv + argc); -} - -int ClangTool::Run(FrontendActionFactory *ActionFactory) { - llvm::StringRef BaseDirectory(::getenv("PWD")); - bool ProcessingFailed = false; - for (unsigned I = 0; I < Files.size(); ++I) { - llvm::SmallString<1024> File(GetAbsolutePath(Files[I], BaseDirectory)); - llvm::outs() << "Processing " << File << ".\n"; - std::string ErrorMessage; - clang::tooling::CompileCommand LookupResult = - clang::tooling::FindCompileArgsInJsonDatabase( - File.str(), JsonDatabase->getBuffer(), ErrorMessage); - if (!LookupResult.CommandLine.empty()) { - if (!LookupResult.Directory.empty()) { - // FIXME: What should happen if CommandLine includes -working-directory - // as well? - LookupResult.CommandLine.push_back( - "-working-directory=" + LookupResult.Directory); - } - if (!clang::tooling::RunToolWithFlags( - ActionFactory->New(), - LookupResult.CommandLine.size(), - &clang::tooling::CommandLineToArgv( - &LookupResult.CommandLine)[0])) { - llvm::outs() << "Error while processing " << File << ".\n"; - ProcessingFailed = true; - } - } else { - // FIXME: There are two use cases here: doing a fuzzy - // "find . -name '*.cc' |xargs tool" match, where as a user I don't care - // about the .cc files that were not found, and the use case where I - // specify all files I want to run over explicitly, where this should - // be an error. We'll want to add an option for this. - llvm::outs() << "Skipping " << File << ". Command line not found.\n"; - } - } - return ProcessingFailed ? 1 : 0; -} - -} // end namespace tooling -} // end namespace clang - diff --git a/test/Tooling/remove-cstr-calls.cpp b/test/Tooling/remove-cstr-calls.cpp deleted file mode 100644 index 701683b285..0000000000 --- a/test/Tooling/remove-cstr-calls.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: rm -rf %t -// RUN: mkdir %t -// RUN: echo '[{"directory":".","command":"clang++ '$(llvm-config --cppflags all)' -c %s","file":"%s"}]' > %t/compile_commands.json -// RUN: remove-cstr-calls %t %s | FileCheck %s -// XFAIL: * - -#include <string> - -namespace llvm { struct StringRef { StringRef(const char *p); }; } - -void f1(const std::string &s) { - f1(s.c_str()); // CHECK:remove-cstr-calls.cpp:11:6:11:14:s -} -void f2(const llvm::StringRef r) { - std::string s; - f2(s.c_str()); // CHECK:remove-cstr-calls.cpp:15:6:15:14:s -} -void f3(const llvm::StringRef &r) { - std::string s; - f3(s.c_str()); // CHECK:remove-cstr-calls.cpp:19:6:19:14:s -} diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 1fc11ab66e..cb44dc59dc 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -59,18 +59,3 @@ add_clang_unittest(Frontend Frontend/FrontendActionTest.cpp USED_LIBS gtest gtest_main clangFrontend ) - -add_clang_unittest(Tooling - Tooling/ToolingTest.cpp - USED_LIBS gtest gtest_main clangTooling - ) - -add_clang_unittest(JsonCompileCommandLineDatabase - Tooling/JsonCompileCommandLineDatabaseTest.cpp - USED_LIBS gtest gtest_main clangTooling - ) - -add_clang_unittest(ASTMatchersTest - Tooling/ASTMatchersTest.cpp - USED_LIBS gtest gtest_main clangTooling - ) diff --git a/unittests/Tooling/ASTMatchersTest.cpp b/unittests/Tooling/ASTMatchersTest.cpp deleted file mode 100644 index 933e59c9f7..0000000000 --- a/unittests/Tooling/ASTMatchersTest.cpp +++ /dev/null @@ -1,1604 +0,0 @@ -//===- unittest/Tooling/ASTMatchersTest.cpp - AST matcher unit tests ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/ASTMatchers.h" -#include "gtest/gtest.h" - -namespace clang { -namespace tooling { - -using match::AnyOf; -using match::AllOf; -using match::ArgumentCountIs; -using match::BinaryOperator; -using match::BoolLiteral; -using match::StringLiteral; -using match::IntegerLiteral; -using match::CharacterLiteral; -using match::Call; -using match::Callee; -using match::Class; -using match::CompoundStatement; -using match::ConstructorCall; -using match::DeclarationMatcher; -using match::DefaultArgument; -using match::ConditionalOperator; -using match::DeclarationReference; -using match::Expression; -using match::Equals; -using match::For; -using match::Has; -using match::HasAnyArgument; -using match::HasAnyParameter; -using match::HasAnySubstatement; -using match::HasArgument; -using match::HasBody; -using match::HasCondition; -using match::HasDeclaration; -using match::HasDescendant; -using match::HasEitherOperand; -using match::HasFalseExpression; -using match::HasInitializer; -using match::HasLHS; -using match::HasName; -using match::HasUnaryOperand; -using match::HasOperatorName; -using match::HasOverloadedOperatorName; -using match::HasParameter; -using match::HasRHS; -using match::HasTrueExpression; -using match::HasType; -using match::Id; -using match::If; -using match::IsArrow; -using match::IsDefinition; -using match::IsDerivedFrom; -using match::MemberExpression; -using match::Method; -using match::Not; -using match::OfClass; -using match::On; -using match::OverloadedOperatorCall; -using match::PointsTo; -using match::References; -using match::StatementCountIs; -using match::StatementMatcher; -using match::ThisPointerType; -using match::To; -using match::TypeMatcher; -using match::UnaryOperator; -using match::Variable; - -class BoundNodesCallback { - public: - virtual ~BoundNodesCallback() {} - virtual bool Run(const BoundNodes *BoundNodes) = 0; -}; - -// If 'FindResultVerifier' is not NULL, sets *Verified to the result of -// running 'FindResultVerifier' with the bound nodes as argument. -// If 'FindResultVerifier' is NULL, sets *Verified to true when Run is called. -class VerifyMatch : public MatchFinder::MatchCallback { - public: - VerifyMatch(BoundNodesCallback *FindResultVerifier, bool *Verified) - : Verified(Verified), FindResultReviewer(FindResultVerifier) {} - - virtual void Run(const MatchFinder::MatchResult &Result) { - if (FindResultReviewer != NULL) { - *Verified = FindResultReviewer->Run(&Result.Nodes); - } else { - *Verified = true; - } - } - - private: - bool *const Verified; - BoundNodesCallback *const FindResultReviewer; -}; - -template <typename T> -testing::AssertionResult MatchesConditionally( - const std::string &Code, const T &AMatcher, bool ExpectMatch) { - bool Found = false; - MatchFinder Finder; - Finder.AddMatcher(AMatcher, new VerifyMatch(NULL, &Found)); - if (!Finder.FindAll(Code)) { - return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; - } - if (!Found && ExpectMatch) { - return testing::AssertionFailure() - << "Could not find match in \"" << Code << "\""; - } else if (Found && !ExpectMatch) { - return testing::AssertionFailure() - << "Found unexpected match in \"" << Code << "\""; - } - return testing::AssertionSuccess(); -} - -template <typename T> -testing::AssertionResult Matches(const std::string &Code, const T &AMatcher) { - return MatchesConditionally(Code, AMatcher, true); -} - -template <typename T> -testing::AssertionResult NotMatches( - const std::string &Code, const T &AMatcher) { - return MatchesConditionally(Code, AMatcher, false); -} - -template <typename T> -testing::AssertionResult MatchAndVerifyResultConditionally( - const std::string &Code, const T &AMatcher, - BoundNodesCallback *FindResultVerifier, bool ExpectResult) { - llvm::OwningPtr<BoundNodesCallback> ScopedVerifier(FindResultVerifier); - bool VerifiedResult = false; - MatchFinder Finder; - Finder.AddMatcher( - AMatcher, new VerifyMatch(FindResultVerifier, &VerifiedResult)); - if (!Finder.FindAll(Code)) { - return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; - } - if (!VerifiedResult && ExpectResult) { - return testing::AssertionFailure() - << "Could not verify result in \"" << Code << "\""; - } else if (VerifiedResult && !ExpectResult) { - return testing::AssertionFailure() - << "Verified unexpected result in \"" << Code << "\""; - } - return testing::AssertionSuccess(); -} - -// FIXME: Find better names for these functions (or document what they -// do more precisely). -template <typename T> -testing::AssertionResult MatchAndVerifyResultTrue( - const std::string &Code, const T &AMatcher, - BoundNodesCallback *FindResultVerifier) { - return MatchAndVerifyResultConditionally( - Code, AMatcher, FindResultVerifier, true); -} - -template <typename T> -testing::AssertionResult MatchAndVerifyResultFalse( - const std::string &Code, const T &AMatcher, - BoundNodesCallback *FindResultVerifier) { - return MatchAndVerifyResultConditionally( - Code, AMatcher, FindResultVerifier, false); -} - -TEST(HasNameDeathTest, DiesOnEmptyName) { - ASSERT_DEBUG_DEATH({ - DeclarationMatcher HasEmptyName = Class(HasName("")); - EXPECT_TRUE(NotMatches("class X {};", HasEmptyName)); - }, ""); -} - -TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) { - ASSERT_DEBUG_DEATH({ - DeclarationMatcher IsDerivedFromEmpty = Class(IsDerivedFrom("")); - EXPECT_TRUE(NotMatches("class X {};", IsDerivedFromEmpty)); - }, ""); -} - -TEST(DeclarationMatcher, MatchClass) { - DeclarationMatcher ClassMatcher(Class()); - // Even for an empty string there are classes in the AST. - EXPECT_TRUE(Matches("", ClassMatcher)); - - DeclarationMatcher ClassX = Class(Class(HasName("X"))); - EXPECT_TRUE(Matches("class X;", ClassX)); - EXPECT_TRUE(Matches("class X {};", ClassX)); - EXPECT_TRUE(Matches("template<class T> class X {};", ClassX)); - EXPECT_TRUE(NotMatches("", ClassX)); -} - -TEST(DeclarationMatcher, ClassIsDerived) { - DeclarationMatcher IsDerivedFromX = Class(IsDerivedFrom("X")); - - EXPECT_TRUE(Matches("class X {}; class Y : public X {};", IsDerivedFromX)); - EXPECT_TRUE(Matches("class X {}; class Y : public X {};", IsDerivedFromX)); - EXPECT_TRUE(Matches("class X {};", IsDerivedFromX)); - EXPECT_TRUE(Matches("class X;", IsDerivedFromX)); - EXPECT_TRUE(NotMatches("class Y;", IsDerivedFromX)); - EXPECT_TRUE(NotMatches("", IsDerivedFromX)); - - DeclarationMatcher ZIsDerivedFromX = - Class(HasName("Z"), IsDerivedFrom("X")); - EXPECT_TRUE( - Matches("class X {}; class Y : public X {}; class Z : public Y {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class X {};" - "template<class T> class Y : public X {};" - "class Z : public Y<int> {};", ZIsDerivedFromX)); - EXPECT_TRUE(Matches("class X {}; template<class T> class Z : public X {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class T> class X {}; " - "template<class T> class Z : public X<T> {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class T, class U=T> class X {}; " - "template<class T> class Z : public X<T> {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template<class X> class A { class Z : public X {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class X> class A { public: class Z : public X {}; }; " - "class X{}; void y() { A<X>::Z z; }", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template <class T> class X {}; " - "template<class Y> class A { class Z : public X<Y> {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template<template<class T> class X> class A { " - " class Z : public X<int> {}; };", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<template<class T> class X> class A { " - " public: class Z : public X<int> {}; }; " - "template<class T> class X {}; void y() { A<X>::Z z; }", - ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template<class X> class A { class Z : public X::D {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class X> class A { public: " - " class Z : public X::D {}; }; " - "class Y { public: class X {}; typedef X D; }; " - "void y() { A<Y>::Z z; }", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class X {}; typedef X Y; class Z : public Y {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class T> class Y { typedef typename T::U X; " - " class Z : public X {}; };", ZIsDerivedFromX)); - EXPECT_TRUE(Matches("class X {}; class Z : public ::X {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template<class T> class X {}; " - "template<class T> class A { class Z : public X<T>::D {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class T> class X { public: typedef X<T> D; }; " - "template<class T> class A { public: " - " class Z : public X<T>::D {}; }; void y() { A<int>::Z z; }", - ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template<class X> class A { class Z : public X::D::E {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class X {}; typedef X V; typedef V W; class Z : public W {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class X {}; class Y : public X {}; " - "typedef Y V; typedef V W; class Z : public W {};", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("template<class T, class U> class X {}; " - "template<class T> class A { class Z : public X<T, int> {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template<class X> class D { typedef X A; typedef A B; " - " typedef B C; class Z : public C {}; };", - ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class X {}; typedef X A; typedef A B; " - "class Z : public B {};", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class X {}; typedef X A; typedef A B; typedef B C; " - "class Z : public C {};", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class U {}; typedef U X; typedef X V; " - "class Z : public V {};", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class Base {}; typedef Base X; " - "class Z : public Base {};", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class Base {}; typedef Base Base2; typedef Base2 X; " - "class Z : public Base {};", ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("class Base {}; class Base2 {}; typedef Base2 X; " - "class Z : public Base {};", ZIsDerivedFromX)); - EXPECT_TRUE( - Matches("class A {}; typedef A X; typedef A Y; " - "class Z : public Y {};", ZIsDerivedFromX)); - EXPECT_TRUE( - NotMatches("template <typename T> class Z;" - "template <> class Z<void> {};" - "template <typename T> class Z : public Z<void> {};", - IsDerivedFromX)); - EXPECT_TRUE( - Matches("template <typename T> class X;" - "template <> class X<void> {};" - "template <typename T> class X : public X<void> {};", - IsDerivedFromX)); - EXPECT_TRUE(Matches( - "class X {};" - "template <typename T> class Z;" - "template <> class Z<void> {};" - "template <typename T> class Z : public Z<void>, public X {};", - ZIsDerivedFromX)); - - // FIXME: Once we have better matchers for template type matching, - // get rid of the Variable(...) matching and match the right template - // declarations directly. - const char *RecursiveTemplateOneParameter = - "class Base1 {}; class Base2 {};" - "template <typename T> class Z;" - "template <> class Z<void> : public Base1 {};" - "template <> class Z<int> : public Base2 {};" - "template <> class Z<float> : public Z<void> {};" - "template <> class Z<double> : public Z<int> {};" - "template <typename T> class Z : public Z<float>, public Z<double> {};" - "void f() { Z<float> z_float; Z<double> z_double; Z<char> z_char; }"; - EXPECT_TRUE(Matches( - RecursiveTemplateOneParameter, - Variable(HasName("z_float"), - HasInitializer(HasType(Class(IsDerivedFrom("Base1"))))))); - EXPECT_TRUE(NotMatches( - RecursiveTemplateOneParameter, - Variable( - HasName("z_float"), - HasInitializer(HasType(Class(IsDerivedFrom("Base2"))))))); - EXPECT_TRUE(Matches( - RecursiveTemplateOneParameter, - Variable( - HasName("z_char"), - HasInitializer(HasType(Class(IsDerivedFrom("Base1"), - IsDerivedFrom("Base2"))))))); - - const char *RecursiveTemplateTwoParameters = - "class Base1 {}; class Base2 {};" - "template <typename T1, typename T2> class Z;" - "template <typename T> class Z<void, T> : public Base1 {};" - "template <typename T> class Z<int, T> : public Base2 {};" - "template <typename T> class Z<float, T> : public Z<void, T> {};" - "template <typename T> class Z<double, T> : public Z<int, T> {};" - "template <typename T1, typename T2> class Z : " - " public Z<float, T2>, public Z<double, T2> {};" - "void f() { Z<float, void> z_float; Z<double, void> z_double; " - " Z<char, void> z_char; }"; - EXPECT_TRUE(Matches( - RecursiveTemplateTwoParameters, - Variable( - HasName("z_float"), - HasInitializer(HasType(Class(IsDerivedFrom("Base1"))))))); - EXPECT_TRUE(NotMatches( - RecursiveTemplateTwoParameters, - Variable( - HasName("z_float"), - HasInitializer(HasType(Class(IsDerivedFrom("Base2"))))))); - EXPECT_TRUE(Matches( - RecursiveTemplateTwoParameters, - Variable( - HasName("z_char"), - HasInitializer(HasType(Class(IsDerivedFrom("Base1"), - IsDerivedFrom("Base2"))))))); -} - -TEST(DeclarationMatcher, MatchAnyOf) { - DeclarationMatcher YOrZDerivedFromX = - Class(AnyOf(HasName("Y"), AllOf(IsDerivedFrom("X"), HasName("Z")))); - - EXPECT_TRUE( - Matches("class X {}; class Z : public X {};", YOrZDerivedFromX)); - EXPECT_TRUE(Matches("class Y {};", YOrZDerivedFromX)); - EXPECT_TRUE( - NotMatches("class X {}; class W : public X {};", YOrZDerivedFromX)); - EXPECT_TRUE(NotMatches("class Z {};", YOrZDerivedFromX)); - - DeclarationMatcher XOrYOrZOrU = - Class(AnyOf(HasName("X"), HasName("Y"), HasName("Z"), HasName("U"))); - - EXPECT_TRUE(Matches("class X {};", XOrYOrZOrU)); - EXPECT_TRUE(Matches("class Y {};", XOrYOrZOrU)); - EXPECT_TRUE(Matches("class Z {};", XOrYOrZOrU)); - EXPECT_TRUE(Matches("class U {};", XOrYOrZOrU)); - EXPECT_TRUE(NotMatches("class A {};", XOrYOrZOrU)); -} - -TEST(DeclarationMatcher, MatchHas) { - DeclarationMatcher HasClassX = Class(Has(Class(HasName("X")))); - - EXPECT_TRUE(Matches("class Y { class X {}; };", HasClassX)); - EXPECT_TRUE(Matches("class X {};", HasClassX)); - - DeclarationMatcher YHasClassX = - Class(HasName("Y"), Has(Class(HasName("X")))); - EXPECT_TRUE(Matches("class Y { class X {}; };", YHasClassX)); - EXPECT_TRUE(NotMatches("class X {};", YHasClassX)); - EXPECT_TRUE( - NotMatches("class Y { class Z { class X {}; }; };", YHasClassX)); -} - -TEST(DeclarationMatcher, MatchHasRecursiveAllOf) { - DeclarationMatcher Recursive = - Class( - Has(Class( - Has(Class( - HasName("X"))), - Has(Class( - HasName("Y"))), - HasName("Z"))), - Has(Class( - Has(Class( - HasName("A"))), - Has(Class( - HasName("B"))), - HasName("C"))), - HasName("F")); - - EXPECT_TRUE(Matches( - "class F {" - " class Z {" - " class X {};" - " class Y {};" - " };" - " class C {" - " class A {};" - " class B {};" - " };" - "};", Recursive)); - - EXPECT_TRUE(Matches( - "class F {" - " class Z {" - " class A {};" - " class X {};" - " class Y {};" - " };" - " class C {" - " class X {};" - " class A {};" - " class B {};" - " };" - "};", Recursive)); - - EXPECT_TRUE(Matches( - "class O1 {" - " class O2 {" - " class F {" - " class Z {" - " class A {};" - " class X {};" - " class Y {};" - " };" - " class C {" - " class X {};" - " class A {};" - " class B {};" - " };" - " };" - " };" - "};", Recursive)); -} - -TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) { - DeclarationMatcher Recursive = - Class( - AnyOf( - Has(Class( - AnyOf( - Has(Class( - HasName("X"))), - Has(Class( - HasName("Y"))), - HasName("Z")))), - Has(Class( - AnyOf( - HasName("C"), - Has(Class( - HasName("A"))), - Has(Class( - HasName("B")))))), - HasName("F"))); - - EXPECT_TRUE(Matches("class F {};", Recursive)); - EXPECT_TRUE(Matches("class Z {};", Recursive)); - EXPECT_TRUE(Matches("class C {};", Recursive)); - EXPECT_TRUE(Matches("class M { class N { class X {}; }; };", Recursive)); - EXPECT_TRUE(Matches("class M { class N { class B {}; }; };", Recursive)); - EXPECT_TRUE( - Matches("class O1 { class O2 {" - " class M { class N { class B {}; }; }; " - "}; };", Recursive)); -} - -TEST(DeclarationMatcher, MatchNot) { - DeclarationMatcher NotClassX = - Class( - IsDerivedFrom("Y"), - Not(HasName("Y")), - Not(HasName("X"))); - EXPECT_TRUE(NotMatches("", NotClassX)); - EXPECT_TRUE(NotMatches("class Y {};", NotClassX)); - EXPECT_TRUE(Matches("class Y {}; class Z : public Y {};", NotClassX)); - EXPECT_TRUE(NotMatches("class Y {}; class X : public Y {};", NotClassX)); - EXPECT_TRUE( - NotMatches("class Y {}; class Z {}; class X : public Y {};", - NotClassX)); - - DeclarationMatcher ClassXHasNotClassY = - Class( - HasName("X"), - Has(Class(HasName("Z"))), - Not( - Has(Class(HasName("Y"))))); - EXPECT_TRUE(Matches("class X { class Z {}; };", ClassXHasNotClassY)); - EXPECT_TRUE(NotMatches("class X { class Y {}; class Z {}; };", - ClassXHasNotClassY)); -} - -TEST(DeclarationMatcher, HasDescendant) { - DeclarationMatcher ZDescendantClassX = - Class( - HasDescendant(Class(HasName("X"))), - HasName("Z")); - EXPECT_TRUE(Matches("class Z { class X {}; };", ZDescendantClassX)); - EXPECT_TRUE( - Matches("class Z { class Y { class X {}; }; };", ZDescendantClassX)); - EXPECT_TRUE( - Matches("class Z { class A { class Y { class X {}; }; }; };", - ZDescendantClassX)); - EXPECT_TRUE( - Matches("class Z { class A { class B { class Y { class X {}; }; }; }; };", - ZDescendantClassX)); - EXPECT_TRUE(NotMatches("class Z {};", ZDescendantClassX)); - - DeclarationMatcher ZDescendantClassXHasClassY = - Class( - HasDescendant(Class(Has(Class(HasName("Y"))), - HasName("X"))), - HasName("Z")); - EXPECT_TRUE(Matches("class Z { class X { class Y {}; }; };", - ZDescendantClassXHasClassY)); - EXPECT_TRUE( - Matches("class Z { class A { class B { class X { class Y {}; }; }; }; };", - ZDescendantClassXHasClassY)); - EXPECT_TRUE(NotMatches( - "class Z {" - " class A {" - " class B {" - " class X {" - " class C {" - " class Y {};" - " };" - " };" - " }; " - " };" - "};", ZDescendantClassXHasClassY)); - - DeclarationMatcher ZDescendantClassXDescendantClassY = - Class( - HasDescendant(Class(HasDescendant(Class(HasName("Y"))), - HasName("X"))), - HasName("Z")); - EXPECT_TRUE( - Matches("class Z { class A { class X { class B { class Y {}; }; }; }; };", - ZDescendantClassXDescendantClassY)); - EXPECT_TRUE(Matches( - "class Z {" - " class A {" - " class X {" - " class B {" - " class Y {};" - " };" - " class Y {};" - " };" - " };" - "};", ZDescendantClassXDescendantClassY)); -} - -TEST(StatementMatcher, Has) { - StatementMatcher HasVariableI = - Expression( - HasType(PointsTo(Class(HasName("X")))), - Has(DeclarationReference(To(Variable(HasName("i")))))); - - EXPECT_TRUE(Matches( - "class X; X *x(int); void c() { int i; x(i); }", HasVariableI)); - EXPECT_TRUE(NotMatches( - "class X; X *x(int); void c() { int i; x(42); }", HasVariableI)); -} - -TEST(StatementMatcher, HasDescendant) { - StatementMatcher HasDescendantVariableI = - Expression( - HasType(PointsTo(Class(HasName("X")))), - HasDescendant(DeclarationReference(To(Variable(HasName("i")))))); - - EXPECT_TRUE(Matches( - "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }", - HasDescendantVariableI)); - EXPECT_TRUE(NotMatches( - "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }", - HasDescendantVariableI)); -} - -TEST(TypeMatcher, MatchesClassType) { - TypeMatcher TypeA = HasDeclaration(Class(HasName("A"))); - - EXPECT_TRUE(Matches("class A { public: A *a; };", TypeA)); - EXPECT_TRUE(NotMatches("class A {};", TypeA)); - - TypeMatcher TypeDerivedFromA = HasDeclaration(Class(IsDerivedFrom("A"))); - - EXPECT_TRUE(Matches("class A {}; class B : public A { public: B *b; };", - TypeDerivedFromA)); - EXPECT_TRUE(NotMatches("class A {};", TypeA)); - - TypeMatcher TypeAHasClassB = HasDeclaration( - Class(HasName("A"), Has(Class(HasName("B"))))); - - EXPECT_TRUE( - Matches("class A { public: A *a; class B {}; };", TypeAHasClassB)); -} - -// Returns whether 'bound_nodes' contain a Decl for bound to 'id', which -// can be dynamically casted to T. -template <typename T> -class VerifyIdIsBoundToDecl : public BoundNodesCallback { - public: - explicit VerifyIdIsBoundToDecl(const std::string &Id) : Id(Id) {} - virtual bool Run(const BoundNodes *Nodes) { - const T *Node = Nodes->GetDeclAs<T>(Id); - return Node != NULL; - } - - private: - const std::string Id; -}; -template <typename T> -class VerifyIdIsBoundToStmt : public BoundNodesCallback { - public: - explicit VerifyIdIsBoundToStmt(const std::string &Id) : Id(Id) {} - virtual bool Run(const BoundNodes *Nodes) { - const T *Node = Nodes->GetStmtAs<T>(Id); - return Node != NULL; - } - private: - const std::string Id; -}; - -TEST(Matcher, BindMatchedNodes) { - DeclarationMatcher ClassX = Has(Id("x", Class(HasName("X")))); - - EXPECT_TRUE(MatchAndVerifyResultTrue("class X {};", - ClassX, new VerifyIdIsBoundToDecl<clang::CXXRecordDecl>("x"))); - - EXPECT_TRUE(MatchAndVerifyResultFalse("class X {};", - ClassX, new VerifyIdIsBoundToDecl<clang::CXXRecordDecl>("other-id"))); - - TypeMatcher TypeAHasClassB = HasDeclaration( - Class(HasName("A"), Has(Id("b", Class(HasName("B")))))); - - EXPECT_TRUE(MatchAndVerifyResultTrue("class A { public: A *a; class B {}; };", - TypeAHasClassB, - new VerifyIdIsBoundToDecl<clang::Decl>("b"))); - - StatementMatcher MethodX = Id("x", Call(Callee(Method(HasName("x"))))); - - EXPECT_TRUE(MatchAndVerifyResultTrue("class A { void x() { x(); } };", - MethodX, - new VerifyIdIsBoundToStmt<clang::CXXMemberCallExpr>("x"))); -} - -TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) { - TypeMatcher ClassX = HasDeclaration(Class(HasName("X"))); - EXPECT_TRUE( - Matches("class X {}; void y(X &x) { x; }", Expression(HasType(ClassX)))); - EXPECT_TRUE( - NotMatches("class X {}; void y(X *x) { x; }", - Expression(HasType(ClassX)))); - EXPECT_TRUE( - Matches("class X {}; void y(X *x) { x; }", - Expression(HasType(PointsTo(ClassX))))); -} - -TEST(HasType, TakesQualTypeMatcherAndMatchesValueDecl) { - TypeMatcher ClassX = HasDeclaration(Class(HasName("X"))); - EXPECT_TRUE( - Matches("class X {}; void y() { X x; }", Variable(HasType(ClassX)))); - EXPECT_TRUE( - NotMatches("class X {}; void y() { X *x; }", Variable(HasType(ClassX)))); - EXPECT_TRUE( - Matches("class X {}; void y() { X *x; }", - Variable(HasType(PointsTo(ClassX))))); -} - -TEST(HasType, TakesDeclMatcherAndMatchesExpr) { - DeclarationMatcher ClassX = Class(HasName("X")); - EXPECT_TRUE( - Matches("class X {}; void y(X &x) { x; }", Expression(HasType(ClassX)))); - EXPECT_TRUE( - NotMatches("class X {}; void y(X *x) { x; }", - Expression(HasType(ClassX)))); -} - -TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) { - DeclarationMatcher ClassX = Class(HasName("X")); - EXPECT_TRUE( - Matches("class X {}; void y() { X x; }", Variable(HasType(ClassX)))); - EXPECT_TRUE( - NotMatches("class X {}; void y() { X *x; }", Variable(HasType(ClassX)))); -} - -TEST(Matcher, Call) { - // FIXME: Do we want to overload Call() to directly take - // Matcher<clang::Decl>, too? - StatementMatcher MethodX = Call(HasDeclaration(Method(HasName("x")))); - - EXPECT_TRUE(Matches("class Y { void x() { x(); } };", MethodX)); - EXPECT_TRUE(NotMatches("class Y { void x() {} };", MethodX)); - - StatementMatcher MethodOnY = Call(On(HasType(Class(HasName("Y"))))); - - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z() { Y y; y.x(); }", - MethodOnY)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }", - MethodOnY)); - EXPECT_TRUE( - NotMatches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }", - MethodOnY)); - EXPECT_TRUE( - NotMatches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }", - MethodOnY)); - EXPECT_TRUE( - NotMatches("class Y { public: void x(); }; void z() { Y *y; y->x(); }", - MethodOnY)); - - StatementMatcher MethodOnYPointer = - Call(On(HasType(PointsTo(Class(HasName("Y")))))); - - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }", - MethodOnYPointer)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }", - MethodOnYPointer)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }", - MethodOnYPointer)); - EXPECT_TRUE( - NotMatches("class Y { public: void x(); }; void z() { Y y; y.x(); }", - MethodOnYPointer)); - EXPECT_TRUE( - NotMatches("class Y { public: void x(); }; void z(Y &y) { y.x(); }", - MethodOnYPointer)); -} - -TEST(Matcher, OverloadedOperatorCall) { - StatementMatcher OpCall = OverloadedOperatorCall(); - // Unary operator - EXPECT_TRUE(Matches("class Y { }; " - "bool operator!(Y x) { return false; }; " - "Y y; bool c = !y;", OpCall)); - // No match -- special operators like "new", "delete" - // FIXME: operator new takes size_t, for which we need stddef.h, for which - // we need to figure out include paths in the test. - // EXPECT_TRUE(NotMatches("#include <stddef.h>\n" - // "class Y { }; " - // "void *operator new(size_t size) { return 0; } " - // "Y *y = new Y;", OpCall)); - EXPECT_TRUE(NotMatches("class Y { }; " - "void operator delete(void *p) { } " - "void a() {Y *y = new Y; delete y;}", OpCall)); - // Binary operator - EXPECT_TRUE(Matches("class Y { }; " - "bool operator&&(Y x, Y y) { return true; }; " - "Y a; Y b; bool c = a && b;", - OpCall)); - // No match -- normal operator, not an overloaded one. - EXPECT_TRUE(NotMatches("bool x = true, y = true; bool t = x && y;", OpCall)); - EXPECT_TRUE(NotMatches("int t = 5 << 2;", OpCall)); -} - -TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) { - StatementMatcher OpCallAndAnd = - OverloadedOperatorCall(HasOverloadedOperatorName("&&")); - EXPECT_TRUE(Matches("class Y { }; " - "bool operator&&(Y x, Y y) { return true; }; " - "Y a; Y b; bool c = a && b;", OpCallAndAnd)); - StatementMatcher OpCallLessLess = - OverloadedOperatorCall(HasOverloadedOperatorName("<<")); - EXPECT_TRUE(NotMatches("class Y { }; " - "bool operator&&(Y x, Y y) { return true; }; " - "Y a; Y b; bool c = a && b;", - OpCallLessLess)); -} - -TEST(Matcher, ThisPointerType) { - StatementMatcher MethodOnY = Call(ThisPointerType(Class(HasName("Y")))); - - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z() { Y y; y.x(); }", - MethodOnY)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }", - MethodOnY)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }", - MethodOnY)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }", - MethodOnY)); - EXPECT_TRUE( - Matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }", - MethodOnY)); - - EXPECT_TRUE(Matches( - "class Y {" - " public: virtual void x();" - "};" - "class X : public Y {" - " public: virtual void x();" - "};" - "void z() { X *x; x->Y::x(); }", MethodOnY)); -} - -TEST(Matcher, VariableUsage) { - StatementMatcher Reference = - DeclarationReference(To( - Variable(HasInitializer( - Call(ThisPointerType(Class(HasName("Y")))))))); - - EXPECT_TRUE(Matches( - "class Y {" - " public:" - " bool x() const;" - "};" - "void z(const Y &y) {" - " bool b = y.x();" - " if (b) {}" - "}", Reference)); - - EXPECT_TRUE(NotMatches( - "class Y {" - " public:" - " bool x() const;" - "};" - "void z(const Y &y) {" - " bool b = y.x();" - "}", Reference)); -} - -TEST(Matcher, CalledVariable) { - StatementMatcher CallOnVariableY = Expression( - Call(On(DeclarationReference(To(Variable(HasName("y"))))))); - - EXPECT_TRUE(Matches( - "class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY)); - EXPECT_TRUE(Matches( - "class Y { public: void x() const { Y y; y.x(); } };", CallOnVariableY)); - EXPECT_TRUE(Matches( - "class Y { public: void x(); };" - "class X : public Y { void z() { X y; y.x(); } };", CallOnVariableY)); - EXPECT_TRUE(Matches( - "class Y { public: void x(); };" - "class X : public Y { void z() { X *y; y->x(); } };", CallOnVariableY)); - EXPECT_TRUE(NotMatches( - "class Y { public: void x(); };" - "class X : public Y { void z() { unsigned long y; ((X*)y)->x(); } };", - CallOnVariableY)); -} - -TEST(MemberExpression, DoesNotMatchClasses) { - EXPECT_TRUE(NotMatches("class Y { void x() {} };", MemberExpression())); -} - -TEST(MemberExpression, MatchesMemberFunctionCall) { - EXPECT_TRUE(Matches("class Y { void x() { x(); } };", MemberExpression())); -} - -TEST(MemberExpression, MatchesVariable) { - EXPECT_TRUE( - Matches("class Y { void x() { this->y; } int y; };", MemberExpression())); - EXPECT_TRUE( - Matches("class Y { void x() { y; } int y; };", MemberExpression())); - EXPECT_TRUE( - Matches("class Y { void x() { Y y; y.y; } int y; };", - MemberExpression())); -} - -TEST(MemberExpression, MatchesStaticVariable) { - EXPECT_TRUE(Matches("class Y { void x() { this->y; } static int y; };", - MemberExpression())); - EXPECT_TRUE(NotMatches("class Y { void x() { y; } static int y; };", - MemberExpression())); - EXPECT_TRUE(NotMatches("class Y { void x() { Y::y; } static int y; };", - MemberExpression())); -} - -TEST(IsArrow, MatchesMemberVariablesViaArrow) { - EXPECT_TRUE(Matches("class Y { void x() { this->y; } int y; };", - MemberExpression(IsArrow()))); - EXPECT_TRUE(Matches("class Y { void x() { y; } int y; };", - MemberExpression(IsArrow()))); - EXPECT_TRUE(NotMatches("class Y { void x() { (*this).y; } int y; };", - MemberExpression(IsArrow()))); -} - -TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) { - EXPECT_TRUE(Matches("class Y { void x() { this->y; } static int y; };", - MemberExpression(IsArrow()))); - EXPECT_TRUE(NotMatches("class Y { void x() { y; } static int y; };", - MemberExpression(IsArrow()))); - EXPECT_TRUE(NotMatches("class Y { void x() { (*this).y; } static int y; };", - MemberExpression(IsArrow()))); -} - -TEST(IsArrow, MatchesMemberCallsViaArrow) { - EXPECT_TRUE(Matches("class Y { void x() { this->x(); } };", - MemberExpression(IsArrow()))); - EXPECT_TRUE(Matches("class Y { void x() { x(); } };", - MemberExpression(IsArrow()))); - EXPECT_TRUE(NotMatches("class Y { void x() { Y y; y.x(); } };", - MemberExpression(IsArrow()))); -} - -TEST(Callee, MatchesDeclarations) { - StatementMatcher CallMethodX = Call(Callee(Method(HasName("x")))); - - EXPECT_TRUE(Matches("class Y { void x() { x(); } };", CallMethodX)); - EXPECT_TRUE(NotMatches("class Y { void x() {} };", CallMethodX)); -} - -TEST(Callee, MatchesMemberExpressions) { - EXPECT_TRUE(Matches("class Y { void x() { this->x(); } };", - Call(Callee(MemberExpression())))); - EXPECT_TRUE( - NotMatches("class Y { void x() { this->x(); } };", Call(Callee(Call())))); -} - -TEST(Matcher, Argument) { - StatementMatcher CallArgumentY = Expression(Call( - HasArgument(0, DeclarationReference(To(Variable(HasName("y"))))))); - - EXPECT_TRUE(Matches("void x(int) { int y; x(y); }", CallArgumentY)); - EXPECT_TRUE( - Matches("class X { void x(int) { int y; x(y); } };", CallArgumentY)); - EXPECT_TRUE(NotMatches("void x(int) { int z; x(z); }", CallArgumentY)); - - StatementMatcher WrongIndex = Expression(Call( - HasArgument(42, DeclarationReference(To(Variable(HasName("y"))))))); - EXPECT_TRUE(NotMatches("void x(int) { int y; x(y); }", WrongIndex)); -} - -TEST(Matcher, AnyArgument) { - StatementMatcher CallArgumentY = Expression(Call( - HasAnyArgument(DeclarationReference(To(Variable(HasName("y"))))))); - EXPECT_TRUE(Matches("void x(int, int) { int y; x(1, y); }", CallArgumentY)); - EXPECT_TRUE(Matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY)); - EXPECT_TRUE(NotMatches("void x(int, int) { x(1, 2); }", CallArgumentY)); -} - -TEST(Matcher, ArgumentCount) { - StatementMatcher Call1Arg = Expression(Call(ArgumentCountIs(1))); - - EXPECT_TRUE(Matches("void x(int) { x(0); }", Call1Arg)); - EXPECT_TRUE(Matches("class X { void x(int) { x(0); } };", Call1Arg)); - EXPECT_TRUE(NotMatches("void x(int, int) { x(0, 0); }", Call1Arg)); -} - -TEST(Matcher, References) { - DeclarationMatcher ReferenceClassX = Variable( - HasType(References(Class(HasName("X"))))); - EXPECT_TRUE(Matches("class X {}; void y(X y) { X &x = y; }", ReferenceClassX)); - EXPECT_TRUE( - Matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX)); - EXPECT_TRUE( - NotMatches("class X {}; void y(X y) { X x = y; }", ReferenceClassX)); - EXPECT_TRUE( - NotMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX)); -} - -TEST(HasParameter, CallsInnerMatcher) { - EXPECT_TRUE(Matches("class X { void x(int) {} };", - Method(HasParameter(0, Variable())))); - EXPECT_TRUE(NotMatches("class X { void x(int) {} };", - Method(HasParameter(0, HasName("x"))))); -} - -TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) { - EXPECT_TRUE(NotMatches("class X { void x(int) {} };", - Method(HasParameter(42, Variable())))); -} - -TEST(HasType, MatchesParameterVariableTypesStrictly) { - EXPECT_TRUE(Matches("class X { void x(X x) {} };", - Method(HasParameter(0, HasType(Class(HasName("X"))))))); - EXPECT_TRUE(NotMatches("class X { void x(const X &x) {} };", - Method(HasParameter(0, HasType(Class(HasName("X"))))))); - EXPECT_TRUE(Matches("class X { void x(const X *x) {} };", - Method(HasParameter(0, HasType(PointsTo(Class(HasName("X")))))))); - EXPECT_TRUE(Matches("class X { void x(const X &x) {} };", - Method(HasParameter(0, HasType(References(Class(HasName("X")))))))); -} - -TEST(HasAnyParameter, MatchesIndependentlyOfPosition) { - EXPECT_TRUE(Matches("class Y {}; class X { void x(X x, Y y) {} };", - Method(HasAnyParameter(HasType(Class(HasName("X"))))))); - EXPECT_TRUE(Matches("class Y {}; class X { void x(Y y, X x) {} };", - Method(HasAnyParameter(HasType(Class(HasName("X"))))))); -} - -TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) { - EXPECT_TRUE(NotMatches("class Y {}; class X { void x(int) {} };", - Method(HasAnyParameter(HasType(Class(HasName("X"))))))); -} - -TEST(HasAnyParameter, DoesNotMatchThisPointer) { - EXPECT_TRUE(NotMatches("class Y {}; class X { void x() {} };", - Method(HasAnyParameter(HasType(PointsTo(Class(HasName("X")))))))); -} - -TEST(HasName, MatchesParameterVariableDeclartions) { - EXPECT_TRUE(Matches("class Y {}; class X { void x(int x) {} };", - Method(HasAnyParameter(HasName("x"))))); - EXPECT_TRUE(NotMatches("class Y {}; class X { void x(int) {} };", - Method(HasAnyParameter(HasName("x"))))); -} - -TEST(Matcher, ConstructorCall) { - StatementMatcher Constructor = Expression(ConstructorCall()); - - EXPECT_TRUE( - Matches("class X { public: X(); }; void x() { X x; }", Constructor)); - EXPECT_TRUE( - Matches("class X { public: X(); }; void x() { X x = X(); }", - Constructor)); - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { X x = 0; }", - Constructor)); - EXPECT_TRUE(Matches("class X {}; void x(int) { X x; }", Constructor)); -} - -TEST(Matcher, ConstructorArgument) { - StatementMatcher Constructor = Expression(ConstructorCall( - HasArgument(0, DeclarationReference(To(Variable(HasName("y"))))))); - - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { int y; X x(y); }", - Constructor)); - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { int y; X x = X(y); }", - Constructor)); - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { int y; X x = y; }", - Constructor)); - EXPECT_TRUE( - NotMatches("class X { public: X(int); }; void x() { int z; X x(z); }", - Constructor)); - - StatementMatcher WrongIndex = Expression(ConstructorCall( - HasArgument(42, DeclarationReference(To(Variable(HasName("y"))))))); - EXPECT_TRUE( - NotMatches("class X { public: X(int); }; void x() { int y; X x(y); }", - WrongIndex)); -} - -TEST(Matcher, ConstructorArgumentCount) { - StatementMatcher Constructor1Arg = - Expression(ConstructorCall(ArgumentCountIs(1))); - - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { X x(0); }", - Constructor1Arg)); - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { X x = X(0); }", - Constructor1Arg)); - EXPECT_TRUE( - Matches("class X { public: X(int); }; void x() { X x = 0; }", - Constructor1Arg)); - EXPECT_TRUE( - NotMatches("class X { public: X(int, int); }; void x() { X x(0, 0); }", - Constructor1Arg)); -} - -TEST(Matcher, DefaultArgument) { - StatementMatcher Arg = DefaultArgument(); - - EXPECT_TRUE(Matches("void x(int, int = 0) { int y; x(y); }", Arg)); - EXPECT_TRUE( - Matches("class X { void x(int, int = 0) { int y; x(y); } };", Arg)); - EXPECT_TRUE(NotMatches("void x(int, int = 0) { int y; x(y, 0); }", Arg)); -} - -TEST(Matcher, StringLiterals) { - StatementMatcher Literal = Expression(StringLiteral()); - EXPECT_TRUE(Matches("const char *s = \"string\";", Literal)); - // wide string - EXPECT_TRUE(Matches("const wchar_t *s = L\"string\";", Literal)); - // with escaped characters - EXPECT_TRUE(Matches("const char *s = \"\x05five\";", Literal)); - // no matching -- though the data type is the same, there is no string literal - EXPECT_TRUE(NotMatches("const char s[1] = {'a'};", Literal)); -} - -TEST(Matcher, CharacterLiterals) { - StatementMatcher CharLiteral = Expression(CharacterLiteral()); - EXPECT_TRUE(Matches("const char c = 'c';", CharLiteral)); - // wide character - EXPECT_TRUE(Matches("const char c = L'c';", CharLiteral)); - // wide character, Hex encoded, NOT MATCHED! - EXPECT_TRUE(NotMatches("const wchar_t c = 0x2126;", CharLiteral)); - EXPECT_TRUE(NotMatches("const char c = 0x1;", CharLiteral)); -} - -TEST(Matcher, IntegerLiterals) { - StatementMatcher HasIntLiteral = Expression(IntegerLiteral()); - EXPECT_TRUE(Matches("int i = 10;", HasIntLiteral)); - EXPECT_TRUE(Matches("int i = 0x1AB;", HasIntLiteral)); - EXPECT_TRUE(Matches("int i = 10L;", HasIntLiteral)); - EXPECT_TRUE(Matches("int i = 10U;", HasIntLiteral)); - - // Non-matching cases (character literals, float and double) - EXPECT_TRUE(NotMatches("int i = L'a';", - HasIntLiteral)); // this is actually a character - // literal cast to int - EXPECT_TRUE(NotMatches("int i = 'a';", HasIntLiteral)); - EXPECT_TRUE(NotMatches("int i = 1e10;", HasIntLiteral)); - EXPECT_TRUE(NotMatches("int i = 10.0;", HasIntLiteral)); -} - -TEST(Matcher, Conditions) { - StatementMatcher Condition = If(HasCondition(BoolLiteral(Equals(true)))); - - EXPECT_TRUE(Matches("void x() { if (true) {} }", Condition)); - EXPECT_TRUE(NotMatches("void x() { if (false) {} }", Condition)); - EXPECT_TRUE(NotMatches("void x() { bool a = true; if (a) {} }", Condition)); - EXPECT_TRUE(NotMatches("void x() { if (true || false) {} }", Condition)); - EXPECT_TRUE(NotMatches("void x() { if (1) {} }", Condition)); -} - -TEST(MatchBinaryOperator, HasOperatorName) { - StatementMatcher OperatorOr = BinaryOperator(HasOperatorName("||")); - - EXPECT_TRUE(Matches("void x() { true || false; }", OperatorOr)); - EXPECT_TRUE(NotMatches("void x() { true && false; }", OperatorOr)); -} - -TEST(MatchBinaryOperator, HasLHSAndHasRHS) { - StatementMatcher OperatorTrueFalse = - BinaryOperator(HasLHS(BoolLiteral(Equals(true))), - HasRHS(BoolLiteral(Equals(false)))); - - EXPECT_TRUE(Matches("void x() { true || false; }", OperatorTrueFalse)); - EXPECT_TRUE(Matches("void x() { true && false; }", OperatorTrueFalse)); - EXPECT_TRUE(NotMatches("void x() { false || true; }", OperatorTrueFalse)); -} - -TEST(MatchBinaryOperator, HasEitherOperand) { - StatementMatcher HasOperand = - BinaryOperator(HasEitherOperand(BoolLiteral(Equals(false)))); - - EXPECT_TRUE(Matches("void x() { true || false; }", HasOperand)); - EXPECT_TRUE(Matches("void x() { false && true; }", HasOperand)); - EXPECT_TRUE(NotMatches("void x() { true || true; }", HasOperand)); -} - -TEST(Matcher, BinaryOperatorTypes) { - // Integration test that verifies the AST provides all binary operators in - // a way we expect. - // FIXME: Operator ',' - EXPECT_TRUE( - Matches("void x() { 3, 4; }", BinaryOperator(HasOperatorName(",")))); - EXPECT_TRUE( - Matches("bool b; bool c = (b = true);", - BinaryOperator(HasOperatorName("=")))); - EXPECT_TRUE( - Matches("bool b = 1 != 2;", BinaryOperator(HasOperatorName("!=")))); - EXPECT_TRUE( - Matches("bool b = 1 == 2;", BinaryOperator(HasOperatorName("==")))); - EXPECT_TRUE(Matches("bool b = 1 < 2;", BinaryOperator(HasOperatorName("<")))); - EXPECT_TRUE( - Matches("bool b = 1 <= 2;", BinaryOperator(HasOperatorName("<=")))); - EXPECT_TRUE( - Matches("int i = 1 << 2;", BinaryOperator(HasOperatorName("<<")))); - EXPECT_TRUE( - Matches("int i = 1; int j = (i <<= 2);", - BinaryOperator(HasOperatorName("<<=")))); - EXPECT_TRUE(Matches("bool b = 1 > 2;", BinaryOperator(HasOperatorName(">")))); - EXPECT_TRUE( - Matches("bool b = 1 >= 2;", BinaryOperator(HasOperatorName(">=")))); - EXPECT_TRUE( - Matches("int i = 1 >> 2;", BinaryOperator(HasOperatorName(">>")))); - EXPECT_TRUE( - Matches("int i = 1; int j = (i >>= 2);", - BinaryOperator(HasOperatorName(">>=")))); - EXPECT_TRUE( - Matches("int i = 42 ^ 23;", BinaryOperator(HasOperatorName("^")))); - EXPECT_TRUE( - Matches("int i = 42; int j = (i ^= 42);", - BinaryOperator(HasOperatorName("^=")))); - EXPECT_TRUE( - Matches("int i = 42 % 23;", BinaryOperator(HasOperatorName("%")))); - EXPECT_TRUE( - Matches("int i = 42; int j = (i %= 42);", - BinaryOperator(HasOperatorName("%=")))); - EXPECT_TRUE( - Matches("bool b = 42 &23;", BinaryOperator(HasOperatorName("&")))); - EXPECT_TRUE( - Matches("bool b = true && false;", - BinaryOperator(HasOperatorName("&&")))); - EXPECT_TRUE( - Matches("bool b = true; bool c = (b &= false);", - BinaryOperator(HasOperatorName("&=")))); - EXPECT_TRUE( - Matches("bool b = 42 | 23;", BinaryOperator(HasOperatorName("|")))); - EXPECT_TRUE( - Matches("bool b = true || false;", - BinaryOperator(HasOperatorName("||")))); - EXPECT_TRUE( - Matches("bool b = true; bool c = (b |= false);", - BinaryOperator(HasOperatorName("|=")))); - EXPECT_TRUE( - Matches("int i = 42 *23;", BinaryOperator(HasOperatorName("*")))); - EXPECT_TRUE( - Matches("int i = 42; int j = (i *= 23);", - BinaryOperator(HasOperatorName("*=")))); - EXPECT_TRUE( - Matches("int i = 42 / 23;", BinaryOperator(HasOperatorName("/")))); - EXPECT_TRUE( - Matches("int i = 42; int j = (i /= 23);", - BinaryOperator(HasOperatorName("/=")))); - EXPECT_TRUE( - Matches("int i = 42 + 23;", BinaryOperator(HasOperatorName("+")))); - EXPECT_TRUE( - Matches("int i = 42; int j = (i += 23);", - BinaryOperator(HasOperatorName("+=")))); - EXPECT_TRUE( - Matches("int i = 42 - 23;", BinaryOperator(HasOperatorName("-")))); - EXPECT_TRUE( - Matches("int i = 42; int j = (i -= 23);", - BinaryOperator(HasOperatorName("-=")))); - EXPECT_TRUE( - Matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };", - BinaryOperator(HasOperatorName("->*")))); - EXPECT_TRUE( - Matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };", - BinaryOperator(HasOperatorName(".*")))); - - // Member expressions as operators are not supported in matches. - EXPECT_TRUE( - NotMatches("struct A { void x(A *a) { a->x(this); } };", - BinaryOperator(HasOperatorName("->")))); - - // Initializer assignments are not represented as operator equals. - EXPECT_TRUE( - NotMatches("bool b = true;", BinaryOperator(HasOperatorName("=")))); - - // Array indexing is not represented as operator. - EXPECT_TRUE(NotMatches("int a[42]; void x() { a[23]; }", UnaryOperator())); - - // Overloaded operators do not match at all. - EXPECT_TRUE(NotMatches( - "struct A { bool operator&&(const A &a) const { return false; } };" - "void x() { A a, b; a && b; }", - BinaryOperator())); -} - -TEST(MatchUnaryOperator, HasOperatorName) { - StatementMatcher OperatorNot = UnaryOperator(HasOperatorName("!")); - - EXPECT_TRUE(Matches("void x() { !true; } ", OperatorNot)); - EXPECT_TRUE(NotMatches("void x() { true; } ", OperatorNot)); -} - -TEST(MatchUnaryOperator, HasUnaryOperand) { - StatementMatcher OperatorOnFalse = - UnaryOperator(HasUnaryOperand(BoolLiteral(Equals(false)))); - - EXPECT_TRUE(Matches("void x() { !false; }", OperatorOnFalse)); - EXPECT_TRUE(NotMatches("void x() { !true; }", OperatorOnFalse)); -} - -TEST(Matcher, UnaryOperatorTypes) { - // Integration test that verifies the AST provides all unary operators in - // a way we expect. - EXPECT_TRUE(Matches("bool b = !true;", UnaryOperator(HasOperatorName("!")))); - EXPECT_TRUE( - Matches("bool b; bool *p = &b;", UnaryOperator(HasOperatorName("&")))); - EXPECT_TRUE(Matches("int i = ~ 1;", UnaryOperator(HasOperatorName("~")))); - EXPECT_TRUE( - Matches("bool *p; bool b = *p;", UnaryOperator(HasOperatorName("*")))); - EXPECT_TRUE( - Matches("int i; int j = +i;", UnaryOperator(HasOperatorName("+")))); - EXPECT_TRUE( - Matches("int i; int j = -i;", UnaryOperator(HasOperatorName("-")))); - EXPECT_TRUE( - Matches("int i; int j = ++i;", UnaryOperator(HasOperatorName("++")))); - EXPECT_TRUE( - Matches("int i; int j = i++;", UnaryOperator(HasOperatorName("++")))); - EXPECT_TRUE( - Matches("int i; int j = --i;", UnaryOperator(HasOperatorName("--")))); - EXPECT_TRUE( - Matches("int i; int j = i--;", UnaryOperator(HasOperatorName("--")))); - - // We don't match conversion operators. - EXPECT_TRUE(NotMatches("int i; double d = (double)i;", UnaryOperator())); - - // Function calls are not represented as operator. - EXPECT_TRUE(NotMatches("void f(); void x() { f(); }", UnaryOperator())); - - // Overloaded operators do not match at all. - // FIXME: We probably want to add that. - EXPECT_TRUE(NotMatches( - "struct A { bool operator!() const { return false; } };" - "void x() { A a; !a; }", UnaryOperator(HasOperatorName("!")))); -} - -TEST(Matcher, ConditionalOperator) { - StatementMatcher Conditional = ConditionalOperator( - HasCondition(BoolLiteral(Equals(true))), - HasTrueExpression(BoolLiteral(Equals(false)))); - - EXPECT_TRUE(Matches("void x() { true ? false : true; }", Conditional)); - EXPECT_TRUE(NotMatches("void x() { false ? false : true; }", Conditional)); - EXPECT_TRUE(NotMatches("void x() { true ? true : false; }", Conditional)); - - StatementMatcher ConditionalFalse = ConditionalOperator( - HasFalseExpression(BoolLiteral(Equals(false)))); - - EXPECT_TRUE(Matches("void x() { true ? true : false; }", ConditionalFalse)); - EXPECT_TRUE( - NotMatches("void x() { true ? false : true; }", ConditionalFalse)); -} - -TEST(Matcher, HasNameSupportsNamespaces) { - EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }", - Class(HasName("a::b::C")))); - EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }", - Class(HasName("::a::b::C")))); - EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }", - Class(HasName("b::C")))); - EXPECT_TRUE(Matches("namespace a { namespace b { class C; } }", - Class(HasName("C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("c::b::C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("a::c::C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("a::b::A")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("::C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("::b::C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("z::a::b::C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class C; } }", - Class(HasName("a+b::C")))); - EXPECT_TRUE(NotMatches("namespace a { namespace b { class AC; } }", - Class(HasName("C")))); -} - -TEST(Matcher, HasNameSupportsOuterClasses) { - EXPECT_TRUE( - Matches("class A { class B { class C; }; };", Class(HasName("A::B::C")))); - EXPECT_TRUE( - Matches("class A { class B { class C; }; };", - Class(HasName("::A::B::C")))); - EXPECT_TRUE( - Matches("class A { class B { class C; }; };", Class(HasName("B::C")))); - EXPECT_TRUE( - Matches("class A { class B { class C; }; };", Class(HasName("C")))); - EXPECT_TRUE( - NotMatches("class A { class B { class C; }; };", - Class(HasName("c::B::C")))); - EXPECT_TRUE( - NotMatches("class A { class B { class C; }; };", - Class(HasName("A::c::C")))); - EXPECT_TRUE( - NotMatches("class A { class B { class C; }; };", - Class(HasName("A::B::A")))); - EXPECT_TRUE( - NotMatches("class A { class B { class C; }; };", Class(HasName("::C")))); - EXPECT_TRUE( - NotMatches("class A { class B { class C; }; };", - Class(HasName("::B::C")))); - EXPECT_TRUE(NotMatches("class A { class B { class C; }; };", - Class(HasName("z::A::B::C")))); - EXPECT_TRUE( - NotMatches("class A { class B { class C; }; };", - Class(HasName("A+B::C")))); -} - -TEST(Matcher, IsDefinition) { - DeclarationMatcher DefinitionOfClassA = - Class(HasName("A"), IsDefinition()); - EXPECT_TRUE(Matches("class A {};", DefinitionOfClassA)); - EXPECT_TRUE(NotMatches("class A;", DefinitionOfClassA)); - - DeclarationMatcher DefinitionOfVariableA = - Variable(HasName("a"), IsDefinition()); - EXPECT_TRUE(Matches("int a;", DefinitionOfVariableA)); - EXPECT_TRUE(NotMatches("extern int a;", DefinitionOfVariableA)); - - DeclarationMatcher DefinitionOfMethodA = - Method(HasName("a"), IsDefinition()); - EXPECT_TRUE(Matches("class A { void a() {} };", DefinitionOfMethodA)); - EXPECT_TRUE(NotMatches("class A { void a(); };", DefinitionOfMethodA)); -} - -TEST(Matcher, OfClass) { - StatementMatcher Constructor = ConstructorCall(HasDeclaration(Method( - OfClass(HasName("X"))))); - - EXPECT_TRUE( - Matches("class X { public: X(); }; void x(int) { X x; }", Constructor)); - EXPECT_TRUE( - Matches("class X { public: X(); }; void x(int) { X x = X(); }", - Constructor)); - EXPECT_TRUE( - NotMatches("class Y { public: Y(); }; void x(int) { Y y; }", - Constructor)); -} - -TEST(Matcher, VisitsTemplateInstantiations) { - EXPECT_TRUE(Matches( - "class A { public: void x(); };" - "template <typename T> class B { public: void y() { T t; t.x(); } };" - "void f() { B<A> b; b.y(); }", Call(Callee(Method(HasName("x")))))); - - EXPECT_TRUE(Matches( - "class A { public: void x(); };" - "class C {" - " public:" - " template <typename T> class B { public: void y() { T t; t.x(); } };" - "};" - "void f() {" - " C::B<A> b; b.y();" - "}", Class(HasName("C"), - HasDescendant(Call(Callee(Method(HasName("x")))))))); -} - -// For testing AST_MATCHER_P(). -AST_MATCHER_P(clang::Decl, Just, Matcher<clang::Decl>, AMatcher) { - // Make sure all special variables are used: node, match_finder, - // bound_nodes_builder, and the parameter named 'AMatcher'. - return AMatcher.Matches(Node, Finder, Builder); -} - -TEST(AstMatcherPMacro, Works) { - DeclarationMatcher HasClassB = Just(Has(Id("b", Class(HasName("B"))))); - - EXPECT_TRUE(MatchAndVerifyResultTrue("class A { class B {}; };", - HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b"))); - - EXPECT_TRUE(MatchAndVerifyResultFalse("class A { class B {}; };", - HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("a"))); - - EXPECT_TRUE(MatchAndVerifyResultFalse("class A { class C {}; };", - HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b"))); -} - -AST_POLYMORPHIC_MATCHER_P( - PolymorphicHas, Matcher<clang::Decl>, AMatcher) { - COMPILE_ASSERT((llvm::is_same<NodeType, clang::Decl>::value) || - (llvm::is_same<NodeType, clang::Stmt>::value), - assert_node_type_is_accessible); - TypedBaseMatcher<clang::Decl> ChildMatcher(AMatcher); - return Finder->MatchesChildOf( - Node, ChildMatcher, Builder, - ASTMatchFinder::kIgnoreImplicitCastsAndParentheses); -} - -TEST(AstPolymorphicMatcherPMacro, Works) { - DeclarationMatcher HasClassB = PolymorphicHas(Id("b", Class(HasName("B")))); - - EXPECT_TRUE(MatchAndVerifyResultTrue("class A { class B {}; };", - HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b"))); - - EXPECT_TRUE(MatchAndVerifyResultFalse("class A { class B {}; };", - HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("a"))); - - EXPECT_TRUE(MatchAndVerifyResultFalse("class A { class C {}; };", - HasClassB, new VerifyIdIsBoundToDecl<clang::Decl>("b"))); - - StatementMatcher StatementHasClassB = - PolymorphicHas(Class(HasName("B"))); - - EXPECT_TRUE(Matches("void x() { class B {}; }", StatementHasClassB)); -} - -TEST(For, FindsForLoops) { - EXPECT_TRUE(Matches("void f() { for(;;); }", For())); - EXPECT_TRUE(Matches("void f() { if(true) for(;;); }", For())); -} - -TEST(For, ReportsNoFalsePositives) { - EXPECT_TRUE(NotMatches("void f() { ; }", For())); - EXPECT_TRUE(NotMatches("void f() { if(true); }", For())); -} - -TEST(CompoundStatement, HandlesSimpleCases) { - EXPECT_TRUE(NotMatches("void f();", CompoundStatement())); - EXPECT_TRUE(Matches("void f() {}", CompoundStatement())); - EXPECT_TRUE(Matches("void f() {{}}", CompoundStatement())); -} - -TEST(CompoundStatement, DoesNotMatchEmptyStruct) { - // It's not a compound statement just because there's "{}" in the source - // text. This is an AST search, not grep. - EXPECT_TRUE(NotMatches("namespace n { struct S {}; }", - CompoundStatement())); - EXPECT_TRUE(Matches("namespace n { struct S { void f() {{}} }; }", - CompoundStatement())); -} - -TEST(HasBody, FindsBodyOfForLoop) { - StatementMatcher HasCompoundStatementBody = - For(HasBody(CompoundStatement())); - EXPECT_TRUE(Matches("void f() { for(;;) {} }", - HasCompoundStatementBody)); - EXPECT_TRUE(NotMatches("void f() { for(;;); }", - HasCompoundStatementBody)); -} - -TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) { - // The simplest case: every compound statement is in a function - // definition, and the function body itself must be a compound - // statement. - EXPECT_TRUE(Matches("void f() { for (;;); }", - CompoundStatement(HasAnySubstatement(For())))); -} - -TEST(HasAnySubstatement, IsNotRecursive) { - // It's really "has any immediate substatement". - EXPECT_TRUE(NotMatches("void f() { if (true) for (;;); }", - CompoundStatement(HasAnySubstatement(For())))); -} - -TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) { - EXPECT_TRUE(Matches("void f() { if (true) { for (;;); } }", - CompoundStatement(HasAnySubstatement(For())))); -} - -TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) { - EXPECT_TRUE(Matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }", - CompoundStatement(HasAnySubstatement(For())))); -} - -TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) { - EXPECT_TRUE(Matches("void f() { }", - CompoundStatement(StatementCountIs(0)))); - EXPECT_TRUE(NotMatches("void f() {}", - CompoundStatement(StatementCountIs(1)))); -} - -TEST(StatementCountIs, AppearsToMatchOnlyOneCount) { - EXPECT_TRUE(Matches("void f() { 1; }", - CompoundStatement(StatementCountIs(1)))); - EXPECT_TRUE(NotMatches("void f() { 1; }", - CompoundStatement(StatementCountIs(0)))); - EXPECT_TRUE(NotMatches("void f() { 1; }", - CompoundStatement(StatementCountIs(2)))); -} - -TEST(StatementCountIs, WorksWithMultipleStatements) { - EXPECT_TRUE(Matches("void f() { 1; 2; 3; }", - CompoundStatement(StatementCountIs(3)))); -} - -TEST(StatementCountIs, WorksWithNestedCompoundStatements) { - EXPECT_TRUE(Matches("void f() { { 1; } { 1; 2; 3; 4; } }", - CompoundStatement(StatementCountIs(1)))); - EXPECT_TRUE(Matches("void f() { { 1; } { 1; 2; 3; 4; } }", - CompoundStatement(StatementCountIs(2)))); - EXPECT_TRUE(NotMatches("void f() { { 1; } { 1; 2; 3; 4; } }", - CompoundStatement(StatementCountIs(3)))); - EXPECT_TRUE(Matches("void f() { { 1; } { 1; 2; 3; 4; } }", - CompoundStatement(StatementCountIs(4)))); -} - -} // end namespace tooling -} // end namespace clang diff --git a/unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp b/unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp deleted file mode 100644 index 2a911d1063..0000000000 --- a/unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//===- unittest/Tooling/JsonCompileCommandLineDatabaseTest ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "../../lib/Tooling/JsonCompileCommandLineDatabase.h" -#include "gtest/gtest.h" - -namespace clang { -namespace tooling { - -TEST(UnescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) { - std::vector<std::string> Result = UnescapeJsonCommandLine(""); - EXPECT_TRUE(Result.empty()); -} - -TEST(UnescapeJsonCommandLine, SplitsOnSpaces) { - std::vector<std::string> Result = UnescapeJsonCommandLine("a b c"); - ASSERT_EQ(3ul, Result.size()); - EXPECT_EQ("a", Result[0]); - EXPECT_EQ("b", Result[1]); - EXPECT_EQ("c", Result[2]); -} - -TEST(UnescapeJsonCommandLine, MungesMultipleSpaces) { - std::vector<std::string> Result = UnescapeJsonCommandLine(" a b "); - ASSERT_EQ(2ul, Result.size()); - EXPECT_EQ("a", Result[0]); - EXPECT_EQ("b", Result[1]); -} - -TEST(UnescapeJsonCommandLine, UnescapesBackslashCharacters) { - std::vector<std::string> Backslash = UnescapeJsonCommandLine("a\\\\\\\\"); - ASSERT_EQ(1ul, Backslash.size()); - EXPECT_EQ("a\\", Backslash[0]); - std::vector<std::string> Quote = UnescapeJsonCommandLine("a\\\\\\\""); - ASSERT_EQ(1ul, Quote.size()); - EXPECT_EQ("a\"", Quote[0]); -} - -TEST(UnescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) { - std::vector<std::string> Result = UnescapeJsonCommandLine("\\\" a b \\\""); - ASSERT_EQ(1ul, Result.size()); - EXPECT_EQ(" a b ", Result[0]); -} - -TEST(UnescapeJsonCommandLine, AllowsMultipleQuotedArguments) { - std::vector<std::string> Result = UnescapeJsonCommandLine( - " \\\" a \\\" \\\" b \\\" "); - ASSERT_EQ(2ul, Result.size()); - EXPECT_EQ(" a ", Result[0]); - EXPECT_EQ(" b ", Result[1]); -} - -TEST(UnescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) { - std::vector<std::string> Result = UnescapeJsonCommandLine( - "\\\"\\\"\\\"\\\""); - ASSERT_EQ(1ul, Result.size()); - EXPECT_TRUE(Result[0].empty()) << Result[0]; -} - -TEST(UnescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) { - std::vector<std::string> Result = UnescapeJsonCommandLine( - "\\\"\\\\\\\"\\\""); - ASSERT_EQ(1ul, Result.size()); - EXPECT_EQ("\"", Result[0]); -} - -TEST(UnescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) { - std::vector<std::string> Result = UnescapeJsonCommandLine( - " \\\\\\\" \\\"a \\\\\\\" b \\\" \\\"and\\\\\\\\c\\\" \\\\\\\""); - ASSERT_EQ(4ul, Result.size()); - EXPECT_EQ("\"", Result[0]); - EXPECT_EQ("a \" b ", Result[1]); - EXPECT_EQ("and\\c", Result[2]); - EXPECT_EQ("\"", Result[3]); -} - -TEST(UnescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) { - std::vector<std::string> QuotedNoSpaces = UnescapeJsonCommandLine( - "\\\"a\\\"\\\"b\\\""); - ASSERT_EQ(1ul, QuotedNoSpaces.size()); - EXPECT_EQ("ab", QuotedNoSpaces[0]); - - std::vector<std::string> MixedNoSpaces = UnescapeJsonCommandLine( - "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\""); - ASSERT_EQ(1ul, MixedNoSpaces.size()); - EXPECT_EQ("abcdefg", MixedNoSpaces[0]); -} - -TEST(UnescapeJsonCommandLine, ParsesQuotedStringWithoutClosingQuote) { - std::vector<std::string> Unclosed = UnescapeJsonCommandLine("\"abc"); - ASSERT_EQ(1ul, Unclosed.size()); - EXPECT_EQ("abc", Unclosed[0]); - - std::vector<std::string> EndsInBackslash = UnescapeJsonCommandLine("\"a\\"); - ASSERT_EQ(1ul, EndsInBackslash.size()); - EXPECT_EQ("a", EndsInBackslash[0]); - - std::vector<std::string> Empty = UnescapeJsonCommandLine("\""); - ASSERT_EQ(1ul, Empty.size()); - EXPECT_EQ("", Empty[0]); -} - -TEST(JsonCompileCommandLineParser, FailsOnEmptyString) { - JsonCompileCommandLineParser Parser("", NULL); - EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, DoesNotReadAfterInput) { - JsonCompileCommandLineParser Parser(llvm::StringRef(NULL, 0), NULL); - EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesEmptyArray) { - JsonCompileCommandLineParser Parser("[]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsIfNotClosingArray) { - JsonCompileCommandLineParser JustOpening("[", NULL); - EXPECT_FALSE(JustOpening.Parse()) << JustOpening.GetErrorMessage(); - JsonCompileCommandLineParser WithSpaces(" [ ", NULL); - EXPECT_FALSE(WithSpaces.Parse()) << WithSpaces.GetErrorMessage(); - JsonCompileCommandLineParser WithGarbage(" [x", NULL); - EXPECT_FALSE(WithGarbage.Parse()) << WithGarbage.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesEmptyArrayWithWhitespace) { - JsonCompileCommandLineParser Spaces(" [ ] ", NULL); - EXPECT_TRUE(Spaces.Parse()) << Spaces.GetErrorMessage(); - JsonCompileCommandLineParser AllWhites("\t\r\n[\t\n \t\r ]\t\r \n\n", NULL); - EXPECT_TRUE(AllWhites.Parse()) << AllWhites.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsIfNotStartingArray) { - JsonCompileCommandLineParser ObjectStart("{", NULL); - EXPECT_FALSE(ObjectStart.Parse()) << ObjectStart.GetErrorMessage(); - // We don't implement a full JSON parser, and thus parse only a subset - // of valid JSON. - JsonCompileCommandLineParser Object("{}", NULL); - EXPECT_FALSE(Object.Parse()) << Object.GetErrorMessage(); - JsonCompileCommandLineParser Character("x", NULL); - EXPECT_FALSE(Character.Parse()) << Character.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesEmptyObject) { - JsonCompileCommandLineParser Parser("[{}]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesObject) { - JsonCompileCommandLineParser Parser("[{\"a\":\"/b\"}]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesMultipleKeyValuePairsInObject) { - JsonCompileCommandLineParser Parser( - "[{\"a\":\"/b\",\"c\":\"d\",\"e\":\"f\"}]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsIfNotClosingObject) { - JsonCompileCommandLineParser MissingCloseOnEmpty("[{]", NULL); - EXPECT_FALSE(MissingCloseOnEmpty.Parse()) - << MissingCloseOnEmpty.GetErrorMessage(); - JsonCompileCommandLineParser MissingCloseAfterPair("[{\"a\":\"b\"]", NULL); - EXPECT_FALSE(MissingCloseAfterPair.Parse()) - << MissingCloseAfterPair.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsIfMissingColon) { - JsonCompileCommandLineParser StringString("[{\"a\"\"/b\"}]", NULL); - EXPECT_FALSE(StringString.Parse()) << StringString.GetErrorMessage(); - JsonCompileCommandLineParser StringSpaceString("[{\"a\" \"b\"}]", NULL); - EXPECT_FALSE(StringSpaceString.Parse()) - << StringSpaceString.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsOnMissingQuote) { - JsonCompileCommandLineParser OpenQuote("[{a\":\"b\"}]", NULL); - EXPECT_FALSE(OpenQuote.Parse()) << OpenQuote.GetErrorMessage(); - JsonCompileCommandLineParser CloseQuote("[{\"a\":\"b}]", NULL); - EXPECT_FALSE(CloseQuote.Parse()) << CloseQuote.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesEscapedQuotes) { - JsonCompileCommandLineParser Parser( - "[{\"a\":\"\\\"b\\\" \\\" \\\"\"}]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesEmptyString) { - JsonCompileCommandLineParser Parser("[{\"a\":\"\"}]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsOnMissingString) { - JsonCompileCommandLineParser MissingValue("[{\"a\":}]", NULL); - EXPECT_FALSE(MissingValue.Parse()) << MissingValue.GetErrorMessage(); - JsonCompileCommandLineParser MissingKey("[{:\"b\"}]", NULL); - EXPECT_FALSE(MissingKey.Parse()) << MissingKey.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesMultipleObjects) { - JsonCompileCommandLineParser Parser( - "[" - " { \"a\" : \"b\" }," - " { \"a\" : \"b\" }," - " { \"a\" : \"b\" }" - "]", NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsOnMissingComma) { - JsonCompileCommandLineParser Parser( - "[" - " { \"a\" : \"b\" }" - " { \"a\" : \"b\" }" - "]", NULL); - EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, FailsOnSuperfluousComma) { - JsonCompileCommandLineParser Parser( - "[ { \"a\" : \"b\" }, ]", NULL); - EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -TEST(JsonCompileCommandLineParser, ParsesSpacesInBetweenTokens) { - JsonCompileCommandLineParser Parser( - " \t \n\n \r [ \t \n\n \r" - " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :" - " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r,\t \n\n \r" - " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :" - " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r]\t \n\n \r", - NULL); - EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage(); -} - -} // end namespace tooling -} // end namespace clang diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp deleted file mode 100644 index 6e5bc6b613..0000000000 --- a/unittests/Tooling/ToolingTest.cpp +++ /dev/null @@ -1,175 +0,0 @@ -//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Twine.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Tooling/Tooling.h" -#include "gtest/gtest.h" - -namespace clang { -namespace tooling { - -namespace { -/// Takes an ast consumer and returns it from CreateASTConsumer. This only -/// works with single translation unit compilations. -class TestAction : public clang::ASTFrontendAction { - public: - /// Takes ownership of TestConsumer. - explicit TestAction(clang::ASTConsumer *TestConsumer) - : TestConsumer(TestConsumer) {} - - protected: - virtual clang::ASTConsumer* CreateASTConsumer( - clang::CompilerInstance& compiler, llvm::StringRef dummy) { - /// TestConsumer will be deleted by the framework calling us. - return TestConsumer; - } - - private: - clang::ASTConsumer * const TestConsumer; -}; - -class FindTopLevelDeclConsumer : public clang::ASTConsumer { - public: - explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl) - : FoundTopLevelDecl(FoundTopLevelDecl) {} - virtual void HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) { - *FoundTopLevelDecl = true; - } - private: - bool * const FoundTopLevelDecl; -}; -} // end namespace - -TEST(RunSyntaxOnlyToolOnCode, FindsTopLevelDeclOnEmptyCode) { - bool FoundTopLevelDecl = false; - EXPECT_TRUE(RunSyntaxOnlyToolOnCode( - new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), "")); - EXPECT_TRUE(FoundTopLevelDecl); -} - -namespace { -class FindClassDeclXConsumer : public clang::ASTConsumer { - public: - FindClassDeclXConsumer(bool *FoundClassDeclX) - : FoundClassDeclX(FoundClassDeclX) {} - virtual void HandleTopLevelDecl(clang::DeclGroupRef GroupRef) { - if (CXXRecordDecl* Record = llvm::dyn_cast<clang::CXXRecordDecl>( - *GroupRef.begin())) { - if (Record->getName() == "X") { - *FoundClassDeclX = true; - } - } - } - private: - bool *FoundClassDeclX; -}; -} // end namespace - -TEST(RunSyntaxOnlyToolOnCode, FindsClassDecl) { - bool FoundClassDeclX = false; - EXPECT_TRUE(RunSyntaxOnlyToolOnCode(new TestAction( - new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;")); - EXPECT_TRUE(FoundClassDeclX); - - FoundClassDeclX = false; - EXPECT_TRUE(RunSyntaxOnlyToolOnCode(new TestAction( - new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;")); - EXPECT_FALSE(FoundClassDeclX); -} - -TEST(FindCompileArgsInJsonDatabase, FindsNothingIfEmpty) { - std::string ErrorMessage; - CompileCommand NotFound = FindCompileArgsInJsonDatabase( - "a-file.cpp", "", ErrorMessage); - EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage; - EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage; -} - -TEST(FindCompileArgsInJsonDatabase, ReadsSingleEntry) { - llvm::StringRef Directory("/some/directory"); - llvm::StringRef FileName("/path/to/a-file.cpp"); - llvm::StringRef Command("/path/to/compiler and some arguments"); - std::string ErrorMessage; - CompileCommand FoundCommand = FindCompileArgsInJsonDatabase( - FileName, - (llvm::Twine("[{\"directory\":\"") + Directory + "\"," + - "\"command\":\"" + Command + "\"," - "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage); - EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage; - ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage; - EXPECT_EQ("/path/to/compiler", FoundCommand.CommandLine[0]) << ErrorMessage; - EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage; - EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage; - EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage; - - CompileCommand NotFound = FindCompileArgsInJsonDatabase( - "a-file.cpp", - (llvm::Twine("[{\"directory\":\"") + Directory + "\"," + - "\"command\":\"" + Command + "\"," - "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage); - EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage; - EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage; -} - -TEST(FindCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) { - llvm::StringRef Directory("/some/directory"); - llvm::StringRef FileName("/path/to/a-file.cpp"); - llvm::StringRef Command("\\\"/path to compiler\\\" \\\"and an argument\\\""); - std::string ErrorMessage; - CompileCommand FoundCommand = FindCompileArgsInJsonDatabase( - FileName, - (llvm::Twine("[{\"directory\":\"") + Directory + "\"," + - "\"command\":\"" + Command + "\"," - "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage); - ASSERT_EQ(2u, FoundCommand.CommandLine.size()); - EXPECT_EQ("/path to compiler", FoundCommand.CommandLine[0]) << ErrorMessage; - EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage; -} - -TEST(FindCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) { - llvm::StringRef Directory("/some directory / with spaces"); - llvm::StringRef FileName("/path/to/a-file.cpp"); - llvm::StringRef Command("a command"); - std::string ErrorMessage; - CompileCommand FoundCommand = FindCompileArgsInJsonDatabase( - FileName, - (llvm::Twine("[{\"directory\":\"") + Directory + "\"," + - "\"command\":\"" + Command + "\"," - "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage); - EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage; -} - -TEST(FindCompileArgsInJsonDatabase, FindsEntry) { - llvm::StringRef Directory("directory"); - llvm::StringRef FileName("file"); - llvm::StringRef Command("command"); - std::string JsonDatabase = "["; - for (int I = 0; I < 10; ++I) { - if (I > 0) JsonDatabase += ","; - JsonDatabase += (llvm::Twine( - "{\"directory\":\"") + Directory + llvm::Twine(I) + "\"," + - "\"command\":\"" + Command + llvm::Twine(I) + "\"," - "\"file\":\"" + FileName + llvm::Twine(I) + "\"}").str(); - } - JsonDatabase += "]"; - std::string ErrorMessage; - CompileCommand FoundCommand = FindCompileArgsInJsonDatabase( - "file4", JsonDatabase, ErrorMessage); - EXPECT_EQ("directory4", FoundCommand.Directory) << ErrorMessage; - ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage; - EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage; -} - -} // end namespace tooling -} // end namespace clang - |