blob: 5f3079017ab2f37c90530090e25e81299738e46f [file] [log] [blame]
Manuel Klimek24db0f02013-05-14 09:13:00 +00001//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
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#include <vector>
11
12#include "../ASTMatchersTest.h"
13#include "clang/ASTMatchers/Dynamic/Registry.h"
14#include "gtest/gtest.h"
15
16namespace clang {
17namespace ast_matchers {
18namespace dynamic {
19namespace {
20
21using ast_matchers::internal::Matcher;
22
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000023class RegistryTest : public ::testing::Test {
24public:
25 std::vector<ParserValue> Args() { return std::vector<ParserValue>(); }
26 std::vector<ParserValue> Args(const VariantValue &Arg1) {
27 std::vector<ParserValue> Out(1);
28 Out[0].Value = Arg1;
29 return Out;
30 }
31 std::vector<ParserValue> Args(const VariantValue &Arg1,
32 const VariantValue &Arg2) {
33 std::vector<ParserValue> Out(2);
34 Out[0].Value = Arg1;
35 Out[1].Value = Arg2;
36 return Out;
37 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000038
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000039 llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
40 Diagnostics *Error = 0) {
41 Diagnostics DummyError;
42 if (!Error) Error = &DummyError;
43 llvm::Optional<MatcherCtor> Ctor =
44 Registry::lookupMatcherCtor(MatcherName, SourceRange(), Error);
45 EXPECT_EQ("", DummyError.toStringFull());
46 return Ctor;
47 }
48
Samuel Benzaquen0239b692013-08-13 14:54:51 +000049 VariantMatcher constructMatcher(StringRef MatcherName,
50 Diagnostics *Error = NULL) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000051 Diagnostics DummyError;
52 if (!Error) Error = &DummyError;
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000053 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
54 VariantMatcher Out;
55 if (Ctor)
56 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000057 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000058 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000059 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000060
Samuel Benzaquen0239b692013-08-13 14:54:51 +000061 VariantMatcher constructMatcher(StringRef MatcherName,
62 const VariantValue &Arg1,
63 Diagnostics *Error = NULL) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000064 Diagnostics DummyError;
65 if (!Error) Error = &DummyError;
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000066 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
67 VariantMatcher Out;
68 if (Ctor)
69 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000070 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000071 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000072 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000073
Samuel Benzaquen0239b692013-08-13 14:54:51 +000074 VariantMatcher constructMatcher(StringRef MatcherName,
75 const VariantValue &Arg1,
76 const VariantValue &Arg2,
77 Diagnostics *Error = NULL) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000078 Diagnostics DummyError;
79 if (!Error) Error = &DummyError;
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000080 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
81 VariantMatcher Out;
82 if (Ctor)
83 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
84 Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000085 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000086 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000087 }
88};
89
90TEST_F(RegistryTest, CanConstructNoArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000091 Matcher<Stmt> IsArrowValue = constructMatcher(
92 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
93 Matcher<Stmt> BoolValue =
94 constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
Manuel Klimek24db0f02013-05-14 09:13:00 +000095
96 const std::string ClassSnippet = "struct Foo { int x; };\n"
97 "Foo *foo = new Foo;\n"
98 "int i = foo->x;\n";
99 const std::string BoolSnippet = "bool Foo = true;\n";
100
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000101 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
102 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
103 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
104 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000105}
106
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000107TEST_F(RegistryTest, ConstructWithSimpleArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000108 Matcher<Decl> Value = constructMatcher(
109 "namedDecl", constructMatcher("hasName", std::string("X")))
110 .getTypedMatcher<Decl>();
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000111 EXPECT_TRUE(matches("class X {};", Value));
112 EXPECT_FALSE(matches("int x;", Value));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000113
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000114 Value = functionDecl(constructMatcher("parameterCountIs", 2)
115 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000116 EXPECT_TRUE(matches("void foo(int,int);", Value));
117 EXPECT_FALSE(matches("void foo(int);", Value));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000118}
119
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000120TEST_F(RegistryTest, ConstructWithMatcherArgs) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000121 Matcher<Decl> HasInitializerSimple = constructMatcher(
122 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
123 .getTypedMatcher<Decl>();
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000124 Matcher<Decl> HasInitializerComplex = constructMatcher(
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000125 "varDecl",
126 constructMatcher("hasInitializer", constructMatcher("callExpr")))
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000127 .getTypedMatcher<Decl>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000128
129 std::string code = "int i;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000130 EXPECT_FALSE(matches(code, HasInitializerSimple));
131 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000132
133 code = "int i = 1;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000134 EXPECT_TRUE(matches(code, HasInitializerSimple));
135 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000136
137 code = "int y(); int i = y();";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000138 EXPECT_TRUE(matches(code, HasInitializerSimple));
139 EXPECT_TRUE(matches(code, HasInitializerComplex));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000140
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000141 Matcher<Decl> HasParameter =
142 functionDecl(constructMatcher(
143 "hasParameter", 1, constructMatcher("hasName", std::string("x")))
144 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000145 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
146 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000147}
148
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000149TEST_F(RegistryTest, OverloadedMatchers) {
150 Matcher<Stmt> CallExpr0 = constructMatcher(
151 "callExpr",
152 constructMatcher("callee", constructMatcher("memberExpr",
153 constructMatcher("isArrow"))))
154 .getTypedMatcher<Stmt>();
155
156 Matcher<Stmt> CallExpr1 = constructMatcher(
157 "callExpr",
158 constructMatcher(
159 "callee",
160 constructMatcher("methodDecl",
161 constructMatcher("hasName", std::string("x")))))
162 .getTypedMatcher<Stmt>();
163
164 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
165 EXPECT_FALSE(matches(Code, CallExpr0));
166 EXPECT_TRUE(matches(Code, CallExpr1));
167
168 Code = "class Z { public: void z() { this->z(); } };";
169 EXPECT_TRUE(matches(Code, CallExpr0));
170 EXPECT_FALSE(matches(Code, CallExpr1));
171}
172
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000173TEST_F(RegistryTest, PolymorphicMatchers) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000174 const VariantMatcher IsDefinition = constructMatcher("isDefinition");
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000175 Matcher<Decl> Var =
176 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000177 Matcher<Decl> Class =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000178 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000179 Matcher<Decl> Func =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000180 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000181 EXPECT_TRUE(matches("int a;", Var));
182 EXPECT_FALSE(matches("extern int a;", Var));
183 EXPECT_TRUE(matches("class A {};", Class));
184 EXPECT_FALSE(matches("class A;", Class));
185 EXPECT_TRUE(matches("void f(){};", Func));
186 EXPECT_FALSE(matches("void f();", Func));
187
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000188 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000189 Matcher<Decl> RecordDecl = constructMatcher(
190 "recordDecl", constructMatcher("hasName", std::string("Foo")),
191 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000192
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000193 EXPECT_TRUE(matches("int Foo;", Anything));
194 EXPECT_TRUE(matches("class Foo {};", Anything));
195 EXPECT_TRUE(matches("void Foo(){};", Anything));
196 EXPECT_FALSE(matches("int Foo;", RecordDecl));
197 EXPECT_TRUE(matches("class Foo {};", RecordDecl));
198 EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000199
200 Matcher<Stmt> ConstructExpr = constructMatcher(
201 "constructExpr",
202 constructMatcher(
203 "hasDeclaration",
204 constructMatcher(
205 "methodDecl",
206 constructMatcher(
207 "ofClass", constructMatcher("hasName", std::string("Foo"))))))
208 .getTypedMatcher<Stmt>();
209 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
210 EXPECT_TRUE(
211 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000212}
213
Samuel Benzaquen21b3da02013-07-17 15:11:30 +0000214TEST_F(RegistryTest, TemplateArgument) {
215 Matcher<Decl> HasTemplateArgument = constructMatcher(
216 "classTemplateSpecializationDecl",
217 constructMatcher(
218 "hasAnyTemplateArgument",
219 constructMatcher("refersToType",
220 constructMatcher("asString", std::string("int")))))
221 .getTypedMatcher<Decl>();
222 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
223 HasTemplateArgument));
224 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
225 HasTemplateArgument));
226}
227
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000228TEST_F(RegistryTest, TypeTraversal) {
229 Matcher<Type> M = constructMatcher(
230 "pointerType",
231 constructMatcher("pointee", constructMatcher("isConstQualified"),
232 constructMatcher("isInteger"))).getTypedMatcher<Type>();
233 EXPECT_FALSE(matches("int *a;", M));
234 EXPECT_TRUE(matches("int const *b;", M));
235
236 M = constructMatcher(
237 "arrayType",
238 constructMatcher("hasElementType", constructMatcher("builtinType")))
239 .getTypedMatcher<Type>();
240 EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
241 EXPECT_TRUE(matches("int b[7];", M));
242}
243
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000244TEST_F(RegistryTest, CXXCtorInitializer) {
245 Matcher<Decl> CtorDecl = constructMatcher(
246 "constructorDecl",
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000247 constructMatcher(
248 "hasAnyConstructorInitializer",
249 constructMatcher("forField",
250 constructMatcher("hasName", std::string("foo")))))
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000251 .getTypedMatcher<Decl>();
252 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
253 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
254 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
255}
256
Samuel Benzaquen7f8a5b12013-07-24 14:48:01 +0000257TEST_F(RegistryTest, Adaptative) {
258 Matcher<Decl> D = constructMatcher(
259 "recordDecl",
260 constructMatcher(
261 "has",
262 constructMatcher("recordDecl",
263 constructMatcher("hasName", std::string("X")))))
264 .getTypedMatcher<Decl>();
265 EXPECT_TRUE(matches("class X {};", D));
266 EXPECT_TRUE(matches("class Y { class X {}; };", D));
267 EXPECT_FALSE(matches("class Y { class Z {}; };", D));
268
269 Matcher<Stmt> S = constructMatcher(
270 "forStmt",
271 constructMatcher(
272 "hasDescendant",
273 constructMatcher("varDecl",
274 constructMatcher("hasName", std::string("X")))))
275 .getTypedMatcher<Stmt>();
276 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
277 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
278 EXPECT_FALSE(matches("void foo() { for(;;); }", S));
279 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
280
281 S = constructMatcher(
282 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
283 .getTypedMatcher<Stmt>();
284 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
285 EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
286}
287
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000288TEST_F(RegistryTest, VariadicOp) {
289 Matcher<Decl> D = constructMatcher(
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000290 "anyOf",
291 constructMatcher("recordDecl",
292 constructMatcher("hasName", std::string("Foo"))),
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000293 constructMatcher("namedDecl",
294 constructMatcher("hasName", std::string("foo"))))
295 .getTypedMatcher<Decl>();
296
297 EXPECT_TRUE(matches("void foo(){}", D));
298 EXPECT_TRUE(matches("struct Foo{};", D));
299 EXPECT_FALSE(matches("int i = 0;", D));
300
301 D = constructMatcher(
302 "allOf", constructMatcher("recordDecl"),
303 constructMatcher(
304 "namedDecl",
305 constructMatcher("anyOf",
306 constructMatcher("hasName", std::string("Foo")),
307 constructMatcher("hasName", std::string("Bar")))))
308 .getTypedMatcher<Decl>();
309
310 EXPECT_FALSE(matches("void foo(){}", D));
311 EXPECT_TRUE(matches("struct Foo{};", D));
312 EXPECT_FALSE(matches("int i = 0;", D));
313 EXPECT_TRUE(matches("class Bar{};", D));
314 EXPECT_FALSE(matches("class OtherBar{};", D));
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000315
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000316 D = recordDecl(
317 has(fieldDecl(hasName("Foo"))),
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000318 constructMatcher(
319 "unless",
320 constructMatcher("namedDecl",
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000321 constructMatcher("hasName", std::string("Bar"))))
322 .getTypedMatcher<Decl>());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000323
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000324 EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
325 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000326}
327
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000328TEST_F(RegistryTest, Errors) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000329 // Incorrect argument count.
330 OwningPtr<Diagnostics> Error(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000331 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000332 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000333 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000334 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000335 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000336 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000337 Error->toString());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000338 Error.reset(new Diagnostics());
339 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
340 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
341 Error->toString());
342 Error.reset(new Diagnostics());
343 EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
344 Error.get()).isNull());
345 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
346 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000347
348 // Bad argument type
349 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000350 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000351 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
352 "(Actual = String)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000353 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000354 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000355 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
356 constructMatcher("parameterCountIs", 3),
357 Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000358 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
359 "(Actual = Matcher<FunctionDecl>)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000360 Error->toString());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000361
362 // Bad argument type with variadic.
363 Error.reset(new Diagnostics());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000364 EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
365 Error.get()).isNull());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000366 EXPECT_EQ(
367 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
368 Error->toString());
369 Error.reset(new Diagnostics());
370 EXPECT_TRUE(constructMatcher(
371 "recordDecl",
372 constructMatcher("allOf",
373 constructMatcher("isDerivedFrom", std::string("FOO")),
374 constructMatcher("isArrow")),
375 Error.get()).isNull());
376 EXPECT_EQ("Incorrect type for arg 1. "
377 "(Expected = Matcher<CXXRecordDecl>) != "
378 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
379 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000380}
381
382} // end anonymous namespace
383} // end namespace dynamic
384} // end namespace ast_matchers
385} // end namespace clang