xref: /llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp (revision 31edb51a4f274e97a9c54ae830b1896c690b8cf7)
1 //===--- Registry.cpp - Matcher registry -------------------------===//
2 //
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 //
8 //===------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Registry map populated at static initialization time.
12 ///
13 //===------------------------------------------------------------===//
14 
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 
25 namespace clang {
26 namespace ast_matchers {
27 namespace dynamic {
28 namespace {
29 
30 using internal::MatcherCreateCallback;
31 
32 typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap;
33 class RegistryMaps {
34 public:
35   RegistryMaps();
36   ~RegistryMaps();
37 
38   const ConstructorMap &constructors() const { return Constructors; }
39 
40 private:
41   void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback);
42   ConstructorMap Constructors;
43 };
44 
45 void 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.
55 RegistryMaps::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 
123 RegistryMaps::~RegistryMaps() {
124   for (ConstructorMap::iterator it = Constructors.begin(),
125                                 end = Constructors.end();
126        it != end; ++it) {
127     delete it->second;
128   }
129 }
130 
131 static llvm::ManagedStatic<RegistryMaps> RegistryData;
132 
133 } // anonymous namespace
134 
135 // static
136 DynTypedMatcher *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 
151 // static
152 DynTypedMatcher *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 
168 }  // namespace dynamic
169 }  // namespace ast_matchers
170 }  // namespace clang
171