blob: 6e543fc850458b620acc1f3bbc3c0f5ba581d15f [file] [log] [blame]
Samuel Benzaquene30903d2013-05-15 19:49:05 +00001//===--- Registry.cpp - Matcher registry -------------------------===//
Manuel Klimekf7f295f2013-05-14 09:13:00 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
Samuel Benzaquene30903d2013-05-15 19:49:05 +00008//===------------------------------------------------------------===//
Manuel Klimekf7f295f2013-05-14 09:13:00 +00009///
10/// \file
11/// \brief Registry map populated at static initialization time.
12///
Samuel Benzaquene30903d2013-05-15 19:49:05 +000013//===------------------------------------------------------------===//
Manuel Klimekf7f295f2013-05-14 09:13:00 +000014
15#include "clang/ASTMatchers/Dynamic/Registry.h"
16
17#include <utility>
18
19#include "Marshallers.h"
20#include "clang/ASTMatchers/ASTMatchers.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/ManagedStatic.h"
24
25namespace clang {
26namespace ast_matchers {
27namespace dynamic {
28namespace {
29
30using internal::MatcherCreateCallback;
31
32typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;
33class RegistryMaps {
34public:
35 RegistryMaps();
36 ~RegistryMaps();
37
38 const ConstructorMap &constructors() const { return Constructors; }
39
40private:
41 void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback);
42 ConstructorMap Constructors;
43};
44
45void RegistryMaps::registerMatcher(StringRef MatcherName,
46 MatcherCreateCallback *Callback) {
47 Constructors[MatcherName] = Callback;
48}
49
50#define REGISTER_MATCHER(name) \
51 registerMatcher(#name, internal::makeMatcherAutoMarshall( \
52 ::clang::ast_matchers::name, #name));
53
54/// \brief Generate a registry map with all the known matchers.
55RegistryMaps::RegistryMaps() {
56 // TODO: This list is not complete. It only has non-overloaded matchers,
57 // which are the simplest to add to the system. Overloaded matchers require
58 // more supporting code that was omitted from the first revision for
59 // simplicitly of code review.
60
61 REGISTER_MATCHER(binaryOperator);
62 REGISTER_MATCHER(bindTemporaryExpr);
63 REGISTER_MATCHER(boolLiteral);
64 REGISTER_MATCHER(callExpr);
65 REGISTER_MATCHER(characterLiteral);
66 REGISTER_MATCHER(compoundStmt);
67 REGISTER_MATCHER(conditionalOperator);
68 REGISTER_MATCHER(constCastExpr);
69 REGISTER_MATCHER(constructExpr);
70 REGISTER_MATCHER(constructorDecl);
71 REGISTER_MATCHER(declRefExpr);
72 REGISTER_MATCHER(declStmt);
73 REGISTER_MATCHER(defaultArgExpr);
74 REGISTER_MATCHER(doStmt);
75 REGISTER_MATCHER(dynamicCastExpr);
76 REGISTER_MATCHER(explicitCastExpr);
77 REGISTER_MATCHER(expr);
78 REGISTER_MATCHER(fieldDecl);
79 REGISTER_MATCHER(forStmt);
80 REGISTER_MATCHER(functionDecl);
81 REGISTER_MATCHER(hasAnyParameter);
82 REGISTER_MATCHER(hasAnySubstatement);
83 REGISTER_MATCHER(hasConditionVariableStatement);
84 REGISTER_MATCHER(hasDestinationType);
85 REGISTER_MATCHER(hasEitherOperand);
86 REGISTER_MATCHER(hasFalseExpression);
87 REGISTER_MATCHER(hasImplicitDestinationType);
88 REGISTER_MATCHER(hasInitializer);
89 REGISTER_MATCHER(hasLHS);
90 REGISTER_MATCHER(hasName);
91 REGISTER_MATCHER(hasObjectExpression);
92 REGISTER_MATCHER(hasRHS);
93 REGISTER_MATCHER(hasSourceExpression);
94 REGISTER_MATCHER(hasTrueExpression);
95 REGISTER_MATCHER(hasUnaryOperand);
96 REGISTER_MATCHER(ifStmt);
97 REGISTER_MATCHER(implicitCastExpr);
98 REGISTER_MATCHER(integerLiteral);
99 REGISTER_MATCHER(isArrow);
100 REGISTER_MATCHER(isConstQualified);
101 REGISTER_MATCHER(isImplicit);
102 REGISTER_MATCHER(member);
103 REGISTER_MATCHER(memberExpr);
104 REGISTER_MATCHER(methodDecl);
105 REGISTER_MATCHER(namedDecl);
106 REGISTER_MATCHER(newExpr);
107 REGISTER_MATCHER(ofClass);
108 REGISTER_MATCHER(on);
109 REGISTER_MATCHER(onImplicitObjectArgument);
110 REGISTER_MATCHER(operatorCallExpr);
111 REGISTER_MATCHER(recordDecl);
112 REGISTER_MATCHER(reinterpretCastExpr);
113 REGISTER_MATCHER(staticCastExpr);
114 REGISTER_MATCHER(stmt);
115 REGISTER_MATCHER(stringLiteral);
116 REGISTER_MATCHER(switchCase);
117 REGISTER_MATCHER(to);
118 REGISTER_MATCHER(unaryOperator);
119 REGISTER_MATCHER(varDecl);
120 REGISTER_MATCHER(whileStmt);
121}
122
123RegistryMaps::~RegistryMaps() {
124 for (ConstructorMap::iterator it = Constructors.begin(),
125 end = Constructors.end();
126 it != end; ++it) {
127 delete it->second;
128 }
129}
130
131static llvm::ManagedStatic<RegistryMaps> RegistryData;
132
133} // anonymous namespace
134
135// static
136DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName,
137 const SourceRange &NameRange,
138 ArrayRef<ParserValue> Args,
139 Diagnostics *Error) {
140 ConstructorMap::const_iterator it =
141 RegistryData->constructors().find(MatcherName);
142 if (it == RegistryData->constructors().end()) {
143 Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound)
144 << MatcherName;
145 return NULL;
146 }
147
148 return it->second->run(NameRange, Args, Error);
149}
150
Samuel Benzaquen4f37d922013-06-03 19:31:08 +0000151// static
152DynTypedMatcher *Registry::constructBoundMatcher(StringRef MatcherName,
153 const SourceRange &NameRange,
154 StringRef BindID,
155 ArrayRef<ParserValue> Args,
156 Diagnostics *Error) {
157 OwningPtr<DynTypedMatcher> Out(
158 constructMatcher(MatcherName, NameRange, Args, Error));
159 if (!Out) return NULL;
160 DynTypedMatcher *Bound = Out->tryBind(BindID);
161 if (!Bound) {
162 Error->pushErrorFrame(NameRange, Error->ET_RegistryNotBindable);
163 return NULL;
164 }
165 return Bound;
166}
167
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000168} // namespace dynamic
169} // namespace ast_matchers
170} // namespace clang