Clang Project

clang_source_code/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
1//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===-----------------------------------------------------------------------===//
8
9#include "../ASTMatchersTest.h"
10#include "clang/ASTMatchers/Dynamic/Registry.h"
11#include "gtest/gtest.h"
12#include <vector>
13
14namespace clang {
15namespace ast_matchers {
16namespace dynamic {
17namespace {
18
19using ast_matchers::internal::Matcher;
20
21class RegistryTest : public ::testing::Test {
22public:
23  std::vector<ParserValue> Args() { return std::vector<ParserValue>(); }
24  std::vector<ParserValue> Args(const VariantValue &Arg1) {
25    std::vector<ParserValue> Out(1);
26    Out[0].Value = Arg1;
27    return Out;
28  }
29  std::vector<ParserValue> Args(const VariantValue &Arg1,
30                                const VariantValue &Arg2) {
31    std::vector<ParserValue> Out(2);
32    Out[0].Value = Arg1;
33    Out[1].Value = Arg2;
34    return Out;
35  }
36
37  llvm::Optional<MatcherCtorlookupMatcherCtor(StringRef MatcherName) {
38    return Registry::lookupMatcherCtor(MatcherName);
39  }
40
41  VariantMatcher constructMatcher(StringRef MatcherName,
42                                  Diagnostics *Error = nullptr) {
43    Diagnostics DummyError;
44    if (!ErrorError = &DummyError;
45    llvm::Optional<MatcherCtorCtor = lookupMatcherCtor(MatcherName);
46    VariantMatcher Out;
47    if (Ctor)
48      Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
49    EXPECT_EQ(""DummyError.toStringFull());
50    return Out;
51  }
52
53  VariantMatcher constructMatcher(StringRef MatcherName,
54                                  const VariantValue &Arg1,
55                                  Diagnostics *Error = nullptr) {
56    Diagnostics DummyError;
57    if (!ErrorError = &DummyError;
58    llvm::Optional<MatcherCtorCtor = lookupMatcherCtor(MatcherName);
59    VariantMatcher Out;
60    if (Ctor)
61      Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
62    EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
63    return Out;
64  }
65
66  VariantMatcher constructMatcher(StringRef MatcherName,
67                                  const VariantValue &Arg1,
68                                  const VariantValue &Arg2,
69                                  Diagnostics *Error = nullptr) {
70    Diagnostics DummyError;
71    if (!ErrorError = &DummyError;
72    llvm::Optional<MatcherCtorCtor = lookupMatcherCtor(MatcherName);
73    VariantMatcher Out;
74    if (Ctor)
75      Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
76                                       Error);
77    EXPECT_EQ(""DummyError.toStringFull());
78    return Out;
79  }
80
81  typedef std::vector<MatcherCompletion> CompVector;
82
83  CompVector getCompletions() {
84    std::vector<std::pair<MatcherCtor, unsigned> > Context;
85    return Registry::getMatcherCompletions(
86        Registry::getAcceptedCompletionTypes(Context));
87  }
88
89  CompVector getCompletions(StringRef MatcherName1unsigned ArgNo1) {
90    std::vector<std::pair<MatcherCtor, unsigned> > Context;
91    llvm::Optional<MatcherCtorCtor = lookupMatcherCtor(MatcherName1);
92    if (!Ctor)
93      return CompVector();
94    Context.push_back(std::make_pair(*Ctor, ArgNo1));
95    return Registry::getMatcherCompletions(
96        Registry::getAcceptedCompletionTypes(Context));
97  }
98
99  CompVector getCompletions(StringRef MatcherName1unsigned ArgNo1,
100                            StringRef MatcherName2unsigned ArgNo2) {
101    std::vector<std::pair<MatcherCtor, unsigned> > Context;
102    llvm::Optional<MatcherCtorCtor = lookupMatcherCtor(MatcherName1);
103    if (!Ctor)
104      return CompVector();
105    Context.push_back(std::make_pair(*Ctor, ArgNo1));
106    Ctor = lookupMatcherCtor(MatcherName2);
107    if (!Ctor)
108      return CompVector();
109    Context.push_back(std::make_pair(*Ctor, ArgNo2));
110    return Registry::getMatcherCompletions(
111        Registry::getAcceptedCompletionTypes(Context));
112  }
113
114  bool hasCompletion(const CompVector &CompsStringRef TypedText,
115                     StringRef MatcherDecl = StringRef()) {
116    for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E;
117         ++I) {
118      if (I->TypedText == TypedText &&
119          (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
120        return true;
121      }
122    }
123    return false;
124  }
125};
126
127TEST_F(RegistryTest, CanConstructNoArgs) {
128  Matcher<StmtIsArrowValue = constructMatcher(
129      "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
130  Matcher<StmtBoolValue =
131      constructMatcher("cxxBoolLiteral").getTypedMatcher<Stmt>();
132
133  const std::string ClassSnippet = "struct Foo { int x; };\n"
134                                   "Foo *foo = new Foo;\n"
135                                   "int i = foo->x;\n";
136  const std::string BoolSnippet = "bool Foo = true;\n";
137
138  EXPECT_TRUE(matches(ClassSnippetIsArrowValue));
139  EXPECT_TRUE(matches(BoolSnippetBoolValue));
140  EXPECT_FALSE(matches(ClassSnippetBoolValue));
141  EXPECT_FALSE(matches(BoolSnippetIsArrowValue));
142}
143
144TEST_F(RegistryTest, ConstructWithSimpleArgs) {
145  Matcher<DeclValue = constructMatcher(
146      "namedDecl", constructMatcher("hasName", StringRef("X")))
147      .getTypedMatcher<Decl>();
148  EXPECT_TRUE(matches("class X {};"Value));
149  EXPECT_FALSE(matches("int x;"Value));
150
151  Value = functionDecl(constructMatcher("parameterCountIs"2)
152                           .getTypedMatcher<FunctionDecl>());
153  EXPECT_TRUE(matches("void foo(int,int);"Value));
154  EXPECT_FALSE(matches("void foo(int);"Value));
155}
156
157TEST_F(RegistryTest, ConstructWithMatcherArgs) {
158  Matcher<DeclHasInitializerSimple = constructMatcher(
159      "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
160      .getTypedMatcher<Decl>();
161  Matcher<DeclHasInitializerComplex = constructMatcher(
162      "varDecl",
163      constructMatcher("hasInitializer", constructMatcher("callExpr")))
164      .getTypedMatcher<Decl>();
165
166  std::string code = "int i;";
167  EXPECT_FALSE(matches(codeHasInitializerSimple));
168  EXPECT_FALSE(matches(codeHasInitializerComplex));
169
170  code = "int i = 1;";
171  EXPECT_TRUE(matches(codeHasInitializerSimple));
172  EXPECT_FALSE(matches(codeHasInitializerComplex));
173
174  code = "int y(); int i = y();";
175  EXPECT_TRUE(matches(codeHasInitializerSimple));
176  EXPECT_TRUE(matches(codeHasInitializerComplex));
177
178  Matcher<DeclHasParameter =
179      functionDecl(constructMatcher(
180          "hasParameter"1, constructMatcher("hasName", StringRef("x")))
181                       .getTypedMatcher<FunctionDecl>());
182  EXPECT_TRUE(matches("void f(int a, int x);"HasParameter));
183  EXPECT_FALSE(matches("void f(int x, int a);"HasParameter));
184}
185
186TEST_F(RegistryTest, OverloadedMatchers) {
187  Matcher<StmtCallExpr0 = constructMatcher(
188      "callExpr",
189      constructMatcher("callee", constructMatcher("memberExpr",
190                                                  constructMatcher("isArrow"))))
191      .getTypedMatcher<Stmt>();
192
193  Matcher<StmtCallExpr1 = constructMatcher(
194      "callExpr",
195      constructMatcher(
196          "callee",
197          constructMatcher("cxxMethodDecl",
198                           constructMatcher("hasName", StringRef("x")))))
199      .getTypedMatcher<Stmt>();
200
201  std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
202  EXPECT_FALSE(matches(CodeCallExpr0));
203  EXPECT_TRUE(matches(CodeCallExpr1));
204
205  Code = "class Z { public: void z() { this->z(); } };";
206  EXPECT_TRUE(matches(CodeCallExpr0));
207  EXPECT_FALSE(matches(CodeCallExpr1));
208
209  Matcher<DeclDeclDecl = declaratorDecl(hasTypeLoc(
210      constructMatcher(
211          "loc", constructMatcher("asString", StringRef("const double *")))
212          .getTypedMatcher<TypeLoc>()));
213
214  Matcher<NestedNameSpecifierLocNNSL =
215      constructMatcher(
216          "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
217                     specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
218          .getTypedMatcher<NestedNameSpecifierLoc>();
219
220  Code = "const double * x = 0;";
221  EXPECT_TRUE(matches(CodeDeclDecl));
222  EXPECT_FALSE(matches(CodeNNSL));
223
224  Code = "struct A { struct B {}; }; A::B a_b;";
225  EXPECT_FALSE(matches(CodeDeclDecl));
226  EXPECT_TRUE(matches(CodeNNSL));
227}
228
229TEST_F(RegistryTest, PolymorphicMatchers) {
230  const VariantMatcher IsDefinition = constructMatcher("isDefinition");
231  Matcher<DeclVar =
232      constructMatcher("varDecl"IsDefinition).getTypedMatcher<Decl>();
233  Matcher<DeclClass =
234      constructMatcher("recordDecl"IsDefinition).getTypedMatcher<Decl>();
235  Matcher<DeclFunc =
236      constructMatcher("functionDecl"IsDefinition).getTypedMatcher<Decl>();
237  EXPECT_TRUE(matches("int a;"Var));
238  EXPECT_FALSE(matches("extern int a;"Var));
239  EXPECT_TRUE(matches("class A {};"Class));
240  EXPECT_FALSE(matches("class A;"Class));
241  EXPECT_TRUE(matches("void f(){};"Func));
242  EXPECT_FALSE(matches("void f();"Func));
243
244  Matcher<DeclAnything = constructMatcher("anything").getTypedMatcher<Decl>();
245  Matcher<DeclRecordDecl = constructMatcher(
246      "recordDecl", constructMatcher("hasName", StringRef("Foo")),
247      VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
248
249  EXPECT_TRUE(matches("int Foo;"Anything));
250  EXPECT_TRUE(matches("class Foo {};"Anything));
251  EXPECT_TRUE(matches("void Foo(){};"Anything));
252  EXPECT_FALSE(matches("int Foo;"RecordDecl));
253  EXPECT_TRUE(matches("class Foo {};"RecordDecl));
254  EXPECT_FALSE(matches("void Foo(){};"RecordDecl));
255
256  Matcher<StmtConstructExpr = constructMatcher(
257      "cxxConstructExpr",
258      constructMatcher(
259          "hasDeclaration",
260          constructMatcher(
261              "cxxMethodDecl",
262              constructMatcher(
263                  "ofClass", constructMatcher("hasName", StringRef("Foo"))))))
264                                    .getTypedMatcher<Stmt>();
265  EXPECT_FALSE(matches("class Foo { public: Foo(); };"ConstructExpr));
266  EXPECT_TRUE(
267      matches("class Foo { public: Foo(); }; Foo foo = Foo();"ConstructExpr));
268}
269
270TEST_F(RegistryTest, TemplateArgument) {
271  Matcher<DeclHasTemplateArgument = constructMatcher(
272      "classTemplateSpecializationDecl",
273      constructMatcher(
274          "hasAnyTemplateArgument",
275          constructMatcher("refersToType",
276                           constructMatcher("asString", StringRef("int")))))
277      .getTypedMatcher<Decl>();
278  EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
279                      HasTemplateArgument));
280  EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
281                       HasTemplateArgument));
282}
283
284TEST_F(RegistryTest, TypeTraversal) {
285  Matcher<TypeM = constructMatcher(
286      "pointerType",
287      constructMatcher("pointee", constructMatcher("isConstQualified"),
288                       constructMatcher("isInteger"))).getTypedMatcher<Type>();
289  EXPECT_FALSE(matches("int *a;"M));
290  EXPECT_TRUE(matches("int const *b;"M));
291
292  M = constructMatcher(
293      "arrayType",
294      constructMatcher("hasElementType", constructMatcher("builtinType")))
295      .getTypedMatcher<Type>();
296  EXPECT_FALSE(matches("struct A{}; A a[7];;"M));
297  EXPECT_TRUE(matches("int b[7];"M));
298}
299
300TEST_F(RegistryTest, CXXCtorInitializer) {
301  Matcher<DeclCtorDecl = constructMatcher(
302      "cxxConstructorDecl",
303      constructMatcher(
304          "hasAnyConstructorInitializer",
305          constructMatcher("forField",
306                           constructMatcher("hasName", StringRef("foo")))))
307      .getTypedMatcher<Decl>();
308  EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };"CtorDecl));
309  EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };"CtorDecl));
310  EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };"CtorDecl));
311}
312
313TEST_F(RegistryTest, Adaptative) {
314  Matcher<DeclD = constructMatcher(
315      "recordDecl",
316      constructMatcher(
317          "has",
318          constructMatcher("recordDecl",
319                           constructMatcher("hasName", StringRef("X")))))
320      .getTypedMatcher<Decl>();
321  EXPECT_TRUE(matches("class X {};"D));
322  EXPECT_TRUE(matches("class Y { class X {}; };"D));
323  EXPECT_FALSE(matches("class Y { class Z {}; };"D));
324
325  Matcher<StmtS = constructMatcher(
326      "forStmt",
327      constructMatcher(
328          "hasDescendant",
329          constructMatcher("varDecl",
330                           constructMatcher("hasName", StringRef("X")))))
331      .getTypedMatcher<Stmt>();
332  EXPECT_TRUE(matches("void foo() { for(int X;;); }"S));
333  EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }"S));
334  EXPECT_FALSE(matches("void foo() { for(;;); }"S));
335  EXPECT_FALSE(matches("void foo() { if (int X = 0){} }"S));
336
337  S = constructMatcher(
338      "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
339      .getTypedMatcher<Stmt>();
340  EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }"S));
341  EXPECT_FALSE(matches("void foo() { if (true) return; }"S));
342}
343
344TEST_F(RegistryTest, VariadicOp) {
345  Matcher<DeclD = constructMatcher(
346      "anyOf",
347      constructMatcher("recordDecl",
348                       constructMatcher("hasName", StringRef("Foo"))),
349      constructMatcher("functionDecl",
350                       constructMatcher("hasName", StringRef("foo"))))
351      .getTypedMatcher<Decl>();
352
353  EXPECT_TRUE(matches("void foo(){}"D));
354  EXPECT_TRUE(matches("struct Foo{};"D));
355  EXPECT_FALSE(matches("int i = 0;"D));
356
357  D = constructMatcher(
358      "allOf", constructMatcher("recordDecl"),
359      constructMatcher(
360          "namedDecl",
361          constructMatcher("anyOf",
362                           constructMatcher("hasName", StringRef("Foo")),
363                           constructMatcher("hasName", StringRef("Bar")))))
364      .getTypedMatcher<Decl>();
365
366  EXPECT_FALSE(matches("void foo(){}"D));
367  EXPECT_TRUE(matches("struct Foo{};"D));
368  EXPECT_FALSE(matches("int i = 0;"D));
369  EXPECT_TRUE(matches("class Bar{};"D));
370  EXPECT_FALSE(matches("class OtherBar{};"D));
371
372  D = recordDecl(
373      has(fieldDecl(hasName("Foo"))),
374      constructMatcher(
375          "unless",
376          constructMatcher("namedDecl",
377                           constructMatcher("hasName", StringRef("Bar"))))
378          .getTypedMatcher<Decl>());
379
380  EXPECT_FALSE(matches("class Bar{ int Foo; };"D));
381  EXPECT_TRUE(matches("class OtherBar{ int Foo; };"D));
382
383  D = constructMatcher(
384          "namedDecl", constructMatcher("hasName", StringRef("Foo")),
385          constructMatcher("unless", constructMatcher("recordDecl")))
386          .getTypedMatcher<Decl>();
387  EXPECT_TRUE(matches("void Foo(){}"D));
388  EXPECT_TRUE(notMatches("struct Foo {};"D));
389}
390
391TEST_F(RegistryTest, Errors) {
392  // Incorrect argument count.
393  std::unique_ptr<Diagnostics> Error(new Diagnostics());
394  EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
395  EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
396            Error->toString());
397  Error.reset(new Diagnostics());
398  EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull());
399  EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
400            Error->toString());
401  Error.reset(new Diagnostics());
402  EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
403  EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
404            Error->toString());
405  Error.reset(new Diagnostics());
406  EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(),
407                               Error.get()).isNull());
408  EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
409            Error->toString());
410
411  // Bad argument type
412  Error.reset(new Diagnostics());
413  EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull());
414  EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
415            "(Actual = String)",
416            Error->toString());
417  Error.reset(new Diagnostics());
418  EXPECT_TRUE(
419      constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"),
420                       constructMatcher("parameterCountIs"3), Error.get())
421          .isNull());
422  EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
423            "(Actual = Matcher<FunctionDecl|FunctionProtoType>)",
424            Error->toString());
425
426  // Bad argument type with variadic.
427  Error.reset(new Diagnostics());
428  EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(),
429                               Error.get()).isNull());
430  EXPECT_EQ(
431      "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
432      Error->toString());
433  Error.reset(new Diagnostics());
434  EXPECT_TRUE(constructMatcher(
435      "cxxRecordDecl",
436      constructMatcher("allOf",
437                       constructMatcher("isDerivedFrom", StringRef("FOO")),
438                       constructMatcher("isArrow")),
439      Error.get()).isNull());
440  EXPECT_EQ("Incorrect type for arg 1. "
441            "(Expected = Matcher<CXXRecordDecl>) != "
442            "(Actual = Matcher<CXXRecordDecl>&Matcher"
443            "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)",
444            Error->toString());
445}
446
447TEST_F(RegistryTest, Completion) {
448  CompVector Comps = getCompletions();
449  // Overloaded
450  EXPECT_TRUE(hasCompletion(
451      Comps, "hasParent(",
452      "Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...> "
453      "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));
454  // Variadic.
455  EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
456                            "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
457  // Polymorphic.
458  EXPECT_TRUE(hasCompletion(
459      Comps, "hasDescendant(",
460      "Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> "
461      "hasDescendant(Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...>)"));
462
463  CompVector WhileComps = getCompletions("whileStmt"0);
464
465  EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
466                            "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
467  EXPECT_TRUE(hasCompletion(
468      WhileComps, "hasParent(",
469      "Matcher<Stmt> "
470      "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));
471  EXPECT_TRUE(
472      hasCompletion(WhileComps, "allOf(""Matcher<T> allOf(Matcher<T>...)"));
473
474  EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
475  EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
476
477  CompVector AllOfWhileComps =
478      getCompletions("allOf"0"whileStmt"0);
479  ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
480  EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
481                         AllOfWhileComps.begin()));
482
483  CompVector DeclWhileComps =
484      getCompletions("decl"0"whileStmt"0);
485  EXPECT_EQ(0u, DeclWhileComps.size());
486
487  CompVector NamedDeclComps = getCompletions("namedDecl"0);
488  EXPECT_TRUE(
489      hasCompletion(NamedDeclComps, "isPublic()""Matcher<Decl> isPublic()"));
490  EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
491                            "Matcher<NamedDecl> hasName(string)"));
492
493  // Heterogeneous overloads.
494  Comps = getCompletions("classTemplateSpecializationDecl"0);
495  EXPECT_TRUE(hasCompletion(
496      Comps, "isSameOrDerivedFrom(",
497      "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
498}
499
500TEST_F(RegistryTest, HasArgs) {
501  Matcher<DeclValue = constructMatcher(
502      "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused")))
503      .getTypedMatcher<Decl>();
504  EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};"Value));
505  EXPECT_FALSE(matches("struct X {};"Value));
506}
507
508TEST_F(RegistryTest, ParenExpr) {
509  Matcher<StmtValue = constructMatcher("parenExpr").getTypedMatcher<Stmt>();
510  EXPECT_TRUE(matches("int i = (1);"Value));
511  EXPECT_FALSE(matches("int i = 1;"Value));
512}
513
514TEST_F(RegistryTest, EqualsMatcher) {
515  Matcher<StmtBooleanStmt = constructMatcher(
516      "cxxBoolLiteral", constructMatcher("equals"VariantValue(true)))
517      .getTypedMatcher<Stmt>();
518  EXPECT_TRUE(matches("bool x = true;"BooleanStmt));
519  EXPECT_FALSE(matches("bool x = false;"BooleanStmt));
520  EXPECT_FALSE(matches("bool x = 0;"BooleanStmt));
521
522  BooleanStmt = constructMatcher(
523      "cxxBoolLiteral", constructMatcher("equals"VariantValue(0)))
524      .getTypedMatcher<Stmt>();
525  EXPECT_TRUE(matches("bool x = false;"BooleanStmt));
526  EXPECT_FALSE(matches("bool x = true;"BooleanStmt));
527  EXPECT_FALSE(matches("bool x = 0;"BooleanStmt));
528
529  Matcher<StmtDoubleStmt = constructMatcher(
530      "floatLiteral", constructMatcher("equals"VariantValue(1.2)))
531      .getTypedMatcher<Stmt>();
532  EXPECT_TRUE(matches("double x = 1.2;"DoubleStmt));
533#if 0
534  // FIXME floatLiteral matching should work regardless of suffix.
535  EXPECT_TRUE(matches("double x = 1.2f;", DoubleStmt));
536  EXPECT_TRUE(matches("double x = 1.2l;", DoubleStmt));
537#endif
538  EXPECT_TRUE(matches("double x = 12e-1;"DoubleStmt));
539  EXPECT_FALSE(matches("double x = 1.23;"DoubleStmt));
540
541  Matcher<StmtIntegerStmt = constructMatcher(
542      "integerLiteral", constructMatcher("equals"VariantValue(42)))
543      .getTypedMatcher<Stmt>();
544  EXPECT_TRUE(matches("int x = 42;"IntegerStmt));
545  EXPECT_FALSE(matches("int x = 1;"IntegerStmt));
546
547  Matcher<StmtCharStmt = constructMatcher(
548      "characterLiteral", constructMatcher("equals"VariantValue('x')))
549      .getTypedMatcher<Stmt>();
550  EXPECT_TRUE(matches("int x = 'x';"CharStmt));
551  EXPECT_TRUE(matches("int x = L'x';"CharStmt));
552  EXPECT_TRUE(matches("int x = u'x';"CharStmt));
553  EXPECT_TRUE(matches("int x = U'x';"CharStmt));
554  EXPECT_FALSE(matches("int x = 120;"CharStmt));
555}
556
557// end anonymous namespace
558// end namespace dynamic
559// end namespace ast_matchers
560// end namespace clang
561