diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CMakeLists.txt | 1 | ||||
-rwxr-xr-x | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/Tooling/ASTMatchers.cpp | 564 | ||||
-rw-r--r-- | lib/Tooling/CMakeLists.txt | 7 | ||||
-rw-r--r-- | lib/Tooling/JsonCompileCommandLineDatabase.cpp | 214 | ||||
-rw-r--r-- | lib/Tooling/JsonCompileCommandLineDatabase.h | 107 | ||||
-rw-r--r-- | lib/Tooling/Makefile | 15 | ||||
-rw-r--r-- | lib/Tooling/Tooling.cpp | 403 |
8 files changed, 1 insertions, 1312 deletions
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 |