blob: 6e543fc850458b620acc1f3bbc3c0f5ba581d15f [file] [log] [blame]
//===--- 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 <utility>
#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<const MatcherCreateCallback *> 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<RegistryMaps> RegistryData;
} // anonymous namespace
// static
DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName,
const SourceRange &NameRange,
ArrayRef<ParserValue> 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<ParserValue> Args,
Diagnostics *Error) {
OwningPtr<DynTypedMatcher> 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