//===--- Registry.cpp - Matcher registry -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===------------------------------------------------------------===// /// /// \file /// \brief Registry map populated at static initialization time. /// //===------------------------------------------------------------===// #include "clang/ASTMatchers/Dynamic/Registry.h" #include #include "Marshallers.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ManagedStatic.h" namespace clang { namespace ast_matchers { namespace dynamic { namespace { using internal::MatcherCreateCallback; typedef llvm::StringMap ConstructorMap; class RegistryMaps { public: RegistryMaps(); ~RegistryMaps(); const ConstructorMap &constructors() const { return Constructors; } private: void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback); ConstructorMap Constructors; }; void RegistryMaps::registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback) { Constructors[MatcherName] = Callback; } #define REGISTER_MATCHER(name) \ registerMatcher(#name, internal::makeMatcherAutoMarshall( \ ::clang::ast_matchers::name, #name)); /// \brief Generate a registry map with all the known matchers. RegistryMaps::RegistryMaps() { // TODO: This list is not complete. It only has non-overloaded matchers, // which are the simplest to add to the system. Overloaded matchers require // more supporting code that was omitted from the first revision for // simplicitly of code review. REGISTER_MATCHER(binaryOperator); REGISTER_MATCHER(bindTemporaryExpr); REGISTER_MATCHER(boolLiteral); REGISTER_MATCHER(callExpr); REGISTER_MATCHER(characterLiteral); REGISTER_MATCHER(compoundStmt); REGISTER_MATCHER(conditionalOperator); REGISTER_MATCHER(constCastExpr); REGISTER_MATCHER(constructExpr); REGISTER_MATCHER(constructorDecl); REGISTER_MATCHER(declRefExpr); REGISTER_MATCHER(declStmt); REGISTER_MATCHER(defaultArgExpr); REGISTER_MATCHER(doStmt); REGISTER_MATCHER(dynamicCastExpr); REGISTER_MATCHER(explicitCastExpr); REGISTER_MATCHER(expr); REGISTER_MATCHER(fieldDecl); REGISTER_MATCHER(forStmt); REGISTER_MATCHER(functionDecl); REGISTER_MATCHER(hasAnyParameter); REGISTER_MATCHER(hasAnySubstatement); REGISTER_MATCHER(hasConditionVariableStatement); REGISTER_MATCHER(hasDestinationType); REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasFalseExpression); REGISTER_MATCHER(hasImplicitDestinationType); REGISTER_MATCHER(hasInitializer); REGISTER_MATCHER(hasLHS); REGISTER_MATCHER(hasName); REGISTER_MATCHER(hasObjectExpression); REGISTER_MATCHER(hasRHS); REGISTER_MATCHER(hasSourceExpression); REGISTER_MATCHER(hasTrueExpression); REGISTER_MATCHER(hasUnaryOperand); REGISTER_MATCHER(ifStmt); REGISTER_MATCHER(implicitCastExpr); REGISTER_MATCHER(integerLiteral); REGISTER_MATCHER(isArrow); REGISTER_MATCHER(isConstQualified); REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(member); REGISTER_MATCHER(memberExpr); REGISTER_MATCHER(methodDecl); REGISTER_MATCHER(namedDecl); REGISTER_MATCHER(newExpr); REGISTER_MATCHER(ofClass); REGISTER_MATCHER(on); REGISTER_MATCHER(onImplicitObjectArgument); REGISTER_MATCHER(operatorCallExpr); REGISTER_MATCHER(recordDecl); REGISTER_MATCHER(reinterpretCastExpr); REGISTER_MATCHER(staticCastExpr); REGISTER_MATCHER(stmt); REGISTER_MATCHER(stringLiteral); REGISTER_MATCHER(switchCase); REGISTER_MATCHER(to); REGISTER_MATCHER(unaryOperator); REGISTER_MATCHER(varDecl); REGISTER_MATCHER(whileStmt); } RegistryMaps::~RegistryMaps() { for (ConstructorMap::iterator it = Constructors.begin(), end = Constructors.end(); it != end; ++it) { delete it->second; } } static llvm::ManagedStatic RegistryData; } // anonymous namespace // static DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName, const SourceRange &NameRange, ArrayRef Args, Diagnostics *Error) { ConstructorMap::const_iterator it = RegistryData->constructors().find(MatcherName); if (it == RegistryData->constructors().end()) { Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound) << MatcherName; return NULL; } return it->second->run(NameRange, Args, Error); } // static DynTypedMatcher *Registry::constructBoundMatcher(StringRef MatcherName, const SourceRange &NameRange, StringRef BindID, ArrayRef Args, Diagnostics *Error) { OwningPtr Out( constructMatcher(MatcherName, NameRange, Args, Error)); if (!Out) return NULL; DynTypedMatcher *Bound = Out->tryBind(BindID); if (!Bound) { Error->pushErrorFrame(NameRange, Error->ET_RegistryNotBindable); return NULL; } return Bound; } } // namespace dynamic } // namespace ast_matchers } // namespace clang