1f4a2713aSLionel Sambuc //===- unittest/Tooling/ASTMatchersTest.cpp - AST matcher unit tests ------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc
10f4a2713aSLionel Sambuc #include "ASTMatchersTest.h"
11f4a2713aSLionel Sambuc #include "clang/AST/PrettyPrinter.h"
12f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchFinder.h"
13f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchers.h"
14f4a2713aSLionel Sambuc #include "clang/Tooling/Tooling.h"
15*0a6a1f1dSLionel Sambuc #include "llvm/ADT/Triple.h"
16*0a6a1f1dSLionel Sambuc #include "llvm/Support/Host.h"
17f4a2713aSLionel Sambuc #include "gtest/gtest.h"
18f4a2713aSLionel Sambuc
19f4a2713aSLionel Sambuc namespace clang {
20f4a2713aSLionel Sambuc namespace ast_matchers {
21f4a2713aSLionel Sambuc
22f4a2713aSLionel Sambuc #if GTEST_HAS_DEATH_TEST
TEST(HasNameDeathTest,DiesOnEmptyName)23f4a2713aSLionel Sambuc TEST(HasNameDeathTest, DiesOnEmptyName) {
24f4a2713aSLionel Sambuc ASSERT_DEBUG_DEATH({
25f4a2713aSLionel Sambuc DeclarationMatcher HasEmptyName = recordDecl(hasName(""));
26f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
27f4a2713aSLionel Sambuc }, "");
28f4a2713aSLionel Sambuc }
29f4a2713aSLionel Sambuc
TEST(HasNameDeathTest,DiesOnEmptyPattern)30f4a2713aSLionel Sambuc TEST(HasNameDeathTest, DiesOnEmptyPattern) {
31f4a2713aSLionel Sambuc ASSERT_DEBUG_DEATH({
32f4a2713aSLionel Sambuc DeclarationMatcher HasEmptyName = recordDecl(matchesName(""));
33f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
34f4a2713aSLionel Sambuc }, "");
35f4a2713aSLionel Sambuc }
36f4a2713aSLionel Sambuc
TEST(IsDerivedFromDeathTest,DiesOnEmptyBaseName)37f4a2713aSLionel Sambuc TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
38f4a2713aSLionel Sambuc ASSERT_DEBUG_DEATH({
39f4a2713aSLionel Sambuc DeclarationMatcher IsDerivedFromEmpty = recordDecl(isDerivedFrom(""));
40f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
41f4a2713aSLionel Sambuc }, "");
42f4a2713aSLionel Sambuc }
43f4a2713aSLionel Sambuc #endif
44f4a2713aSLionel Sambuc
TEST(Finder,DynamicOnlyAcceptsSomeMatchers)45f4a2713aSLionel Sambuc TEST(Finder, DynamicOnlyAcceptsSomeMatchers) {
46f4a2713aSLionel Sambuc MatchFinder Finder;
47*0a6a1f1dSLionel Sambuc EXPECT_TRUE(Finder.addDynamicMatcher(decl(), nullptr));
48*0a6a1f1dSLionel Sambuc EXPECT_TRUE(Finder.addDynamicMatcher(callExpr(), nullptr));
49*0a6a1f1dSLionel Sambuc EXPECT_TRUE(Finder.addDynamicMatcher(constantArrayType(hasSize(42)),
50*0a6a1f1dSLionel Sambuc nullptr));
51f4a2713aSLionel Sambuc
52f4a2713aSLionel Sambuc // Do not accept non-toplevel matchers.
53*0a6a1f1dSLionel Sambuc EXPECT_FALSE(Finder.addDynamicMatcher(isArrow(), nullptr));
54*0a6a1f1dSLionel Sambuc EXPECT_FALSE(Finder.addDynamicMatcher(hasSize(2), nullptr));
55*0a6a1f1dSLionel Sambuc EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr));
56f4a2713aSLionel Sambuc }
57f4a2713aSLionel Sambuc
TEST(Decl,MatchesDeclarations)58f4a2713aSLionel Sambuc TEST(Decl, MatchesDeclarations) {
59f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("", decl(usingDecl())));
60f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace x { class X {}; } using x::X;",
61f4a2713aSLionel Sambuc decl(usingDecl())));
62f4a2713aSLionel Sambuc }
63f4a2713aSLionel Sambuc
TEST(NameableDeclaration,MatchesVariousDecls)64f4a2713aSLionel Sambuc TEST(NameableDeclaration, MatchesVariousDecls) {
65f4a2713aSLionel Sambuc DeclarationMatcher NamedX = namedDecl(hasName("X"));
66f4a2713aSLionel Sambuc EXPECT_TRUE(matches("typedef int X;", NamedX));
67f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int X;", NamedX));
68f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class foo { virtual void X(); };", NamedX));
69f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", NamedX));
70f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() { int X; }", NamedX));
71f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace X { }", NamedX));
72f4a2713aSLionel Sambuc EXPECT_TRUE(matches("enum X { A, B, C };", NamedX));
73f4a2713aSLionel Sambuc
74f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("#define X 1", NamedX));
75f4a2713aSLionel Sambuc }
76f4a2713aSLionel Sambuc
TEST(NameableDeclaration,REMatchesVariousDecls)77f4a2713aSLionel Sambuc TEST(NameableDeclaration, REMatchesVariousDecls) {
78f4a2713aSLionel Sambuc DeclarationMatcher NamedX = namedDecl(matchesName("::X"));
79f4a2713aSLionel Sambuc EXPECT_TRUE(matches("typedef int Xa;", NamedX));
80f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int Xb;", NamedX));
81f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class foo { virtual void Xc(); };", NamedX));
82f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() try { } catch(int Xdef) { }", NamedX));
83f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() { int Xgh; }", NamedX));
84f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace Xij { }", NamedX));
85f4a2713aSLionel Sambuc EXPECT_TRUE(matches("enum X { A, B, C };", NamedX));
86f4a2713aSLionel Sambuc
87f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("#define Xkl 1", NamedX));
88f4a2713aSLionel Sambuc
89f4a2713aSLionel Sambuc DeclarationMatcher StartsWithNo = namedDecl(matchesName("::no"));
90f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int no_foo;", StartsWithNo));
91f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class foo { virtual void nobody(); };", StartsWithNo));
92f4a2713aSLionel Sambuc
93f4a2713aSLionel Sambuc DeclarationMatcher Abc = namedDecl(matchesName("a.*b.*c"));
94f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int abc;", Abc));
95f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int aFOObBARc;", Abc));
96f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int cab;", Abc));
97f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int cabc;", Abc));
98f4a2713aSLionel Sambuc
99f4a2713aSLionel Sambuc DeclarationMatcher StartsWithK = namedDecl(matchesName(":k[^:]*$"));
100f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int k;", StartsWithK));
101f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int kAbc;", StartsWithK));
102f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace x { int kTest; }", StartsWithK));
103f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class C { int k; };", StartsWithK));
104f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class C { int ckc; };", StartsWithK));
105f4a2713aSLionel Sambuc }
106f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,MatchClass)107f4a2713aSLionel Sambuc TEST(DeclarationMatcher, MatchClass) {
108f4a2713aSLionel Sambuc DeclarationMatcher ClassMatcher(recordDecl());
109*0a6a1f1dSLionel Sambuc llvm::Triple Triple(llvm::sys::getDefaultTargetTriple());
110*0a6a1f1dSLionel Sambuc if (Triple.getOS() != llvm::Triple::Win32 ||
111*0a6a1f1dSLionel Sambuc Triple.getEnvironment() != llvm::Triple::MSVC)
112f4a2713aSLionel Sambuc EXPECT_FALSE(matches("", ClassMatcher));
113*0a6a1f1dSLionel Sambuc else
114f4a2713aSLionel Sambuc // Matches class type_info.
115f4a2713aSLionel Sambuc EXPECT_TRUE(matches("", ClassMatcher));
116f4a2713aSLionel Sambuc
117f4a2713aSLionel Sambuc DeclarationMatcher ClassX = recordDecl(recordDecl(hasName("X")));
118f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X;", ClassX));
119f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {};", ClassX));
120f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template<class T> class X {};", ClassX));
121f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("", ClassX));
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,ClassIsDerived)124f4a2713aSLionel Sambuc TEST(DeclarationMatcher, ClassIsDerived) {
125f4a2713aSLionel Sambuc DeclarationMatcher IsDerivedFromX = recordDecl(isDerivedFrom("X"));
126f4a2713aSLionel Sambuc
127f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX));
128f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", IsDerivedFromX));
129f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X;", IsDerivedFromX));
130f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
131f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("", IsDerivedFromX));
132f4a2713aSLionel Sambuc
133f4a2713aSLionel Sambuc DeclarationMatcher IsAX = recordDecl(isSameOrDerivedFrom("X"));
134f4a2713aSLionel Sambuc
135f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsAX));
136f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {};", IsAX));
137f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X;", IsAX));
138f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y;", IsAX));
139f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("", IsAX));
140f4a2713aSLionel Sambuc
141f4a2713aSLionel Sambuc DeclarationMatcher ZIsDerivedFromX =
142f4a2713aSLionel Sambuc recordDecl(hasName("Z"), isDerivedFrom("X"));
143f4a2713aSLionel Sambuc EXPECT_TRUE(
144f4a2713aSLionel Sambuc matches("class X {}; class Y : public X {}; class Z : public Y {};",
145f4a2713aSLionel Sambuc ZIsDerivedFromX));
146f4a2713aSLionel Sambuc EXPECT_TRUE(
147f4a2713aSLionel Sambuc matches("class X {};"
148f4a2713aSLionel Sambuc "template<class T> class Y : public X {};"
149f4a2713aSLionel Sambuc "class Z : public Y<int> {};", ZIsDerivedFromX));
150f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; template<class T> class Z : public X {};",
151f4a2713aSLionel Sambuc ZIsDerivedFromX));
152f4a2713aSLionel Sambuc EXPECT_TRUE(
153f4a2713aSLionel Sambuc matches("template<class T> class X {}; "
154f4a2713aSLionel Sambuc "template<class T> class Z : public X<T> {};",
155f4a2713aSLionel Sambuc ZIsDerivedFromX));
156f4a2713aSLionel Sambuc EXPECT_TRUE(
157f4a2713aSLionel Sambuc matches("template<class T, class U=T> class X {}; "
158f4a2713aSLionel Sambuc "template<class T> class Z : public X<T> {};",
159f4a2713aSLionel Sambuc ZIsDerivedFromX));
160f4a2713aSLionel Sambuc EXPECT_TRUE(
161f4a2713aSLionel Sambuc notMatches("template<class X> class A { class Z : public X {}; };",
162f4a2713aSLionel Sambuc ZIsDerivedFromX));
163f4a2713aSLionel Sambuc EXPECT_TRUE(
164f4a2713aSLionel Sambuc matches("template<class X> class A { public: class Z : public X {}; }; "
165f4a2713aSLionel Sambuc "class X{}; void y() { A<X>::Z z; }", ZIsDerivedFromX));
166f4a2713aSLionel Sambuc EXPECT_TRUE(
167f4a2713aSLionel Sambuc matches("template <class T> class X {}; "
168f4a2713aSLionel Sambuc "template<class Y> class A { class Z : public X<Y> {}; };",
169f4a2713aSLionel Sambuc ZIsDerivedFromX));
170f4a2713aSLionel Sambuc EXPECT_TRUE(
171f4a2713aSLionel Sambuc notMatches("template<template<class T> class X> class A { "
172f4a2713aSLionel Sambuc " class Z : public X<int> {}; };", ZIsDerivedFromX));
173f4a2713aSLionel Sambuc EXPECT_TRUE(
174f4a2713aSLionel Sambuc matches("template<template<class T> class X> class A { "
175f4a2713aSLionel Sambuc " public: class Z : public X<int> {}; }; "
176f4a2713aSLionel Sambuc "template<class T> class X {}; void y() { A<X>::Z z; }",
177f4a2713aSLionel Sambuc ZIsDerivedFromX));
178f4a2713aSLionel Sambuc EXPECT_TRUE(
179f4a2713aSLionel Sambuc notMatches("template<class X> class A { class Z : public X::D {}; };",
180f4a2713aSLionel Sambuc ZIsDerivedFromX));
181f4a2713aSLionel Sambuc EXPECT_TRUE(
182f4a2713aSLionel Sambuc matches("template<class X> class A { public: "
183f4a2713aSLionel Sambuc " class Z : public X::D {}; }; "
184f4a2713aSLionel Sambuc "class Y { public: class X {}; typedef X D; }; "
185f4a2713aSLionel Sambuc "void y() { A<Y>::Z z; }", ZIsDerivedFromX));
186f4a2713aSLionel Sambuc EXPECT_TRUE(
187f4a2713aSLionel Sambuc matches("class X {}; typedef X Y; class Z : public Y {};",
188f4a2713aSLionel Sambuc ZIsDerivedFromX));
189f4a2713aSLionel Sambuc EXPECT_TRUE(
190f4a2713aSLionel Sambuc matches("template<class T> class Y { typedef typename T::U X; "
191f4a2713aSLionel Sambuc " class Z : public X {}; };", ZIsDerivedFromX));
192f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; class Z : public ::X {};",
193f4a2713aSLionel Sambuc ZIsDerivedFromX));
194f4a2713aSLionel Sambuc EXPECT_TRUE(
195f4a2713aSLionel Sambuc notMatches("template<class T> class X {}; "
196f4a2713aSLionel Sambuc "template<class T> class A { class Z : public X<T>::D {}; };",
197f4a2713aSLionel Sambuc ZIsDerivedFromX));
198f4a2713aSLionel Sambuc EXPECT_TRUE(
199f4a2713aSLionel Sambuc matches("template<class T> class X { public: typedef X<T> D; }; "
200f4a2713aSLionel Sambuc "template<class T> class A { public: "
201f4a2713aSLionel Sambuc " class Z : public X<T>::D {}; }; void y() { A<int>::Z z; }",
202f4a2713aSLionel Sambuc ZIsDerivedFromX));
203f4a2713aSLionel Sambuc EXPECT_TRUE(
204f4a2713aSLionel Sambuc notMatches("template<class X> class A { class Z : public X::D::E {}; };",
205f4a2713aSLionel Sambuc ZIsDerivedFromX));
206f4a2713aSLionel Sambuc EXPECT_TRUE(
207f4a2713aSLionel Sambuc matches("class X {}; typedef X V; typedef V W; class Z : public W {};",
208f4a2713aSLionel Sambuc ZIsDerivedFromX));
209f4a2713aSLionel Sambuc EXPECT_TRUE(
210f4a2713aSLionel Sambuc matches("class X {}; class Y : public X {}; "
211f4a2713aSLionel Sambuc "typedef Y V; typedef V W; class Z : public W {};",
212f4a2713aSLionel Sambuc ZIsDerivedFromX));
213f4a2713aSLionel Sambuc EXPECT_TRUE(
214f4a2713aSLionel Sambuc matches("template<class T, class U> class X {}; "
215f4a2713aSLionel Sambuc "template<class T> class A { class Z : public X<T, int> {}; };",
216f4a2713aSLionel Sambuc ZIsDerivedFromX));
217f4a2713aSLionel Sambuc EXPECT_TRUE(
218f4a2713aSLionel Sambuc notMatches("template<class X> class D { typedef X A; typedef A B; "
219f4a2713aSLionel Sambuc " typedef B C; class Z : public C {}; };",
220f4a2713aSLionel Sambuc ZIsDerivedFromX));
221f4a2713aSLionel Sambuc EXPECT_TRUE(
222f4a2713aSLionel Sambuc matches("class X {}; typedef X A; typedef A B; "
223f4a2713aSLionel Sambuc "class Z : public B {};", ZIsDerivedFromX));
224f4a2713aSLionel Sambuc EXPECT_TRUE(
225f4a2713aSLionel Sambuc matches("class X {}; typedef X A; typedef A B; typedef B C; "
226f4a2713aSLionel Sambuc "class Z : public C {};", ZIsDerivedFromX));
227f4a2713aSLionel Sambuc EXPECT_TRUE(
228f4a2713aSLionel Sambuc matches("class U {}; typedef U X; typedef X V; "
229f4a2713aSLionel Sambuc "class Z : public V {};", ZIsDerivedFromX));
230f4a2713aSLionel Sambuc EXPECT_TRUE(
231f4a2713aSLionel Sambuc matches("class Base {}; typedef Base X; "
232f4a2713aSLionel Sambuc "class Z : public Base {};", ZIsDerivedFromX));
233f4a2713aSLionel Sambuc EXPECT_TRUE(
234f4a2713aSLionel Sambuc matches("class Base {}; typedef Base Base2; typedef Base2 X; "
235f4a2713aSLionel Sambuc "class Z : public Base {};", ZIsDerivedFromX));
236f4a2713aSLionel Sambuc EXPECT_TRUE(
237f4a2713aSLionel Sambuc notMatches("class Base {}; class Base2 {}; typedef Base2 X; "
238f4a2713aSLionel Sambuc "class Z : public Base {};", ZIsDerivedFromX));
239f4a2713aSLionel Sambuc EXPECT_TRUE(
240f4a2713aSLionel Sambuc matches("class A {}; typedef A X; typedef A Y; "
241f4a2713aSLionel Sambuc "class Z : public Y {};", ZIsDerivedFromX));
242f4a2713aSLionel Sambuc EXPECT_TRUE(
243f4a2713aSLionel Sambuc notMatches("template <typename T> class Z;"
244f4a2713aSLionel Sambuc "template <> class Z<void> {};"
245f4a2713aSLionel Sambuc "template <typename T> class Z : public Z<void> {};",
246f4a2713aSLionel Sambuc IsDerivedFromX));
247f4a2713aSLionel Sambuc EXPECT_TRUE(
248f4a2713aSLionel Sambuc matches("template <typename T> class X;"
249f4a2713aSLionel Sambuc "template <> class X<void> {};"
250f4a2713aSLionel Sambuc "template <typename T> class X : public X<void> {};",
251f4a2713aSLionel Sambuc IsDerivedFromX));
252f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
253f4a2713aSLionel Sambuc "class X {};"
254f4a2713aSLionel Sambuc "template <typename T> class Z;"
255f4a2713aSLionel Sambuc "template <> class Z<void> {};"
256f4a2713aSLionel Sambuc "template <typename T> class Z : public Z<void>, public X {};",
257f4a2713aSLionel Sambuc ZIsDerivedFromX));
258f4a2713aSLionel Sambuc EXPECT_TRUE(
259f4a2713aSLionel Sambuc notMatches("template<int> struct X;"
260f4a2713aSLionel Sambuc "template<int i> struct X : public X<i-1> {};",
261f4a2713aSLionel Sambuc recordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
262f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
263f4a2713aSLionel Sambuc "struct A {};"
264f4a2713aSLionel Sambuc "template<int> struct X;"
265f4a2713aSLionel Sambuc "template<int i> struct X : public X<i-1> {};"
266f4a2713aSLionel Sambuc "template<> struct X<0> : public A {};"
267f4a2713aSLionel Sambuc "struct B : public X<42> {};",
268f4a2713aSLionel Sambuc recordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
269f4a2713aSLionel Sambuc
270f4a2713aSLionel Sambuc // FIXME: Once we have better matchers for template type matching,
271f4a2713aSLionel Sambuc // get rid of the Variable(...) matching and match the right template
272f4a2713aSLionel Sambuc // declarations directly.
273f4a2713aSLionel Sambuc const char *RecursiveTemplateOneParameter =
274f4a2713aSLionel Sambuc "class Base1 {}; class Base2 {};"
275f4a2713aSLionel Sambuc "template <typename T> class Z;"
276f4a2713aSLionel Sambuc "template <> class Z<void> : public Base1 {};"
277f4a2713aSLionel Sambuc "template <> class Z<int> : public Base2 {};"
278f4a2713aSLionel Sambuc "template <> class Z<float> : public Z<void> {};"
279f4a2713aSLionel Sambuc "template <> class Z<double> : public Z<int> {};"
280f4a2713aSLionel Sambuc "template <typename T> class Z : public Z<float>, public Z<double> {};"
281f4a2713aSLionel Sambuc "void f() { Z<float> z_float; Z<double> z_double; Z<char> z_char; }";
282f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
283f4a2713aSLionel Sambuc RecursiveTemplateOneParameter,
284f4a2713aSLionel Sambuc varDecl(hasName("z_float"),
285f4a2713aSLionel Sambuc hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
286f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
287f4a2713aSLionel Sambuc RecursiveTemplateOneParameter,
288f4a2713aSLionel Sambuc varDecl(hasName("z_float"),
289f4a2713aSLionel Sambuc hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
290f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
291f4a2713aSLionel Sambuc RecursiveTemplateOneParameter,
292f4a2713aSLionel Sambuc varDecl(hasName("z_char"),
293f4a2713aSLionel Sambuc hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
294f4a2713aSLionel Sambuc isDerivedFrom("Base2")))))));
295f4a2713aSLionel Sambuc
296f4a2713aSLionel Sambuc const char *RecursiveTemplateTwoParameters =
297f4a2713aSLionel Sambuc "class Base1 {}; class Base2 {};"
298f4a2713aSLionel Sambuc "template <typename T1, typename T2> class Z;"
299f4a2713aSLionel Sambuc "template <typename T> class Z<void, T> : public Base1 {};"
300f4a2713aSLionel Sambuc "template <typename T> class Z<int, T> : public Base2 {};"
301f4a2713aSLionel Sambuc "template <typename T> class Z<float, T> : public Z<void, T> {};"
302f4a2713aSLionel Sambuc "template <typename T> class Z<double, T> : public Z<int, T> {};"
303f4a2713aSLionel Sambuc "template <typename T1, typename T2> class Z : "
304f4a2713aSLionel Sambuc " public Z<float, T2>, public Z<double, T2> {};"
305f4a2713aSLionel Sambuc "void f() { Z<float, void> z_float; Z<double, void> z_double; "
306f4a2713aSLionel Sambuc " Z<char, void> z_char; }";
307f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
308f4a2713aSLionel Sambuc RecursiveTemplateTwoParameters,
309f4a2713aSLionel Sambuc varDecl(hasName("z_float"),
310f4a2713aSLionel Sambuc hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
311f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
312f4a2713aSLionel Sambuc RecursiveTemplateTwoParameters,
313f4a2713aSLionel Sambuc varDecl(hasName("z_float"),
314f4a2713aSLionel Sambuc hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
315f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
316f4a2713aSLionel Sambuc RecursiveTemplateTwoParameters,
317f4a2713aSLionel Sambuc varDecl(hasName("z_char"),
318f4a2713aSLionel Sambuc hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
319f4a2713aSLionel Sambuc isDerivedFrom("Base2")))))));
320f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
321f4a2713aSLionel Sambuc "namespace ns { class X {}; class Y : public X {}; }",
322f4a2713aSLionel Sambuc recordDecl(isDerivedFrom("::ns::X"))));
323f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
324f4a2713aSLionel Sambuc "class X {}; class Y : public X {};",
325f4a2713aSLionel Sambuc recordDecl(isDerivedFrom("::ns::X"))));
326f4a2713aSLionel Sambuc
327f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
328f4a2713aSLionel Sambuc "class X {}; class Y : public X {};",
329f4a2713aSLionel Sambuc recordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
330f4a2713aSLionel Sambuc
331f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
332f4a2713aSLionel Sambuc "template<typename T> class X {};"
333f4a2713aSLionel Sambuc "template<typename T> using Z = X<T>;"
334f4a2713aSLionel Sambuc "template <typename T> class Y : Z<T> {};",
335f4a2713aSLionel Sambuc recordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
336f4a2713aSLionel Sambuc }
337f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,hasMethod)338f4a2713aSLionel Sambuc TEST(DeclarationMatcher, hasMethod) {
339f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class A { void func(); };",
340f4a2713aSLionel Sambuc recordDecl(hasMethod(hasName("func")))));
341f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A { void func(); };",
342f4a2713aSLionel Sambuc recordDecl(hasMethod(isPublic()))));
343f4a2713aSLionel Sambuc }
344f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,ClassDerivedFromDependentTemplateSpecialization)345f4a2713aSLionel Sambuc TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
346f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
347f4a2713aSLionel Sambuc "template <typename T> struct A {"
348f4a2713aSLionel Sambuc " template <typename T2> struct F {};"
349f4a2713aSLionel Sambuc "};"
350f4a2713aSLionel Sambuc "template <typename T> struct B : A<T>::template F<T> {};"
351f4a2713aSLionel Sambuc "B<int> b;",
352f4a2713aSLionel Sambuc recordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
353f4a2713aSLionel Sambuc }
354f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,hasDeclContext)355f4a2713aSLionel Sambuc TEST(DeclarationMatcher, hasDeclContext) {
356f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
357f4a2713aSLionel Sambuc "namespace N {"
358f4a2713aSLionel Sambuc " namespace M {"
359f4a2713aSLionel Sambuc " class D {};"
360f4a2713aSLionel Sambuc " }"
361f4a2713aSLionel Sambuc "}",
362f4a2713aSLionel Sambuc recordDecl(hasDeclContext(namespaceDecl(hasName("M"))))));
363f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
364f4a2713aSLionel Sambuc "namespace N {"
365f4a2713aSLionel Sambuc " namespace M {"
366f4a2713aSLionel Sambuc " class D {};"
367f4a2713aSLionel Sambuc " }"
368f4a2713aSLionel Sambuc "}",
369f4a2713aSLionel Sambuc recordDecl(hasDeclContext(namespaceDecl(hasName("N"))))));
370f4a2713aSLionel Sambuc
371f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace {"
372f4a2713aSLionel Sambuc " namespace M {"
373f4a2713aSLionel Sambuc " class D {};"
374f4a2713aSLionel Sambuc " }"
375f4a2713aSLionel Sambuc "}",
376f4a2713aSLionel Sambuc recordDecl(hasDeclContext(namespaceDecl(
377f4a2713aSLionel Sambuc hasName("M"), hasDeclContext(namespaceDecl()))))));
378*0a6a1f1dSLionel Sambuc
379*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("class D{};", decl(hasDeclContext(decl()))));
380*0a6a1f1dSLionel Sambuc }
381*0a6a1f1dSLionel Sambuc
TEST(DeclarationMatcher,LinkageSpecification)382*0a6a1f1dSLionel Sambuc TEST(DeclarationMatcher, LinkageSpecification) {
383*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("extern \"C\" { void foo() {}; }", linkageSpecDecl()));
384*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void foo() {};", linkageSpecDecl()));
385f4a2713aSLionel Sambuc }
386f4a2713aSLionel Sambuc
TEST(ClassTemplate,DoesNotMatchClass)387f4a2713aSLionel Sambuc TEST(ClassTemplate, DoesNotMatchClass) {
388f4a2713aSLionel Sambuc DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));
389f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X;", ClassX));
390f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", ClassX));
391f4a2713aSLionel Sambuc }
392f4a2713aSLionel Sambuc
TEST(ClassTemplate,MatchesClassTemplate)393f4a2713aSLionel Sambuc TEST(ClassTemplate, MatchesClassTemplate) {
394f4a2713aSLionel Sambuc DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));
395f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template<typename T> class X {};", ClassX));
396f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Z { template<class T> class X {}; };", ClassX));
397f4a2713aSLionel Sambuc }
398f4a2713aSLionel Sambuc
TEST(ClassTemplate,DoesNotMatchClassTemplateExplicitSpecialization)399f4a2713aSLionel Sambuc TEST(ClassTemplate, DoesNotMatchClassTemplateExplicitSpecialization) {
400f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> class X { };"
401f4a2713aSLionel Sambuc "template<> class X<int> { int a; };",
402f4a2713aSLionel Sambuc classTemplateDecl(hasName("X"),
403f4a2713aSLionel Sambuc hasDescendant(fieldDecl(hasName("a"))))));
404f4a2713aSLionel Sambuc }
405f4a2713aSLionel Sambuc
TEST(ClassTemplate,DoesNotMatchClassTemplatePartialSpecialization)406f4a2713aSLionel Sambuc TEST(ClassTemplate, DoesNotMatchClassTemplatePartialSpecialization) {
407f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T, typename U> class X { };"
408f4a2713aSLionel Sambuc "template<typename T> class X<T, int> { int a; };",
409f4a2713aSLionel Sambuc classTemplateDecl(hasName("X"),
410f4a2713aSLionel Sambuc hasDescendant(fieldDecl(hasName("a"))))));
411f4a2713aSLionel Sambuc }
412f4a2713aSLionel Sambuc
TEST(AllOf,AllOverloadsWork)413f4a2713aSLionel Sambuc TEST(AllOf, AllOverloadsWork) {
414f4a2713aSLionel Sambuc const char Program[] =
415f4a2713aSLionel Sambuc "struct T { };"
416f4a2713aSLionel Sambuc "int f(int, T*, int, int);"
417f4a2713aSLionel Sambuc "void g(int x) { T t; f(x, &t, 3, 4); }";
418f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Program,
419f4a2713aSLionel Sambuc callExpr(allOf(callee(functionDecl(hasName("f"))),
420f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl())))))));
421f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Program,
422f4a2713aSLionel Sambuc callExpr(allOf(callee(functionDecl(hasName("f"))),
423f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl()))),
424f4a2713aSLionel Sambuc hasArgument(1, hasType(pointsTo(
425f4a2713aSLionel Sambuc recordDecl(hasName("T")))))))));
426f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Program,
427f4a2713aSLionel Sambuc callExpr(allOf(callee(functionDecl(hasName("f"))),
428f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl()))),
429f4a2713aSLionel Sambuc hasArgument(1, hasType(pointsTo(
430f4a2713aSLionel Sambuc recordDecl(hasName("T"))))),
431f4a2713aSLionel Sambuc hasArgument(2, integerLiteral(equals(3)))))));
432f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Program,
433f4a2713aSLionel Sambuc callExpr(allOf(callee(functionDecl(hasName("f"))),
434f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl()))),
435f4a2713aSLionel Sambuc hasArgument(1, hasType(pointsTo(
436f4a2713aSLionel Sambuc recordDecl(hasName("T"))))),
437f4a2713aSLionel Sambuc hasArgument(2, integerLiteral(equals(3))),
438f4a2713aSLionel Sambuc hasArgument(3, integerLiteral(equals(4)))))));
439f4a2713aSLionel Sambuc }
440f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,MatchAnyOf)441f4a2713aSLionel Sambuc TEST(DeclarationMatcher, MatchAnyOf) {
442f4a2713aSLionel Sambuc DeclarationMatcher YOrZDerivedFromX =
443f4a2713aSLionel Sambuc recordDecl(anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
444f4a2713aSLionel Sambuc EXPECT_TRUE(
445f4a2713aSLionel Sambuc matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
446f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
447f4a2713aSLionel Sambuc EXPECT_TRUE(
448f4a2713aSLionel Sambuc notMatches("class X {}; class W : public X {};", YOrZDerivedFromX));
449f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Z {};", YOrZDerivedFromX));
450f4a2713aSLionel Sambuc
451f4a2713aSLionel Sambuc DeclarationMatcher XOrYOrZOrU =
452f4a2713aSLionel Sambuc recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U")));
453f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {};", XOrYOrZOrU));
454f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class V {};", XOrYOrZOrU));
455f4a2713aSLionel Sambuc
456f4a2713aSLionel Sambuc DeclarationMatcher XOrYOrZOrUOrV =
457f4a2713aSLionel Sambuc recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U"),
458f4a2713aSLionel Sambuc hasName("V")));
459f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {};", XOrYOrZOrUOrV));
460f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y {};", XOrYOrZOrUOrV));
461f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Z {};", XOrYOrZOrUOrV));
462f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class U {};", XOrYOrZOrUOrV));
463f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class V {};", XOrYOrZOrUOrV));
464f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A {};", XOrYOrZOrUOrV));
465*0a6a1f1dSLionel Sambuc
466*0a6a1f1dSLionel Sambuc StatementMatcher MixedTypes = stmt(anyOf(ifStmt(), binaryOperator()));
467*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("int F() { return 1 + 2; }", MixedTypes));
468*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("int F() { if (true) return 1; }", MixedTypes));
469*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("int F() { return 1; }", MixedTypes));
470f4a2713aSLionel Sambuc }
471f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,MatchHas)472f4a2713aSLionel Sambuc TEST(DeclarationMatcher, MatchHas) {
473f4a2713aSLionel Sambuc DeclarationMatcher HasClassX = recordDecl(has(recordDecl(hasName("X"))));
474f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { class X {}; };", HasClassX));
475f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {};", HasClassX));
476f4a2713aSLionel Sambuc
477f4a2713aSLionel Sambuc DeclarationMatcher YHasClassX =
478f4a2713aSLionel Sambuc recordDecl(hasName("Y"), has(recordDecl(hasName("X"))));
479f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { class X {}; };", YHasClassX));
480f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", YHasClassX));
481f4a2713aSLionel Sambuc EXPECT_TRUE(
482f4a2713aSLionel Sambuc notMatches("class Y { class Z { class X {}; }; };", YHasClassX));
483f4a2713aSLionel Sambuc }
484f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,MatchHasRecursiveAllOf)485f4a2713aSLionel Sambuc TEST(DeclarationMatcher, MatchHasRecursiveAllOf) {
486f4a2713aSLionel Sambuc DeclarationMatcher Recursive =
487f4a2713aSLionel Sambuc recordDecl(
488f4a2713aSLionel Sambuc has(recordDecl(
489f4a2713aSLionel Sambuc has(recordDecl(hasName("X"))),
490f4a2713aSLionel Sambuc has(recordDecl(hasName("Y"))),
491f4a2713aSLionel Sambuc hasName("Z"))),
492f4a2713aSLionel Sambuc has(recordDecl(
493f4a2713aSLionel Sambuc has(recordDecl(hasName("A"))),
494f4a2713aSLionel Sambuc has(recordDecl(hasName("B"))),
495f4a2713aSLionel Sambuc hasName("C"))),
496f4a2713aSLionel Sambuc hasName("F"));
497f4a2713aSLionel Sambuc
498f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
499f4a2713aSLionel Sambuc "class F {"
500f4a2713aSLionel Sambuc " class Z {"
501f4a2713aSLionel Sambuc " class X {};"
502f4a2713aSLionel Sambuc " class Y {};"
503f4a2713aSLionel Sambuc " };"
504f4a2713aSLionel Sambuc " class C {"
505f4a2713aSLionel Sambuc " class A {};"
506f4a2713aSLionel Sambuc " class B {};"
507f4a2713aSLionel Sambuc " };"
508f4a2713aSLionel Sambuc "};", Recursive));
509f4a2713aSLionel Sambuc
510f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
511f4a2713aSLionel Sambuc "class F {"
512f4a2713aSLionel Sambuc " class Z {"
513f4a2713aSLionel Sambuc " class A {};"
514f4a2713aSLionel Sambuc " class X {};"
515f4a2713aSLionel Sambuc " class Y {};"
516f4a2713aSLionel Sambuc " };"
517f4a2713aSLionel Sambuc " class C {"
518f4a2713aSLionel Sambuc " class X {};"
519f4a2713aSLionel Sambuc " class A {};"
520f4a2713aSLionel Sambuc " class B {};"
521f4a2713aSLionel Sambuc " };"
522f4a2713aSLionel Sambuc "};", Recursive));
523f4a2713aSLionel Sambuc
524f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
525f4a2713aSLionel Sambuc "class O1 {"
526f4a2713aSLionel Sambuc " class O2 {"
527f4a2713aSLionel Sambuc " class F {"
528f4a2713aSLionel Sambuc " class Z {"
529f4a2713aSLionel Sambuc " class A {};"
530f4a2713aSLionel Sambuc " class X {};"
531f4a2713aSLionel Sambuc " class Y {};"
532f4a2713aSLionel Sambuc " };"
533f4a2713aSLionel Sambuc " class C {"
534f4a2713aSLionel Sambuc " class X {};"
535f4a2713aSLionel Sambuc " class A {};"
536f4a2713aSLionel Sambuc " class B {};"
537f4a2713aSLionel Sambuc " };"
538f4a2713aSLionel Sambuc " };"
539f4a2713aSLionel Sambuc " };"
540f4a2713aSLionel Sambuc "};", Recursive));
541f4a2713aSLionel Sambuc }
542f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,MatchHasRecursiveAnyOf)543f4a2713aSLionel Sambuc TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
544f4a2713aSLionel Sambuc DeclarationMatcher Recursive =
545f4a2713aSLionel Sambuc recordDecl(
546f4a2713aSLionel Sambuc anyOf(
547f4a2713aSLionel Sambuc has(recordDecl(
548f4a2713aSLionel Sambuc anyOf(
549f4a2713aSLionel Sambuc has(recordDecl(
550f4a2713aSLionel Sambuc hasName("X"))),
551f4a2713aSLionel Sambuc has(recordDecl(
552f4a2713aSLionel Sambuc hasName("Y"))),
553f4a2713aSLionel Sambuc hasName("Z")))),
554f4a2713aSLionel Sambuc has(recordDecl(
555f4a2713aSLionel Sambuc anyOf(
556f4a2713aSLionel Sambuc hasName("C"),
557f4a2713aSLionel Sambuc has(recordDecl(
558f4a2713aSLionel Sambuc hasName("A"))),
559f4a2713aSLionel Sambuc has(recordDecl(
560f4a2713aSLionel Sambuc hasName("B")))))),
561f4a2713aSLionel Sambuc hasName("F")));
562f4a2713aSLionel Sambuc
563f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class F {};", Recursive));
564f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Z {};", Recursive));
565f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class C {};", Recursive));
566f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class M { class N { class X {}; }; };", Recursive));
567f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class M { class N { class B {}; }; };", Recursive));
568f4a2713aSLionel Sambuc EXPECT_TRUE(
569f4a2713aSLionel Sambuc matches("class O1 { class O2 {"
570f4a2713aSLionel Sambuc " class M { class N { class B {}; }; }; "
571f4a2713aSLionel Sambuc "}; };", Recursive));
572f4a2713aSLionel Sambuc }
573f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,MatchNot)574f4a2713aSLionel Sambuc TEST(DeclarationMatcher, MatchNot) {
575f4a2713aSLionel Sambuc DeclarationMatcher NotClassX =
576f4a2713aSLionel Sambuc recordDecl(
577f4a2713aSLionel Sambuc isDerivedFrom("Y"),
578f4a2713aSLionel Sambuc unless(hasName("X")));
579f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("", NotClassX));
580f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y {};", NotClassX));
581f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y {}; class Z : public Y {};", NotClassX));
582f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y {}; class X : public Y {};", NotClassX));
583f4a2713aSLionel Sambuc EXPECT_TRUE(
584f4a2713aSLionel Sambuc notMatches("class Y {}; class Z {}; class X : public Y {};",
585f4a2713aSLionel Sambuc NotClassX));
586f4a2713aSLionel Sambuc
587f4a2713aSLionel Sambuc DeclarationMatcher ClassXHasNotClassY =
588f4a2713aSLionel Sambuc recordDecl(
589f4a2713aSLionel Sambuc hasName("X"),
590f4a2713aSLionel Sambuc has(recordDecl(hasName("Z"))),
591f4a2713aSLionel Sambuc unless(
592f4a2713aSLionel Sambuc has(recordDecl(hasName("Y")))));
593f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { class Z {}; };", ClassXHasNotClassY));
594f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { class Y {}; class Z {}; };",
595f4a2713aSLionel Sambuc ClassXHasNotClassY));
596*0a6a1f1dSLionel Sambuc
597*0a6a1f1dSLionel Sambuc DeclarationMatcher NamedNotRecord =
598*0a6a1f1dSLionel Sambuc namedDecl(hasName("Foo"), unless(recordDecl()));
599*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void Foo(){}", NamedNotRecord));
600*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("struct Foo {};", NamedNotRecord));
601f4a2713aSLionel Sambuc }
602f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,HasDescendant)603f4a2713aSLionel Sambuc TEST(DeclarationMatcher, HasDescendant) {
604f4a2713aSLionel Sambuc DeclarationMatcher ZDescendantClassX =
605f4a2713aSLionel Sambuc recordDecl(
606f4a2713aSLionel Sambuc hasDescendant(recordDecl(hasName("X"))),
607f4a2713aSLionel Sambuc hasName("Z"));
608f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Z { class X {}; };", ZDescendantClassX));
609f4a2713aSLionel Sambuc EXPECT_TRUE(
610f4a2713aSLionel Sambuc matches("class Z { class Y { class X {}; }; };", ZDescendantClassX));
611f4a2713aSLionel Sambuc EXPECT_TRUE(
612f4a2713aSLionel Sambuc matches("class Z { class A { class Y { class X {}; }; }; };",
613f4a2713aSLionel Sambuc ZDescendantClassX));
614f4a2713aSLionel Sambuc EXPECT_TRUE(
615f4a2713aSLionel Sambuc matches("class Z { class A { class B { class Y { class X {}; }; }; }; };",
616f4a2713aSLionel Sambuc ZDescendantClassX));
617f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Z {};", ZDescendantClassX));
618f4a2713aSLionel Sambuc
619f4a2713aSLionel Sambuc DeclarationMatcher ZDescendantClassXHasClassY =
620f4a2713aSLionel Sambuc recordDecl(
621f4a2713aSLionel Sambuc hasDescendant(recordDecl(has(recordDecl(hasName("Y"))),
622f4a2713aSLionel Sambuc hasName("X"))),
623f4a2713aSLionel Sambuc hasName("Z"));
624f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Z { class X { class Y {}; }; };",
625f4a2713aSLionel Sambuc ZDescendantClassXHasClassY));
626f4a2713aSLionel Sambuc EXPECT_TRUE(
627f4a2713aSLionel Sambuc matches("class Z { class A { class B { class X { class Y {}; }; }; }; };",
628f4a2713aSLionel Sambuc ZDescendantClassXHasClassY));
629f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
630f4a2713aSLionel Sambuc "class Z {"
631f4a2713aSLionel Sambuc " class A {"
632f4a2713aSLionel Sambuc " class B {"
633f4a2713aSLionel Sambuc " class X {"
634f4a2713aSLionel Sambuc " class C {"
635f4a2713aSLionel Sambuc " class Y {};"
636f4a2713aSLionel Sambuc " };"
637f4a2713aSLionel Sambuc " };"
638f4a2713aSLionel Sambuc " }; "
639f4a2713aSLionel Sambuc " };"
640f4a2713aSLionel Sambuc "};", ZDescendantClassXHasClassY));
641f4a2713aSLionel Sambuc
642f4a2713aSLionel Sambuc DeclarationMatcher ZDescendantClassXDescendantClassY =
643f4a2713aSLionel Sambuc recordDecl(
644f4a2713aSLionel Sambuc hasDescendant(recordDecl(hasDescendant(recordDecl(hasName("Y"))),
645f4a2713aSLionel Sambuc hasName("X"))),
646f4a2713aSLionel Sambuc hasName("Z"));
647f4a2713aSLionel Sambuc EXPECT_TRUE(
648f4a2713aSLionel Sambuc matches("class Z { class A { class X { class B { class Y {}; }; }; }; };",
649f4a2713aSLionel Sambuc ZDescendantClassXDescendantClassY));
650f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
651f4a2713aSLionel Sambuc "class Z {"
652f4a2713aSLionel Sambuc " class A {"
653f4a2713aSLionel Sambuc " class X {"
654f4a2713aSLionel Sambuc " class B {"
655f4a2713aSLionel Sambuc " class Y {};"
656f4a2713aSLionel Sambuc " };"
657f4a2713aSLionel Sambuc " class Y {};"
658f4a2713aSLionel Sambuc " };"
659f4a2713aSLionel Sambuc " };"
660f4a2713aSLionel Sambuc "};", ZDescendantClassXDescendantClassY));
661f4a2713aSLionel Sambuc }
662f4a2713aSLionel Sambuc
TEST(DeclarationMatcher,HasDescendantMemoization)663*0a6a1f1dSLionel Sambuc TEST(DeclarationMatcher, HasDescendantMemoization) {
664*0a6a1f1dSLionel Sambuc DeclarationMatcher CannotMemoize =
665*0a6a1f1dSLionel Sambuc decl(hasDescendant(typeLoc().bind("x")), has(decl()));
666*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { int i; }", CannotMemoize));
667*0a6a1f1dSLionel Sambuc }
668*0a6a1f1dSLionel Sambuc
TEST(DeclarationMatcher,HasDescendantMemoizationUsesRestrictKind)669*0a6a1f1dSLionel Sambuc TEST(DeclarationMatcher, HasDescendantMemoizationUsesRestrictKind) {
670*0a6a1f1dSLionel Sambuc auto Name = hasName("i");
671*0a6a1f1dSLionel Sambuc auto VD = internal::Matcher<VarDecl>(Name).dynCastTo<Decl>();
672*0a6a1f1dSLionel Sambuc auto RD = internal::Matcher<RecordDecl>(Name).dynCastTo<Decl>();
673*0a6a1f1dSLionel Sambuc // Matching VD first should not make a cache hit for RD.
674*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void f() { int i; }",
675*0a6a1f1dSLionel Sambuc decl(hasDescendant(VD), hasDescendant(RD))));
676*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void f() { int i; }",
677*0a6a1f1dSLionel Sambuc decl(hasDescendant(RD), hasDescendant(VD))));
678*0a6a1f1dSLionel Sambuc // Not matching RD first should not make a cache hit for VD either.
679*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { int i; }",
680*0a6a1f1dSLionel Sambuc decl(anyOf(hasDescendant(RD), hasDescendant(VD)))));
681*0a6a1f1dSLionel Sambuc }
682*0a6a1f1dSLionel Sambuc
TEST(DeclarationMatcher,HasAttr)683*0a6a1f1dSLionel Sambuc TEST(DeclarationMatcher, HasAttr) {
684*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};",
685*0a6a1f1dSLionel Sambuc decl(hasAttr(clang::attr::WarnUnused))));
686*0a6a1f1dSLionel Sambuc EXPECT_FALSE(matches("struct X {};",
687*0a6a1f1dSLionel Sambuc decl(hasAttr(clang::attr::WarnUnused))));
688*0a6a1f1dSLionel Sambuc }
689*0a6a1f1dSLionel Sambuc
TEST(DeclarationMatcher,MatchCudaDecl)690*0a6a1f1dSLionel Sambuc TEST(DeclarationMatcher, MatchCudaDecl) {
691*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesWithCuda("__global__ void f() { }"
692*0a6a1f1dSLionel Sambuc "void g() { f<<<1, 2>>>(); }",
693*0a6a1f1dSLionel Sambuc CUDAKernelCallExpr()));
694*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesWithCuda("__attribute__((device)) void f() {}",
695*0a6a1f1dSLionel Sambuc hasAttr(clang::attr::CUDADevice)));
696*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatchesWithCuda("void f() {}",
697*0a6a1f1dSLionel Sambuc CUDAKernelCallExpr()));
698*0a6a1f1dSLionel Sambuc EXPECT_FALSE(notMatchesWithCuda("__attribute__((global)) void f() {}",
699*0a6a1f1dSLionel Sambuc hasAttr(clang::attr::CUDAGlobal)));
700*0a6a1f1dSLionel Sambuc }
701*0a6a1f1dSLionel Sambuc
702f4a2713aSLionel Sambuc // Implements a run method that returns whether BoundNodes contains a
703f4a2713aSLionel Sambuc // Decl bound to Id that can be dynamically cast to T.
704f4a2713aSLionel Sambuc // Optionally checks that the check succeeded a specific number of times.
705f4a2713aSLionel Sambuc template <typename T>
706f4a2713aSLionel Sambuc class VerifyIdIsBoundTo : public BoundNodesCallback {
707f4a2713aSLionel Sambuc public:
708f4a2713aSLionel Sambuc // Create an object that checks that a node of type \c T was bound to \c Id.
709f4a2713aSLionel Sambuc // Does not check for a certain number of matches.
VerifyIdIsBoundTo(llvm::StringRef Id)710f4a2713aSLionel Sambuc explicit VerifyIdIsBoundTo(llvm::StringRef Id)
711f4a2713aSLionel Sambuc : Id(Id), ExpectedCount(-1), Count(0) {}
712f4a2713aSLionel Sambuc
713f4a2713aSLionel Sambuc // Create an object that checks that a node of type \c T was bound to \c Id.
714f4a2713aSLionel Sambuc // Checks that there were exactly \c ExpectedCount matches.
VerifyIdIsBoundTo(llvm::StringRef Id,int ExpectedCount)715f4a2713aSLionel Sambuc VerifyIdIsBoundTo(llvm::StringRef Id, int ExpectedCount)
716f4a2713aSLionel Sambuc : Id(Id), ExpectedCount(ExpectedCount), Count(0) {}
717f4a2713aSLionel Sambuc
718f4a2713aSLionel Sambuc // Create an object that checks that a node of type \c T was bound to \c Id.
719f4a2713aSLionel Sambuc // Checks that there was exactly one match with the name \c ExpectedName.
720f4a2713aSLionel Sambuc // Note that \c T must be a NamedDecl for this to work.
VerifyIdIsBoundTo(llvm::StringRef Id,llvm::StringRef ExpectedName,int ExpectedCount=1)721f4a2713aSLionel Sambuc VerifyIdIsBoundTo(llvm::StringRef Id, llvm::StringRef ExpectedName,
722f4a2713aSLionel Sambuc int ExpectedCount = 1)
723f4a2713aSLionel Sambuc : Id(Id), ExpectedCount(ExpectedCount), Count(0),
724f4a2713aSLionel Sambuc ExpectedName(ExpectedName) {}
725f4a2713aSLionel Sambuc
onEndOfTranslationUnit()726*0a6a1f1dSLionel Sambuc void onEndOfTranslationUnit() override {
727f4a2713aSLionel Sambuc if (ExpectedCount != -1)
728f4a2713aSLionel Sambuc EXPECT_EQ(ExpectedCount, Count);
729f4a2713aSLionel Sambuc if (!ExpectedName.empty())
730f4a2713aSLionel Sambuc EXPECT_EQ(ExpectedName, Name);
731f4a2713aSLionel Sambuc Count = 0;
732f4a2713aSLionel Sambuc Name.clear();
733f4a2713aSLionel Sambuc }
734f4a2713aSLionel Sambuc
~VerifyIdIsBoundTo()735f4a2713aSLionel Sambuc ~VerifyIdIsBoundTo() {
736f4a2713aSLionel Sambuc EXPECT_EQ(0, Count);
737f4a2713aSLionel Sambuc EXPECT_EQ("", Name);
738f4a2713aSLionel Sambuc }
739f4a2713aSLionel Sambuc
run(const BoundNodes * Nodes)740*0a6a1f1dSLionel Sambuc virtual bool run(const BoundNodes *Nodes) override {
741f4a2713aSLionel Sambuc const BoundNodes::IDToNodeMap &M = Nodes->getMap();
742f4a2713aSLionel Sambuc if (Nodes->getNodeAs<T>(Id)) {
743f4a2713aSLionel Sambuc ++Count;
744f4a2713aSLionel Sambuc if (const NamedDecl *Named = Nodes->getNodeAs<NamedDecl>(Id)) {
745f4a2713aSLionel Sambuc Name = Named->getNameAsString();
746f4a2713aSLionel Sambuc } else if (const NestedNameSpecifier *NNS =
747f4a2713aSLionel Sambuc Nodes->getNodeAs<NestedNameSpecifier>(Id)) {
748f4a2713aSLionel Sambuc llvm::raw_string_ostream OS(Name);
749f4a2713aSLionel Sambuc NNS->print(OS, PrintingPolicy(LangOptions()));
750f4a2713aSLionel Sambuc }
751f4a2713aSLionel Sambuc BoundNodes::IDToNodeMap::const_iterator I = M.find(Id);
752f4a2713aSLionel Sambuc EXPECT_NE(M.end(), I);
753f4a2713aSLionel Sambuc if (I != M.end())
754f4a2713aSLionel Sambuc EXPECT_EQ(Nodes->getNodeAs<T>(Id), I->second.get<T>());
755f4a2713aSLionel Sambuc return true;
756f4a2713aSLionel Sambuc }
757*0a6a1f1dSLionel Sambuc EXPECT_TRUE(M.count(Id) == 0 ||
758*0a6a1f1dSLionel Sambuc M.find(Id)->second.template get<T>() == nullptr);
759f4a2713aSLionel Sambuc return false;
760f4a2713aSLionel Sambuc }
761f4a2713aSLionel Sambuc
run(const BoundNodes * Nodes,ASTContext * Context)762*0a6a1f1dSLionel Sambuc virtual bool run(const BoundNodes *Nodes, ASTContext *Context) override {
763f4a2713aSLionel Sambuc return run(Nodes);
764f4a2713aSLionel Sambuc }
765f4a2713aSLionel Sambuc
766f4a2713aSLionel Sambuc private:
767f4a2713aSLionel Sambuc const std::string Id;
768f4a2713aSLionel Sambuc const int ExpectedCount;
769f4a2713aSLionel Sambuc int Count;
770f4a2713aSLionel Sambuc const std::string ExpectedName;
771f4a2713aSLionel Sambuc std::string Name;
772f4a2713aSLionel Sambuc };
773f4a2713aSLionel Sambuc
TEST(HasDescendant,MatchesDescendantTypes)774f4a2713aSLionel Sambuc TEST(HasDescendant, MatchesDescendantTypes) {
775f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int i = 3; }",
776f4a2713aSLionel Sambuc decl(hasDescendant(loc(builtinType())))));
777f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int i = 3; }",
778f4a2713aSLionel Sambuc stmt(hasDescendant(builtinType()))));
779f4a2713aSLionel Sambuc
780f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int i = 3; }",
781f4a2713aSLionel Sambuc stmt(hasDescendant(loc(builtinType())))));
782f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int i = 3; }",
783f4a2713aSLionel Sambuc stmt(hasDescendant(qualType(builtinType())))));
784f4a2713aSLionel Sambuc
785f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }",
786f4a2713aSLionel Sambuc stmt(hasDescendant(isInteger()))));
787f4a2713aSLionel Sambuc
788f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
789f4a2713aSLionel Sambuc "void f() { int a; float c; int d; int e; }",
790f4a2713aSLionel Sambuc functionDecl(forEachDescendant(
791f4a2713aSLionel Sambuc varDecl(hasDescendant(isInteger())).bind("x"))),
792f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 3)));
793f4a2713aSLionel Sambuc }
794f4a2713aSLionel Sambuc
TEST(HasDescendant,MatchesDescendantsOfTypes)795f4a2713aSLionel Sambuc TEST(HasDescendant, MatchesDescendantsOfTypes) {
796f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int*** i; }",
797f4a2713aSLionel Sambuc qualType(hasDescendant(builtinType()))));
798f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int*** i; }",
799f4a2713aSLionel Sambuc qualType(hasDescendant(
800f4a2713aSLionel Sambuc pointerType(pointee(builtinType()))))));
801f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { int*** i; }",
802f4a2713aSLionel Sambuc typeLoc(hasDescendant(loc(builtinType())))));
803f4a2713aSLionel Sambuc
804f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
805f4a2713aSLionel Sambuc "void f() { int*** i; }",
806f4a2713aSLionel Sambuc qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))),
807f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Type>("x", 2)));
808f4a2713aSLionel Sambuc }
809f4a2713aSLionel Sambuc
TEST(Has,MatchesChildrenOfTypes)810f4a2713aSLionel Sambuc TEST(Has, MatchesChildrenOfTypes) {
811f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i;",
812f4a2713aSLionel Sambuc varDecl(hasName("i"), has(isInteger()))));
813f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int** i;",
814f4a2713aSLionel Sambuc varDecl(hasName("i"), has(isInteger()))));
815f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
816f4a2713aSLionel Sambuc "int (*f)(float, int);",
817f4a2713aSLionel Sambuc qualType(functionType(), forEach(qualType(isInteger()).bind("x"))),
818f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<QualType>("x", 2)));
819f4a2713aSLionel Sambuc }
820f4a2713aSLionel Sambuc
TEST(Has,MatchesChildTypes)821f4a2713aSLionel Sambuc TEST(Has, MatchesChildTypes) {
822f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
823f4a2713aSLionel Sambuc "int* i;",
824f4a2713aSLionel Sambuc varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));
825f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
826f4a2713aSLionel Sambuc "int* i;",
827f4a2713aSLionel Sambuc varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));
828f4a2713aSLionel Sambuc }
829f4a2713aSLionel Sambuc
TEST(ValueDecl,Matches)830*0a6a1f1dSLionel Sambuc TEST(ValueDecl, Matches) {
831*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("enum EnumType { EnumValue };",
832*0a6a1f1dSLionel Sambuc valueDecl(hasType(asString("enum EnumType")))));
833*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void FunctionDecl();",
834*0a6a1f1dSLionel Sambuc valueDecl(hasType(asString("void (void)")))));
835*0a6a1f1dSLionel Sambuc }
836*0a6a1f1dSLionel Sambuc
TEST(Enum,DoesNotMatchClasses)837f4a2713aSLionel Sambuc TEST(Enum, DoesNotMatchClasses) {
838f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", enumDecl(hasName("X"))));
839f4a2713aSLionel Sambuc }
840f4a2713aSLionel Sambuc
TEST(Enum,MatchesEnums)841f4a2713aSLionel Sambuc TEST(Enum, MatchesEnums) {
842f4a2713aSLionel Sambuc EXPECT_TRUE(matches("enum X {};", enumDecl(hasName("X"))));
843f4a2713aSLionel Sambuc }
844f4a2713aSLionel Sambuc
TEST(EnumConstant,Matches)845f4a2713aSLionel Sambuc TEST(EnumConstant, Matches) {
846f4a2713aSLionel Sambuc DeclarationMatcher Matcher = enumConstantDecl(hasName("A"));
847f4a2713aSLionel Sambuc EXPECT_TRUE(matches("enum X{ A };", Matcher));
848f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("enum X{ B };", Matcher));
849f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("enum X {};", Matcher));
850f4a2713aSLionel Sambuc }
851f4a2713aSLionel Sambuc
TEST(StatementMatcher,Has)852f4a2713aSLionel Sambuc TEST(StatementMatcher, Has) {
853f4a2713aSLionel Sambuc StatementMatcher HasVariableI =
854f4a2713aSLionel Sambuc expr(hasType(pointsTo(recordDecl(hasName("X")))),
855f4a2713aSLionel Sambuc has(declRefExpr(to(varDecl(hasName("i"))))));
856f4a2713aSLionel Sambuc
857f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
858f4a2713aSLionel Sambuc "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));
859f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
860f4a2713aSLionel Sambuc "class X; X *x(int); void c() { int i; x(42); }", HasVariableI));
861f4a2713aSLionel Sambuc }
862f4a2713aSLionel Sambuc
TEST(StatementMatcher,HasDescendant)863f4a2713aSLionel Sambuc TEST(StatementMatcher, HasDescendant) {
864f4a2713aSLionel Sambuc StatementMatcher HasDescendantVariableI =
865f4a2713aSLionel Sambuc expr(hasType(pointsTo(recordDecl(hasName("X")))),
866f4a2713aSLionel Sambuc hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));
867f4a2713aSLionel Sambuc
868f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
869f4a2713aSLionel Sambuc "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",
870f4a2713aSLionel Sambuc HasDescendantVariableI));
871f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
872f4a2713aSLionel Sambuc "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",
873f4a2713aSLionel Sambuc HasDescendantVariableI));
874f4a2713aSLionel Sambuc }
875f4a2713aSLionel Sambuc
TEST(TypeMatcher,MatchesClassType)876f4a2713aSLionel Sambuc TEST(TypeMatcher, MatchesClassType) {
877f4a2713aSLionel Sambuc TypeMatcher TypeA = hasDeclaration(recordDecl(hasName("A")));
878f4a2713aSLionel Sambuc
879f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));
880f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A {};", TypeA));
881f4a2713aSLionel Sambuc
882f4a2713aSLionel Sambuc TypeMatcher TypeDerivedFromA = hasDeclaration(recordDecl(isDerivedFrom("A")));
883f4a2713aSLionel Sambuc
884f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",
885f4a2713aSLionel Sambuc TypeDerivedFromA));
886f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A {};", TypeA));
887f4a2713aSLionel Sambuc
888f4a2713aSLionel Sambuc TypeMatcher TypeAHasClassB = hasDeclaration(
889f4a2713aSLionel Sambuc recordDecl(hasName("A"), has(recordDecl(hasName("B")))));
890f4a2713aSLionel Sambuc
891f4a2713aSLionel Sambuc EXPECT_TRUE(
892f4a2713aSLionel Sambuc matches("class A { public: A *a; class B {}; };", TypeAHasClassB));
893f4a2713aSLionel Sambuc }
894f4a2713aSLionel Sambuc
TEST(Matcher,BindMatchedNodes)895f4a2713aSLionel Sambuc TEST(Matcher, BindMatchedNodes) {
896f4a2713aSLionel Sambuc DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x"));
897f4a2713aSLionel Sambuc
898f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class X {};",
899f4a2713aSLionel Sambuc ClassX, new VerifyIdIsBoundTo<CXXRecordDecl>("x")));
900f4a2713aSLionel Sambuc
901f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse("class X {};",
902f4a2713aSLionel Sambuc ClassX, new VerifyIdIsBoundTo<CXXRecordDecl>("other-id")));
903f4a2713aSLionel Sambuc
904f4a2713aSLionel Sambuc TypeMatcher TypeAHasClassB = hasDeclaration(
905f4a2713aSLionel Sambuc recordDecl(hasName("A"), has(recordDecl(hasName("B")).bind("b"))));
906f4a2713aSLionel Sambuc
907f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class A { public: A *a; class B {}; };",
908f4a2713aSLionel Sambuc TypeAHasClassB,
909f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("b")));
910f4a2713aSLionel Sambuc
911f4a2713aSLionel Sambuc StatementMatcher MethodX =
912f4a2713aSLionel Sambuc callExpr(callee(methodDecl(hasName("x")))).bind("x");
913f4a2713aSLionel Sambuc
914f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };",
915f4a2713aSLionel Sambuc MethodX,
916f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXMemberCallExpr>("x")));
917f4a2713aSLionel Sambuc }
918f4a2713aSLionel Sambuc
TEST(Matcher,BindTheSameNameInAlternatives)919f4a2713aSLionel Sambuc TEST(Matcher, BindTheSameNameInAlternatives) {
920f4a2713aSLionel Sambuc StatementMatcher matcher = anyOf(
921f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("+"),
922f4a2713aSLionel Sambuc hasLHS(expr().bind("x")),
923f4a2713aSLionel Sambuc hasRHS(integerLiteral(equals(0)))),
924f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("+"),
925f4a2713aSLionel Sambuc hasLHS(integerLiteral(equals(0))),
926f4a2713aSLionel Sambuc hasRHS(expr().bind("x"))));
927f4a2713aSLionel Sambuc
928f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
929f4a2713aSLionel Sambuc // The first branch of the matcher binds x to 0 but then fails.
930f4a2713aSLionel Sambuc // The second branch binds x to f() and succeeds.
931f4a2713aSLionel Sambuc "int f() { return 0 + f(); }",
932f4a2713aSLionel Sambuc matcher,
933f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CallExpr>("x")));
934f4a2713aSLionel Sambuc }
935f4a2713aSLionel Sambuc
TEST(Matcher,BindsIDForMemoizedResults)936f4a2713aSLionel Sambuc TEST(Matcher, BindsIDForMemoizedResults) {
937f4a2713aSLionel Sambuc // Using the same matcher in two match expressions will make memoization
938f4a2713aSLionel Sambuc // kick in.
939f4a2713aSLionel Sambuc DeclarationMatcher ClassX = recordDecl(hasName("X")).bind("x");
940f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
941f4a2713aSLionel Sambuc "class A { class B { class X {}; }; };",
942f4a2713aSLionel Sambuc DeclarationMatcher(anyOf(
943f4a2713aSLionel Sambuc recordDecl(hasName("A"), hasDescendant(ClassX)),
944f4a2713aSLionel Sambuc recordDecl(hasName("B"), hasDescendant(ClassX)))),
945f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 2)));
946f4a2713aSLionel Sambuc }
947f4a2713aSLionel Sambuc
TEST(HasDeclaration,HasDeclarationOfEnumType)948f4a2713aSLionel Sambuc TEST(HasDeclaration, HasDeclarationOfEnumType) {
949f4a2713aSLionel Sambuc EXPECT_TRUE(matches("enum X {}; void y(X *x) { x; }",
950f4a2713aSLionel Sambuc expr(hasType(pointsTo(
951f4a2713aSLionel Sambuc qualType(hasDeclaration(enumDecl(hasName("X")))))))));
952f4a2713aSLionel Sambuc }
953f4a2713aSLionel Sambuc
TEST(HasDeclaration,HasGetDeclTraitTest)954f4a2713aSLionel Sambuc TEST(HasDeclaration, HasGetDeclTraitTest) {
955f4a2713aSLionel Sambuc EXPECT_TRUE(internal::has_getDecl<TypedefType>::value);
956f4a2713aSLionel Sambuc EXPECT_TRUE(internal::has_getDecl<RecordType>::value);
957f4a2713aSLionel Sambuc EXPECT_FALSE(internal::has_getDecl<TemplateSpecializationType>::value);
958f4a2713aSLionel Sambuc }
959f4a2713aSLionel Sambuc
TEST(HasDeclaration,HasDeclarationOfTypeWithDecl)960f4a2713aSLionel Sambuc TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) {
961f4a2713aSLionel Sambuc EXPECT_TRUE(matches("typedef int X; X a;",
962f4a2713aSLionel Sambuc varDecl(hasName("a"),
963f4a2713aSLionel Sambuc hasType(typedefType(hasDeclaration(decl()))))));
964f4a2713aSLionel Sambuc
965f4a2713aSLionel Sambuc // FIXME: Add tests for other types with getDecl() (e.g. RecordType)
966f4a2713aSLionel Sambuc }
967f4a2713aSLionel Sambuc
TEST(HasDeclaration,HasDeclarationOfTemplateSpecializationType)968f4a2713aSLionel Sambuc TEST(HasDeclaration, HasDeclarationOfTemplateSpecializationType) {
969f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template <typename T> class A {}; A<int> a;",
970f4a2713aSLionel Sambuc varDecl(hasType(templateSpecializationType(
971f4a2713aSLionel Sambuc hasDeclaration(namedDecl(hasName("A"))))))));
972f4a2713aSLionel Sambuc }
973f4a2713aSLionel Sambuc
TEST(HasType,TakesQualTypeMatcherAndMatchesExpr)974f4a2713aSLionel Sambuc TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
975f4a2713aSLionel Sambuc TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
976f4a2713aSLionel Sambuc EXPECT_TRUE(
977f4a2713aSLionel Sambuc matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));
978f4a2713aSLionel Sambuc EXPECT_TRUE(
979f4a2713aSLionel Sambuc notMatches("class X {}; void y(X *x) { x; }",
980f4a2713aSLionel Sambuc expr(hasType(ClassX))));
981f4a2713aSLionel Sambuc EXPECT_TRUE(
982f4a2713aSLionel Sambuc matches("class X {}; void y(X *x) { x; }",
983f4a2713aSLionel Sambuc expr(hasType(pointsTo(ClassX)))));
984f4a2713aSLionel Sambuc }
985f4a2713aSLionel Sambuc
TEST(HasType,TakesQualTypeMatcherAndMatchesValueDecl)986f4a2713aSLionel Sambuc TEST(HasType, TakesQualTypeMatcherAndMatchesValueDecl) {
987f4a2713aSLionel Sambuc TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
988f4a2713aSLionel Sambuc EXPECT_TRUE(
989f4a2713aSLionel Sambuc matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));
990f4a2713aSLionel Sambuc EXPECT_TRUE(
991f4a2713aSLionel Sambuc notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
992f4a2713aSLionel Sambuc EXPECT_TRUE(
993f4a2713aSLionel Sambuc matches("class X {}; void y() { X *x; }",
994f4a2713aSLionel Sambuc varDecl(hasType(pointsTo(ClassX)))));
995f4a2713aSLionel Sambuc }
996f4a2713aSLionel Sambuc
TEST(HasType,TakesDeclMatcherAndMatchesExpr)997f4a2713aSLionel Sambuc TEST(HasType, TakesDeclMatcherAndMatchesExpr) {
998f4a2713aSLionel Sambuc DeclarationMatcher ClassX = recordDecl(hasName("X"));
999f4a2713aSLionel Sambuc EXPECT_TRUE(
1000f4a2713aSLionel Sambuc matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));
1001f4a2713aSLionel Sambuc EXPECT_TRUE(
1002f4a2713aSLionel Sambuc notMatches("class X {}; void y(X *x) { x; }",
1003f4a2713aSLionel Sambuc expr(hasType(ClassX))));
1004f4a2713aSLionel Sambuc }
1005f4a2713aSLionel Sambuc
TEST(HasType,TakesDeclMatcherAndMatchesValueDecl)1006f4a2713aSLionel Sambuc TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {
1007f4a2713aSLionel Sambuc DeclarationMatcher ClassX = recordDecl(hasName("X"));
1008f4a2713aSLionel Sambuc EXPECT_TRUE(
1009f4a2713aSLionel Sambuc matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));
1010f4a2713aSLionel Sambuc EXPECT_TRUE(
1011f4a2713aSLionel Sambuc notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
1012f4a2713aSLionel Sambuc }
1013f4a2713aSLionel Sambuc
TEST(HasTypeLoc,MatchesDeclaratorDecls)1014f4a2713aSLionel Sambuc TEST(HasTypeLoc, MatchesDeclaratorDecls) {
1015f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x;",
1016f4a2713aSLionel Sambuc varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
1017f4a2713aSLionel Sambuc
1018f4a2713aSLionel Sambuc // Make sure we don't crash on implicit constructors.
1019f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {}; X x;",
1020f4a2713aSLionel Sambuc declaratorDecl(hasTypeLoc(loc(asString("int"))))));
1021f4a2713aSLionel Sambuc }
1022f4a2713aSLionel Sambuc
TEST(Matcher,Call)1023f4a2713aSLionel Sambuc TEST(Matcher, Call) {
1024f4a2713aSLionel Sambuc // FIXME: Do we want to overload Call() to directly take
1025f4a2713aSLionel Sambuc // Matcher<Decl>, too?
1026f4a2713aSLionel Sambuc StatementMatcher MethodX = callExpr(hasDeclaration(methodDecl(hasName("x"))));
1027f4a2713aSLionel Sambuc
1028f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));
1029f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));
1030f4a2713aSLionel Sambuc
1031f4a2713aSLionel Sambuc StatementMatcher MethodOnY =
1032f4a2713aSLionel Sambuc memberCallExpr(on(hasType(recordDecl(hasName("Y")))));
1033f4a2713aSLionel Sambuc
1034f4a2713aSLionel Sambuc EXPECT_TRUE(
1035f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
1036f4a2713aSLionel Sambuc MethodOnY));
1037f4a2713aSLionel Sambuc EXPECT_TRUE(
1038f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
1039f4a2713aSLionel Sambuc MethodOnY));
1040f4a2713aSLionel Sambuc EXPECT_TRUE(
1041f4a2713aSLionel Sambuc notMatches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
1042f4a2713aSLionel Sambuc MethodOnY));
1043f4a2713aSLionel Sambuc EXPECT_TRUE(
1044f4a2713aSLionel Sambuc notMatches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
1045f4a2713aSLionel Sambuc MethodOnY));
1046f4a2713aSLionel Sambuc EXPECT_TRUE(
1047f4a2713aSLionel Sambuc notMatches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
1048f4a2713aSLionel Sambuc MethodOnY));
1049f4a2713aSLionel Sambuc
1050f4a2713aSLionel Sambuc StatementMatcher MethodOnYPointer =
1051f4a2713aSLionel Sambuc memberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
1052f4a2713aSLionel Sambuc
1053f4a2713aSLionel Sambuc EXPECT_TRUE(
1054f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
1055f4a2713aSLionel Sambuc MethodOnYPointer));
1056f4a2713aSLionel Sambuc EXPECT_TRUE(
1057f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
1058f4a2713aSLionel Sambuc MethodOnYPointer));
1059f4a2713aSLionel Sambuc EXPECT_TRUE(
1060f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
1061f4a2713aSLionel Sambuc MethodOnYPointer));
1062f4a2713aSLionel Sambuc EXPECT_TRUE(
1063f4a2713aSLionel Sambuc notMatches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
1064f4a2713aSLionel Sambuc MethodOnYPointer));
1065f4a2713aSLionel Sambuc EXPECT_TRUE(
1066f4a2713aSLionel Sambuc notMatches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
1067f4a2713aSLionel Sambuc MethodOnYPointer));
1068f4a2713aSLionel Sambuc }
1069f4a2713aSLionel Sambuc
TEST(Matcher,Lambda)1070f4a2713aSLionel Sambuc TEST(Matcher, Lambda) {
1071*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("auto f = [] (int i) { return i; };",
1072f4a2713aSLionel Sambuc lambdaExpr()));
1073f4a2713aSLionel Sambuc }
1074f4a2713aSLionel Sambuc
TEST(Matcher,ForRange)1075f4a2713aSLionel Sambuc TEST(Matcher, ForRange) {
1076f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int as[] = { 1, 2, 3 };"
1077f4a2713aSLionel Sambuc "void f() { for (auto &a : as); }",
1078f4a2713aSLionel Sambuc forRangeStmt()));
1079f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { for (int i; i<5; ++i); }",
1080f4a2713aSLionel Sambuc forRangeStmt()));
1081f4a2713aSLionel Sambuc }
1082f4a2713aSLionel Sambuc
TEST(Matcher,SubstNonTypeTemplateParm)1083*0a6a1f1dSLionel Sambuc TEST(Matcher, SubstNonTypeTemplateParm) {
1084*0a6a1f1dSLionel Sambuc EXPECT_FALSE(matches("template<int N>\n"
1085*0a6a1f1dSLionel Sambuc "struct A { static const int n = 0; };\n"
1086*0a6a1f1dSLionel Sambuc "struct B : public A<42> {};",
1087*0a6a1f1dSLionel Sambuc substNonTypeTemplateParmExpr()));
1088*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<int N>\n"
1089*0a6a1f1dSLionel Sambuc "struct A { static const int n = N; };\n"
1090*0a6a1f1dSLionel Sambuc "struct B : public A<42> {};",
1091*0a6a1f1dSLionel Sambuc substNonTypeTemplateParmExpr()));
1092*0a6a1f1dSLionel Sambuc }
1093*0a6a1f1dSLionel Sambuc
TEST(Matcher,UserDefinedLiteral)1094f4a2713aSLionel Sambuc TEST(Matcher, UserDefinedLiteral) {
1095f4a2713aSLionel Sambuc EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"
1096f4a2713aSLionel Sambuc " return i + 1;"
1097f4a2713aSLionel Sambuc "}"
1098f4a2713aSLionel Sambuc "char c = 'a'_inc;",
1099f4a2713aSLionel Sambuc userDefinedLiteral()));
1100f4a2713aSLionel Sambuc }
1101f4a2713aSLionel Sambuc
TEST(Matcher,FlowControl)1102f4a2713aSLionel Sambuc TEST(Matcher, FlowControl) {
1103f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { while(true) { break; } }", breakStmt()));
1104f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { while(true) { continue; } }",
1105f4a2713aSLionel Sambuc continueStmt()));
1106f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", gotoStmt()));
1107f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", labelStmt()));
1108f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { return; }", returnStmt()));
1109f4a2713aSLionel Sambuc }
1110f4a2713aSLionel Sambuc
TEST(HasType,MatchesAsString)1111f4a2713aSLionel Sambuc TEST(HasType, MatchesAsString) {
1112f4a2713aSLionel Sambuc EXPECT_TRUE(
1113f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
1114f4a2713aSLionel Sambuc memberCallExpr(on(hasType(asString("class Y *"))))));
1115f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void x(int x) {} };",
1116f4a2713aSLionel Sambuc methodDecl(hasParameter(0, hasType(asString("int"))))));
1117f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace ns { struct A {}; } struct B { ns::A a; };",
1118f4a2713aSLionel Sambuc fieldDecl(hasType(asString("ns::A")))));
1119f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace { struct A {}; } struct B { A a; };",
1120*0a6a1f1dSLionel Sambuc fieldDecl(hasType(asString("struct (anonymous namespace)::A")))));
1121f4a2713aSLionel Sambuc }
1122f4a2713aSLionel Sambuc
TEST(Matcher,OverloadedOperatorCall)1123f4a2713aSLionel Sambuc TEST(Matcher, OverloadedOperatorCall) {
1124f4a2713aSLionel Sambuc StatementMatcher OpCall = operatorCallExpr();
1125f4a2713aSLionel Sambuc // Unary operator
1126f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { }; "
1127f4a2713aSLionel Sambuc "bool operator!(Y x) { return false; }; "
1128f4a2713aSLionel Sambuc "Y y; bool c = !y;", OpCall));
1129f4a2713aSLionel Sambuc // No match -- special operators like "new", "delete"
1130f4a2713aSLionel Sambuc // FIXME: operator new takes size_t, for which we need stddef.h, for which
1131f4a2713aSLionel Sambuc // we need to figure out include paths in the test.
1132f4a2713aSLionel Sambuc // EXPECT_TRUE(NotMatches("#include <stddef.h>\n"
1133f4a2713aSLionel Sambuc // "class Y { }; "
1134f4a2713aSLionel Sambuc // "void *operator new(size_t size) { return 0; } "
1135f4a2713aSLionel Sambuc // "Y *y = new Y;", OpCall));
1136f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { }; "
1137f4a2713aSLionel Sambuc "void operator delete(void *p) { } "
1138f4a2713aSLionel Sambuc "void a() {Y *y = new Y; delete y;}", OpCall));
1139f4a2713aSLionel Sambuc // Binary operator
1140f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { }; "
1141f4a2713aSLionel Sambuc "bool operator&&(Y x, Y y) { return true; }; "
1142f4a2713aSLionel Sambuc "Y a; Y b; bool c = a && b;",
1143f4a2713aSLionel Sambuc OpCall));
1144f4a2713aSLionel Sambuc // No match -- normal operator, not an overloaded one.
1145f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("bool x = true, y = true; bool t = x && y;", OpCall));
1146f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int t = 5 << 2;", OpCall));
1147f4a2713aSLionel Sambuc }
1148f4a2713aSLionel Sambuc
TEST(Matcher,HasOperatorNameForOverloadedOperatorCall)1149f4a2713aSLionel Sambuc TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
1150f4a2713aSLionel Sambuc StatementMatcher OpCallAndAnd =
1151f4a2713aSLionel Sambuc operatorCallExpr(hasOverloadedOperatorName("&&"));
1152f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { }; "
1153f4a2713aSLionel Sambuc "bool operator&&(Y x, Y y) { return true; }; "
1154f4a2713aSLionel Sambuc "Y a; Y b; bool c = a && b;", OpCallAndAnd));
1155f4a2713aSLionel Sambuc StatementMatcher OpCallLessLess =
1156f4a2713aSLionel Sambuc operatorCallExpr(hasOverloadedOperatorName("<<"));
1157f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { }; "
1158f4a2713aSLionel Sambuc "bool operator&&(Y x, Y y) { return true; }; "
1159f4a2713aSLionel Sambuc "Y a; Y b; bool c = a && b;",
1160f4a2713aSLionel Sambuc OpCallLessLess));
1161*0a6a1f1dSLionel Sambuc StatementMatcher OpStarCall =
1162*0a6a1f1dSLionel Sambuc operatorCallExpr(hasOverloadedOperatorName("*"));
1163*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("class Y; int operator*(Y &); void f(Y &y) { *y; }",
1164*0a6a1f1dSLionel Sambuc OpStarCall));
1165f4a2713aSLionel Sambuc DeclarationMatcher ClassWithOpStar =
1166f4a2713aSLionel Sambuc recordDecl(hasMethod(hasOverloadedOperatorName("*")));
1167f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { int operator*(); };",
1168f4a2713aSLionel Sambuc ClassWithOpStar));
1169f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void myOperator(); };",
1170f4a2713aSLionel Sambuc ClassWithOpStar)) ;
1171*0a6a1f1dSLionel Sambuc DeclarationMatcher AnyOpStar = functionDecl(hasOverloadedOperatorName("*"));
1172*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("class Y; int operator*(Y &);", AnyOpStar));
1173*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("class Y { int operator*(); };", AnyOpStar));
1174f4a2713aSLionel Sambuc }
1175f4a2713aSLionel Sambuc
TEST(Matcher,NestedOverloadedOperatorCalls)1176f4a2713aSLionel Sambuc TEST(Matcher, NestedOverloadedOperatorCalls) {
1177f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
1178f4a2713aSLionel Sambuc "class Y { }; "
1179f4a2713aSLionel Sambuc "Y& operator&&(Y& x, Y& y) { return x; }; "
1180f4a2713aSLionel Sambuc "Y a; Y b; Y c; Y d = a && b && c;",
1181f4a2713aSLionel Sambuc operatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
1182f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXOperatorCallExpr>("x", 2)));
1183f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1184f4a2713aSLionel Sambuc "class Y { }; "
1185f4a2713aSLionel Sambuc "Y& operator&&(Y& x, Y& y) { return x; }; "
1186f4a2713aSLionel Sambuc "Y a; Y b; Y c; Y d = a && b && c;",
1187f4a2713aSLionel Sambuc operatorCallExpr(hasParent(operatorCallExpr()))));
1188f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1189f4a2713aSLionel Sambuc "class Y { }; "
1190f4a2713aSLionel Sambuc "Y& operator&&(Y& x, Y& y) { return x; }; "
1191f4a2713aSLionel Sambuc "Y a; Y b; Y c; Y d = a && b && c;",
1192f4a2713aSLionel Sambuc operatorCallExpr(hasDescendant(operatorCallExpr()))));
1193f4a2713aSLionel Sambuc }
1194f4a2713aSLionel Sambuc
TEST(Matcher,ThisPointerType)1195f4a2713aSLionel Sambuc TEST(Matcher, ThisPointerType) {
1196f4a2713aSLionel Sambuc StatementMatcher MethodOnY =
1197f4a2713aSLionel Sambuc memberCallExpr(thisPointerType(recordDecl(hasName("Y"))));
1198f4a2713aSLionel Sambuc
1199f4a2713aSLionel Sambuc EXPECT_TRUE(
1200f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
1201f4a2713aSLionel Sambuc MethodOnY));
1202f4a2713aSLionel Sambuc EXPECT_TRUE(
1203f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
1204f4a2713aSLionel Sambuc MethodOnY));
1205f4a2713aSLionel Sambuc EXPECT_TRUE(
1206f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
1207f4a2713aSLionel Sambuc MethodOnY));
1208f4a2713aSLionel Sambuc EXPECT_TRUE(
1209f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
1210f4a2713aSLionel Sambuc MethodOnY));
1211f4a2713aSLionel Sambuc EXPECT_TRUE(
1212f4a2713aSLionel Sambuc matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
1213f4a2713aSLionel Sambuc MethodOnY));
1214f4a2713aSLionel Sambuc
1215f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1216f4a2713aSLionel Sambuc "class Y {"
1217f4a2713aSLionel Sambuc " public: virtual void x();"
1218f4a2713aSLionel Sambuc "};"
1219f4a2713aSLionel Sambuc "class X : public Y {"
1220f4a2713aSLionel Sambuc " public: virtual void x();"
1221f4a2713aSLionel Sambuc "};"
1222f4a2713aSLionel Sambuc "void z() { X *x; x->Y::x(); }", MethodOnY));
1223f4a2713aSLionel Sambuc }
1224f4a2713aSLionel Sambuc
TEST(Matcher,VariableUsage)1225f4a2713aSLionel Sambuc TEST(Matcher, VariableUsage) {
1226f4a2713aSLionel Sambuc StatementMatcher Reference =
1227f4a2713aSLionel Sambuc declRefExpr(to(
1228f4a2713aSLionel Sambuc varDecl(hasInitializer(
1229f4a2713aSLionel Sambuc memberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
1230f4a2713aSLionel Sambuc
1231f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1232f4a2713aSLionel Sambuc "class Y {"
1233f4a2713aSLionel Sambuc " public:"
1234f4a2713aSLionel Sambuc " bool x() const;"
1235f4a2713aSLionel Sambuc "};"
1236f4a2713aSLionel Sambuc "void z(const Y &y) {"
1237f4a2713aSLionel Sambuc " bool b = y.x();"
1238f4a2713aSLionel Sambuc " if (b) {}"
1239f4a2713aSLionel Sambuc "}", Reference));
1240f4a2713aSLionel Sambuc
1241f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
1242f4a2713aSLionel Sambuc "class Y {"
1243f4a2713aSLionel Sambuc " public:"
1244f4a2713aSLionel Sambuc " bool x() const;"
1245f4a2713aSLionel Sambuc "};"
1246f4a2713aSLionel Sambuc "void z(const Y &y) {"
1247f4a2713aSLionel Sambuc " bool b = y.x();"
1248f4a2713aSLionel Sambuc "}", Reference));
1249f4a2713aSLionel Sambuc }
1250f4a2713aSLionel Sambuc
TEST(Matcher,VarDecl_Storage)1251*0a6a1f1dSLionel Sambuc TEST(Matcher, VarDecl_Storage) {
1252*0a6a1f1dSLionel Sambuc auto M = varDecl(hasName("X"), hasLocalStorage());
1253*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { int X; }", M));
1254*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("int X;", M));
1255*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void f() { static int X; }", M));
1256*0a6a1f1dSLionel Sambuc
1257*0a6a1f1dSLionel Sambuc M = varDecl(hasName("X"), hasGlobalStorage());
1258*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void f() { int X; }", M));
1259*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("int X;", M));
1260*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { static int X; }", M));
1261*0a6a1f1dSLionel Sambuc }
1262*0a6a1f1dSLionel Sambuc
TEST(Matcher,FindsVarDeclInFunctionParameter)1263f4a2713aSLionel Sambuc TEST(Matcher, FindsVarDeclInFunctionParameter) {
1264f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1265f4a2713aSLionel Sambuc "void f(int i) {}",
1266f4a2713aSLionel Sambuc varDecl(hasName("i"))));
1267f4a2713aSLionel Sambuc }
1268f4a2713aSLionel Sambuc
TEST(Matcher,CalledVariable)1269f4a2713aSLionel Sambuc TEST(Matcher, CalledVariable) {
1270f4a2713aSLionel Sambuc StatementMatcher CallOnVariableY =
1271f4a2713aSLionel Sambuc memberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
1272f4a2713aSLionel Sambuc
1273f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1274f4a2713aSLionel Sambuc "class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY));
1275f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1276f4a2713aSLionel Sambuc "class Y { public: void x() const { Y y; y.x(); } };", CallOnVariableY));
1277f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1278f4a2713aSLionel Sambuc "class Y { public: void x(); };"
1279f4a2713aSLionel Sambuc "class X : public Y { void z() { X y; y.x(); } };", CallOnVariableY));
1280f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1281f4a2713aSLionel Sambuc "class Y { public: void x(); };"
1282f4a2713aSLionel Sambuc "class X : public Y { void z() { X *y; y->x(); } };", CallOnVariableY));
1283f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
1284f4a2713aSLionel Sambuc "class Y { public: void x(); };"
1285f4a2713aSLionel Sambuc "class X : public Y { void z() { unsigned long y; ((X*)y)->x(); } };",
1286f4a2713aSLionel Sambuc CallOnVariableY));
1287f4a2713aSLionel Sambuc }
1288f4a2713aSLionel Sambuc
TEST(UnaryExprOrTypeTraitExpr,MatchesSizeOfAndAlignOf)1289f4a2713aSLionel Sambuc TEST(UnaryExprOrTypeTraitExpr, MatchesSizeOfAndAlignOf) {
1290f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { int a = sizeof(a); }",
1291f4a2713aSLionel Sambuc unaryExprOrTypeTraitExpr()));
1292f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }",
1293f4a2713aSLionel Sambuc alignOfExpr(anything())));
1294f4a2713aSLionel Sambuc // FIXME: Uncomment once alignof is enabled.
1295f4a2713aSLionel Sambuc // EXPECT_TRUE(matches("void x() { int a = alignof(a); }",
1296f4a2713aSLionel Sambuc // unaryExprOrTypeTraitExpr()));
1297f4a2713aSLionel Sambuc // EXPECT_TRUE(notMatches("void x() { int a = alignof(a); }",
1298f4a2713aSLionel Sambuc // sizeOfExpr()));
1299f4a2713aSLionel Sambuc }
1300f4a2713aSLionel Sambuc
TEST(UnaryExpressionOrTypeTraitExpression,MatchesCorrectType)1301f4a2713aSLionel Sambuc TEST(UnaryExpressionOrTypeTraitExpression, MatchesCorrectType) {
1302f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { int a = sizeof(a); }", sizeOfExpr(
1303f4a2713aSLionel Sambuc hasArgumentOfType(asString("int")))));
1304f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr(
1305f4a2713aSLionel Sambuc hasArgumentOfType(asString("float")))));
1306f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1307f4a2713aSLionel Sambuc "struct A {}; void x() { A a; int b = sizeof(a); }",
1308f4a2713aSLionel Sambuc sizeOfExpr(hasArgumentOfType(hasDeclaration(recordDecl(hasName("A")))))));
1309f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr(
1310f4a2713aSLionel Sambuc hasArgumentOfType(hasDeclaration(recordDecl(hasName("string")))))));
1311f4a2713aSLionel Sambuc }
1312f4a2713aSLionel Sambuc
TEST(MemberExpression,DoesNotMatchClasses)1313f4a2713aSLionel Sambuc TEST(MemberExpression, DoesNotMatchClasses) {
1314f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpr()));
1315f4a2713aSLionel Sambuc }
1316f4a2713aSLionel Sambuc
TEST(MemberExpression,MatchesMemberFunctionCall)1317f4a2713aSLionel Sambuc TEST(MemberExpression, MatchesMemberFunctionCall) {
1318f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr()));
1319f4a2713aSLionel Sambuc }
1320f4a2713aSLionel Sambuc
TEST(MemberExpression,MatchesVariable)1321f4a2713aSLionel Sambuc TEST(MemberExpression, MatchesVariable) {
1322f4a2713aSLionel Sambuc EXPECT_TRUE(
1323f4a2713aSLionel Sambuc matches("class Y { void x() { this->y; } int y; };", memberExpr()));
1324f4a2713aSLionel Sambuc EXPECT_TRUE(
1325f4a2713aSLionel Sambuc matches("class Y { void x() { y; } int y; };", memberExpr()));
1326f4a2713aSLionel Sambuc EXPECT_TRUE(
1327f4a2713aSLionel Sambuc matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));
1328f4a2713aSLionel Sambuc }
1329f4a2713aSLionel Sambuc
TEST(MemberExpression,MatchesStaticVariable)1330f4a2713aSLionel Sambuc TEST(MemberExpression, MatchesStaticVariable) {
1331f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
1332f4a2713aSLionel Sambuc memberExpr()));
1333f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
1334f4a2713aSLionel Sambuc memberExpr()));
1335f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() { Y::y; } static int y; };",
1336f4a2713aSLionel Sambuc memberExpr()));
1337f4a2713aSLionel Sambuc }
1338f4a2713aSLionel Sambuc
TEST(IsInteger,MatchesIntegers)1339f4a2713aSLionel Sambuc TEST(IsInteger, MatchesIntegers) {
1340f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isInteger()))));
1341f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1342f4a2713aSLionel Sambuc "long long i = 0; void f(long long) { }; void g() {f(i);}",
1343f4a2713aSLionel Sambuc callExpr(hasArgument(0, declRefExpr(
1344f4a2713aSLionel Sambuc to(varDecl(hasType(isInteger()))))))));
1345f4a2713aSLionel Sambuc }
1346f4a2713aSLionel Sambuc
TEST(IsInteger,ReportsNoFalsePositives)1347f4a2713aSLionel Sambuc TEST(IsInteger, ReportsNoFalsePositives) {
1348f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int *i;", varDecl(hasType(isInteger()))));
1349f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}",
1350f4a2713aSLionel Sambuc callExpr(hasArgument(0, declRefExpr(
1351f4a2713aSLionel Sambuc to(varDecl(hasType(isInteger()))))))));
1352f4a2713aSLionel Sambuc }
1353f4a2713aSLionel Sambuc
TEST(IsArrow,MatchesMemberVariablesViaArrow)1354f4a2713aSLionel Sambuc TEST(IsArrow, MatchesMemberVariablesViaArrow) {
1355f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
1356f4a2713aSLionel Sambuc memberExpr(isArrow())));
1357f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { y; } int y; };",
1358f4a2713aSLionel Sambuc memberExpr(isArrow())));
1359f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
1360f4a2713aSLionel Sambuc memberExpr(isArrow())));
1361f4a2713aSLionel Sambuc }
1362f4a2713aSLionel Sambuc
TEST(IsArrow,MatchesStaticMemberVariablesViaArrow)1363f4a2713aSLionel Sambuc TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) {
1364f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
1365f4a2713aSLionel Sambuc memberExpr(isArrow())));
1366f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
1367f4a2713aSLionel Sambuc memberExpr(isArrow())));
1368f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } static int y; };",
1369f4a2713aSLionel Sambuc memberExpr(isArrow())));
1370f4a2713aSLionel Sambuc }
1371f4a2713aSLionel Sambuc
TEST(IsArrow,MatchesMemberCallsViaArrow)1372f4a2713aSLionel Sambuc TEST(IsArrow, MatchesMemberCallsViaArrow) {
1373f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
1374f4a2713aSLionel Sambuc memberExpr(isArrow())));
1375f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { x(); } };",
1376f4a2713aSLionel Sambuc memberExpr(isArrow())));
1377f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
1378f4a2713aSLionel Sambuc memberExpr(isArrow())));
1379f4a2713aSLionel Sambuc }
1380f4a2713aSLionel Sambuc
TEST(Callee,MatchesDeclarations)1381f4a2713aSLionel Sambuc TEST(Callee, MatchesDeclarations) {
1382f4a2713aSLionel Sambuc StatementMatcher CallMethodX = callExpr(callee(methodDecl(hasName("x"))));
1383f4a2713aSLionel Sambuc
1384f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));
1385f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));
1386f4a2713aSLionel Sambuc }
1387f4a2713aSLionel Sambuc
TEST(Callee,MatchesMemberExpressions)1388f4a2713aSLionel Sambuc TEST(Callee, MatchesMemberExpressions) {
1389f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
1390f4a2713aSLionel Sambuc callExpr(callee(memberExpr()))));
1391f4a2713aSLionel Sambuc EXPECT_TRUE(
1392f4a2713aSLionel Sambuc notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));
1393f4a2713aSLionel Sambuc }
1394f4a2713aSLionel Sambuc
TEST(Function,MatchesFunctionDeclarations)1395f4a2713aSLionel Sambuc TEST(Function, MatchesFunctionDeclarations) {
1396f4a2713aSLionel Sambuc StatementMatcher CallFunctionF = callExpr(callee(functionDecl(hasName("f"))));
1397f4a2713aSLionel Sambuc
1398f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { f(); }", CallFunctionF));
1399f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { }", CallFunctionF));
1400f4a2713aSLionel Sambuc
1401*0a6a1f1dSLionel Sambuc if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getOS() !=
1402*0a6a1f1dSLionel Sambuc llvm::Triple::Win32) {
1403f4a2713aSLionel Sambuc // FIXME: Make this work for MSVC.
1404f4a2713aSLionel Sambuc // Dependent contexts, but a non-dependent call.
1405f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(); template <int N> void g() { f(); }",
1406f4a2713aSLionel Sambuc CallFunctionF));
1407f4a2713aSLionel Sambuc EXPECT_TRUE(
1408f4a2713aSLionel Sambuc matches("void f(); template <int N> struct S { void g() { f(); } };",
1409f4a2713aSLionel Sambuc CallFunctionF));
1410*0a6a1f1dSLionel Sambuc }
1411f4a2713aSLionel Sambuc
1412f4a2713aSLionel Sambuc // Depedent calls don't match.
1413f4a2713aSLionel Sambuc EXPECT_TRUE(
1414f4a2713aSLionel Sambuc notMatches("void f(int); template <typename T> void g(T t) { f(t); }",
1415f4a2713aSLionel Sambuc CallFunctionF));
1416f4a2713aSLionel Sambuc EXPECT_TRUE(
1417f4a2713aSLionel Sambuc notMatches("void f(int);"
1418f4a2713aSLionel Sambuc "template <typename T> struct S { void g(T t) { f(t); } };",
1419f4a2713aSLionel Sambuc CallFunctionF));
1420f4a2713aSLionel Sambuc }
1421f4a2713aSLionel Sambuc
TEST(FunctionTemplate,MatchesFunctionTemplateDeclarations)1422f4a2713aSLionel Sambuc TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
1423f4a2713aSLionel Sambuc EXPECT_TRUE(
1424f4a2713aSLionel Sambuc matches("template <typename T> void f(T t) {}",
1425f4a2713aSLionel Sambuc functionTemplateDecl(hasName("f"))));
1426f4a2713aSLionel Sambuc }
1427f4a2713aSLionel Sambuc
TEST(FunctionTemplate,DoesNotMatchFunctionDeclarations)1428f4a2713aSLionel Sambuc TEST(FunctionTemplate, DoesNotMatchFunctionDeclarations) {
1429f4a2713aSLionel Sambuc EXPECT_TRUE(
1430f4a2713aSLionel Sambuc notMatches("void f(double d); void f(int t) {}",
1431f4a2713aSLionel Sambuc functionTemplateDecl(hasName("f"))));
1432f4a2713aSLionel Sambuc }
1433f4a2713aSLionel Sambuc
TEST(FunctionTemplate,DoesNotMatchFunctionTemplateSpecializations)1434f4a2713aSLionel Sambuc TEST(FunctionTemplate, DoesNotMatchFunctionTemplateSpecializations) {
1435f4a2713aSLionel Sambuc EXPECT_TRUE(
1436f4a2713aSLionel Sambuc notMatches("void g(); template <typename T> void f(T t) {}"
1437f4a2713aSLionel Sambuc "template <> void f(int t) { g(); }",
1438f4a2713aSLionel Sambuc functionTemplateDecl(hasName("f"),
1439f4a2713aSLionel Sambuc hasDescendant(declRefExpr(to(
1440f4a2713aSLionel Sambuc functionDecl(hasName("g"))))))));
1441f4a2713aSLionel Sambuc }
1442f4a2713aSLionel Sambuc
TEST(Matcher,Argument)1443f4a2713aSLionel Sambuc TEST(Matcher, Argument) {
1444f4a2713aSLionel Sambuc StatementMatcher CallArgumentY = callExpr(
1445f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
1446f4a2713aSLionel Sambuc
1447f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY));
1448f4a2713aSLionel Sambuc EXPECT_TRUE(
1449f4a2713aSLionel Sambuc matches("class X { void x(int) { int y; x(y); } };", CallArgumentY));
1450f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY));
1451f4a2713aSLionel Sambuc
1452f4a2713aSLionel Sambuc StatementMatcher WrongIndex = callExpr(
1453f4a2713aSLionel Sambuc hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
1454f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex));
1455f4a2713aSLionel Sambuc }
1456f4a2713aSLionel Sambuc
TEST(Matcher,AnyArgument)1457f4a2713aSLionel Sambuc TEST(Matcher, AnyArgument) {
1458f4a2713aSLionel Sambuc StatementMatcher CallArgumentY = callExpr(
1459f4a2713aSLionel Sambuc hasAnyArgument(declRefExpr(to(varDecl(hasName("y"))))));
1460f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
1461f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
1462f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
1463f4a2713aSLionel Sambuc }
1464f4a2713aSLionel Sambuc
TEST(Matcher,ArgumentCount)1465f4a2713aSLionel Sambuc TEST(Matcher, ArgumentCount) {
1466f4a2713aSLionel Sambuc StatementMatcher Call1Arg = callExpr(argumentCountIs(1));
1467f4a2713aSLionel Sambuc
1468f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x(int) { x(0); }", Call1Arg));
1469f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void x(int) { x(0); } };", Call1Arg));
1470f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x(int, int) { x(0, 0); }", Call1Arg));
1471f4a2713aSLionel Sambuc }
1472f4a2713aSLionel Sambuc
TEST(Matcher,ParameterCount)1473f4a2713aSLionel Sambuc TEST(Matcher, ParameterCount) {
1474f4a2713aSLionel Sambuc DeclarationMatcher Function1Arg = functionDecl(parameterCountIs(1));
1475f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(int i) {}", Function1Arg));
1476f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void f(int i) {} };", Function1Arg));
1477f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {}", Function1Arg));
1478f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f(int i, int j, int k) {}", Function1Arg));
1479f4a2713aSLionel Sambuc }
1480f4a2713aSLionel Sambuc
TEST(Matcher,References)1481f4a2713aSLionel Sambuc TEST(Matcher, References) {
1482f4a2713aSLionel Sambuc DeclarationMatcher ReferenceClassX = varDecl(
1483f4a2713aSLionel Sambuc hasType(references(recordDecl(hasName("X")))));
1484f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; void y(X y) { X &x = y; }",
1485f4a2713aSLionel Sambuc ReferenceClassX));
1486f4a2713aSLionel Sambuc EXPECT_TRUE(
1487f4a2713aSLionel Sambuc matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX));
1488f4a2713aSLionel Sambuc // The match here is on the implicit copy constructor code for
1489f4a2713aSLionel Sambuc // class X, not on code 'X x = y'.
1490f4a2713aSLionel Sambuc EXPECT_TRUE(
1491f4a2713aSLionel Sambuc matches("class X {}; void y(X y) { X x = y; }", ReferenceClassX));
1492f4a2713aSLionel Sambuc EXPECT_TRUE(
1493f4a2713aSLionel Sambuc notMatches("class X {}; extern X x;", ReferenceClassX));
1494f4a2713aSLionel Sambuc EXPECT_TRUE(
1495f4a2713aSLionel Sambuc notMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX));
1496f4a2713aSLionel Sambuc }
1497f4a2713aSLionel Sambuc
TEST(QualType,hasCanonicalType)1498f4a2713aSLionel Sambuc TEST(QualType, hasCanonicalType) {
1499f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("typedef int &int_ref;"
1500f4a2713aSLionel Sambuc "int a;"
1501f4a2713aSLionel Sambuc "int_ref b = a;",
1502f4a2713aSLionel Sambuc varDecl(hasType(qualType(referenceType())))));
1503f4a2713aSLionel Sambuc EXPECT_TRUE(
1504f4a2713aSLionel Sambuc matches("typedef int &int_ref;"
1505f4a2713aSLionel Sambuc "int a;"
1506f4a2713aSLionel Sambuc "int_ref b = a;",
1507f4a2713aSLionel Sambuc varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));
1508f4a2713aSLionel Sambuc }
1509f4a2713aSLionel Sambuc
TEST(QualType,hasLocalQualifiers)1510f4a2713aSLionel Sambuc TEST(QualType, hasLocalQualifiers) {
1511f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("typedef const int const_int; const_int i = 1;",
1512f4a2713aSLionel Sambuc varDecl(hasType(hasLocalQualifiers()))));
1513f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int *const j = nullptr;",
1514f4a2713aSLionel Sambuc varDecl(hasType(hasLocalQualifiers()))));
1515f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int *volatile k;",
1516f4a2713aSLionel Sambuc varDecl(hasType(hasLocalQualifiers()))));
1517f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int m;",
1518f4a2713aSLionel Sambuc varDecl(hasType(hasLocalQualifiers()))));
1519f4a2713aSLionel Sambuc }
1520f4a2713aSLionel Sambuc
TEST(HasParameter,CallsInnerMatcher)1521f4a2713aSLionel Sambuc TEST(HasParameter, CallsInnerMatcher) {
1522f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void x(int) {} };",
1523f4a2713aSLionel Sambuc methodDecl(hasParameter(0, varDecl()))));
1524f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1525f4a2713aSLionel Sambuc methodDecl(hasParameter(0, hasName("x")))));
1526f4a2713aSLionel Sambuc }
1527f4a2713aSLionel Sambuc
TEST(HasParameter,DoesNotMatchIfIndexOutOfBounds)1528f4a2713aSLionel Sambuc TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
1529f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1530f4a2713aSLionel Sambuc methodDecl(hasParameter(42, varDecl()))));
1531f4a2713aSLionel Sambuc }
1532f4a2713aSLionel Sambuc
TEST(HasType,MatchesParameterVariableTypesStrictly)1533f4a2713aSLionel Sambuc TEST(HasType, MatchesParameterVariableTypesStrictly) {
1534f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void x(X x) {} };",
1535f4a2713aSLionel Sambuc methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1536f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { void x(const X &x) {} };",
1537f4a2713aSLionel Sambuc methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1538f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
1539f4a2713aSLionel Sambuc methodDecl(hasParameter(0,
1540f4a2713aSLionel Sambuc hasType(pointsTo(recordDecl(hasName("X"))))))));
1541f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
1542f4a2713aSLionel Sambuc methodDecl(hasParameter(0,
1543f4a2713aSLionel Sambuc hasType(references(recordDecl(hasName("X"))))))));
1544f4a2713aSLionel Sambuc }
1545f4a2713aSLionel Sambuc
TEST(HasAnyParameter,MatchesIndependentlyOfPosition)1546f4a2713aSLionel Sambuc TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
1547f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y {}; class X { void x(X x, Y y) {} };",
1548f4a2713aSLionel Sambuc methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1549f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y {}; class X { void x(Y y, X x) {} };",
1550f4a2713aSLionel Sambuc methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1551f4a2713aSLionel Sambuc }
1552f4a2713aSLionel Sambuc
TEST(Returns,MatchesReturnTypes)1553f4a2713aSLionel Sambuc TEST(Returns, MatchesReturnTypes) {
1554f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { int f() { return 1; } };",
1555f4a2713aSLionel Sambuc functionDecl(returns(asString("int")))));
1556f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",
1557f4a2713aSLionel Sambuc functionDecl(returns(asString("float")))));
1558f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",
1559f4a2713aSLionel Sambuc functionDecl(returns(hasDeclaration(
1560f4a2713aSLionel Sambuc recordDecl(hasName("Y")))))));
1561f4a2713aSLionel Sambuc }
1562f4a2713aSLionel Sambuc
TEST(IsExternC,MatchesExternCFunctionDeclarations)1563f4a2713aSLionel Sambuc TEST(IsExternC, MatchesExternCFunctionDeclarations) {
1564f4a2713aSLionel Sambuc EXPECT_TRUE(matches("extern \"C\" void f() {}", functionDecl(isExternC())));
1565f4a2713aSLionel Sambuc EXPECT_TRUE(matches("extern \"C\" { void f() {} }",
1566f4a2713aSLionel Sambuc functionDecl(isExternC())));
1567f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {}", functionDecl(isExternC())));
1568f4a2713aSLionel Sambuc }
1569f4a2713aSLionel Sambuc
TEST(IsDeleted,MatchesDeletedFunctionDeclarations)1570*0a6a1f1dSLionel Sambuc TEST(IsDeleted, MatchesDeletedFunctionDeclarations) {
1571*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
1572*0a6a1f1dSLionel Sambuc notMatches("void Func();", functionDecl(hasName("Func"), isDeleted())));
1573*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void Func() = delete;",
1574*0a6a1f1dSLionel Sambuc functionDecl(hasName("Func"), isDeleted())));
1575*0a6a1f1dSLionel Sambuc }
1576*0a6a1f1dSLionel Sambuc
TEST(HasAnyParameter,DoesntMatchIfInnerMatcherDoesntMatch)1577f4a2713aSLionel Sambuc TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
1578f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
1579f4a2713aSLionel Sambuc methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1580f4a2713aSLionel Sambuc }
1581f4a2713aSLionel Sambuc
TEST(HasAnyParameter,DoesNotMatchThisPointer)1582f4a2713aSLionel Sambuc TEST(HasAnyParameter, DoesNotMatchThisPointer) {
1583f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
1584f4a2713aSLionel Sambuc methodDecl(hasAnyParameter(hasType(pointsTo(
1585f4a2713aSLionel Sambuc recordDecl(hasName("X"))))))));
1586f4a2713aSLionel Sambuc }
1587f4a2713aSLionel Sambuc
TEST(HasName,MatchesParameterVariableDeclarations)1588*0a6a1f1dSLionel Sambuc TEST(HasName, MatchesParameterVariableDeclarations) {
1589f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
1590f4a2713aSLionel Sambuc methodDecl(hasAnyParameter(hasName("x")))));
1591f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
1592f4a2713aSLionel Sambuc methodDecl(hasAnyParameter(hasName("x")))));
1593f4a2713aSLionel Sambuc }
1594f4a2713aSLionel Sambuc
TEST(Matcher,MatchesClassTemplateSpecialization)1595f4a2713aSLionel Sambuc TEST(Matcher, MatchesClassTemplateSpecialization) {
1596f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template<typename T> struct A {};"
1597f4a2713aSLionel Sambuc "template<> struct A<int> {};",
1598f4a2713aSLionel Sambuc classTemplateSpecializationDecl()));
1599f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template<typename T> struct A {}; A<int> a;",
1600f4a2713aSLionel Sambuc classTemplateSpecializationDecl()));
1601f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> struct A {};",
1602f4a2713aSLionel Sambuc classTemplateSpecializationDecl()));
1603f4a2713aSLionel Sambuc }
1604f4a2713aSLionel Sambuc
TEST(DeclaratorDecl,MatchesDeclaratorDecls)1605f4a2713aSLionel Sambuc TEST(DeclaratorDecl, MatchesDeclaratorDecls) {
1606f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x;", declaratorDecl()));
1607f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A {};", declaratorDecl()));
1608f4a2713aSLionel Sambuc }
1609f4a2713aSLionel Sambuc
TEST(ParmVarDecl,MatchesParmVars)1610f4a2713aSLionel Sambuc TEST(ParmVarDecl, MatchesParmVars) {
1611f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(int x);", parmVarDecl()));
1612f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f();", parmVarDecl()));
1613f4a2713aSLionel Sambuc }
1614f4a2713aSLionel Sambuc
TEST(Matcher,MatchesTypeTemplateArgument)1615f4a2713aSLionel Sambuc TEST(Matcher, MatchesTypeTemplateArgument) {
1616f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1617f4a2713aSLionel Sambuc "template<typename T> struct B {};"
1618f4a2713aSLionel Sambuc "B<int> b;",
1619f4a2713aSLionel Sambuc classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
1620f4a2713aSLionel Sambuc asString("int"))))));
1621f4a2713aSLionel Sambuc }
1622f4a2713aSLionel Sambuc
TEST(Matcher,MatchesDeclarationReferenceTemplateArgument)1623f4a2713aSLionel Sambuc TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {
1624f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1625f4a2713aSLionel Sambuc "struct B { int next; };"
1626f4a2713aSLionel Sambuc "template<int(B::*next_ptr)> struct A {};"
1627f4a2713aSLionel Sambuc "A<&B::next> a;",
1628f4a2713aSLionel Sambuc classTemplateSpecializationDecl(hasAnyTemplateArgument(
1629f4a2713aSLionel Sambuc refersToDeclaration(fieldDecl(hasName("next")))))));
1630f4a2713aSLionel Sambuc
1631f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
1632f4a2713aSLionel Sambuc "template <typename T> struct A {};"
1633f4a2713aSLionel Sambuc "A<int> a;",
1634f4a2713aSLionel Sambuc classTemplateSpecializationDecl(hasAnyTemplateArgument(
1635f4a2713aSLionel Sambuc refersToDeclaration(decl())))));
1636*0a6a1f1dSLionel Sambuc
1637*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches(
1638*0a6a1f1dSLionel Sambuc "struct B { int next; };"
1639*0a6a1f1dSLionel Sambuc "template<int(B::*next_ptr)> struct A {};"
1640*0a6a1f1dSLionel Sambuc "A<&B::next> a;",
1641*0a6a1f1dSLionel Sambuc templateSpecializationType(hasAnyTemplateArgument(isExpr(
1642*0a6a1f1dSLionel Sambuc hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));
1643*0a6a1f1dSLionel Sambuc
1644*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches(
1645*0a6a1f1dSLionel Sambuc "template <typename T> struct A {};"
1646*0a6a1f1dSLionel Sambuc "A<int> a;",
1647*0a6a1f1dSLionel Sambuc templateSpecializationType(hasAnyTemplateArgument(
1648*0a6a1f1dSLionel Sambuc refersToDeclaration(decl())))));
1649f4a2713aSLionel Sambuc }
1650f4a2713aSLionel Sambuc
TEST(Matcher,MatchesSpecificArgument)1651f4a2713aSLionel Sambuc TEST(Matcher, MatchesSpecificArgument) {
1652f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1653f4a2713aSLionel Sambuc "template<typename T, typename U> class A {};"
1654f4a2713aSLionel Sambuc "A<bool, int> a;",
1655f4a2713aSLionel Sambuc classTemplateSpecializationDecl(hasTemplateArgument(
1656f4a2713aSLionel Sambuc 1, refersToType(asString("int"))))));
1657f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
1658f4a2713aSLionel Sambuc "template<typename T, typename U> class A {};"
1659f4a2713aSLionel Sambuc "A<int, bool> a;",
1660f4a2713aSLionel Sambuc classTemplateSpecializationDecl(hasTemplateArgument(
1661f4a2713aSLionel Sambuc 1, refersToType(asString("int"))))));
1662*0a6a1f1dSLionel Sambuc
1663*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches(
1664*0a6a1f1dSLionel Sambuc "template<typename T, typename U> class A {};"
1665*0a6a1f1dSLionel Sambuc "A<bool, int> a;",
1666*0a6a1f1dSLionel Sambuc templateSpecializationType(hasTemplateArgument(
1667*0a6a1f1dSLionel Sambuc 1, refersToType(asString("int"))))));
1668*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches(
1669*0a6a1f1dSLionel Sambuc "template<typename T, typename U> class A {};"
1670*0a6a1f1dSLionel Sambuc "A<int, bool> a;",
1671*0a6a1f1dSLionel Sambuc templateSpecializationType(hasTemplateArgument(
1672*0a6a1f1dSLionel Sambuc 1, refersToType(asString("int"))))));
1673*0a6a1f1dSLionel Sambuc }
1674*0a6a1f1dSLionel Sambuc
TEST(TemplateArgument,Matches)1675*0a6a1f1dSLionel Sambuc TEST(TemplateArgument, Matches) {
1676*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
1677*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(
1678*0a6a1f1dSLionel Sambuc hasAnyTemplateArgument(templateArgument()))));
1679*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches(
1680*0a6a1f1dSLionel Sambuc "template<typename T> struct C {}; C<int> c;",
1681*0a6a1f1dSLionel Sambuc templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
1682*0a6a1f1dSLionel Sambuc }
1683*0a6a1f1dSLionel Sambuc
TEST(TemplateArgumentCountIs,Matches)1684*0a6a1f1dSLionel Sambuc TEST(TemplateArgumentCountIs, Matches) {
1685*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
1686*0a6a1f1dSLionel Sambuc matches("template<typename T> struct C {}; C<int> c;",
1687*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(templateArgumentCountIs(1))));
1688*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
1689*0a6a1f1dSLionel Sambuc notMatches("template<typename T> struct C {}; C<int> c;",
1690*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(templateArgumentCountIs(2))));
1691*0a6a1f1dSLionel Sambuc
1692*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
1693*0a6a1f1dSLionel Sambuc templateSpecializationType(templateArgumentCountIs(1))));
1694*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
1695*0a6a1f1dSLionel Sambuc notMatches("template<typename T> struct C {}; C<int> c;",
1696*0a6a1f1dSLionel Sambuc templateSpecializationType(templateArgumentCountIs(2))));
1697*0a6a1f1dSLionel Sambuc }
1698*0a6a1f1dSLionel Sambuc
TEST(IsIntegral,Matches)1699*0a6a1f1dSLionel Sambuc TEST(IsIntegral, Matches) {
1700*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1701*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(
1702*0a6a1f1dSLionel Sambuc hasAnyTemplateArgument(isIntegral()))));
1703*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> struct C {}; C<int> c;",
1704*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(hasAnyTemplateArgument(
1705*0a6a1f1dSLionel Sambuc templateArgument(isIntegral())))));
1706*0a6a1f1dSLionel Sambuc }
1707*0a6a1f1dSLionel Sambuc
TEST(RefersToIntegralType,Matches)1708*0a6a1f1dSLionel Sambuc TEST(RefersToIntegralType, Matches) {
1709*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1710*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(
1711*0a6a1f1dSLionel Sambuc hasAnyTemplateArgument(refersToIntegralType(
1712*0a6a1f1dSLionel Sambuc asString("int"))))));
1713*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",
1714*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(hasAnyTemplateArgument(
1715*0a6a1f1dSLionel Sambuc refersToIntegralType(asString("int"))))));
1716*0a6a1f1dSLionel Sambuc }
1717*0a6a1f1dSLionel Sambuc
TEST(EqualsIntegralValue,Matches)1718*0a6a1f1dSLionel Sambuc TEST(EqualsIntegralValue, Matches) {
1719*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1720*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(
1721*0a6a1f1dSLionel Sambuc hasAnyTemplateArgument(equalsIntegralValue("42")))));
1722*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<int T> struct C {}; C<-42> c;",
1723*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(
1724*0a6a1f1dSLionel Sambuc hasAnyTemplateArgument(equalsIntegralValue("-42")))));
1725*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<int T> struct C {}; C<-0042> c;",
1726*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(
1727*0a6a1f1dSLionel Sambuc hasAnyTemplateArgument(equalsIntegralValue("-34")))));
1728*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<int T> struct C {}; C<42> c;",
1729*0a6a1f1dSLionel Sambuc classTemplateSpecializationDecl(hasAnyTemplateArgument(
1730*0a6a1f1dSLionel Sambuc equalsIntegralValue("0042")))));
1731f4a2713aSLionel Sambuc }
1732f4a2713aSLionel Sambuc
TEST(Matcher,MatchesAccessSpecDecls)1733f4a2713aSLionel Sambuc TEST(Matcher, MatchesAccessSpecDecls) {
1734f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class C { public: int i; };", accessSpecDecl()));
1735f4a2713aSLionel Sambuc EXPECT_TRUE(
1736f4a2713aSLionel Sambuc matches("class C { public: int i; };", accessSpecDecl(isPublic())));
1737f4a2713aSLionel Sambuc EXPECT_TRUE(
1738f4a2713aSLionel Sambuc notMatches("class C { public: int i; };", accessSpecDecl(isProtected())));
1739f4a2713aSLionel Sambuc EXPECT_TRUE(
1740f4a2713aSLionel Sambuc notMatches("class C { public: int i; };", accessSpecDecl(isPrivate())));
1741f4a2713aSLionel Sambuc
1742f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class C { int i; };", accessSpecDecl()));
1743f4a2713aSLionel Sambuc }
1744f4a2713aSLionel Sambuc
TEST(Matcher,MatchesVirtualMethod)1745f4a2713aSLionel Sambuc TEST(Matcher, MatchesVirtualMethod) {
1746f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { virtual int f(); };",
1747f4a2713aSLionel Sambuc methodDecl(isVirtual(), hasName("::X::f"))));
1748f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { int f(); };",
1749f4a2713aSLionel Sambuc methodDecl(isVirtual())));
1750f4a2713aSLionel Sambuc }
1751f4a2713aSLionel Sambuc
TEST(Matcher,MatchesPureMethod)1752*0a6a1f1dSLionel Sambuc TEST(Matcher, MatchesPureMethod) {
1753*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("class X { virtual int f() = 0; };",
1754*0a6a1f1dSLionel Sambuc methodDecl(isPure(), hasName("::X::f"))));
1755*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("class X { int f(); };",
1756*0a6a1f1dSLionel Sambuc methodDecl(isPure())));
1757*0a6a1f1dSLionel Sambuc }
1758*0a6a1f1dSLionel Sambuc
TEST(Matcher,MatchesConstMethod)1759f4a2713aSLionel Sambuc TEST(Matcher, MatchesConstMethod) {
1760f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct A { void foo() const; };",
1761f4a2713aSLionel Sambuc methodDecl(isConst())));
1762f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct A { void foo(); };",
1763f4a2713aSLionel Sambuc methodDecl(isConst())));
1764f4a2713aSLionel Sambuc }
1765f4a2713aSLionel Sambuc
TEST(Matcher,MatchesOverridingMethod)1766f4a2713aSLionel Sambuc TEST(Matcher, MatchesOverridingMethod) {
1767f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { virtual int f(); }; "
1768f4a2713aSLionel Sambuc "class Y : public X { int f(); };",
1769f4a2713aSLionel Sambuc methodDecl(isOverride(), hasName("::Y::f"))));
1770f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { virtual int f(); }; "
1771f4a2713aSLionel Sambuc "class Y : public X { int f(); };",
1772f4a2713aSLionel Sambuc methodDecl(isOverride(), hasName("::X::f"))));
1773f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { int f(); }; "
1774f4a2713aSLionel Sambuc "class Y : public X { int f(); };",
1775f4a2713aSLionel Sambuc methodDecl(isOverride())));
1776f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { int f(); int f(int); }; ",
1777f4a2713aSLionel Sambuc methodDecl(isOverride())));
1778f4a2713aSLionel Sambuc }
1779f4a2713aSLionel Sambuc
TEST(Matcher,ConstructorCall)1780f4a2713aSLionel Sambuc TEST(Matcher, ConstructorCall) {
1781f4a2713aSLionel Sambuc StatementMatcher Constructor = constructExpr();
1782f4a2713aSLionel Sambuc
1783f4a2713aSLionel Sambuc EXPECT_TRUE(
1784f4a2713aSLionel Sambuc matches("class X { public: X(); }; void x() { X x; }", Constructor));
1785f4a2713aSLionel Sambuc EXPECT_TRUE(
1786f4a2713aSLionel Sambuc matches("class X { public: X(); }; void x() { X x = X(); }",
1787f4a2713aSLionel Sambuc Constructor));
1788f4a2713aSLionel Sambuc EXPECT_TRUE(
1789f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { X x = 0; }",
1790f4a2713aSLionel Sambuc Constructor));
1791f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor));
1792f4a2713aSLionel Sambuc }
1793f4a2713aSLionel Sambuc
TEST(Matcher,ConstructorArgument)1794f4a2713aSLionel Sambuc TEST(Matcher, ConstructorArgument) {
1795f4a2713aSLionel Sambuc StatementMatcher Constructor = constructExpr(
1796f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
1797f4a2713aSLionel Sambuc
1798f4a2713aSLionel Sambuc EXPECT_TRUE(
1799f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { int y; X x(y); }",
1800f4a2713aSLionel Sambuc Constructor));
1801f4a2713aSLionel Sambuc EXPECT_TRUE(
1802f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { int y; X x = X(y); }",
1803f4a2713aSLionel Sambuc Constructor));
1804f4a2713aSLionel Sambuc EXPECT_TRUE(
1805f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { int y; X x = y; }",
1806f4a2713aSLionel Sambuc Constructor));
1807f4a2713aSLionel Sambuc EXPECT_TRUE(
1808f4a2713aSLionel Sambuc notMatches("class X { public: X(int); }; void x() { int z; X x(z); }",
1809f4a2713aSLionel Sambuc Constructor));
1810f4a2713aSLionel Sambuc
1811f4a2713aSLionel Sambuc StatementMatcher WrongIndex = constructExpr(
1812f4a2713aSLionel Sambuc hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
1813f4a2713aSLionel Sambuc EXPECT_TRUE(
1814f4a2713aSLionel Sambuc notMatches("class X { public: X(int); }; void x() { int y; X x(y); }",
1815f4a2713aSLionel Sambuc WrongIndex));
1816f4a2713aSLionel Sambuc }
1817f4a2713aSLionel Sambuc
TEST(Matcher,ConstructorArgumentCount)1818f4a2713aSLionel Sambuc TEST(Matcher, ConstructorArgumentCount) {
1819f4a2713aSLionel Sambuc StatementMatcher Constructor1Arg = constructExpr(argumentCountIs(1));
1820f4a2713aSLionel Sambuc
1821f4a2713aSLionel Sambuc EXPECT_TRUE(
1822f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { X x(0); }",
1823f4a2713aSLionel Sambuc Constructor1Arg));
1824f4a2713aSLionel Sambuc EXPECT_TRUE(
1825f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { X x = X(0); }",
1826f4a2713aSLionel Sambuc Constructor1Arg));
1827f4a2713aSLionel Sambuc EXPECT_TRUE(
1828f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { X x = 0; }",
1829f4a2713aSLionel Sambuc Constructor1Arg));
1830f4a2713aSLionel Sambuc EXPECT_TRUE(
1831f4a2713aSLionel Sambuc notMatches("class X { public: X(int, int); }; void x() { X x(0, 0); }",
1832f4a2713aSLionel Sambuc Constructor1Arg));
1833f4a2713aSLionel Sambuc }
1834f4a2713aSLionel Sambuc
TEST(Matcher,ConstructorListInitialization)1835*0a6a1f1dSLionel Sambuc TEST(Matcher, ConstructorListInitialization) {
1836*0a6a1f1dSLionel Sambuc StatementMatcher ConstructorListInit = constructExpr(isListInitialization());
1837*0a6a1f1dSLionel Sambuc
1838*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
1839*0a6a1f1dSLionel Sambuc matches("class X { public: X(int); }; void x() { X x{0}; }",
1840*0a6a1f1dSLionel Sambuc ConstructorListInit));
1841*0a6a1f1dSLionel Sambuc EXPECT_FALSE(
1842*0a6a1f1dSLionel Sambuc matches("class X { public: X(int); }; void x() { X x(0); }",
1843*0a6a1f1dSLionel Sambuc ConstructorListInit));
1844*0a6a1f1dSLionel Sambuc }
1845*0a6a1f1dSLionel Sambuc
TEST(Matcher,ThisExpr)1846f4a2713aSLionel Sambuc TEST(Matcher,ThisExpr) {
1847f4a2713aSLionel Sambuc EXPECT_TRUE(
1848f4a2713aSLionel Sambuc matches("struct X { int a; int f () { return a; } };", thisExpr()));
1849f4a2713aSLionel Sambuc EXPECT_TRUE(
1850f4a2713aSLionel Sambuc notMatches("struct X { int f () { int a; return a; } };", thisExpr()));
1851f4a2713aSLionel Sambuc }
1852f4a2713aSLionel Sambuc
TEST(Matcher,BindTemporaryExpression)1853f4a2713aSLionel Sambuc TEST(Matcher, BindTemporaryExpression) {
1854f4a2713aSLionel Sambuc StatementMatcher TempExpression = bindTemporaryExpr();
1855f4a2713aSLionel Sambuc
1856f4a2713aSLionel Sambuc std::string ClassString = "class string { public: string(); ~string(); }; ";
1857f4a2713aSLionel Sambuc
1858f4a2713aSLionel Sambuc EXPECT_TRUE(
1859f4a2713aSLionel Sambuc matches(ClassString +
1860f4a2713aSLionel Sambuc "string GetStringByValue();"
1861f4a2713aSLionel Sambuc "void FunctionTakesString(string s);"
1862f4a2713aSLionel Sambuc "void run() { FunctionTakesString(GetStringByValue()); }",
1863f4a2713aSLionel Sambuc TempExpression));
1864f4a2713aSLionel Sambuc
1865f4a2713aSLionel Sambuc EXPECT_TRUE(
1866f4a2713aSLionel Sambuc notMatches(ClassString +
1867f4a2713aSLionel Sambuc "string* GetStringPointer(); "
1868f4a2713aSLionel Sambuc "void FunctionTakesStringPtr(string* s);"
1869f4a2713aSLionel Sambuc "void run() {"
1870f4a2713aSLionel Sambuc " string* s = GetStringPointer();"
1871f4a2713aSLionel Sambuc " FunctionTakesStringPtr(GetStringPointer());"
1872f4a2713aSLionel Sambuc " FunctionTakesStringPtr(s);"
1873f4a2713aSLionel Sambuc "}",
1874f4a2713aSLionel Sambuc TempExpression));
1875f4a2713aSLionel Sambuc
1876f4a2713aSLionel Sambuc EXPECT_TRUE(
1877f4a2713aSLionel Sambuc notMatches("class no_dtor {};"
1878f4a2713aSLionel Sambuc "no_dtor GetObjByValue();"
1879f4a2713aSLionel Sambuc "void ConsumeObj(no_dtor param);"
1880f4a2713aSLionel Sambuc "void run() { ConsumeObj(GetObjByValue()); }",
1881f4a2713aSLionel Sambuc TempExpression));
1882f4a2713aSLionel Sambuc }
1883f4a2713aSLionel Sambuc
TEST(MaterializeTemporaryExpr,MatchesTemporary)1884f4a2713aSLionel Sambuc TEST(MaterializeTemporaryExpr, MatchesTemporary) {
1885f4a2713aSLionel Sambuc std::string ClassString =
1886f4a2713aSLionel Sambuc "class string { public: string(); int length(); }; ";
1887f4a2713aSLionel Sambuc
1888f4a2713aSLionel Sambuc EXPECT_TRUE(
1889f4a2713aSLionel Sambuc matches(ClassString +
1890f4a2713aSLionel Sambuc "string GetStringByValue();"
1891f4a2713aSLionel Sambuc "void FunctionTakesString(string s);"
1892f4a2713aSLionel Sambuc "void run() { FunctionTakesString(GetStringByValue()); }",
1893f4a2713aSLionel Sambuc materializeTemporaryExpr()));
1894f4a2713aSLionel Sambuc
1895f4a2713aSLionel Sambuc EXPECT_TRUE(
1896f4a2713aSLionel Sambuc notMatches(ClassString +
1897f4a2713aSLionel Sambuc "string* GetStringPointer(); "
1898f4a2713aSLionel Sambuc "void FunctionTakesStringPtr(string* s);"
1899f4a2713aSLionel Sambuc "void run() {"
1900f4a2713aSLionel Sambuc " string* s = GetStringPointer();"
1901f4a2713aSLionel Sambuc " FunctionTakesStringPtr(GetStringPointer());"
1902f4a2713aSLionel Sambuc " FunctionTakesStringPtr(s);"
1903f4a2713aSLionel Sambuc "}",
1904f4a2713aSLionel Sambuc materializeTemporaryExpr()));
1905f4a2713aSLionel Sambuc
1906f4a2713aSLionel Sambuc EXPECT_TRUE(
1907f4a2713aSLionel Sambuc notMatches(ClassString +
1908f4a2713aSLionel Sambuc "string GetStringByValue();"
1909f4a2713aSLionel Sambuc "void run() { int k = GetStringByValue().length(); }",
1910f4a2713aSLionel Sambuc materializeTemporaryExpr()));
1911f4a2713aSLionel Sambuc
1912f4a2713aSLionel Sambuc EXPECT_TRUE(
1913f4a2713aSLionel Sambuc notMatches(ClassString +
1914f4a2713aSLionel Sambuc "string GetStringByValue();"
1915f4a2713aSLionel Sambuc "void run() { GetStringByValue(); }",
1916f4a2713aSLionel Sambuc materializeTemporaryExpr()));
1917f4a2713aSLionel Sambuc }
1918f4a2713aSLionel Sambuc
TEST(ConstructorDeclaration,SimpleCase)1919f4a2713aSLionel Sambuc TEST(ConstructorDeclaration, SimpleCase) {
1920f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Foo { Foo(int i); };",
1921f4a2713aSLionel Sambuc constructorDecl(ofClass(hasName("Foo")))));
1922f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
1923f4a2713aSLionel Sambuc constructorDecl(ofClass(hasName("Bar")))));
1924f4a2713aSLionel Sambuc }
1925f4a2713aSLionel Sambuc
TEST(ConstructorDeclaration,IsImplicit)1926f4a2713aSLionel Sambuc TEST(ConstructorDeclaration, IsImplicit) {
1927f4a2713aSLionel Sambuc // This one doesn't match because the constructor is not added by the
1928f4a2713aSLionel Sambuc // compiler (it is not needed).
1929f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Foo { };",
1930f4a2713aSLionel Sambuc constructorDecl(isImplicit())));
1931f4a2713aSLionel Sambuc // The compiler added the implicit default constructor.
1932f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
1933f4a2713aSLionel Sambuc constructorDecl(isImplicit())));
1934f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Foo { Foo(){} };",
1935f4a2713aSLionel Sambuc constructorDecl(unless(isImplicit()))));
1936*0a6a1f1dSLionel Sambuc // The compiler added an implicit assignment operator.
1937*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("struct A { int x; } a = {0}, b = a; void f() { a = b; }",
1938*0a6a1f1dSLionel Sambuc methodDecl(isImplicit(), hasName("operator="))));
1939f4a2713aSLionel Sambuc }
1940f4a2713aSLionel Sambuc
TEST(DestructorDeclaration,MatchesVirtualDestructor)1941f4a2713aSLionel Sambuc TEST(DestructorDeclaration, MatchesVirtualDestructor) {
1942f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
1943f4a2713aSLionel Sambuc destructorDecl(ofClass(hasName("Foo")))));
1944f4a2713aSLionel Sambuc }
1945f4a2713aSLionel Sambuc
TEST(DestructorDeclaration,DoesNotMatchImplicitDestructor)1946f4a2713aSLionel Sambuc TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {
1947f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class Foo {};",
1948f4a2713aSLionel Sambuc destructorDecl(ofClass(hasName("Foo")))));
1949f4a2713aSLionel Sambuc }
1950f4a2713aSLionel Sambuc
TEST(HasAnyConstructorInitializer,SimpleCase)1951f4a2713aSLionel Sambuc TEST(HasAnyConstructorInitializer, SimpleCase) {
1952f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
1953f4a2713aSLionel Sambuc "class Foo { Foo() { } };",
1954f4a2713aSLionel Sambuc constructorDecl(hasAnyConstructorInitializer(anything()))));
1955f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
1956f4a2713aSLionel Sambuc "class Foo {"
1957f4a2713aSLionel Sambuc " Foo() : foo_() { }"
1958f4a2713aSLionel Sambuc " int foo_;"
1959f4a2713aSLionel Sambuc "};",
1960f4a2713aSLionel Sambuc constructorDecl(hasAnyConstructorInitializer(anything()))));
1961f4a2713aSLionel Sambuc }
1962f4a2713aSLionel Sambuc
TEST(HasAnyConstructorInitializer,ForField)1963f4a2713aSLionel Sambuc TEST(HasAnyConstructorInitializer, ForField) {
1964f4a2713aSLionel Sambuc static const char Code[] =
1965f4a2713aSLionel Sambuc "class Baz { };"
1966f4a2713aSLionel Sambuc "class Foo {"
1967f4a2713aSLionel Sambuc " Foo() : foo_() { }"
1968f4a2713aSLionel Sambuc " Baz foo_;"
1969f4a2713aSLionel Sambuc " Baz bar_;"
1970f4a2713aSLionel Sambuc "};";
1971f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
1972f4a2713aSLionel Sambuc forField(hasType(recordDecl(hasName("Baz"))))))));
1973f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
1974f4a2713aSLionel Sambuc forField(hasName("foo_"))))));
1975f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
1976f4a2713aSLionel Sambuc forField(hasType(recordDecl(hasName("Bar"))))))));
1977f4a2713aSLionel Sambuc }
1978f4a2713aSLionel Sambuc
TEST(HasAnyConstructorInitializer,WithInitializer)1979f4a2713aSLionel Sambuc TEST(HasAnyConstructorInitializer, WithInitializer) {
1980f4a2713aSLionel Sambuc static const char Code[] =
1981f4a2713aSLionel Sambuc "class Foo {"
1982f4a2713aSLionel Sambuc " Foo() : foo_(0) { }"
1983f4a2713aSLionel Sambuc " int foo_;"
1984f4a2713aSLionel Sambuc "};";
1985f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
1986f4a2713aSLionel Sambuc withInitializer(integerLiteral(equals(0)))))));
1987f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
1988f4a2713aSLionel Sambuc withInitializer(integerLiteral(equals(1)))))));
1989f4a2713aSLionel Sambuc }
1990f4a2713aSLionel Sambuc
TEST(HasAnyConstructorInitializer,IsWritten)1991f4a2713aSLionel Sambuc TEST(HasAnyConstructorInitializer, IsWritten) {
1992f4a2713aSLionel Sambuc static const char Code[] =
1993f4a2713aSLionel Sambuc "struct Bar { Bar(){} };"
1994f4a2713aSLionel Sambuc "class Foo {"
1995f4a2713aSLionel Sambuc " Foo() : foo_() { }"
1996f4a2713aSLionel Sambuc " Bar foo_;"
1997f4a2713aSLionel Sambuc " Bar bar_;"
1998f4a2713aSLionel Sambuc "};";
1999f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
2000f4a2713aSLionel Sambuc allOf(forField(hasName("foo_")), isWritten())))));
2001f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
2002f4a2713aSLionel Sambuc allOf(forField(hasName("bar_")), isWritten())))));
2003f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
2004f4a2713aSLionel Sambuc allOf(forField(hasName("bar_")), unless(isWritten()))))));
2005f4a2713aSLionel Sambuc }
2006f4a2713aSLionel Sambuc
TEST(Matcher,NewExpression)2007f4a2713aSLionel Sambuc TEST(Matcher, NewExpression) {
2008f4a2713aSLionel Sambuc StatementMatcher New = newExpr();
2009f4a2713aSLionel Sambuc
2010f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }", New));
2011f4a2713aSLionel Sambuc EXPECT_TRUE(
2012f4a2713aSLionel Sambuc matches("class X { public: X(); }; void x() { new X(); }", New));
2013f4a2713aSLionel Sambuc EXPECT_TRUE(
2014f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { new X(0); }", New));
2015f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X {}; void x(int) { new X; }", New));
2016f4a2713aSLionel Sambuc }
2017f4a2713aSLionel Sambuc
TEST(Matcher,NewExpressionArgument)2018f4a2713aSLionel Sambuc TEST(Matcher, NewExpressionArgument) {
2019f4a2713aSLionel Sambuc StatementMatcher New = constructExpr(
2020f4a2713aSLionel Sambuc hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
2021f4a2713aSLionel Sambuc
2022f4a2713aSLionel Sambuc EXPECT_TRUE(
2023f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { int y; new X(y); }",
2024f4a2713aSLionel Sambuc New));
2025f4a2713aSLionel Sambuc EXPECT_TRUE(
2026f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { int y; new X(y); }",
2027f4a2713aSLionel Sambuc New));
2028f4a2713aSLionel Sambuc EXPECT_TRUE(
2029f4a2713aSLionel Sambuc notMatches("class X { public: X(int); }; void x() { int z; new X(z); }",
2030f4a2713aSLionel Sambuc New));
2031f4a2713aSLionel Sambuc
2032f4a2713aSLionel Sambuc StatementMatcher WrongIndex = constructExpr(
2033f4a2713aSLionel Sambuc hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
2034f4a2713aSLionel Sambuc EXPECT_TRUE(
2035f4a2713aSLionel Sambuc notMatches("class X { public: X(int); }; void x() { int y; new X(y); }",
2036f4a2713aSLionel Sambuc WrongIndex));
2037f4a2713aSLionel Sambuc }
2038f4a2713aSLionel Sambuc
TEST(Matcher,NewExpressionArgumentCount)2039f4a2713aSLionel Sambuc TEST(Matcher, NewExpressionArgumentCount) {
2040f4a2713aSLionel Sambuc StatementMatcher New = constructExpr(argumentCountIs(1));
2041f4a2713aSLionel Sambuc
2042f4a2713aSLionel Sambuc EXPECT_TRUE(
2043f4a2713aSLionel Sambuc matches("class X { public: X(int); }; void x() { new X(0); }", New));
2044f4a2713aSLionel Sambuc EXPECT_TRUE(
2045f4a2713aSLionel Sambuc notMatches("class X { public: X(int, int); }; void x() { new X(0, 0); }",
2046f4a2713aSLionel Sambuc New));
2047f4a2713aSLionel Sambuc }
2048f4a2713aSLionel Sambuc
TEST(Matcher,DeleteExpression)2049f4a2713aSLionel Sambuc TEST(Matcher, DeleteExpression) {
2050f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct A {}; void f(A* a) { delete a; }",
2051f4a2713aSLionel Sambuc deleteExpr()));
2052f4a2713aSLionel Sambuc }
2053f4a2713aSLionel Sambuc
TEST(Matcher,DefaultArgument)2054f4a2713aSLionel Sambuc TEST(Matcher, DefaultArgument) {
2055f4a2713aSLionel Sambuc StatementMatcher Arg = defaultArgExpr();
2056f4a2713aSLionel Sambuc
2057f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));
2058f4a2713aSLionel Sambuc EXPECT_TRUE(
2059f4a2713aSLionel Sambuc matches("class X { void x(int, int = 0) { int y; x(y); } };", Arg));
2060f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x(int, int = 0) { int y; x(y, 0); }", Arg));
2061f4a2713aSLionel Sambuc }
2062f4a2713aSLionel Sambuc
TEST(Matcher,StringLiterals)2063f4a2713aSLionel Sambuc TEST(Matcher, StringLiterals) {
2064f4a2713aSLionel Sambuc StatementMatcher Literal = stringLiteral();
2065f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const char *s = \"string\";", Literal));
2066f4a2713aSLionel Sambuc // wide string
2067f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const wchar_t *s = L\"string\";", Literal));
2068f4a2713aSLionel Sambuc // with escaped characters
2069f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const char *s = \"\x05five\";", Literal));
2070f4a2713aSLionel Sambuc // no matching -- though the data type is the same, there is no string literal
2071f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("const char s[1] = {'a'};", Literal));
2072f4a2713aSLionel Sambuc }
2073f4a2713aSLionel Sambuc
TEST(Matcher,CharacterLiterals)2074f4a2713aSLionel Sambuc TEST(Matcher, CharacterLiterals) {
2075f4a2713aSLionel Sambuc StatementMatcher CharLiteral = characterLiteral();
2076f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const char c = 'c';", CharLiteral));
2077f4a2713aSLionel Sambuc // wide character
2078f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const char c = L'c';", CharLiteral));
2079f4a2713aSLionel Sambuc // wide character, Hex encoded, NOT MATCHED!
2080f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("const wchar_t c = 0x2126;", CharLiteral));
2081f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("const char c = 0x1;", CharLiteral));
2082f4a2713aSLionel Sambuc }
2083f4a2713aSLionel Sambuc
TEST(Matcher,IntegerLiterals)2084f4a2713aSLionel Sambuc TEST(Matcher, IntegerLiterals) {
2085f4a2713aSLionel Sambuc StatementMatcher HasIntLiteral = integerLiteral();
2086f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = 10;", HasIntLiteral));
2087f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = 0x1AB;", HasIntLiteral));
2088f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = 10L;", HasIntLiteral));
2089f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = 10U;", HasIntLiteral));
2090f4a2713aSLionel Sambuc
2091f4a2713aSLionel Sambuc // Non-matching cases (character literals, float and double)
2092f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = L'a';",
2093f4a2713aSLionel Sambuc HasIntLiteral)); // this is actually a character
2094f4a2713aSLionel Sambuc // literal cast to int
2095f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = 'a';", HasIntLiteral));
2096f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = 1e10;", HasIntLiteral));
2097f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = 10.0;", HasIntLiteral));
2098f4a2713aSLionel Sambuc }
2099f4a2713aSLionel Sambuc
TEST(Matcher,FloatLiterals)2100f4a2713aSLionel Sambuc TEST(Matcher, FloatLiterals) {
2101f4a2713aSLionel Sambuc StatementMatcher HasFloatLiteral = floatLiteral();
2102f4a2713aSLionel Sambuc EXPECT_TRUE(matches("float i = 10.0;", HasFloatLiteral));
2103f4a2713aSLionel Sambuc EXPECT_TRUE(matches("float i = 10.0f;", HasFloatLiteral));
2104f4a2713aSLionel Sambuc EXPECT_TRUE(matches("double i = 10.0;", HasFloatLiteral));
2105f4a2713aSLionel Sambuc EXPECT_TRUE(matches("double i = 10.0L;", HasFloatLiteral));
2106f4a2713aSLionel Sambuc EXPECT_TRUE(matches("double i = 1e10;", HasFloatLiteral));
2107f4a2713aSLionel Sambuc
2108f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("float i = 10;", HasFloatLiteral));
2109f4a2713aSLionel Sambuc }
2110f4a2713aSLionel Sambuc
TEST(Matcher,NullPtrLiteral)2111f4a2713aSLionel Sambuc TEST(Matcher, NullPtrLiteral) {
2112f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int* i = nullptr;", nullPtrLiteralExpr()));
2113f4a2713aSLionel Sambuc }
2114f4a2713aSLionel Sambuc
TEST(Matcher,AsmStatement)2115f4a2713aSLionel Sambuc TEST(Matcher, AsmStatement) {
2116f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt()));
2117f4a2713aSLionel Sambuc }
2118f4a2713aSLionel Sambuc
TEST(Matcher,Conditions)2119f4a2713aSLionel Sambuc TEST(Matcher, Conditions) {
2120f4a2713aSLionel Sambuc StatementMatcher Condition = ifStmt(hasCondition(boolLiteral(equals(true))));
2121f4a2713aSLionel Sambuc
2122f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { if (true) {} }", Condition));
2123f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { if (false) {} }", Condition));
2124f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { bool a = true; if (a) {} }", Condition));
2125f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { if (true || false) {} }", Condition));
2126f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { if (1) {} }", Condition));
2127f4a2713aSLionel Sambuc }
2128f4a2713aSLionel Sambuc
TEST(IfStmt,ChildTraversalMatchers)2129*0a6a1f1dSLionel Sambuc TEST(IfStmt, ChildTraversalMatchers) {
2130*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
2131*0a6a1f1dSLionel Sambuc ifStmt(hasThen(boolLiteral(equals(true))))));
2132*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
2133*0a6a1f1dSLionel Sambuc ifStmt(hasThen(boolLiteral(equals(true))))));
2134*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
2135*0a6a1f1dSLionel Sambuc ifStmt(hasElse(boolLiteral(equals(true))))));
2136*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
2137*0a6a1f1dSLionel Sambuc ifStmt(hasElse(boolLiteral(equals(true))))));
2138*0a6a1f1dSLionel Sambuc }
2139*0a6a1f1dSLionel Sambuc
TEST(MatchBinaryOperator,HasOperatorName)2140f4a2713aSLionel Sambuc TEST(MatchBinaryOperator, HasOperatorName) {
2141f4a2713aSLionel Sambuc StatementMatcher OperatorOr = binaryOperator(hasOperatorName("||"));
2142f4a2713aSLionel Sambuc
2143f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr));
2144f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr));
2145f4a2713aSLionel Sambuc }
2146f4a2713aSLionel Sambuc
TEST(MatchBinaryOperator,HasLHSAndHasRHS)2147f4a2713aSLionel Sambuc TEST(MatchBinaryOperator, HasLHSAndHasRHS) {
2148f4a2713aSLionel Sambuc StatementMatcher OperatorTrueFalse =
2149f4a2713aSLionel Sambuc binaryOperator(hasLHS(boolLiteral(equals(true))),
2150f4a2713aSLionel Sambuc hasRHS(boolLiteral(equals(false))));
2151f4a2713aSLionel Sambuc
2152f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));
2153f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));
2154f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse));
2155f4a2713aSLionel Sambuc }
2156f4a2713aSLionel Sambuc
TEST(MatchBinaryOperator,HasEitherOperand)2157f4a2713aSLionel Sambuc TEST(MatchBinaryOperator, HasEitherOperand) {
2158f4a2713aSLionel Sambuc StatementMatcher HasOperand =
2159f4a2713aSLionel Sambuc binaryOperator(hasEitherOperand(boolLiteral(equals(false))));
2160f4a2713aSLionel Sambuc
2161f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));
2162f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));
2163f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand));
2164f4a2713aSLionel Sambuc }
2165f4a2713aSLionel Sambuc
TEST(Matcher,BinaryOperatorTypes)2166f4a2713aSLionel Sambuc TEST(Matcher, BinaryOperatorTypes) {
2167f4a2713aSLionel Sambuc // Integration test that verifies the AST provides all binary operators in
2168f4a2713aSLionel Sambuc // a way we expect.
2169f4a2713aSLionel Sambuc // FIXME: Operator ','
2170f4a2713aSLionel Sambuc EXPECT_TRUE(
2171f4a2713aSLionel Sambuc matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));
2172f4a2713aSLionel Sambuc EXPECT_TRUE(
2173f4a2713aSLionel Sambuc matches("bool b; bool c = (b = true);",
2174f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("="))));
2175f4a2713aSLionel Sambuc EXPECT_TRUE(
2176f4a2713aSLionel Sambuc matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));
2177f4a2713aSLionel Sambuc EXPECT_TRUE(
2178f4a2713aSLionel Sambuc matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));
2179f4a2713aSLionel Sambuc EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));
2180f4a2713aSLionel Sambuc EXPECT_TRUE(
2181f4a2713aSLionel Sambuc matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));
2182f4a2713aSLionel Sambuc EXPECT_TRUE(
2183f4a2713aSLionel Sambuc matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));
2184f4a2713aSLionel Sambuc EXPECT_TRUE(
2185f4a2713aSLionel Sambuc matches("int i = 1; int j = (i <<= 2);",
2186f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("<<="))));
2187f4a2713aSLionel Sambuc EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));
2188f4a2713aSLionel Sambuc EXPECT_TRUE(
2189f4a2713aSLionel Sambuc matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));
2190f4a2713aSLionel Sambuc EXPECT_TRUE(
2191f4a2713aSLionel Sambuc matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));
2192f4a2713aSLionel Sambuc EXPECT_TRUE(
2193f4a2713aSLionel Sambuc matches("int i = 1; int j = (i >>= 2);",
2194f4a2713aSLionel Sambuc binaryOperator(hasOperatorName(">>="))));
2195f4a2713aSLionel Sambuc EXPECT_TRUE(
2196f4a2713aSLionel Sambuc matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));
2197f4a2713aSLionel Sambuc EXPECT_TRUE(
2198f4a2713aSLionel Sambuc matches("int i = 42; int j = (i ^= 42);",
2199f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("^="))));
2200f4a2713aSLionel Sambuc EXPECT_TRUE(
2201f4a2713aSLionel Sambuc matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));
2202f4a2713aSLionel Sambuc EXPECT_TRUE(
2203f4a2713aSLionel Sambuc matches("int i = 42; int j = (i %= 42);",
2204f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("%="))));
2205f4a2713aSLionel Sambuc EXPECT_TRUE(
2206f4a2713aSLionel Sambuc matches("bool b = 42 &23;", binaryOperator(hasOperatorName("&"))));
2207f4a2713aSLionel Sambuc EXPECT_TRUE(
2208f4a2713aSLionel Sambuc matches("bool b = true && false;",
2209f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("&&"))));
2210f4a2713aSLionel Sambuc EXPECT_TRUE(
2211f4a2713aSLionel Sambuc matches("bool b = true; bool c = (b &= false);",
2212f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("&="))));
2213f4a2713aSLionel Sambuc EXPECT_TRUE(
2214f4a2713aSLionel Sambuc matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));
2215f4a2713aSLionel Sambuc EXPECT_TRUE(
2216f4a2713aSLionel Sambuc matches("bool b = true || false;",
2217f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("||"))));
2218f4a2713aSLionel Sambuc EXPECT_TRUE(
2219f4a2713aSLionel Sambuc matches("bool b = true; bool c = (b |= false);",
2220f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("|="))));
2221f4a2713aSLionel Sambuc EXPECT_TRUE(
2222f4a2713aSLionel Sambuc matches("int i = 42 *23;", binaryOperator(hasOperatorName("*"))));
2223f4a2713aSLionel Sambuc EXPECT_TRUE(
2224f4a2713aSLionel Sambuc matches("int i = 42; int j = (i *= 23);",
2225f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("*="))));
2226f4a2713aSLionel Sambuc EXPECT_TRUE(
2227f4a2713aSLionel Sambuc matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));
2228f4a2713aSLionel Sambuc EXPECT_TRUE(
2229f4a2713aSLionel Sambuc matches("int i = 42; int j = (i /= 23);",
2230f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("/="))));
2231f4a2713aSLionel Sambuc EXPECT_TRUE(
2232f4a2713aSLionel Sambuc matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));
2233f4a2713aSLionel Sambuc EXPECT_TRUE(
2234f4a2713aSLionel Sambuc matches("int i = 42; int j = (i += 23);",
2235f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("+="))));
2236f4a2713aSLionel Sambuc EXPECT_TRUE(
2237f4a2713aSLionel Sambuc matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));
2238f4a2713aSLionel Sambuc EXPECT_TRUE(
2239f4a2713aSLionel Sambuc matches("int i = 42; int j = (i -= 23);",
2240f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("-="))));
2241f4a2713aSLionel Sambuc EXPECT_TRUE(
2242f4a2713aSLionel Sambuc matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",
2243f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("->*"))));
2244f4a2713aSLionel Sambuc EXPECT_TRUE(
2245f4a2713aSLionel Sambuc matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",
2246f4a2713aSLionel Sambuc binaryOperator(hasOperatorName(".*"))));
2247f4a2713aSLionel Sambuc
2248f4a2713aSLionel Sambuc // Member expressions as operators are not supported in matches.
2249f4a2713aSLionel Sambuc EXPECT_TRUE(
2250f4a2713aSLionel Sambuc notMatches("struct A { void x(A *a) { a->x(this); } };",
2251f4a2713aSLionel Sambuc binaryOperator(hasOperatorName("->"))));
2252f4a2713aSLionel Sambuc
2253f4a2713aSLionel Sambuc // Initializer assignments are not represented as operator equals.
2254f4a2713aSLionel Sambuc EXPECT_TRUE(
2255f4a2713aSLionel Sambuc notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));
2256f4a2713aSLionel Sambuc
2257f4a2713aSLionel Sambuc // Array indexing is not represented as operator.
2258f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));
2259f4a2713aSLionel Sambuc
2260f4a2713aSLionel Sambuc // Overloaded operators do not match at all.
2261f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2262f4a2713aSLionel Sambuc "struct A { bool operator&&(const A &a) const { return false; } };"
2263f4a2713aSLionel Sambuc "void x() { A a, b; a && b; }",
2264f4a2713aSLionel Sambuc binaryOperator()));
2265f4a2713aSLionel Sambuc }
2266f4a2713aSLionel Sambuc
TEST(MatchUnaryOperator,HasOperatorName)2267f4a2713aSLionel Sambuc TEST(MatchUnaryOperator, HasOperatorName) {
2268f4a2713aSLionel Sambuc StatementMatcher OperatorNot = unaryOperator(hasOperatorName("!"));
2269f4a2713aSLionel Sambuc
2270f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot));
2271f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot));
2272f4a2713aSLionel Sambuc }
2273f4a2713aSLionel Sambuc
TEST(MatchUnaryOperator,HasUnaryOperand)2274f4a2713aSLionel Sambuc TEST(MatchUnaryOperator, HasUnaryOperand) {
2275f4a2713aSLionel Sambuc StatementMatcher OperatorOnFalse =
2276f4a2713aSLionel Sambuc unaryOperator(hasUnaryOperand(boolLiteral(equals(false))));
2277f4a2713aSLionel Sambuc
2278f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));
2279f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));
2280f4a2713aSLionel Sambuc }
2281f4a2713aSLionel Sambuc
TEST(Matcher,UnaryOperatorTypes)2282f4a2713aSLionel Sambuc TEST(Matcher, UnaryOperatorTypes) {
2283f4a2713aSLionel Sambuc // Integration test that verifies the AST provides all unary operators in
2284f4a2713aSLionel Sambuc // a way we expect.
2285f4a2713aSLionel Sambuc EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));
2286f4a2713aSLionel Sambuc EXPECT_TRUE(
2287f4a2713aSLionel Sambuc matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));
2288f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));
2289f4a2713aSLionel Sambuc EXPECT_TRUE(
2290f4a2713aSLionel Sambuc matches("bool *p; bool b = *p;", unaryOperator(hasOperatorName("*"))));
2291f4a2713aSLionel Sambuc EXPECT_TRUE(
2292f4a2713aSLionel Sambuc matches("int i; int j = +i;", unaryOperator(hasOperatorName("+"))));
2293f4a2713aSLionel Sambuc EXPECT_TRUE(
2294f4a2713aSLionel Sambuc matches("int i; int j = -i;", unaryOperator(hasOperatorName("-"))));
2295f4a2713aSLionel Sambuc EXPECT_TRUE(
2296f4a2713aSLionel Sambuc matches("int i; int j = ++i;", unaryOperator(hasOperatorName("++"))));
2297f4a2713aSLionel Sambuc EXPECT_TRUE(
2298f4a2713aSLionel Sambuc matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));
2299f4a2713aSLionel Sambuc EXPECT_TRUE(
2300f4a2713aSLionel Sambuc matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));
2301f4a2713aSLionel Sambuc EXPECT_TRUE(
2302f4a2713aSLionel Sambuc matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));
2303f4a2713aSLionel Sambuc
2304f4a2713aSLionel Sambuc // We don't match conversion operators.
2305f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));
2306f4a2713aSLionel Sambuc
2307f4a2713aSLionel Sambuc // Function calls are not represented as operator.
2308f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));
2309f4a2713aSLionel Sambuc
2310f4a2713aSLionel Sambuc // Overloaded operators do not match at all.
2311f4a2713aSLionel Sambuc // FIXME: We probably want to add that.
2312f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2313f4a2713aSLionel Sambuc "struct A { bool operator!() const { return false; } };"
2314f4a2713aSLionel Sambuc "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
2315f4a2713aSLionel Sambuc }
2316f4a2713aSLionel Sambuc
TEST(Matcher,ConditionalOperator)2317f4a2713aSLionel Sambuc TEST(Matcher, ConditionalOperator) {
2318f4a2713aSLionel Sambuc StatementMatcher Conditional = conditionalOperator(
2319f4a2713aSLionel Sambuc hasCondition(boolLiteral(equals(true))),
2320f4a2713aSLionel Sambuc hasTrueExpression(boolLiteral(equals(false))));
2321f4a2713aSLionel Sambuc
2322f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { true ? false : true; }", Conditional));
2323f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { false ? false : true; }", Conditional));
2324f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { true ? true : false; }", Conditional));
2325f4a2713aSLionel Sambuc
2326f4a2713aSLionel Sambuc StatementMatcher ConditionalFalse = conditionalOperator(
2327f4a2713aSLionel Sambuc hasFalseExpression(boolLiteral(equals(false))));
2328f4a2713aSLionel Sambuc
2329f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));
2330f4a2713aSLionel Sambuc EXPECT_TRUE(
2331f4a2713aSLionel Sambuc notMatches("void x() { true ? false : true; }", ConditionalFalse));
2332f4a2713aSLionel Sambuc }
2333f4a2713aSLionel Sambuc
TEST(ArraySubscriptMatchers,ArraySubscripts)2334f4a2713aSLionel Sambuc TEST(ArraySubscriptMatchers, ArraySubscripts) {
2335f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i[2]; void f() { i[1] = 1; }",
2336f4a2713aSLionel Sambuc arraySubscriptExpr()));
2337f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i; void f() { i = 1; }",
2338f4a2713aSLionel Sambuc arraySubscriptExpr()));
2339f4a2713aSLionel Sambuc }
2340f4a2713aSLionel Sambuc
TEST(ArraySubscriptMatchers,ArrayIndex)2341f4a2713aSLionel Sambuc TEST(ArraySubscriptMatchers, ArrayIndex) {
2342f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2343f4a2713aSLionel Sambuc "int i[2]; void f() { i[1] = 1; }",
2344f4a2713aSLionel Sambuc arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2345f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2346f4a2713aSLionel Sambuc "int i[2]; void f() { 1[i] = 1; }",
2347f4a2713aSLionel Sambuc arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2348f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2349f4a2713aSLionel Sambuc "int i[2]; void f() { i[1] = 1; }",
2350f4a2713aSLionel Sambuc arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));
2351f4a2713aSLionel Sambuc }
2352f4a2713aSLionel Sambuc
TEST(ArraySubscriptMatchers,MatchesArrayBase)2353f4a2713aSLionel Sambuc TEST(ArraySubscriptMatchers, MatchesArrayBase) {
2354f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2355f4a2713aSLionel Sambuc "int i[2]; void f() { i[1] = 2; }",
2356f4a2713aSLionel Sambuc arraySubscriptExpr(hasBase(implicitCastExpr(
2357f4a2713aSLionel Sambuc hasSourceExpression(declRefExpr()))))));
2358f4a2713aSLionel Sambuc }
2359f4a2713aSLionel Sambuc
TEST(Matcher,HasNameSupportsNamespaces)2360f4a2713aSLionel Sambuc TEST(Matcher, HasNameSupportsNamespaces) {
2361f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2362f4a2713aSLionel Sambuc recordDecl(hasName("a::b::C"))));
2363f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2364f4a2713aSLionel Sambuc recordDecl(hasName("::a::b::C"))));
2365f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2366f4a2713aSLionel Sambuc recordDecl(hasName("b::C"))));
2367f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2368f4a2713aSLionel Sambuc recordDecl(hasName("C"))));
2369f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2370f4a2713aSLionel Sambuc recordDecl(hasName("c::b::C"))));
2371f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2372f4a2713aSLionel Sambuc recordDecl(hasName("a::c::C"))));
2373f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2374f4a2713aSLionel Sambuc recordDecl(hasName("a::b::A"))));
2375f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2376f4a2713aSLionel Sambuc recordDecl(hasName("::C"))));
2377f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2378f4a2713aSLionel Sambuc recordDecl(hasName("::b::C"))));
2379f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2380f4a2713aSLionel Sambuc recordDecl(hasName("z::a::b::C"))));
2381f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2382f4a2713aSLionel Sambuc recordDecl(hasName("a+b::C"))));
2383f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace a { namespace b { class AC; } }",
2384f4a2713aSLionel Sambuc recordDecl(hasName("C"))));
2385f4a2713aSLionel Sambuc }
2386f4a2713aSLionel Sambuc
TEST(Matcher,HasNameSupportsOuterClasses)2387f4a2713aSLionel Sambuc TEST(Matcher, HasNameSupportsOuterClasses) {
2388f4a2713aSLionel Sambuc EXPECT_TRUE(
2389f4a2713aSLionel Sambuc matches("class A { class B { class C; }; };",
2390f4a2713aSLionel Sambuc recordDecl(hasName("A::B::C"))));
2391f4a2713aSLionel Sambuc EXPECT_TRUE(
2392f4a2713aSLionel Sambuc matches("class A { class B { class C; }; };",
2393f4a2713aSLionel Sambuc recordDecl(hasName("::A::B::C"))));
2394f4a2713aSLionel Sambuc EXPECT_TRUE(
2395f4a2713aSLionel Sambuc matches("class A { class B { class C; }; };",
2396f4a2713aSLionel Sambuc recordDecl(hasName("B::C"))));
2397f4a2713aSLionel Sambuc EXPECT_TRUE(
2398f4a2713aSLionel Sambuc matches("class A { class B { class C; }; };",
2399f4a2713aSLionel Sambuc recordDecl(hasName("C"))));
2400f4a2713aSLionel Sambuc EXPECT_TRUE(
2401f4a2713aSLionel Sambuc notMatches("class A { class B { class C; }; };",
2402f4a2713aSLionel Sambuc recordDecl(hasName("c::B::C"))));
2403f4a2713aSLionel Sambuc EXPECT_TRUE(
2404f4a2713aSLionel Sambuc notMatches("class A { class B { class C; }; };",
2405f4a2713aSLionel Sambuc recordDecl(hasName("A::c::C"))));
2406f4a2713aSLionel Sambuc EXPECT_TRUE(
2407f4a2713aSLionel Sambuc notMatches("class A { class B { class C; }; };",
2408f4a2713aSLionel Sambuc recordDecl(hasName("A::B::A"))));
2409f4a2713aSLionel Sambuc EXPECT_TRUE(
2410f4a2713aSLionel Sambuc notMatches("class A { class B { class C; }; };",
2411f4a2713aSLionel Sambuc recordDecl(hasName("::C"))));
2412f4a2713aSLionel Sambuc EXPECT_TRUE(
2413f4a2713aSLionel Sambuc notMatches("class A { class B { class C; }; };",
2414f4a2713aSLionel Sambuc recordDecl(hasName("::B::C"))));
2415f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2416f4a2713aSLionel Sambuc recordDecl(hasName("z::A::B::C"))));
2417f4a2713aSLionel Sambuc EXPECT_TRUE(
2418f4a2713aSLionel Sambuc notMatches("class A { class B { class C; }; };",
2419f4a2713aSLionel Sambuc recordDecl(hasName("A+B::C"))));
2420f4a2713aSLionel Sambuc }
2421f4a2713aSLionel Sambuc
TEST(Matcher,IsDefinition)2422f4a2713aSLionel Sambuc TEST(Matcher, IsDefinition) {
2423f4a2713aSLionel Sambuc DeclarationMatcher DefinitionOfClassA =
2424f4a2713aSLionel Sambuc recordDecl(hasName("A"), isDefinition());
2425f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class A {};", DefinitionOfClassA));
2426f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A;", DefinitionOfClassA));
2427f4a2713aSLionel Sambuc
2428f4a2713aSLionel Sambuc DeclarationMatcher DefinitionOfVariableA =
2429f4a2713aSLionel Sambuc varDecl(hasName("a"), isDefinition());
2430f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a;", DefinitionOfVariableA));
2431f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
2432f4a2713aSLionel Sambuc
2433f4a2713aSLionel Sambuc DeclarationMatcher DefinitionOfMethodA =
2434f4a2713aSLionel Sambuc methodDecl(hasName("a"), isDefinition());
2435f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
2436f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
2437f4a2713aSLionel Sambuc }
2438f4a2713aSLionel Sambuc
TEST(Matcher,OfClass)2439f4a2713aSLionel Sambuc TEST(Matcher, OfClass) {
2440f4a2713aSLionel Sambuc StatementMatcher Constructor = constructExpr(hasDeclaration(methodDecl(
2441f4a2713aSLionel Sambuc ofClass(hasName("X")))));
2442f4a2713aSLionel Sambuc
2443f4a2713aSLionel Sambuc EXPECT_TRUE(
2444f4a2713aSLionel Sambuc matches("class X { public: X(); }; void x(int) { X x; }", Constructor));
2445f4a2713aSLionel Sambuc EXPECT_TRUE(
2446f4a2713aSLionel Sambuc matches("class X { public: X(); }; void x(int) { X x = X(); }",
2447f4a2713aSLionel Sambuc Constructor));
2448f4a2713aSLionel Sambuc EXPECT_TRUE(
2449f4a2713aSLionel Sambuc notMatches("class Y { public: Y(); }; void x(int) { Y y; }",
2450f4a2713aSLionel Sambuc Constructor));
2451f4a2713aSLionel Sambuc }
2452f4a2713aSLionel Sambuc
TEST(Matcher,VisitsTemplateInstantiations)2453f4a2713aSLionel Sambuc TEST(Matcher, VisitsTemplateInstantiations) {
2454f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2455f4a2713aSLionel Sambuc "class A { public: void x(); };"
2456f4a2713aSLionel Sambuc "template <typename T> class B { public: void y() { T t; t.x(); } };"
2457f4a2713aSLionel Sambuc "void f() { B<A> b; b.y(); }",
2458f4a2713aSLionel Sambuc callExpr(callee(methodDecl(hasName("x"))))));
2459f4a2713aSLionel Sambuc
2460f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2461f4a2713aSLionel Sambuc "class A { public: void x(); };"
2462f4a2713aSLionel Sambuc "class C {"
2463f4a2713aSLionel Sambuc " public:"
2464f4a2713aSLionel Sambuc " template <typename T> class B { public: void y() { T t; t.x(); } };"
2465f4a2713aSLionel Sambuc "};"
2466f4a2713aSLionel Sambuc "void f() {"
2467f4a2713aSLionel Sambuc " C::B<A> b; b.y();"
2468f4a2713aSLionel Sambuc "}",
2469f4a2713aSLionel Sambuc recordDecl(hasName("C"),
2470f4a2713aSLionel Sambuc hasDescendant(callExpr(callee(methodDecl(hasName("x"))))))));
2471f4a2713aSLionel Sambuc }
2472f4a2713aSLionel Sambuc
TEST(Matcher,HandlesNullQualTypes)2473f4a2713aSLionel Sambuc TEST(Matcher, HandlesNullQualTypes) {
2474f4a2713aSLionel Sambuc // FIXME: Add a Type matcher so we can replace uses of this
2475f4a2713aSLionel Sambuc // variable with Type(True())
2476f4a2713aSLionel Sambuc const TypeMatcher AnyType = anything();
2477f4a2713aSLionel Sambuc
2478f4a2713aSLionel Sambuc // We don't really care whether this matcher succeeds; we're testing that
2479f4a2713aSLionel Sambuc // it completes without crashing.
2480f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2481f4a2713aSLionel Sambuc "struct A { };"
2482f4a2713aSLionel Sambuc "template <typename T>"
2483f4a2713aSLionel Sambuc "void f(T t) {"
2484f4a2713aSLionel Sambuc " T local_t(t /* this becomes a null QualType in the AST */);"
2485f4a2713aSLionel Sambuc "}"
2486f4a2713aSLionel Sambuc "void g() {"
2487f4a2713aSLionel Sambuc " f(0);"
2488f4a2713aSLionel Sambuc "}",
2489f4a2713aSLionel Sambuc expr(hasType(TypeMatcher(
2490f4a2713aSLionel Sambuc anyOf(
2491f4a2713aSLionel Sambuc TypeMatcher(hasDeclaration(anything())),
2492f4a2713aSLionel Sambuc pointsTo(AnyType),
2493f4a2713aSLionel Sambuc references(AnyType)
2494f4a2713aSLionel Sambuc // Other QualType matchers should go here.
2495f4a2713aSLionel Sambuc ))))));
2496f4a2713aSLionel Sambuc }
2497f4a2713aSLionel Sambuc
2498f4a2713aSLionel Sambuc // For testing AST_MATCHER_P().
AST_MATCHER_P(Decl,just,internal::Matcher<Decl>,AMatcher)2499f4a2713aSLionel Sambuc AST_MATCHER_P(Decl, just, internal::Matcher<Decl>, AMatcher) {
2500f4a2713aSLionel Sambuc // Make sure all special variables are used: node, match_finder,
2501f4a2713aSLionel Sambuc // bound_nodes_builder, and the parameter named 'AMatcher'.
2502f4a2713aSLionel Sambuc return AMatcher.matches(Node, Finder, Builder);
2503f4a2713aSLionel Sambuc }
2504f4a2713aSLionel Sambuc
TEST(AstMatcherPMacro,Works)2505f4a2713aSLionel Sambuc TEST(AstMatcherPMacro, Works) {
2506f4a2713aSLionel Sambuc DeclarationMatcher HasClassB = just(has(recordDecl(hasName("B")).bind("b")));
2507f4a2713aSLionel Sambuc
2508f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
2509f4a2713aSLionel Sambuc HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
2510f4a2713aSLionel Sambuc
2511f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
2512f4a2713aSLionel Sambuc HasClassB, new VerifyIdIsBoundTo<Decl>("a")));
2513f4a2713aSLionel Sambuc
2514f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
2515f4a2713aSLionel Sambuc HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
2516f4a2713aSLionel Sambuc }
2517f4a2713aSLionel Sambuc
AST_POLYMORPHIC_MATCHER_P(polymorphicHas,AST_POLYMORPHIC_SUPPORTED_TYPES_2 (Decl,Stmt),internal::Matcher<Decl>,AMatcher)2518f4a2713aSLionel Sambuc AST_POLYMORPHIC_MATCHER_P(
2519f4a2713aSLionel Sambuc polymorphicHas,
2520f4a2713aSLionel Sambuc AST_POLYMORPHIC_SUPPORTED_TYPES_2(Decl, Stmt),
2521f4a2713aSLionel Sambuc internal::Matcher<Decl>, AMatcher) {
2522f4a2713aSLionel Sambuc return Finder->matchesChildOf(
2523f4a2713aSLionel Sambuc Node, AMatcher, Builder,
2524f4a2713aSLionel Sambuc ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
2525f4a2713aSLionel Sambuc ASTMatchFinder::BK_First);
2526f4a2713aSLionel Sambuc }
2527f4a2713aSLionel Sambuc
TEST(AstPolymorphicMatcherPMacro,Works)2528f4a2713aSLionel Sambuc TEST(AstPolymorphicMatcherPMacro, Works) {
2529f4a2713aSLionel Sambuc DeclarationMatcher HasClassB =
2530f4a2713aSLionel Sambuc polymorphicHas(recordDecl(hasName("B")).bind("b"));
2531f4a2713aSLionel Sambuc
2532f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
2533f4a2713aSLionel Sambuc HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
2534f4a2713aSLionel Sambuc
2535f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
2536f4a2713aSLionel Sambuc HasClassB, new VerifyIdIsBoundTo<Decl>("a")));
2537f4a2713aSLionel Sambuc
2538f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
2539f4a2713aSLionel Sambuc HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
2540f4a2713aSLionel Sambuc
2541f4a2713aSLionel Sambuc StatementMatcher StatementHasClassB =
2542f4a2713aSLionel Sambuc polymorphicHas(recordDecl(hasName("B")));
2543f4a2713aSLionel Sambuc
2544f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { class B {}; }", StatementHasClassB));
2545f4a2713aSLionel Sambuc }
2546f4a2713aSLionel Sambuc
TEST(For,FindsForLoops)2547f4a2713aSLionel Sambuc TEST(For, FindsForLoops) {
2548f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { for(;;); }", forStmt()));
2549f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { if(true) for(;;); }", forStmt()));
2550f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int as[] = { 1, 2, 3 };"
2551f4a2713aSLionel Sambuc "void f() { for (auto &a : as); }",
2552f4a2713aSLionel Sambuc forStmt()));
2553f4a2713aSLionel Sambuc }
2554f4a2713aSLionel Sambuc
TEST(For,ForLoopInternals)2555f4a2713aSLionel Sambuc TEST(For, ForLoopInternals) {
2556f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
2557f4a2713aSLionel Sambuc forStmt(hasCondition(anything()))));
2558f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
2559f4a2713aSLionel Sambuc forStmt(hasLoopInit(anything()))));
2560f4a2713aSLionel Sambuc }
2561f4a2713aSLionel Sambuc
TEST(For,ForRangeLoopInternals)2562*0a6a1f1dSLionel Sambuc TEST(For, ForRangeLoopInternals) {
2563*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
2564*0a6a1f1dSLionel Sambuc forRangeStmt(hasLoopVariable(anything()))));
2565*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches(
2566*0a6a1f1dSLionel Sambuc "void f(){ int a[] {1, 2}; for (int i : a); }",
2567*0a6a1f1dSLionel Sambuc forRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
2568*0a6a1f1dSLionel Sambuc }
2569*0a6a1f1dSLionel Sambuc
TEST(For,NegativeForLoopInternals)2570f4a2713aSLionel Sambuc TEST(For, NegativeForLoopInternals) {
2571f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
2572f4a2713aSLionel Sambuc forStmt(hasCondition(expr()))));
2573f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
2574f4a2713aSLionel Sambuc forStmt(hasLoopInit(anything()))));
2575f4a2713aSLionel Sambuc }
2576f4a2713aSLionel Sambuc
TEST(For,ReportsNoFalsePositives)2577f4a2713aSLionel Sambuc TEST(For, ReportsNoFalsePositives) {
2578f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { ; }", forStmt()));
2579f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { if(true); }", forStmt()));
2580f4a2713aSLionel Sambuc }
2581f4a2713aSLionel Sambuc
TEST(CompoundStatement,HandlesSimpleCases)2582f4a2713aSLionel Sambuc TEST(CompoundStatement, HandlesSimpleCases) {
2583f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f();", compoundStmt()));
2584f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {}", compoundStmt()));
2585f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {{}}", compoundStmt()));
2586f4a2713aSLionel Sambuc }
2587f4a2713aSLionel Sambuc
TEST(CompoundStatement,DoesNotMatchEmptyStruct)2588f4a2713aSLionel Sambuc TEST(CompoundStatement, DoesNotMatchEmptyStruct) {
2589f4a2713aSLionel Sambuc // It's not a compound statement just because there's "{}" in the source
2590f4a2713aSLionel Sambuc // text. This is an AST search, not grep.
2591f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace n { struct S {}; }",
2592f4a2713aSLionel Sambuc compoundStmt()));
2593f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace n { struct S { void f() {{}} }; }",
2594f4a2713aSLionel Sambuc compoundStmt()));
2595f4a2713aSLionel Sambuc }
2596f4a2713aSLionel Sambuc
TEST(HasBody,FindsBodyOfForWhileDoLoops)2597f4a2713aSLionel Sambuc TEST(HasBody, FindsBodyOfForWhileDoLoops) {
2598f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { for(;;) {} }",
2599f4a2713aSLionel Sambuc forStmt(hasBody(compoundStmt()))));
2600f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { for(;;); }",
2601f4a2713aSLionel Sambuc forStmt(hasBody(compoundStmt()))));
2602f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { while(true) {} }",
2603f4a2713aSLionel Sambuc whileStmt(hasBody(compoundStmt()))));
2604f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { do {} while(true); }",
2605f4a2713aSLionel Sambuc doStmt(hasBody(compoundStmt()))));
2606*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
2607*0a6a1f1dSLionel Sambuc forRangeStmt(hasBody(compoundStmt()))));
2608f4a2713aSLionel Sambuc }
2609f4a2713aSLionel Sambuc
TEST(HasAnySubstatement,MatchesForTopLevelCompoundStatement)2610f4a2713aSLionel Sambuc TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
2611f4a2713aSLionel Sambuc // The simplest case: every compound statement is in a function
2612f4a2713aSLionel Sambuc // definition, and the function body itself must be a compound
2613f4a2713aSLionel Sambuc // statement.
2614f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { for (;;); }",
2615f4a2713aSLionel Sambuc compoundStmt(hasAnySubstatement(forStmt()))));
2616f4a2713aSLionel Sambuc }
2617f4a2713aSLionel Sambuc
TEST(HasAnySubstatement,IsNotRecursive)2618f4a2713aSLionel Sambuc TEST(HasAnySubstatement, IsNotRecursive) {
2619f4a2713aSLionel Sambuc // It's really "has any immediate substatement".
2620f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
2621f4a2713aSLionel Sambuc compoundStmt(hasAnySubstatement(forStmt()))));
2622f4a2713aSLionel Sambuc }
2623f4a2713aSLionel Sambuc
TEST(HasAnySubstatement,MatchesInNestedCompoundStatements)2624f4a2713aSLionel Sambuc TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {
2625f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
2626f4a2713aSLionel Sambuc compoundStmt(hasAnySubstatement(forStmt()))));
2627f4a2713aSLionel Sambuc }
2628f4a2713aSLionel Sambuc
TEST(HasAnySubstatement,FindsSubstatementBetweenOthers)2629f4a2713aSLionel Sambuc TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {
2630f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
2631f4a2713aSLionel Sambuc compoundStmt(hasAnySubstatement(forStmt()))));
2632f4a2713aSLionel Sambuc }
2633f4a2713aSLionel Sambuc
TEST(StatementCountIs,FindsNoStatementsInAnEmptyCompoundStatement)2634f4a2713aSLionel Sambuc TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
2635f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { }",
2636f4a2713aSLionel Sambuc compoundStmt(statementCountIs(0))));
2637f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {}",
2638f4a2713aSLionel Sambuc compoundStmt(statementCountIs(1))));
2639f4a2713aSLionel Sambuc }
2640f4a2713aSLionel Sambuc
TEST(StatementCountIs,AppearsToMatchOnlyOneCount)2641f4a2713aSLionel Sambuc TEST(StatementCountIs, AppearsToMatchOnlyOneCount) {
2642f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { 1; }",
2643f4a2713aSLionel Sambuc compoundStmt(statementCountIs(1))));
2644f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { 1; }",
2645f4a2713aSLionel Sambuc compoundStmt(statementCountIs(0))));
2646f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { 1; }",
2647f4a2713aSLionel Sambuc compoundStmt(statementCountIs(2))));
2648f4a2713aSLionel Sambuc }
2649f4a2713aSLionel Sambuc
TEST(StatementCountIs,WorksWithMultipleStatements)2650f4a2713aSLionel Sambuc TEST(StatementCountIs, WorksWithMultipleStatements) {
2651f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { 1; 2; 3; }",
2652f4a2713aSLionel Sambuc compoundStmt(statementCountIs(3))));
2653f4a2713aSLionel Sambuc }
2654f4a2713aSLionel Sambuc
TEST(StatementCountIs,WorksWithNestedCompoundStatements)2655f4a2713aSLionel Sambuc TEST(StatementCountIs, WorksWithNestedCompoundStatements) {
2656f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
2657f4a2713aSLionel Sambuc compoundStmt(statementCountIs(1))));
2658f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
2659f4a2713aSLionel Sambuc compoundStmt(statementCountIs(2))));
2660f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() { { 1; } { 1; 2; 3; 4; } }",
2661f4a2713aSLionel Sambuc compoundStmt(statementCountIs(3))));
2662f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
2663f4a2713aSLionel Sambuc compoundStmt(statementCountIs(4))));
2664f4a2713aSLionel Sambuc }
2665f4a2713aSLionel Sambuc
TEST(Member,WorksInSimplestCase)2666f4a2713aSLionel Sambuc TEST(Member, WorksInSimplestCase) {
2667f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct { int first; } s; int i(s.first);",
2668f4a2713aSLionel Sambuc memberExpr(member(hasName("first")))));
2669f4a2713aSLionel Sambuc }
2670f4a2713aSLionel Sambuc
TEST(Member,DoesNotMatchTheBaseExpression)2671f4a2713aSLionel Sambuc TEST(Member, DoesNotMatchTheBaseExpression) {
2672f4a2713aSLionel Sambuc // Don't pick out the wrong part of the member expression, this should
2673f4a2713aSLionel Sambuc // be checking the member (name) only.
2674f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct { int i; } first; int i(first.i);",
2675f4a2713aSLionel Sambuc memberExpr(member(hasName("first")))));
2676f4a2713aSLionel Sambuc }
2677f4a2713aSLionel Sambuc
TEST(Member,MatchesInMemberFunctionCall)2678f4a2713aSLionel Sambuc TEST(Member, MatchesInMemberFunctionCall) {
2679f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {"
2680f4a2713aSLionel Sambuc " struct { void first() {}; } s;"
2681f4a2713aSLionel Sambuc " s.first();"
2682f4a2713aSLionel Sambuc "};",
2683f4a2713aSLionel Sambuc memberExpr(member(hasName("first")))));
2684f4a2713aSLionel Sambuc }
2685f4a2713aSLionel Sambuc
TEST(Member,MatchesMember)2686f4a2713aSLionel Sambuc TEST(Member, MatchesMember) {
2687f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2688f4a2713aSLionel Sambuc "struct A { int i; }; void f() { A a; a.i = 2; }",
2689f4a2713aSLionel Sambuc memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
2690f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2691f4a2713aSLionel Sambuc "struct A { float f; }; void f() { A a; a.f = 2.0f; }",
2692f4a2713aSLionel Sambuc memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
2693f4a2713aSLionel Sambuc }
2694f4a2713aSLionel Sambuc
TEST(Member,UnderstandsAccess)2695f4a2713aSLionel Sambuc TEST(Member, UnderstandsAccess) {
2696f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2697f4a2713aSLionel Sambuc "struct A { int i; };", fieldDecl(isPublic(), hasName("i"))));
2698f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2699f4a2713aSLionel Sambuc "struct A { int i; };", fieldDecl(isProtected(), hasName("i"))));
2700f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2701f4a2713aSLionel Sambuc "struct A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
2702f4a2713aSLionel Sambuc
2703f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2704f4a2713aSLionel Sambuc "class A { int i; };", fieldDecl(isPublic(), hasName("i"))));
2705f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2706f4a2713aSLionel Sambuc "class A { int i; };", fieldDecl(isProtected(), hasName("i"))));
2707f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2708f4a2713aSLionel Sambuc "class A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
2709f4a2713aSLionel Sambuc
2710f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2711f4a2713aSLionel Sambuc "class A { protected: int i; };", fieldDecl(isPublic(), hasName("i"))));
2712f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class A { protected: int i; };",
2713f4a2713aSLionel Sambuc fieldDecl(isProtected(), hasName("i"))));
2714f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2715f4a2713aSLionel Sambuc "class A { protected: int i; };", fieldDecl(isPrivate(), hasName("i"))));
2716f4a2713aSLionel Sambuc
2717f4a2713aSLionel Sambuc // Non-member decls have the AccessSpecifier AS_none and thus aren't matched.
2718f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i;", varDecl(isPublic(), hasName("i"))));
2719f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i;", varDecl(isProtected(), hasName("i"))));
2720f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i;", varDecl(isPrivate(), hasName("i"))));
2721f4a2713aSLionel Sambuc }
2722f4a2713aSLionel Sambuc
TEST(Member,MatchesMemberAllocationFunction)2723f4a2713aSLionel Sambuc TEST(Member, MatchesMemberAllocationFunction) {
2724f4a2713aSLionel Sambuc // Fails in C++11 mode
2725f4a2713aSLionel Sambuc EXPECT_TRUE(matchesConditionally(
2726f4a2713aSLionel Sambuc "namespace std { typedef typeof(sizeof(int)) size_t; }"
2727f4a2713aSLionel Sambuc "class X { void *operator new(std::size_t); };",
2728f4a2713aSLionel Sambuc methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
2729f4a2713aSLionel Sambuc
2730f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { void operator delete(void*); };",
2731f4a2713aSLionel Sambuc methodDecl(ofClass(hasName("X")))));
2732f4a2713aSLionel Sambuc
2733f4a2713aSLionel Sambuc // Fails in C++11 mode
2734f4a2713aSLionel Sambuc EXPECT_TRUE(matchesConditionally(
2735f4a2713aSLionel Sambuc "namespace std { typedef typeof(sizeof(int)) size_t; }"
2736f4a2713aSLionel Sambuc "class X { void operator delete[](void*, std::size_t); };",
2737f4a2713aSLionel Sambuc methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
2738f4a2713aSLionel Sambuc }
2739f4a2713aSLionel Sambuc
TEST(HasObjectExpression,DoesNotMatchMember)2740f4a2713aSLionel Sambuc TEST(HasObjectExpression, DoesNotMatchMember) {
2741f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
2742f4a2713aSLionel Sambuc "class X {}; struct Z { X m; }; void f(Z z) { z.m; }",
2743f4a2713aSLionel Sambuc memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
2744f4a2713aSLionel Sambuc }
2745f4a2713aSLionel Sambuc
TEST(HasObjectExpression,MatchesBaseOfVariable)2746f4a2713aSLionel Sambuc TEST(HasObjectExpression, MatchesBaseOfVariable) {
2747f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2748f4a2713aSLionel Sambuc "struct X { int m; }; void f(X x) { x.m; }",
2749f4a2713aSLionel Sambuc memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
2750f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2751f4a2713aSLionel Sambuc "struct X { int m; }; void f(X* x) { x->m; }",
2752f4a2713aSLionel Sambuc memberExpr(hasObjectExpression(
2753f4a2713aSLionel Sambuc hasType(pointsTo(recordDecl(hasName("X"))))))));
2754f4a2713aSLionel Sambuc }
2755f4a2713aSLionel Sambuc
TEST(HasObjectExpression,MatchesObjectExpressionOfImplicitlyFormedMemberExpression)2756f4a2713aSLionel Sambuc TEST(HasObjectExpression,
2757f4a2713aSLionel Sambuc MatchesObjectExpressionOfImplicitlyFormedMemberExpression) {
2758f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2759f4a2713aSLionel Sambuc "class X {}; struct S { X m; void f() { this->m; } };",
2760f4a2713aSLionel Sambuc memberExpr(hasObjectExpression(
2761f4a2713aSLionel Sambuc hasType(pointsTo(recordDecl(hasName("S"))))))));
2762f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
2763f4a2713aSLionel Sambuc "class X {}; struct S { X m; void f() { m; } };",
2764f4a2713aSLionel Sambuc memberExpr(hasObjectExpression(
2765f4a2713aSLionel Sambuc hasType(pointsTo(recordDecl(hasName("S"))))))));
2766f4a2713aSLionel Sambuc }
2767f4a2713aSLionel Sambuc
TEST(Field,DoesNotMatchNonFieldMembers)2768f4a2713aSLionel Sambuc TEST(Field, DoesNotMatchNonFieldMembers) {
2769f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { void m(); };", fieldDecl(hasName("m"))));
2770f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { class m {}; };", fieldDecl(hasName("m"))));
2771f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { enum { m }; };", fieldDecl(hasName("m"))));
2772f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { enum m {}; };", fieldDecl(hasName("m"))));
2773f4a2713aSLionel Sambuc }
2774f4a2713aSLionel Sambuc
TEST(Field,MatchesField)2775f4a2713aSLionel Sambuc TEST(Field, MatchesField) {
2776f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class X { int m; };", fieldDecl(hasName("m"))));
2777f4a2713aSLionel Sambuc }
2778f4a2713aSLionel Sambuc
TEST(IsConstQualified,MatchesConstInt)2779f4a2713aSLionel Sambuc TEST(IsConstQualified, MatchesConstInt) {
2780f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const int i = 42;",
2781f4a2713aSLionel Sambuc varDecl(hasType(isConstQualified()))));
2782f4a2713aSLionel Sambuc }
2783f4a2713aSLionel Sambuc
TEST(IsConstQualified,MatchesConstPointer)2784f4a2713aSLionel Sambuc TEST(IsConstQualified, MatchesConstPointer) {
2785f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = 42; int* const p(&i);",
2786f4a2713aSLionel Sambuc varDecl(hasType(isConstQualified()))));
2787f4a2713aSLionel Sambuc }
2788f4a2713aSLionel Sambuc
TEST(IsConstQualified,MatchesThroughTypedef)2789f4a2713aSLionel Sambuc TEST(IsConstQualified, MatchesThroughTypedef) {
2790f4a2713aSLionel Sambuc EXPECT_TRUE(matches("typedef const int const_int; const_int i = 42;",
2791f4a2713aSLionel Sambuc varDecl(hasType(isConstQualified()))));
2792f4a2713aSLionel Sambuc EXPECT_TRUE(matches("typedef int* int_ptr; const int_ptr p(0);",
2793f4a2713aSLionel Sambuc varDecl(hasType(isConstQualified()))));
2794f4a2713aSLionel Sambuc }
2795f4a2713aSLionel Sambuc
TEST(IsConstQualified,DoesNotMatchInappropriately)2796f4a2713aSLionel Sambuc TEST(IsConstQualified, DoesNotMatchInappropriately) {
2797f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("typedef int nonconst_int; nonconst_int i = 42;",
2798f4a2713aSLionel Sambuc varDecl(hasType(isConstQualified()))));
2799f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int const* p;",
2800f4a2713aSLionel Sambuc varDecl(hasType(isConstQualified()))));
2801f4a2713aSLionel Sambuc }
2802f4a2713aSLionel Sambuc
TEST(CastExpression,MatchesExplicitCasts)2803f4a2713aSLionel Sambuc TEST(CastExpression, MatchesExplicitCasts) {
2804f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char *p = reinterpret_cast<char *>(&p);",castExpr()));
2805f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void *p = (void *)(&p);", castExpr()));
2806f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char q, *p = const_cast<char *>(&q);", castExpr()));
2807f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char c = char(0);", castExpr()));
2808f4a2713aSLionel Sambuc }
TEST(CastExpression,MatchesImplicitCasts)2809f4a2713aSLionel Sambuc TEST(CastExpression, MatchesImplicitCasts) {
2810f4a2713aSLionel Sambuc // This test creates an implicit cast from int to char.
2811f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char c = 0;", castExpr()));
2812f4a2713aSLionel Sambuc // This test creates an implicit cast from lvalue to rvalue.
2813f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char c = 0, d = c;", castExpr()));
2814f4a2713aSLionel Sambuc }
2815f4a2713aSLionel Sambuc
TEST(CastExpression,DoesNotMatchNonCasts)2816f4a2713aSLionel Sambuc TEST(CastExpression, DoesNotMatchNonCasts) {
2817f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char c = '0';", castExpr()));
2818f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char c, &q = c;", castExpr()));
2819f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = (0);", castExpr()));
2820f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = 0;", castExpr()));
2821f4a2713aSLionel Sambuc }
2822f4a2713aSLionel Sambuc
TEST(ReinterpretCast,MatchesSimpleCase)2823f4a2713aSLionel Sambuc TEST(ReinterpretCast, MatchesSimpleCase) {
2824f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
2825f4a2713aSLionel Sambuc reinterpretCastExpr()));
2826f4a2713aSLionel Sambuc }
2827f4a2713aSLionel Sambuc
TEST(ReinterpretCast,DoesNotMatchOtherCasts)2828f4a2713aSLionel Sambuc TEST(ReinterpretCast, DoesNotMatchOtherCasts) {
2829f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char* p = (char*)(&p);", reinterpretCastExpr()));
2830f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
2831f4a2713aSLionel Sambuc reinterpretCastExpr()));
2832f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void* p = static_cast<void*>(&p);",
2833f4a2713aSLionel Sambuc reinterpretCastExpr()));
2834f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
2835f4a2713aSLionel Sambuc "B b;"
2836f4a2713aSLionel Sambuc "D* p = dynamic_cast<D*>(&b);",
2837f4a2713aSLionel Sambuc reinterpretCastExpr()));
2838f4a2713aSLionel Sambuc }
2839f4a2713aSLionel Sambuc
TEST(FunctionalCast,MatchesSimpleCase)2840f4a2713aSLionel Sambuc TEST(FunctionalCast, MatchesSimpleCase) {
2841*0a6a1f1dSLionel Sambuc std::string foo_class = "class Foo { public: Foo(const char*); };";
2842f4a2713aSLionel Sambuc EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello world\"); }",
2843f4a2713aSLionel Sambuc functionalCastExpr()));
2844f4a2713aSLionel Sambuc }
2845f4a2713aSLionel Sambuc
TEST(FunctionalCast,DoesNotMatchOtherCasts)2846f4a2713aSLionel Sambuc TEST(FunctionalCast, DoesNotMatchOtherCasts) {
2847*0a6a1f1dSLionel Sambuc std::string FooClass = "class Foo { public: Foo(const char*); };";
2848f4a2713aSLionel Sambuc EXPECT_TRUE(
2849f4a2713aSLionel Sambuc notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
2850f4a2713aSLionel Sambuc functionalCastExpr()));
2851f4a2713aSLionel Sambuc EXPECT_TRUE(
2852f4a2713aSLionel Sambuc notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
2853f4a2713aSLionel Sambuc functionalCastExpr()));
2854f4a2713aSLionel Sambuc }
2855f4a2713aSLionel Sambuc
TEST(DynamicCast,MatchesSimpleCase)2856f4a2713aSLionel Sambuc TEST(DynamicCast, MatchesSimpleCase) {
2857f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"
2858f4a2713aSLionel Sambuc "B b;"
2859f4a2713aSLionel Sambuc "D* p = dynamic_cast<D*>(&b);",
2860f4a2713aSLionel Sambuc dynamicCastExpr()));
2861f4a2713aSLionel Sambuc }
2862f4a2713aSLionel Sambuc
TEST(StaticCast,MatchesSimpleCase)2863f4a2713aSLionel Sambuc TEST(StaticCast, MatchesSimpleCase) {
2864f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void* p(static_cast<void*>(&p));",
2865f4a2713aSLionel Sambuc staticCastExpr()));
2866f4a2713aSLionel Sambuc }
2867f4a2713aSLionel Sambuc
TEST(StaticCast,DoesNotMatchOtherCasts)2868f4a2713aSLionel Sambuc TEST(StaticCast, DoesNotMatchOtherCasts) {
2869f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char* p = (char*)(&p);", staticCastExpr()));
2870f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
2871f4a2713aSLionel Sambuc staticCastExpr()));
2872f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void* p = reinterpret_cast<char*>(&p);",
2873f4a2713aSLionel Sambuc staticCastExpr()));
2874f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
2875f4a2713aSLionel Sambuc "B b;"
2876f4a2713aSLionel Sambuc "D* p = dynamic_cast<D*>(&b);",
2877f4a2713aSLionel Sambuc staticCastExpr()));
2878f4a2713aSLionel Sambuc }
2879f4a2713aSLionel Sambuc
TEST(CStyleCast,MatchesSimpleCase)2880f4a2713aSLionel Sambuc TEST(CStyleCast, MatchesSimpleCase) {
2881f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int i = (int) 2.2f;", cStyleCastExpr()));
2882f4a2713aSLionel Sambuc }
2883f4a2713aSLionel Sambuc
TEST(CStyleCast,DoesNotMatchOtherCasts)2884f4a2713aSLionel Sambuc TEST(CStyleCast, DoesNotMatchOtherCasts) {
2885f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);"
2886f4a2713aSLionel Sambuc "char q, *r = const_cast<char*>(&q);"
2887f4a2713aSLionel Sambuc "void* s = reinterpret_cast<char*>(&s);"
2888f4a2713aSLionel Sambuc "struct B { virtual ~B() {} }; struct D : B {};"
2889f4a2713aSLionel Sambuc "B b;"
2890f4a2713aSLionel Sambuc "D* t = dynamic_cast<D*>(&b);",
2891f4a2713aSLionel Sambuc cStyleCastExpr()));
2892f4a2713aSLionel Sambuc }
2893f4a2713aSLionel Sambuc
TEST(HasDestinationType,MatchesSimpleCase)2894f4a2713aSLionel Sambuc TEST(HasDestinationType, MatchesSimpleCase) {
2895f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
2896f4a2713aSLionel Sambuc staticCastExpr(hasDestinationType(
2897f4a2713aSLionel Sambuc pointsTo(TypeMatcher(anything()))))));
2898f4a2713aSLionel Sambuc }
2899f4a2713aSLionel Sambuc
TEST(HasImplicitDestinationType,MatchesSimpleCase)2900f4a2713aSLionel Sambuc TEST(HasImplicitDestinationType, MatchesSimpleCase) {
2901f4a2713aSLionel Sambuc // This test creates an implicit const cast.
2902f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x; const int i = x;",
2903f4a2713aSLionel Sambuc implicitCastExpr(
2904f4a2713aSLionel Sambuc hasImplicitDestinationType(isInteger()))));
2905f4a2713aSLionel Sambuc // This test creates an implicit array-to-pointer cast.
2906f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int arr[3]; int *p = arr;",
2907f4a2713aSLionel Sambuc implicitCastExpr(hasImplicitDestinationType(
2908f4a2713aSLionel Sambuc pointsTo(TypeMatcher(anything()))))));
2909f4a2713aSLionel Sambuc }
2910f4a2713aSLionel Sambuc
TEST(HasImplicitDestinationType,DoesNotMatchIncorrectly)2911f4a2713aSLionel Sambuc TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {
2912f4a2713aSLionel Sambuc // This test creates an implicit cast from int to char.
2913f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char c = 0;",
2914f4a2713aSLionel Sambuc implicitCastExpr(hasImplicitDestinationType(
2915f4a2713aSLionel Sambuc unless(anything())))));
2916f4a2713aSLionel Sambuc // This test creates an implicit array-to-pointer cast.
2917f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
2918f4a2713aSLionel Sambuc implicitCastExpr(hasImplicitDestinationType(
2919f4a2713aSLionel Sambuc unless(anything())))));
2920f4a2713aSLionel Sambuc }
2921f4a2713aSLionel Sambuc
TEST(ImplicitCast,MatchesSimpleCase)2922f4a2713aSLionel Sambuc TEST(ImplicitCast, MatchesSimpleCase) {
2923f4a2713aSLionel Sambuc // This test creates an implicit const cast.
2924f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0; const int y = x;",
2925f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2926f4a2713aSLionel Sambuc // This test creates an implicit cast from int to char.
2927f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char c = 0;",
2928f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2929f4a2713aSLionel Sambuc // This test creates an implicit array-to-pointer cast.
2930f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int arr[6]; int *p = arr;",
2931f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2932f4a2713aSLionel Sambuc }
2933f4a2713aSLionel Sambuc
TEST(ImplicitCast,DoesNotMatchIncorrectly)2934f4a2713aSLionel Sambuc TEST(ImplicitCast, DoesNotMatchIncorrectly) {
2935f4a2713aSLionel Sambuc // This test verifies that implicitCastExpr() matches exactly when implicit casts
2936f4a2713aSLionel Sambuc // are present, and that it ignores explicit and paren casts.
2937f4a2713aSLionel Sambuc
2938f4a2713aSLionel Sambuc // These two test cases have no casts.
2939f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x = 0;",
2940f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2941f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x = 0, &y = x;",
2942f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2943f4a2713aSLionel Sambuc
2944f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x = 0; double d = (double) x;",
2945f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2946f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("const int *p; int *q = const_cast<int *>(p);",
2947f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2948f4a2713aSLionel Sambuc
2949f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x = (0);",
2950f4a2713aSLionel Sambuc varDecl(hasInitializer(implicitCastExpr()))));
2951f4a2713aSLionel Sambuc }
2952f4a2713aSLionel Sambuc
TEST(IgnoringImpCasts,MatchesImpCasts)2953f4a2713aSLionel Sambuc TEST(IgnoringImpCasts, MatchesImpCasts) {
2954f4a2713aSLionel Sambuc // This test checks that ignoringImpCasts matches when implicit casts are
2955f4a2713aSLionel Sambuc // present and its inner matcher alone does not match.
2956f4a2713aSLionel Sambuc // Note that this test creates an implicit const cast.
2957f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0; const int y = x;",
2958f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2959f4a2713aSLionel Sambuc declRefExpr(to(varDecl(hasName("x")))))))));
2960f4a2713aSLionel Sambuc // This test creates an implict cast from int to char.
2961f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char x = 0;",
2962f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2963f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
2964f4a2713aSLionel Sambuc }
2965f4a2713aSLionel Sambuc
TEST(IgnoringImpCasts,DoesNotMatchIncorrectly)2966f4a2713aSLionel Sambuc TEST(IgnoringImpCasts, DoesNotMatchIncorrectly) {
2967f4a2713aSLionel Sambuc // These tests verify that ignoringImpCasts does not match if the inner
2968f4a2713aSLionel Sambuc // matcher does not match.
2969f4a2713aSLionel Sambuc // Note that the first test creates an implicit const cast.
2970f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x; const int y = x;",
2971f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2972f4a2713aSLionel Sambuc unless(anything()))))));
2973f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x; int y = x;",
2974f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2975f4a2713aSLionel Sambuc unless(anything()))))));
2976f4a2713aSLionel Sambuc
2977f4a2713aSLionel Sambuc // These tests verify that ignoringImplictCasts does not look through explicit
2978f4a2713aSLionel Sambuc // casts or parentheses.
2979f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
2980f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2981f4a2713aSLionel Sambuc integerLiteral())))));
2982f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = (0);",
2983f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2984f4a2713aSLionel Sambuc integerLiteral())))));
2985f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("float i = (float)0;",
2986f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2987f4a2713aSLionel Sambuc integerLiteral())))));
2988f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("float i = float(0);",
2989f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2990f4a2713aSLionel Sambuc integerLiteral())))));
2991f4a2713aSLionel Sambuc }
2992f4a2713aSLionel Sambuc
TEST(IgnoringImpCasts,MatchesWithoutImpCasts)2993f4a2713aSLionel Sambuc TEST(IgnoringImpCasts, MatchesWithoutImpCasts) {
2994f4a2713aSLionel Sambuc // This test verifies that expressions that do not have implicit casts
2995f4a2713aSLionel Sambuc // still match the inner matcher.
2996f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0; int &y = x;",
2997f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringImpCasts(
2998f4a2713aSLionel Sambuc declRefExpr(to(varDecl(hasName("x")))))))));
2999f4a2713aSLionel Sambuc }
3000f4a2713aSLionel Sambuc
TEST(IgnoringParenCasts,MatchesParenCasts)3001f4a2713aSLionel Sambuc TEST(IgnoringParenCasts, MatchesParenCasts) {
3002f4a2713aSLionel Sambuc // This test checks that ignoringParenCasts matches when parentheses and/or
3003f4a2713aSLionel Sambuc // casts are present and its inner matcher alone does not match.
3004f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = (0);",
3005f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3006f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3007f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = (((((0)))));",
3008f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3009f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3010f4a2713aSLionel Sambuc
3011f4a2713aSLionel Sambuc // This test creates an implict cast from int to char in addition to the
3012f4a2713aSLionel Sambuc // parentheses.
3013f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char x = (0);",
3014f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3015f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3016f4a2713aSLionel Sambuc
3017f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char x = (char)0;",
3018f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3019f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3020f4a2713aSLionel Sambuc EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
3021f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3022f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3023f4a2713aSLionel Sambuc }
3024f4a2713aSLionel Sambuc
TEST(IgnoringParenCasts,MatchesWithoutParenCasts)3025f4a2713aSLionel Sambuc TEST(IgnoringParenCasts, MatchesWithoutParenCasts) {
3026f4a2713aSLionel Sambuc // This test verifies that expressions that do not have any casts still match.
3027f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0;",
3028f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3029f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3030f4a2713aSLionel Sambuc }
3031f4a2713aSLionel Sambuc
TEST(IgnoringParenCasts,DoesNotMatchIncorrectly)3032f4a2713aSLionel Sambuc TEST(IgnoringParenCasts, DoesNotMatchIncorrectly) {
3033f4a2713aSLionel Sambuc // These tests verify that ignoringImpCasts does not match if the inner
3034f4a2713aSLionel Sambuc // matcher does not match.
3035f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int x = ((0));",
3036f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3037f4a2713aSLionel Sambuc unless(anything()))))));
3038f4a2713aSLionel Sambuc
3039f4a2713aSLionel Sambuc // This test creates an implicit cast from int to char in addition to the
3040f4a2713aSLionel Sambuc // parentheses.
3041f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char x = ((0));",
3042f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3043f4a2713aSLionel Sambuc unless(anything()))))));
3044f4a2713aSLionel Sambuc
3045f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
3046f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenCasts(
3047f4a2713aSLionel Sambuc unless(anything()))))));
3048f4a2713aSLionel Sambuc }
3049f4a2713aSLionel Sambuc
TEST(IgnoringParenAndImpCasts,MatchesParenImpCasts)3050f4a2713aSLionel Sambuc TEST(IgnoringParenAndImpCasts, MatchesParenImpCasts) {
3051f4a2713aSLionel Sambuc // This test checks that ignoringParenAndImpCasts matches when
3052f4a2713aSLionel Sambuc // parentheses and/or implicit casts are present and its inner matcher alone
3053f4a2713aSLionel Sambuc // does not match.
3054f4a2713aSLionel Sambuc // Note that this test creates an implicit const cast.
3055f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0; const int y = x;",
3056f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3057f4a2713aSLionel Sambuc declRefExpr(to(varDecl(hasName("x")))))))));
3058f4a2713aSLionel Sambuc // This test creates an implicit cast from int to char.
3059f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const char x = (0);",
3060f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3061f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3062f4a2713aSLionel Sambuc }
3063f4a2713aSLionel Sambuc
TEST(IgnoringParenAndImpCasts,MatchesWithoutParenImpCasts)3064f4a2713aSLionel Sambuc TEST(IgnoringParenAndImpCasts, MatchesWithoutParenImpCasts) {
3065f4a2713aSLionel Sambuc // This test verifies that expressions that do not have parentheses or
3066f4a2713aSLionel Sambuc // implicit casts still match.
3067f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0; int &y = x;",
3068f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3069f4a2713aSLionel Sambuc declRefExpr(to(varDecl(hasName("x")))))))));
3070f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int x = 0;",
3071f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3072f4a2713aSLionel Sambuc integerLiteral(equals(0)))))));
3073f4a2713aSLionel Sambuc }
3074f4a2713aSLionel Sambuc
TEST(IgnoringParenAndImpCasts,DoesNotMatchIncorrectly)3075f4a2713aSLionel Sambuc TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {
3076f4a2713aSLionel Sambuc // These tests verify that ignoringParenImpCasts does not match if
3077f4a2713aSLionel Sambuc // the inner matcher does not match.
3078f4a2713aSLionel Sambuc // This test creates an implicit cast.
3079f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char c = ((3));",
3080f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3081f4a2713aSLionel Sambuc unless(anything()))))));
3082f4a2713aSLionel Sambuc // These tests verify that ignoringParenAndImplictCasts does not look
3083f4a2713aSLionel Sambuc // through explicit casts.
3084f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("float y = (float(0));",
3085f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3086f4a2713aSLionel Sambuc integerLiteral())))));
3087f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("float y = (float)0;",
3088f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3089f4a2713aSLionel Sambuc integerLiteral())))));
3090f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
3091f4a2713aSLionel Sambuc varDecl(hasInitializer(ignoringParenImpCasts(
3092f4a2713aSLionel Sambuc integerLiteral())))));
3093f4a2713aSLionel Sambuc }
3094f4a2713aSLionel Sambuc
TEST(HasSourceExpression,MatchesImplicitCasts)3095f4a2713aSLionel Sambuc TEST(HasSourceExpression, MatchesImplicitCasts) {
3096f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
3097f4a2713aSLionel Sambuc "void r() {string a_string; URL url = a_string; }",
3098f4a2713aSLionel Sambuc implicitCastExpr(
3099f4a2713aSLionel Sambuc hasSourceExpression(constructExpr()))));
3100f4a2713aSLionel Sambuc }
3101f4a2713aSLionel Sambuc
TEST(HasSourceExpression,MatchesExplicitCasts)3102f4a2713aSLionel Sambuc TEST(HasSourceExpression, MatchesExplicitCasts) {
3103f4a2713aSLionel Sambuc EXPECT_TRUE(matches("float x = static_cast<float>(42);",
3104f4a2713aSLionel Sambuc explicitCastExpr(
3105f4a2713aSLionel Sambuc hasSourceExpression(hasDescendant(
3106f4a2713aSLionel Sambuc expr(integerLiteral()))))));
3107f4a2713aSLionel Sambuc }
3108f4a2713aSLionel Sambuc
TEST(Statement,DoesNotMatchDeclarations)3109f4a2713aSLionel Sambuc TEST(Statement, DoesNotMatchDeclarations) {
3110f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X {};", stmt()));
3111f4a2713aSLionel Sambuc }
3112f4a2713aSLionel Sambuc
TEST(Statement,MatchesCompoundStatments)3113f4a2713aSLionel Sambuc TEST(Statement, MatchesCompoundStatments) {
3114f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() {}", stmt()));
3115f4a2713aSLionel Sambuc }
3116f4a2713aSLionel Sambuc
TEST(DeclarationStatement,DoesNotMatchCompoundStatements)3117f4a2713aSLionel Sambuc TEST(DeclarationStatement, DoesNotMatchCompoundStatements) {
3118f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() {}", declStmt()));
3119f4a2713aSLionel Sambuc }
3120f4a2713aSLionel Sambuc
TEST(DeclarationStatement,MatchesVariableDeclarationStatements)3121f4a2713aSLionel Sambuc TEST(DeclarationStatement, MatchesVariableDeclarationStatements) {
3122f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { int a; }", declStmt()));
3123f4a2713aSLionel Sambuc }
3124f4a2713aSLionel Sambuc
TEST(ExprWithCleanups,MatchesExprWithCleanups)3125*0a6a1f1dSLionel Sambuc TEST(ExprWithCleanups, MatchesExprWithCleanups) {
3126*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("struct Foo { ~Foo(); };"
3127*0a6a1f1dSLionel Sambuc "const Foo f = Foo();",
3128*0a6a1f1dSLionel Sambuc varDecl(hasInitializer(exprWithCleanups()))));
3129*0a6a1f1dSLionel Sambuc EXPECT_FALSE(matches("struct Foo { };"
3130*0a6a1f1dSLionel Sambuc "const Foo f = Foo();",
3131*0a6a1f1dSLionel Sambuc varDecl(hasInitializer(exprWithCleanups()))));
3132*0a6a1f1dSLionel Sambuc }
3133*0a6a1f1dSLionel Sambuc
TEST(InitListExpression,MatchesInitListExpression)3134f4a2713aSLionel Sambuc TEST(InitListExpression, MatchesInitListExpression) {
3135f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[] = { 1, 2 };",
3136f4a2713aSLionel Sambuc initListExpr(hasType(asString("int [2]")))));
3137f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct B { int x, y; }; B b = { 5, 6 };",
3138f4a2713aSLionel Sambuc initListExpr(hasType(recordDecl(hasName("B"))))));
3139f4a2713aSLionel Sambuc }
3140f4a2713aSLionel Sambuc
TEST(UsingDeclaration,MatchesUsingDeclarations)3141f4a2713aSLionel Sambuc TEST(UsingDeclaration, MatchesUsingDeclarations) {
3142f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace X { int x; } using X::x;",
3143f4a2713aSLionel Sambuc usingDecl()));
3144f4a2713aSLionel Sambuc }
3145f4a2713aSLionel Sambuc
TEST(UsingDeclaration,MatchesShadowUsingDelcarations)3146f4a2713aSLionel Sambuc TEST(UsingDeclaration, MatchesShadowUsingDelcarations) {
3147f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace f { int a; } using f::a;",
3148f4a2713aSLionel Sambuc usingDecl(hasAnyUsingShadowDecl(hasName("a")))));
3149f4a2713aSLionel Sambuc }
3150f4a2713aSLionel Sambuc
TEST(UsingDeclaration,MatchesSpecificTarget)3151f4a2713aSLionel Sambuc TEST(UsingDeclaration, MatchesSpecificTarget) {
3152f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",
3153f4a2713aSLionel Sambuc usingDecl(hasAnyUsingShadowDecl(
3154f4a2713aSLionel Sambuc hasTargetDecl(functionDecl())))));
3155f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",
3156f4a2713aSLionel Sambuc usingDecl(hasAnyUsingShadowDecl(
3157f4a2713aSLionel Sambuc hasTargetDecl(functionDecl())))));
3158f4a2713aSLionel Sambuc }
3159f4a2713aSLionel Sambuc
TEST(UsingDeclaration,ThroughUsingDeclaration)3160f4a2713aSLionel Sambuc TEST(UsingDeclaration, ThroughUsingDeclaration) {
3161f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3162f4a2713aSLionel Sambuc "namespace a { void f(); } using a::f; void g() { f(); }",
3163f4a2713aSLionel Sambuc declRefExpr(throughUsingDecl(anything()))));
3164f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3165f4a2713aSLionel Sambuc "namespace a { void f(); } using a::f; void g() { a::f(); }",
3166f4a2713aSLionel Sambuc declRefExpr(throughUsingDecl(anything()))));
3167f4a2713aSLionel Sambuc }
3168f4a2713aSLionel Sambuc
TEST(UsingDirectiveDeclaration,MatchesUsingNamespace)3169*0a6a1f1dSLionel Sambuc TEST(UsingDirectiveDeclaration, MatchesUsingNamespace) {
3170*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("namespace X { int x; } using namespace X;",
3171*0a6a1f1dSLionel Sambuc usingDirectiveDecl()));
3172*0a6a1f1dSLionel Sambuc EXPECT_FALSE(
3173*0a6a1f1dSLionel Sambuc matches("namespace X { int x; } using X::x;", usingDirectiveDecl()));
3174*0a6a1f1dSLionel Sambuc }
3175*0a6a1f1dSLionel Sambuc
TEST(SingleDecl,IsSingleDecl)3176f4a2713aSLionel Sambuc TEST(SingleDecl, IsSingleDecl) {
3177f4a2713aSLionel Sambuc StatementMatcher SingleDeclStmt =
3178f4a2713aSLionel Sambuc declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));
3179f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt));
3180f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt));
3181f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
3182f4a2713aSLionel Sambuc SingleDeclStmt));
3183f4a2713aSLionel Sambuc }
3184f4a2713aSLionel Sambuc
TEST(DeclStmt,ContainsDeclaration)3185f4a2713aSLionel Sambuc TEST(DeclStmt, ContainsDeclaration) {
3186f4a2713aSLionel Sambuc DeclarationMatcher MatchesInit = varDecl(hasInitializer(anything()));
3187f4a2713aSLionel Sambuc
3188f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {int a = 4;}",
3189f4a2713aSLionel Sambuc declStmt(containsDeclaration(0, MatchesInit))));
3190f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
3191f4a2713aSLionel Sambuc declStmt(containsDeclaration(0, MatchesInit),
3192f4a2713aSLionel Sambuc containsDeclaration(1, MatchesInit))));
3193f4a2713aSLionel Sambuc unsigned WrongIndex = 42;
3194f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
3195f4a2713aSLionel Sambuc declStmt(containsDeclaration(WrongIndex,
3196f4a2713aSLionel Sambuc MatchesInit))));
3197f4a2713aSLionel Sambuc }
3198f4a2713aSLionel Sambuc
TEST(DeclCount,DeclCountIsCorrect)3199f4a2713aSLionel Sambuc TEST(DeclCount, DeclCountIsCorrect) {
3200f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {int i,j;}",
3201f4a2713aSLionel Sambuc declStmt(declCountIs(2))));
3202f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int i,j; int k;}",
3203f4a2713aSLionel Sambuc declStmt(declCountIs(3))));
3204f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int i,j, k, l;}",
3205f4a2713aSLionel Sambuc declStmt(declCountIs(3))));
3206f4a2713aSLionel Sambuc }
3207f4a2713aSLionel Sambuc
TEST(While,MatchesWhileLoops)3208f4a2713aSLionel Sambuc TEST(While, MatchesWhileLoops) {
3209f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() {}", whileStmt()));
3210f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { while(true); }", whileStmt()));
3211f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { do {} while(true); }", whileStmt()));
3212f4a2713aSLionel Sambuc }
3213f4a2713aSLionel Sambuc
TEST(Do,MatchesDoLoops)3214f4a2713aSLionel Sambuc TEST(Do, MatchesDoLoops) {
3215f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { do {} while(true); }", doStmt()));
3216f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { do ; while(false); }", doStmt()));
3217f4a2713aSLionel Sambuc }
3218f4a2713aSLionel Sambuc
TEST(Do,DoesNotMatchWhileLoops)3219f4a2713aSLionel Sambuc TEST(Do, DoesNotMatchWhileLoops) {
3220f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { while(true) {} }", doStmt()));
3221f4a2713aSLionel Sambuc }
3222f4a2713aSLionel Sambuc
TEST(SwitchCase,MatchesCase)3223f4a2713aSLionel Sambuc TEST(SwitchCase, MatchesCase) {
3224f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }", switchCase()));
3225f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) { default:; } }", switchCase()));
3226f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) default:; }", switchCase()));
3227f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { switch(42) {} }", switchCase()));
3228f4a2713aSLionel Sambuc }
3229f4a2713aSLionel Sambuc
TEST(SwitchCase,MatchesSwitch)3230f4a2713aSLionel Sambuc TEST(SwitchCase, MatchesSwitch) {
3231f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }", switchStmt()));
3232f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) { default:; } }", switchStmt()));
3233f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) default:; }", switchStmt()));
3234f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() {}", switchStmt()));
3235f4a2713aSLionel Sambuc }
3236f4a2713aSLionel Sambuc
TEST(SwitchCase,MatchesEachCase)3237f4a2713aSLionel Sambuc TEST(SwitchCase, MatchesEachCase) {
3238f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { switch(42); }",
3239f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(caseStmt()))));
3240f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
3241f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(caseStmt()))));
3242f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
3243f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(caseStmt()))));
3244f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3245f4a2713aSLionel Sambuc "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
3246f4a2713aSLionel Sambuc ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
3247f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void x() { switch(42) { case 1+1: case 4:; } }",
3248f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(
3249f4a2713aSLionel Sambuc caseStmt(hasCaseConstant(integerLiteral()))))));
3250f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { switch(42) { case 1+1: case 2+2:; } }",
3251f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(
3252f4a2713aSLionel Sambuc caseStmt(hasCaseConstant(integerLiteral()))))));
3253f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void x() { switch(42) { case 1 ... 2:; } }",
3254f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(
3255f4a2713aSLionel Sambuc caseStmt(hasCaseConstant(integerLiteral()))))));
3256f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3257f4a2713aSLionel Sambuc "void x() { switch (42) { case 1: case 2: case 3: default:; } }",
3258f4a2713aSLionel Sambuc switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
3259f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CaseStmt>("x", 3)));
3260f4a2713aSLionel Sambuc }
3261f4a2713aSLionel Sambuc
TEST(ForEachConstructorInitializer,MatchesInitializers)3262f4a2713aSLionel Sambuc TEST(ForEachConstructorInitializer, MatchesInitializers) {
3263f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3264f4a2713aSLionel Sambuc "struct X { X() : i(42), j(42) {} int i, j; };",
3265f4a2713aSLionel Sambuc constructorDecl(forEachConstructorInitializer(ctorInitializer()))));
3266f4a2713aSLionel Sambuc }
3267f4a2713aSLionel Sambuc
TEST(ExceptionHandling,SimpleCases)3268f4a2713aSLionel Sambuc TEST(ExceptionHandling, SimpleCases) {
3269f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", catchStmt()));
3270f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", tryStmt()));
3271f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void foo() try { } catch(int X) { }", throwExpr()));
3272f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() try { throw; } catch(int X) { }",
3273f4a2713aSLionel Sambuc throwExpr()));
3274f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void foo() try { throw 5;} catch(int X) { }",
3275f4a2713aSLionel Sambuc throwExpr()));
3276f4a2713aSLionel Sambuc }
3277f4a2713aSLionel Sambuc
TEST(HasConditionVariableStatement,DoesNotMatchCondition)3278f4a2713aSLionel Sambuc TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
3279f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3280f4a2713aSLionel Sambuc "void x() { if(true) {} }",
3281f4a2713aSLionel Sambuc ifStmt(hasConditionVariableStatement(declStmt()))));
3282f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3283f4a2713aSLionel Sambuc "void x() { int x; if((x = 42)) {} }",
3284f4a2713aSLionel Sambuc ifStmt(hasConditionVariableStatement(declStmt()))));
3285f4a2713aSLionel Sambuc }
3286f4a2713aSLionel Sambuc
TEST(HasConditionVariableStatement,MatchesConditionVariables)3287f4a2713aSLionel Sambuc TEST(HasConditionVariableStatement, MatchesConditionVariables) {
3288f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3289f4a2713aSLionel Sambuc "void x() { if(int* a = 0) {} }",
3290f4a2713aSLionel Sambuc ifStmt(hasConditionVariableStatement(declStmt()))));
3291f4a2713aSLionel Sambuc }
3292f4a2713aSLionel Sambuc
TEST(ForEach,BindsOneNode)3293f4a2713aSLionel Sambuc TEST(ForEach, BindsOneNode) {
3294f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
3295f4a2713aSLionel Sambuc recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),
3296f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("x", 1)));
3297f4a2713aSLionel Sambuc }
3298f4a2713aSLionel Sambuc
TEST(ForEach,BindsMultipleNodes)3299f4a2713aSLionel Sambuc TEST(ForEach, BindsMultipleNodes) {
3300f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",
3301f4a2713aSLionel Sambuc recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),
3302f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("f", 3)));
3303f4a2713aSLionel Sambuc }
3304f4a2713aSLionel Sambuc
TEST(ForEach,BindsRecursiveCombinations)3305f4a2713aSLionel Sambuc TEST(ForEach, BindsRecursiveCombinations) {
3306f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3307f4a2713aSLionel Sambuc "class C { class D { int x; int y; }; class E { int y; int z; }; };",
3308f4a2713aSLionel Sambuc recordDecl(hasName("C"),
3309f4a2713aSLionel Sambuc forEach(recordDecl(forEach(fieldDecl().bind("f"))))),
3310f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("f", 4)));
3311f4a2713aSLionel Sambuc }
3312f4a2713aSLionel Sambuc
TEST(ForEachDescendant,BindsOneNode)3313f4a2713aSLionel Sambuc TEST(ForEachDescendant, BindsOneNode) {
3314f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",
3315f4a2713aSLionel Sambuc recordDecl(hasName("C"),
3316f4a2713aSLionel Sambuc forEachDescendant(fieldDecl(hasName("x")).bind("x"))),
3317f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("x", 1)));
3318f4a2713aSLionel Sambuc }
3319f4a2713aSLionel Sambuc
TEST(ForEachDescendant,NestedForEachDescendant)3320f4a2713aSLionel Sambuc TEST(ForEachDescendant, NestedForEachDescendant) {
3321f4a2713aSLionel Sambuc DeclarationMatcher m = recordDecl(
3322f4a2713aSLionel Sambuc isDefinition(), decl().bind("x"), hasName("C"));
3323f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3324f4a2713aSLionel Sambuc "class A { class B { class C {}; }; };",
3325f4a2713aSLionel Sambuc recordDecl(hasName("A"), anyOf(m, forEachDescendant(m))),
3326f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", "C")));
3327f4a2713aSLionel Sambuc
3328f4a2713aSLionel Sambuc // Check that a partial match of 'm' that binds 'x' in the
3329f4a2713aSLionel Sambuc // first part of anyOf(m, anything()) will not overwrite the
3330f4a2713aSLionel Sambuc // binding created by the earlier binding in the hasDescendant.
3331f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3332f4a2713aSLionel Sambuc "class A { class B { class C {}; }; };",
3333f4a2713aSLionel Sambuc recordDecl(hasName("A"), allOf(hasDescendant(m), anyOf(m, anything()))),
3334f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", "C")));
3335f4a2713aSLionel Sambuc }
3336f4a2713aSLionel Sambuc
TEST(ForEachDescendant,BindsMultipleNodes)3337f4a2713aSLionel Sambuc TEST(ForEachDescendant, BindsMultipleNodes) {
3338f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3339f4a2713aSLionel Sambuc "class C { class D { int x; int y; }; "
3340f4a2713aSLionel Sambuc " class E { class F { int y; int z; }; }; };",
3341f4a2713aSLionel Sambuc recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),
3342f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("f", 4)));
3343f4a2713aSLionel Sambuc }
3344f4a2713aSLionel Sambuc
TEST(ForEachDescendant,BindsRecursiveCombinations)3345f4a2713aSLionel Sambuc TEST(ForEachDescendant, BindsRecursiveCombinations) {
3346f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3347f4a2713aSLionel Sambuc "class C { class D { "
3348f4a2713aSLionel Sambuc " class E { class F { class G { int y; int z; }; }; }; }; };",
3349f4a2713aSLionel Sambuc recordDecl(hasName("C"), forEachDescendant(recordDecl(
3350f4a2713aSLionel Sambuc forEachDescendant(fieldDecl().bind("f"))))),
3351f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("f", 8)));
3352f4a2713aSLionel Sambuc }
3353f4a2713aSLionel Sambuc
TEST(ForEachDescendant,BindsCombinations)3354f4a2713aSLionel Sambuc TEST(ForEachDescendant, BindsCombinations) {
3355f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3356f4a2713aSLionel Sambuc "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "
3357f4a2713aSLionel Sambuc "(true) {} }",
3358f4a2713aSLionel Sambuc compoundStmt(forEachDescendant(ifStmt().bind("if")),
3359f4a2713aSLionel Sambuc forEachDescendant(whileStmt().bind("while"))),
3360f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<IfStmt>("if", 6)));
3361f4a2713aSLionel Sambuc }
3362f4a2713aSLionel Sambuc
TEST(Has,DoesNotDeleteBindings)3363f4a2713aSLionel Sambuc TEST(Has, DoesNotDeleteBindings) {
3364f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3365f4a2713aSLionel Sambuc "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),
3366f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3367f4a2713aSLionel Sambuc }
3368f4a2713aSLionel Sambuc
TEST(LoopingMatchers,DoNotOverwritePreviousMatchResultOnFailure)3369f4a2713aSLionel Sambuc TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
3370f4a2713aSLionel Sambuc // Those matchers cover all the cases where an inner matcher is called
3371f4a2713aSLionel Sambuc // and there is not a 1:1 relationship between the match of the outer
3372f4a2713aSLionel Sambuc // matcher and the match of the inner matcher.
3373f4a2713aSLionel Sambuc // The pattern to look for is:
3374f4a2713aSLionel Sambuc // ... return InnerMatcher.matches(...); ...
3375f4a2713aSLionel Sambuc // In which case no special handling is needed.
3376f4a2713aSLionel Sambuc //
3377f4a2713aSLionel Sambuc // On the other hand, if there are multiple alternative matches
3378f4a2713aSLionel Sambuc // (for example forEach*) or matches might be discarded (for example has*)
3379f4a2713aSLionel Sambuc // the implementation must make sure that the discarded matches do not
3380f4a2713aSLionel Sambuc // affect the bindings.
3381f4a2713aSLionel Sambuc // When new such matchers are added, add a test here that:
3382f4a2713aSLionel Sambuc // - matches a simple node, and binds it as the first thing in the matcher:
3383f4a2713aSLionel Sambuc // recordDecl(decl().bind("x"), hasName("X")))
3384f4a2713aSLionel Sambuc // - uses the matcher under test afterwards in a way that not the first
3385f4a2713aSLionel Sambuc // alternative is matched; for anyOf, that means the first branch
3386f4a2713aSLionel Sambuc // would need to return false; for hasAncestor, it means that not
3387f4a2713aSLionel Sambuc // the direct parent matches the inner matcher.
3388f4a2713aSLionel Sambuc
3389f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3390f4a2713aSLionel Sambuc "class X { int y; };",
3391f4a2713aSLionel Sambuc recordDecl(
3392f4a2713aSLionel Sambuc recordDecl().bind("x"), hasName("::X"),
3393f4a2713aSLionel Sambuc anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),
3394f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXRecordDecl>("x", 1)));
3395f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3396f4a2713aSLionel Sambuc "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),
3397f4a2713aSLionel Sambuc anyOf(unless(anything()), anything())),
3398f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXRecordDecl>("x", 1)));
3399f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3400f4a2713aSLionel Sambuc "template<typename T1, typename T2> class X {}; X<float, int> x;",
3401f4a2713aSLionel Sambuc classTemplateSpecializationDecl(
3402f4a2713aSLionel Sambuc decl().bind("x"),
3403f4a2713aSLionel Sambuc hasAnyTemplateArgument(refersToType(asString("int")))),
3404f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3405f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3406f4a2713aSLionel Sambuc "class X { void f(); void g(); };",
3407f4a2713aSLionel Sambuc recordDecl(decl().bind("x"), hasMethod(hasName("g"))),
3408f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3409f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3410f4a2713aSLionel Sambuc "class X { X() : a(1), b(2) {} double a; int b; };",
3411f4a2713aSLionel Sambuc recordDecl(decl().bind("x"),
3412f4a2713aSLionel Sambuc has(constructorDecl(
3413f4a2713aSLionel Sambuc hasAnyConstructorInitializer(forField(hasName("b")))))),
3414f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3415f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3416f4a2713aSLionel Sambuc "void x(int, int) { x(0, 42); }",
3417f4a2713aSLionel Sambuc callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),
3418f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Expr>("x", 1)));
3419f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3420f4a2713aSLionel Sambuc "void x(int, int y) {}",
3421f4a2713aSLionel Sambuc functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),
3422f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3423f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3424f4a2713aSLionel Sambuc "void x() { return; if (true) {} }",
3425f4a2713aSLionel Sambuc functionDecl(decl().bind("x"),
3426f4a2713aSLionel Sambuc has(compoundStmt(hasAnySubstatement(ifStmt())))),
3427f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3428f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3429f4a2713aSLionel Sambuc "namespace X { void b(int); void b(); }"
3430f4a2713aSLionel Sambuc "using X::b;",
3431f4a2713aSLionel Sambuc usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(
3432f4a2713aSLionel Sambuc functionDecl(parameterCountIs(1))))),
3433f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3434f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3435f4a2713aSLionel Sambuc "class A{}; class B{}; class C : B, A {};",
3436f4a2713aSLionel Sambuc recordDecl(decl().bind("x"), isDerivedFrom("::A")),
3437f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3438f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3439f4a2713aSLionel Sambuc "class A{}; typedef A B; typedef A C; typedef A D;"
3440f4a2713aSLionel Sambuc "class E : A {};",
3441f4a2713aSLionel Sambuc recordDecl(decl().bind("x"), isDerivedFrom("C")),
3442f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3443f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3444f4a2713aSLionel Sambuc "class A { class B { void f() {} }; };",
3445f4a2713aSLionel Sambuc functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
3446f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3447f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3448f4a2713aSLionel Sambuc "template <typename T> struct A { struct B {"
3449f4a2713aSLionel Sambuc " void f() { if(true) {} }"
3450f4a2713aSLionel Sambuc "}; };"
3451f4a2713aSLionel Sambuc "void t() { A<int>::B b; b.f(); }",
3452f4a2713aSLionel Sambuc ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
3453f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Stmt>("x", 2)));
3454f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3455f4a2713aSLionel Sambuc "class A {};",
3456f4a2713aSLionel Sambuc recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),
3457f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3458f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3459f4a2713aSLionel Sambuc "class A { A() : s(), i(42) {} const char *s; int i; };",
3460f4a2713aSLionel Sambuc constructorDecl(hasName("::A::A"), decl().bind("x"),
3461f4a2713aSLionel Sambuc forEachConstructorInitializer(forField(hasName("i")))),
3462f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("x", 1)));
3463f4a2713aSLionel Sambuc }
3464f4a2713aSLionel Sambuc
TEST(ForEachDescendant,BindsCorrectNodes)3465f4a2713aSLionel Sambuc TEST(ForEachDescendant, BindsCorrectNodes) {
3466f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3467f4a2713aSLionel Sambuc "class C { void f(); int i; };",
3468f4a2713aSLionel Sambuc recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
3469f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("decl", 1)));
3470f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3471f4a2713aSLionel Sambuc "class C { void f() {} int i; };",
3472f4a2713aSLionel Sambuc recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
3473f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FunctionDecl>("decl", 1)));
3474f4a2713aSLionel Sambuc }
3475f4a2713aSLionel Sambuc
TEST(FindAll,BindsNodeOnMatch)3476f4a2713aSLionel Sambuc TEST(FindAll, BindsNodeOnMatch) {
3477f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3478f4a2713aSLionel Sambuc "class A {};",
3479f4a2713aSLionel Sambuc recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),
3480f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXRecordDecl>("v", 1)));
3481f4a2713aSLionel Sambuc }
3482f4a2713aSLionel Sambuc
TEST(FindAll,BindsDescendantNodeOnMatch)3483f4a2713aSLionel Sambuc TEST(FindAll, BindsDescendantNodeOnMatch) {
3484f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3485f4a2713aSLionel Sambuc "class A { int a; int b; };",
3486f4a2713aSLionel Sambuc recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),
3487f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("v", 2)));
3488f4a2713aSLionel Sambuc }
3489f4a2713aSLionel Sambuc
TEST(FindAll,BindsNodeAndDescendantNodesOnOneMatch)3490f4a2713aSLionel Sambuc TEST(FindAll, BindsNodeAndDescendantNodesOnOneMatch) {
3491f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3492f4a2713aSLionel Sambuc "class A { int a; int b; };",
3493f4a2713aSLionel Sambuc recordDecl(hasName("::A"),
3494f4a2713aSLionel Sambuc findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),
3495f4a2713aSLionel Sambuc fieldDecl().bind("v"))))),
3496f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<Decl>("v", 3)));
3497f4a2713aSLionel Sambuc
3498f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3499f4a2713aSLionel Sambuc "class A { class B {}; class C {}; };",
3500f4a2713aSLionel Sambuc recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),
3501f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXRecordDecl>("v", 3)));
3502f4a2713aSLionel Sambuc }
3503f4a2713aSLionel Sambuc
TEST(EachOf,TriggersForEachMatch)3504f4a2713aSLionel Sambuc TEST(EachOf, TriggersForEachMatch) {
3505f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3506f4a2713aSLionel Sambuc "class A { int a; int b; };",
3507f4a2713aSLionel Sambuc recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3508f4a2713aSLionel Sambuc has(fieldDecl(hasName("b")).bind("v")))),
3509f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("v", 2)));
3510f4a2713aSLionel Sambuc }
3511f4a2713aSLionel Sambuc
TEST(EachOf,BehavesLikeAnyOfUnlessBothMatch)3512f4a2713aSLionel Sambuc TEST(EachOf, BehavesLikeAnyOfUnlessBothMatch) {
3513f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3514f4a2713aSLionel Sambuc "class A { int a; int c; };",
3515f4a2713aSLionel Sambuc recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3516f4a2713aSLionel Sambuc has(fieldDecl(hasName("b")).bind("v")))),
3517f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("v", 1)));
3518f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3519f4a2713aSLionel Sambuc "class A { int c; int b; };",
3520f4a2713aSLionel Sambuc recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3521f4a2713aSLionel Sambuc has(fieldDecl(hasName("b")).bind("v")))),
3522f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FieldDecl>("v", 1)));
3523f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3524f4a2713aSLionel Sambuc "class A { int c; int d; };",
3525f4a2713aSLionel Sambuc recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3526f4a2713aSLionel Sambuc has(fieldDecl(hasName("b")).bind("v"))))));
3527f4a2713aSLionel Sambuc }
3528f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,MatchesImplicitClassTemplateInstantiation)3529f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
3530f4a2713aSLionel Sambuc // Make sure that we can both match the class by name (::X) and by the type
3531f4a2713aSLionel Sambuc // the template was instantiated with (via a field).
3532f4a2713aSLionel Sambuc
3533f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3534f4a2713aSLionel Sambuc "template <typename T> class X {}; class A {}; X<A> x;",
3535f4a2713aSLionel Sambuc recordDecl(hasName("::X"), isTemplateInstantiation())));
3536f4a2713aSLionel Sambuc
3537f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3538f4a2713aSLionel Sambuc "template <typename T> class X { T t; }; class A {}; X<A> x;",
3539f4a2713aSLionel Sambuc recordDecl(isTemplateInstantiation(), hasDescendant(
3540f4a2713aSLionel Sambuc fieldDecl(hasType(recordDecl(hasName("A"))))))));
3541f4a2713aSLionel Sambuc }
3542f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,MatchesImplicitFunctionTemplateInstantiation)3543f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation, MatchesImplicitFunctionTemplateInstantiation) {
3544f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3545f4a2713aSLionel Sambuc "template <typename T> void f(T t) {} class A {}; void g() { f(A()); }",
3546f4a2713aSLionel Sambuc functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
3547f4a2713aSLionel Sambuc isTemplateInstantiation())));
3548f4a2713aSLionel Sambuc }
3549f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,MatchesExplicitClassTemplateInstantiation)3550f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
3551f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3552f4a2713aSLionel Sambuc "template <typename T> class X { T t; }; class A {};"
3553f4a2713aSLionel Sambuc "template class X<A>;",
3554f4a2713aSLionel Sambuc recordDecl(isTemplateInstantiation(), hasDescendant(
3555f4a2713aSLionel Sambuc fieldDecl(hasType(recordDecl(hasName("A"))))))));
3556f4a2713aSLionel Sambuc }
3557f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,MatchesInstantiationOfPartiallySpecializedClassTemplate)3558f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation,
3559f4a2713aSLionel Sambuc MatchesInstantiationOfPartiallySpecializedClassTemplate) {
3560f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3561f4a2713aSLionel Sambuc "template <typename T> class X {};"
3562f4a2713aSLionel Sambuc "template <typename T> class X<T*> {}; class A {}; X<A*> x;",
3563f4a2713aSLionel Sambuc recordDecl(hasName("::X"), isTemplateInstantiation())));
3564f4a2713aSLionel Sambuc }
3565f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,MatchesInstantiationOfClassTemplateNestedInNonTemplate)3566f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation,
3567f4a2713aSLionel Sambuc MatchesInstantiationOfClassTemplateNestedInNonTemplate) {
3568f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3569f4a2713aSLionel Sambuc "class A {};"
3570f4a2713aSLionel Sambuc "class X {"
3571f4a2713aSLionel Sambuc " template <typename U> class Y { U u; };"
3572f4a2713aSLionel Sambuc " Y<A> y;"
3573f4a2713aSLionel Sambuc "};",
3574f4a2713aSLionel Sambuc recordDecl(hasName("::X::Y"), isTemplateInstantiation())));
3575f4a2713aSLionel Sambuc }
3576f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,DoesNotMatchInstantiationsInsideOfInstantiation)3577f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
3578f4a2713aSLionel Sambuc // FIXME: Figure out whether this makes sense. It doesn't affect the
3579f4a2713aSLionel Sambuc // normal use case as long as the uppermost instantiation always is marked
3580f4a2713aSLionel Sambuc // as template instantiation, but it might be confusing as a predicate.
3581f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3582f4a2713aSLionel Sambuc "class A {};"
3583f4a2713aSLionel Sambuc "template <typename T> class X {"
3584f4a2713aSLionel Sambuc " template <typename U> class Y { U u; };"
3585f4a2713aSLionel Sambuc " Y<T> y;"
3586f4a2713aSLionel Sambuc "}; X<A> x;",
3587f4a2713aSLionel Sambuc recordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
3588f4a2713aSLionel Sambuc }
3589f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,DoesNotMatchExplicitClassTemplateSpecialization)3590f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) {
3591f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3592f4a2713aSLionel Sambuc "template <typename T> class X {}; class A {};"
3593f4a2713aSLionel Sambuc "template <> class X<A> {}; X<A> x;",
3594f4a2713aSLionel Sambuc recordDecl(hasName("::X"), isTemplateInstantiation())));
3595f4a2713aSLionel Sambuc }
3596f4a2713aSLionel Sambuc
TEST(IsTemplateInstantiation,DoesNotMatchNonTemplate)3597f4a2713aSLionel Sambuc TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
3598f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3599f4a2713aSLionel Sambuc "class A {}; class Y { A a; };",
3600f4a2713aSLionel Sambuc recordDecl(isTemplateInstantiation())));
3601f4a2713aSLionel Sambuc }
3602f4a2713aSLionel Sambuc
TEST(IsInstantiated,MatchesInstantiation)3603*0a6a1f1dSLionel Sambuc TEST(IsInstantiated, MatchesInstantiation) {
3604*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
3605*0a6a1f1dSLionel Sambuc matches("template<typename T> class A { T i; }; class Y { A<int> a; };",
3606*0a6a1f1dSLionel Sambuc recordDecl(isInstantiated())));
3607*0a6a1f1dSLionel Sambuc }
3608*0a6a1f1dSLionel Sambuc
TEST(IsInstantiated,NotMatchesDefinition)3609*0a6a1f1dSLionel Sambuc TEST(IsInstantiated, NotMatchesDefinition) {
3610*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> class A { T i; };",
3611*0a6a1f1dSLionel Sambuc recordDecl(isInstantiated())));
3612*0a6a1f1dSLionel Sambuc }
3613*0a6a1f1dSLionel Sambuc
TEST(IsInTemplateInstantiation,MatchesInstantiationStmt)3614*0a6a1f1dSLionel Sambuc TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) {
3615*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("template<typename T> struct A { A() { T i; } };"
3616*0a6a1f1dSLionel Sambuc "class Y { A<int> a; }; Y y;",
3617*0a6a1f1dSLionel Sambuc declStmt(isInTemplateInstantiation())));
3618*0a6a1f1dSLionel Sambuc }
3619*0a6a1f1dSLionel Sambuc
TEST(IsInTemplateInstantiation,NotMatchesDefinitionStmt)3620*0a6a1f1dSLionel Sambuc TEST(IsInTemplateInstantiation, NotMatchesDefinitionStmt) {
3621*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> struct A { void x() { T i; } };",
3622*0a6a1f1dSLionel Sambuc declStmt(isInTemplateInstantiation())));
3623*0a6a1f1dSLionel Sambuc }
3624*0a6a1f1dSLionel Sambuc
TEST(IsInstantiated,MatchesFunctionInstantiation)3625*0a6a1f1dSLionel Sambuc TEST(IsInstantiated, MatchesFunctionInstantiation) {
3626*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
3627*0a6a1f1dSLionel Sambuc matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
3628*0a6a1f1dSLionel Sambuc functionDecl(isInstantiated())));
3629*0a6a1f1dSLionel Sambuc }
3630*0a6a1f1dSLionel Sambuc
TEST(IsInstantiated,NotMatchesFunctionDefinition)3631*0a6a1f1dSLionel Sambuc TEST(IsInstantiated, NotMatchesFunctionDefinition) {
3632*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }",
3633*0a6a1f1dSLionel Sambuc varDecl(isInstantiated())));
3634*0a6a1f1dSLionel Sambuc }
3635*0a6a1f1dSLionel Sambuc
TEST(IsInTemplateInstantiation,MatchesFunctionInstantiationStmt)3636*0a6a1f1dSLionel Sambuc TEST(IsInTemplateInstantiation, MatchesFunctionInstantiationStmt) {
3637*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
3638*0a6a1f1dSLionel Sambuc matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
3639*0a6a1f1dSLionel Sambuc declStmt(isInTemplateInstantiation())));
3640*0a6a1f1dSLionel Sambuc }
3641*0a6a1f1dSLionel Sambuc
TEST(IsInTemplateInstantiation,NotMatchesFunctionDefinitionStmt)3642*0a6a1f1dSLionel Sambuc TEST(IsInTemplateInstantiation, NotMatchesFunctionDefinitionStmt) {
3643*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }",
3644*0a6a1f1dSLionel Sambuc declStmt(isInTemplateInstantiation())));
3645*0a6a1f1dSLionel Sambuc }
3646*0a6a1f1dSLionel Sambuc
TEST(IsInTemplateInstantiation,Sharing)3647*0a6a1f1dSLionel Sambuc TEST(IsInTemplateInstantiation, Sharing) {
3648*0a6a1f1dSLionel Sambuc auto Matcher = binaryOperator(unless(isInTemplateInstantiation()));
3649*0a6a1f1dSLionel Sambuc // FIXME: Node sharing is an implementation detail, exposing it is ugly
3650*0a6a1f1dSLionel Sambuc // and makes the matcher behave in non-obvious ways.
3651*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches(
3652*0a6a1f1dSLionel Sambuc "int j; template<typename T> void A(T t) { j += 42; } void x() { A(0); }",
3653*0a6a1f1dSLionel Sambuc Matcher));
3654*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches(
3655*0a6a1f1dSLionel Sambuc "int j; template<typename T> void A(T t) { j += t; } void x() { A(0); }",
3656*0a6a1f1dSLionel Sambuc Matcher));
3657*0a6a1f1dSLionel Sambuc }
3658*0a6a1f1dSLionel Sambuc
TEST(IsExplicitTemplateSpecialization,DoesNotMatchPrimaryTemplate)3659f4a2713aSLionel Sambuc TEST(IsExplicitTemplateSpecialization,
3660f4a2713aSLionel Sambuc DoesNotMatchPrimaryTemplate) {
3661f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3662f4a2713aSLionel Sambuc "template <typename T> class X {};",
3663f4a2713aSLionel Sambuc recordDecl(isExplicitTemplateSpecialization())));
3664f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3665f4a2713aSLionel Sambuc "template <typename T> void f(T t);",
3666f4a2713aSLionel Sambuc functionDecl(isExplicitTemplateSpecialization())));
3667f4a2713aSLionel Sambuc }
3668f4a2713aSLionel Sambuc
TEST(IsExplicitTemplateSpecialization,DoesNotMatchExplicitTemplateInstantiations)3669f4a2713aSLionel Sambuc TEST(IsExplicitTemplateSpecialization,
3670f4a2713aSLionel Sambuc DoesNotMatchExplicitTemplateInstantiations) {
3671f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3672f4a2713aSLionel Sambuc "template <typename T> class X {};"
3673f4a2713aSLionel Sambuc "template class X<int>; extern template class X<long>;",
3674f4a2713aSLionel Sambuc recordDecl(isExplicitTemplateSpecialization())));
3675f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3676f4a2713aSLionel Sambuc "template <typename T> void f(T t) {}"
3677f4a2713aSLionel Sambuc "template void f(int t); extern template void f(long t);",
3678f4a2713aSLionel Sambuc functionDecl(isExplicitTemplateSpecialization())));
3679f4a2713aSLionel Sambuc }
3680f4a2713aSLionel Sambuc
TEST(IsExplicitTemplateSpecialization,DoesNotMatchImplicitTemplateInstantiations)3681f4a2713aSLionel Sambuc TEST(IsExplicitTemplateSpecialization,
3682f4a2713aSLionel Sambuc DoesNotMatchImplicitTemplateInstantiations) {
3683f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3684f4a2713aSLionel Sambuc "template <typename T> class X {}; X<int> x;",
3685f4a2713aSLionel Sambuc recordDecl(isExplicitTemplateSpecialization())));
3686f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3687f4a2713aSLionel Sambuc "template <typename T> void f(T t); void g() { f(10); }",
3688f4a2713aSLionel Sambuc functionDecl(isExplicitTemplateSpecialization())));
3689f4a2713aSLionel Sambuc }
3690f4a2713aSLionel Sambuc
TEST(IsExplicitTemplateSpecialization,MatchesExplicitTemplateSpecializations)3691f4a2713aSLionel Sambuc TEST(IsExplicitTemplateSpecialization,
3692f4a2713aSLionel Sambuc MatchesExplicitTemplateSpecializations) {
3693f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3694f4a2713aSLionel Sambuc "template <typename T> class X {};"
3695f4a2713aSLionel Sambuc "template<> class X<int> {};",
3696f4a2713aSLionel Sambuc recordDecl(isExplicitTemplateSpecialization())));
3697f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3698f4a2713aSLionel Sambuc "template <typename T> void f(T t) {}"
3699f4a2713aSLionel Sambuc "template<> void f(int t) {}",
3700f4a2713aSLionel Sambuc functionDecl(isExplicitTemplateSpecialization())));
3701f4a2713aSLionel Sambuc }
3702f4a2713aSLionel Sambuc
TEST(HasAncenstor,MatchesDeclarationAncestors)3703f4a2713aSLionel Sambuc TEST(HasAncenstor, MatchesDeclarationAncestors) {
3704f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3705f4a2713aSLionel Sambuc "class A { class B { class C {}; }; };",
3706f4a2713aSLionel Sambuc recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));
3707f4a2713aSLionel Sambuc }
3708f4a2713aSLionel Sambuc
TEST(HasAncenstor,FailsIfNoAncestorMatches)3709f4a2713aSLionel Sambuc TEST(HasAncenstor, FailsIfNoAncestorMatches) {
3710f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3711f4a2713aSLionel Sambuc "class A { class B { class C {}; }; };",
3712f4a2713aSLionel Sambuc recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));
3713f4a2713aSLionel Sambuc }
3714f4a2713aSLionel Sambuc
TEST(HasAncestor,MatchesDeclarationsThatGetVisitedLater)3715f4a2713aSLionel Sambuc TEST(HasAncestor, MatchesDeclarationsThatGetVisitedLater) {
3716f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3717f4a2713aSLionel Sambuc "class A { class B { void f() { C c; } class C {}; }; };",
3718f4a2713aSLionel Sambuc varDecl(hasName("c"), hasType(recordDecl(hasName("C"),
3719f4a2713aSLionel Sambuc hasAncestor(recordDecl(hasName("A"))))))));
3720f4a2713aSLionel Sambuc }
3721f4a2713aSLionel Sambuc
TEST(HasAncenstor,MatchesStatementAncestors)3722f4a2713aSLionel Sambuc TEST(HasAncenstor, MatchesStatementAncestors) {
3723f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3724f4a2713aSLionel Sambuc "void f() { if (true) { while (false) { 42; } } }",
3725f4a2713aSLionel Sambuc integerLiteral(equals(42), hasAncestor(ifStmt()))));
3726f4a2713aSLionel Sambuc }
3727f4a2713aSLionel Sambuc
TEST(HasAncestor,DrillsThroughDifferentHierarchies)3728f4a2713aSLionel Sambuc TEST(HasAncestor, DrillsThroughDifferentHierarchies) {
3729f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3730f4a2713aSLionel Sambuc "void f() { if (true) { int x = 42; } }",
3731f4a2713aSLionel Sambuc integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));
3732f4a2713aSLionel Sambuc }
3733f4a2713aSLionel Sambuc
TEST(HasAncestor,BindsRecursiveCombinations)3734f4a2713aSLionel Sambuc TEST(HasAncestor, BindsRecursiveCombinations) {
3735f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3736f4a2713aSLionel Sambuc "class C { class D { class E { class F { int y; }; }; }; };",
3737f4a2713aSLionel Sambuc fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),
3738f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXRecordDecl>("r", 1)));
3739f4a2713aSLionel Sambuc }
3740f4a2713aSLionel Sambuc
TEST(HasAncestor,BindsCombinationsWithHasDescendant)3741f4a2713aSLionel Sambuc TEST(HasAncestor, BindsCombinationsWithHasDescendant) {
3742f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3743f4a2713aSLionel Sambuc "class C { class D { class E { class F { int y; }; }; }; };",
3744f4a2713aSLionel Sambuc fieldDecl(hasAncestor(
3745f4a2713aSLionel Sambuc decl(
3746f4a2713aSLionel Sambuc hasDescendant(recordDecl(isDefinition(),
3747f4a2713aSLionel Sambuc hasAncestor(recordDecl())))
3748f4a2713aSLionel Sambuc ).bind("d")
3749f4a2713aSLionel Sambuc )),
3750f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<CXXRecordDecl>("d", "E")));
3751f4a2713aSLionel Sambuc }
3752f4a2713aSLionel Sambuc
TEST(HasAncestor,MatchesClosestAncestor)3753f4a2713aSLionel Sambuc TEST(HasAncestor, MatchesClosestAncestor) {
3754f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
3755f4a2713aSLionel Sambuc "template <typename T> struct C {"
3756f4a2713aSLionel Sambuc " void f(int) {"
3757f4a2713aSLionel Sambuc " struct I { void g(T) { int x; } } i; i.g(42);"
3758f4a2713aSLionel Sambuc " }"
3759f4a2713aSLionel Sambuc "};"
3760f4a2713aSLionel Sambuc "template struct C<int>;",
3761f4a2713aSLionel Sambuc varDecl(hasName("x"),
3762f4a2713aSLionel Sambuc hasAncestor(functionDecl(hasParameter(
3763f4a2713aSLionel Sambuc 0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),
3764f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<FunctionDecl>("f", "g", 2)));
3765f4a2713aSLionel Sambuc }
3766f4a2713aSLionel Sambuc
TEST(HasAncestor,MatchesInTemplateInstantiations)3767f4a2713aSLionel Sambuc TEST(HasAncestor, MatchesInTemplateInstantiations) {
3768f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3769f4a2713aSLionel Sambuc "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
3770f4a2713aSLionel Sambuc "A<int>::B::C a;",
3771f4a2713aSLionel Sambuc fieldDecl(hasType(asString("int")),
3772f4a2713aSLionel Sambuc hasAncestor(recordDecl(hasName("A"))))));
3773f4a2713aSLionel Sambuc }
3774f4a2713aSLionel Sambuc
TEST(HasAncestor,MatchesInImplicitCode)3775f4a2713aSLionel Sambuc TEST(HasAncestor, MatchesInImplicitCode) {
3776f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3777f4a2713aSLionel Sambuc "struct X {}; struct A { A() {} X x; };",
3778f4a2713aSLionel Sambuc constructorDecl(
3779f4a2713aSLionel Sambuc hasAnyConstructorInitializer(withInitializer(expr(
3780f4a2713aSLionel Sambuc hasAncestor(recordDecl(hasName("A")))))))));
3781f4a2713aSLionel Sambuc }
3782f4a2713aSLionel Sambuc
TEST(HasParent,MatchesOnlyParent)3783f4a2713aSLionel Sambuc TEST(HasParent, MatchesOnlyParent) {
3784f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3785f4a2713aSLionel Sambuc "void f() { if (true) { int x = 42; } }",
3786f4a2713aSLionel Sambuc compoundStmt(hasParent(ifStmt()))));
3787f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3788f4a2713aSLionel Sambuc "void f() { for (;;) { int x = 42; } }",
3789f4a2713aSLionel Sambuc compoundStmt(hasParent(ifStmt()))));
3790f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3791f4a2713aSLionel Sambuc "void f() { if (true) for (;;) { int x = 42; } }",
3792f4a2713aSLionel Sambuc compoundStmt(hasParent(ifStmt()))));
3793f4a2713aSLionel Sambuc }
3794f4a2713aSLionel Sambuc
TEST(HasAncestor,MatchesAllAncestors)3795f4a2713aSLionel Sambuc TEST(HasAncestor, MatchesAllAncestors) {
3796f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3797f4a2713aSLionel Sambuc "template <typename T> struct C { static void f() { 42; } };"
3798f4a2713aSLionel Sambuc "void t() { C<int>::f(); }",
3799f4a2713aSLionel Sambuc integerLiteral(
3800f4a2713aSLionel Sambuc equals(42),
3801f4a2713aSLionel Sambuc allOf(hasAncestor(recordDecl(isTemplateInstantiation())),
3802f4a2713aSLionel Sambuc hasAncestor(recordDecl(unless(isTemplateInstantiation())))))));
3803f4a2713aSLionel Sambuc }
3804f4a2713aSLionel Sambuc
TEST(HasParent,MatchesAllParents)3805f4a2713aSLionel Sambuc TEST(HasParent, MatchesAllParents) {
3806f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3807f4a2713aSLionel Sambuc "template <typename T> struct C { static void f() { 42; } };"
3808f4a2713aSLionel Sambuc "void t() { C<int>::f(); }",
3809f4a2713aSLionel Sambuc integerLiteral(
3810f4a2713aSLionel Sambuc equals(42),
3811f4a2713aSLionel Sambuc hasParent(compoundStmt(hasParent(functionDecl(
3812f4a2713aSLionel Sambuc hasParent(recordDecl(isTemplateInstantiation())))))))));
3813f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3814f4a2713aSLionel Sambuc "template <typename T> struct C { static void f() { 42; } };"
3815f4a2713aSLionel Sambuc "void t() { C<int>::f(); }",
3816f4a2713aSLionel Sambuc integerLiteral(
3817f4a2713aSLionel Sambuc equals(42),
3818f4a2713aSLionel Sambuc hasParent(compoundStmt(hasParent(functionDecl(
3819f4a2713aSLionel Sambuc hasParent(recordDecl(unless(isTemplateInstantiation()))))))))));
3820f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3821f4a2713aSLionel Sambuc "template <typename T> struct C { static void f() { 42; } };"
3822f4a2713aSLionel Sambuc "void t() { C<int>::f(); }",
3823f4a2713aSLionel Sambuc integerLiteral(equals(42),
3824f4a2713aSLionel Sambuc hasParent(compoundStmt(allOf(
3825f4a2713aSLionel Sambuc hasParent(functionDecl(
3826f4a2713aSLionel Sambuc hasParent(recordDecl(isTemplateInstantiation())))),
3827f4a2713aSLionel Sambuc hasParent(functionDecl(hasParent(recordDecl(
3828f4a2713aSLionel Sambuc unless(isTemplateInstantiation())))))))))));
3829f4a2713aSLionel Sambuc EXPECT_TRUE(
3830f4a2713aSLionel Sambuc notMatches("template <typename T> struct C { static void f() {} };"
3831f4a2713aSLionel Sambuc "void t() { C<int>::f(); }",
3832f4a2713aSLionel Sambuc compoundStmt(hasParent(recordDecl()))));
3833f4a2713aSLionel Sambuc }
3834f4a2713aSLionel Sambuc
TEST(HasParent,NoDuplicateParents)3835*0a6a1f1dSLionel Sambuc TEST(HasParent, NoDuplicateParents) {
3836*0a6a1f1dSLionel Sambuc class HasDuplicateParents : public BoundNodesCallback {
3837*0a6a1f1dSLionel Sambuc public:
3838*0a6a1f1dSLionel Sambuc bool run(const BoundNodes *Nodes) override { return false; }
3839*0a6a1f1dSLionel Sambuc bool run(const BoundNodes *Nodes, ASTContext *Context) override {
3840*0a6a1f1dSLionel Sambuc const Stmt *Node = Nodes->getNodeAs<Stmt>("node");
3841*0a6a1f1dSLionel Sambuc std::set<const void *> Parents;
3842*0a6a1f1dSLionel Sambuc for (const auto &Parent : Context->getParents(*Node)) {
3843*0a6a1f1dSLionel Sambuc if (!Parents.insert(Parent.getMemoizationData()).second) {
3844*0a6a1f1dSLionel Sambuc return true;
3845*0a6a1f1dSLionel Sambuc }
3846*0a6a1f1dSLionel Sambuc }
3847*0a6a1f1dSLionel Sambuc return false;
3848*0a6a1f1dSLionel Sambuc }
3849*0a6a1f1dSLionel Sambuc };
3850*0a6a1f1dSLionel Sambuc EXPECT_FALSE(matchAndVerifyResultTrue(
3851*0a6a1f1dSLionel Sambuc "template <typename T> int Foo() { return 1 + 2; }\n"
3852*0a6a1f1dSLionel Sambuc "int x = Foo<int>() + Foo<unsigned>();",
3853*0a6a1f1dSLionel Sambuc stmt().bind("node"), new HasDuplicateParents()));
3854*0a6a1f1dSLionel Sambuc }
3855*0a6a1f1dSLionel Sambuc
TEST(TypeMatching,MatchesTypes)3856f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesTypes) {
3857f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
3858f4a2713aSLionel Sambuc }
3859f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesVoid)3860*0a6a1f1dSLionel Sambuc TEST(TypeMatching, MatchesVoid) {
3861*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
3862*0a6a1f1dSLionel Sambuc matches("struct S { void func(); };", methodDecl(returns(voidType()))));
3863*0a6a1f1dSLionel Sambuc }
3864*0a6a1f1dSLionel Sambuc
TEST(TypeMatching,MatchesArrayTypes)3865f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesArrayTypes) {
3866f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[] = {2,3};", arrayType()));
3867f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[42];", arrayType()));
3868f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(int b) { int a[b]; }", arrayType()));
3869f4a2713aSLionel Sambuc
3870f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct A {}; A a[7];",
3871f4a2713aSLionel Sambuc arrayType(hasElementType(builtinType()))));
3872f4a2713aSLionel Sambuc
3873f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3874f4a2713aSLionel Sambuc "int const a[] = { 2, 3 };",
3875f4a2713aSLionel Sambuc qualType(arrayType(hasElementType(builtinType())))));
3876f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3877f4a2713aSLionel Sambuc "int const a[] = { 2, 3 };",
3878f4a2713aSLionel Sambuc qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
3879f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3880f4a2713aSLionel Sambuc "typedef const int T; T x[] = { 1, 2 };",
3881f4a2713aSLionel Sambuc qualType(isConstQualified(), arrayType())));
3882f4a2713aSLionel Sambuc
3883f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3884f4a2713aSLionel Sambuc "int a[] = { 2, 3 };",
3885f4a2713aSLionel Sambuc qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
3886f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3887f4a2713aSLionel Sambuc "int a[] = { 2, 3 };",
3888f4a2713aSLionel Sambuc qualType(arrayType(hasElementType(isConstQualified(), builtinType())))));
3889f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3890f4a2713aSLionel Sambuc "int const a[] = { 2, 3 };",
3891f4a2713aSLionel Sambuc qualType(arrayType(hasElementType(builtinType())),
3892f4a2713aSLionel Sambuc unless(isConstQualified()))));
3893f4a2713aSLionel Sambuc
3894f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[2];",
3895f4a2713aSLionel Sambuc constantArrayType(hasElementType(builtinType()))));
3896f4a2713aSLionel Sambuc EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger())));
3897f4a2713aSLionel Sambuc }
3898f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesComplexTypes)3899f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesComplexTypes) {
3900f4a2713aSLionel Sambuc EXPECT_TRUE(matches("_Complex float f;", complexType()));
3901f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3902f4a2713aSLionel Sambuc "_Complex float f;",
3903f4a2713aSLionel Sambuc complexType(hasElementType(builtinType()))));
3904f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3905f4a2713aSLionel Sambuc "_Complex float f;",
3906f4a2713aSLionel Sambuc complexType(hasElementType(isInteger()))));
3907f4a2713aSLionel Sambuc }
3908f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesConstantArrayTypes)3909f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesConstantArrayTypes) {
3910f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[2];", constantArrayType()));
3911f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3912f4a2713aSLionel Sambuc "void f() { int a[] = { 2, 3 }; int b[a[0]]; }",
3913f4a2713aSLionel Sambuc constantArrayType(hasElementType(builtinType()))));
3914f4a2713aSLionel Sambuc
3915f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[42];", constantArrayType(hasSize(42))));
3916f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int b[2*21];", constantArrayType(hasSize(42))));
3917f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int c[41], d[43];", constantArrayType(hasSize(42))));
3918f4a2713aSLionel Sambuc }
3919f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesDependentSizedArrayTypes)3920f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesDependentSizedArrayTypes) {
3921f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3922f4a2713aSLionel Sambuc "template <typename T, int Size> class array { T data[Size]; };",
3923f4a2713aSLionel Sambuc dependentSizedArrayType()));
3924f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3925f4a2713aSLionel Sambuc "int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }",
3926f4a2713aSLionel Sambuc dependentSizedArrayType()));
3927f4a2713aSLionel Sambuc }
3928f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesIncompleteArrayType)3929f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesIncompleteArrayType) {
3930f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int a[] = { 2, 3 };", incompleteArrayType()));
3931f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(int a[]) {}", incompleteArrayType()));
3932f4a2713aSLionel Sambuc
3933f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int a[42]; void f() { int b[a[0]]; }",
3934f4a2713aSLionel Sambuc incompleteArrayType()));
3935f4a2713aSLionel Sambuc }
3936f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesVariableArrayType)3937f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesVariableArrayType) {
3938f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(int b) { int a[b]; }", variableArrayType()));
3939f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int a[] = {2, 3}; int b[42];", variableArrayType()));
3940f4a2713aSLionel Sambuc
3941f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3942f4a2713aSLionel Sambuc "void f(int b) { int a[b]; }",
3943f4a2713aSLionel Sambuc variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
3944f4a2713aSLionel Sambuc varDecl(hasName("b")))))))));
3945f4a2713aSLionel Sambuc }
3946f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesAtomicTypes)3947f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesAtomicTypes) {
3948*0a6a1f1dSLionel Sambuc if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getOS() !=
3949*0a6a1f1dSLionel Sambuc llvm::Triple::Win32) {
3950*0a6a1f1dSLionel Sambuc // FIXME: Make this work for MSVC.
3951f4a2713aSLionel Sambuc EXPECT_TRUE(matches("_Atomic(int) i;", atomicType()));
3952f4a2713aSLionel Sambuc
3953f4a2713aSLionel Sambuc EXPECT_TRUE(matches("_Atomic(int) i;",
3954f4a2713aSLionel Sambuc atomicType(hasValueType(isInteger()))));
3955f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("_Atomic(float) f;",
3956f4a2713aSLionel Sambuc atomicType(hasValueType(isInteger()))));
3957f4a2713aSLionel Sambuc }
3958*0a6a1f1dSLionel Sambuc }
3959f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesAutoTypes)3960f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesAutoTypes) {
3961f4a2713aSLionel Sambuc EXPECT_TRUE(matches("auto i = 2;", autoType()));
3962f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int v[] = { 2, 3 }; void f() { for (int i : v) {} }",
3963f4a2713aSLionel Sambuc autoType()));
3964f4a2713aSLionel Sambuc
3965f4a2713aSLionel Sambuc // FIXME: Matching against the type-as-written can't work here, because the
3966f4a2713aSLionel Sambuc // type as written was not deduced.
3967f4a2713aSLionel Sambuc //EXPECT_TRUE(matches("auto a = 1;",
3968f4a2713aSLionel Sambuc // autoType(hasDeducedType(isInteger()))));
3969f4a2713aSLionel Sambuc //EXPECT_TRUE(notMatches("auto b = 2.0;",
3970f4a2713aSLionel Sambuc // autoType(hasDeducedType(isInteger()))));
3971f4a2713aSLionel Sambuc }
3972f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesFunctionTypes)3973f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesFunctionTypes) {
3974f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int (*f)(int);", functionType()));
3975f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f(int i) {}", functionType()));
3976f4a2713aSLionel Sambuc }
3977f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesParenType)3978f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesParenType) {
3979f4a2713aSLionel Sambuc EXPECT_TRUE(
3980f4a2713aSLionel Sambuc matches("int (*array)[4];", varDecl(hasType(pointsTo(parenType())))));
3981f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int *array[4];", varDecl(hasType(parenType()))));
3982f4a2713aSLionel Sambuc
3983f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
3984f4a2713aSLionel Sambuc "int (*ptr_to_func)(int);",
3985f4a2713aSLionel Sambuc varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));
3986f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
3987f4a2713aSLionel Sambuc "int (*ptr_to_array)[4];",
3988f4a2713aSLionel Sambuc varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));
3989f4a2713aSLionel Sambuc }
3990f4a2713aSLionel Sambuc
TEST(TypeMatching,PointerTypes)3991f4a2713aSLionel Sambuc TEST(TypeMatching, PointerTypes) {
3992f4a2713aSLionel Sambuc // FIXME: Reactive when these tests can be more specific (not matching
3993f4a2713aSLionel Sambuc // implicit code on certain platforms), likely when we have hasDescendant for
3994f4a2713aSLionel Sambuc // Types/TypeLocs.
3995f4a2713aSLionel Sambuc //EXPECT_TRUE(matchAndVerifyResultTrue(
3996f4a2713aSLionel Sambuc // "int* a;",
3997f4a2713aSLionel Sambuc // pointerTypeLoc(pointeeLoc(typeLoc().bind("loc"))),
3998f4a2713aSLionel Sambuc // new VerifyIdIsBoundTo<TypeLoc>("loc", 1)));
3999f4a2713aSLionel Sambuc //EXPECT_TRUE(matchAndVerifyResultTrue(
4000f4a2713aSLionel Sambuc // "int* a;",
4001f4a2713aSLionel Sambuc // pointerTypeLoc().bind("loc"),
4002f4a2713aSLionel Sambuc // new VerifyIdIsBoundTo<TypeLoc>("loc", 1)));
4003f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4004f4a2713aSLionel Sambuc "int** a;",
4005f4a2713aSLionel Sambuc loc(pointerType(pointee(qualType())))));
4006f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4007f4a2713aSLionel Sambuc "int** a;",
4008f4a2713aSLionel Sambuc loc(pointerType(pointee(pointerType())))));
4009f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4010f4a2713aSLionel Sambuc "int* b; int* * const a = &b;",
4011f4a2713aSLionel Sambuc loc(qualType(isConstQualified(), pointerType()))));
4012f4a2713aSLionel Sambuc
4013f4a2713aSLionel Sambuc std::string Fragment = "struct A { int i; }; int A::* ptr = &A::i;";
4014f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4015f4a2713aSLionel Sambuc hasType(blockPointerType()))));
4016f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("ptr"),
4017f4a2713aSLionel Sambuc hasType(memberPointerType()))));
4018f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4019f4a2713aSLionel Sambuc hasType(pointerType()))));
4020f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4021f4a2713aSLionel Sambuc hasType(referenceType()))));
4022f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4023f4a2713aSLionel Sambuc hasType(lValueReferenceType()))));
4024f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4025f4a2713aSLionel Sambuc hasType(rValueReferenceType()))));
4026f4a2713aSLionel Sambuc
4027f4a2713aSLionel Sambuc Fragment = "int *ptr;";
4028f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4029f4a2713aSLionel Sambuc hasType(blockPointerType()))));
4030f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4031f4a2713aSLionel Sambuc hasType(memberPointerType()))));
4032f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("ptr"),
4033f4a2713aSLionel Sambuc hasType(pointerType()))));
4034f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
4035f4a2713aSLionel Sambuc hasType(referenceType()))));
4036f4a2713aSLionel Sambuc
4037f4a2713aSLionel Sambuc Fragment = "int a; int &ref = a;";
4038f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4039f4a2713aSLionel Sambuc hasType(blockPointerType()))));
4040f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4041f4a2713aSLionel Sambuc hasType(memberPointerType()))));
4042f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4043f4a2713aSLionel Sambuc hasType(pointerType()))));
4044f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("ref"),
4045f4a2713aSLionel Sambuc hasType(referenceType()))));
4046f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("ref"),
4047f4a2713aSLionel Sambuc hasType(lValueReferenceType()))));
4048f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4049f4a2713aSLionel Sambuc hasType(rValueReferenceType()))));
4050f4a2713aSLionel Sambuc
4051f4a2713aSLionel Sambuc Fragment = "int &&ref = 2;";
4052f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4053f4a2713aSLionel Sambuc hasType(blockPointerType()))));
4054f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4055f4a2713aSLionel Sambuc hasType(memberPointerType()))));
4056f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4057f4a2713aSLionel Sambuc hasType(pointerType()))));
4058f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("ref"),
4059f4a2713aSLionel Sambuc hasType(referenceType()))));
4060f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
4061f4a2713aSLionel Sambuc hasType(lValueReferenceType()))));
4062f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("ref"),
4063f4a2713aSLionel Sambuc hasType(rValueReferenceType()))));
4064f4a2713aSLionel Sambuc }
4065f4a2713aSLionel Sambuc
TEST(TypeMatching,AutoRefTypes)4066f4a2713aSLionel Sambuc TEST(TypeMatching, AutoRefTypes) {
4067f4a2713aSLionel Sambuc std::string Fragment = "auto a = 1;"
4068f4a2713aSLionel Sambuc "auto b = a;"
4069f4a2713aSLionel Sambuc "auto &c = a;"
4070f4a2713aSLionel Sambuc "auto &&d = c;"
4071f4a2713aSLionel Sambuc "auto &&e = 2;";
4072f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("a"),
4073f4a2713aSLionel Sambuc hasType(referenceType()))));
4074f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("b"),
4075f4a2713aSLionel Sambuc hasType(referenceType()))));
4076f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("c"),
4077f4a2713aSLionel Sambuc hasType(referenceType()))));
4078f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("c"),
4079f4a2713aSLionel Sambuc hasType(lValueReferenceType()))));
4080f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("c"),
4081f4a2713aSLionel Sambuc hasType(rValueReferenceType()))));
4082f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("d"),
4083f4a2713aSLionel Sambuc hasType(referenceType()))));
4084f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("d"),
4085f4a2713aSLionel Sambuc hasType(lValueReferenceType()))));
4086f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("d"),
4087f4a2713aSLionel Sambuc hasType(rValueReferenceType()))));
4088f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("e"),
4089f4a2713aSLionel Sambuc hasType(referenceType()))));
4090f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("e"),
4091f4a2713aSLionel Sambuc hasType(lValueReferenceType()))));
4092f4a2713aSLionel Sambuc EXPECT_TRUE(matches(Fragment, varDecl(hasName("e"),
4093f4a2713aSLionel Sambuc hasType(rValueReferenceType()))));
4094f4a2713aSLionel Sambuc }
4095f4a2713aSLionel Sambuc
TEST(TypeMatching,PointeeTypes)4096f4a2713aSLionel Sambuc TEST(TypeMatching, PointeeTypes) {
4097f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int b; int &a = b;",
4098f4a2713aSLionel Sambuc referenceType(pointee(builtinType()))));
4099f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));
4100f4a2713aSLionel Sambuc
4101f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int *a;",
4102f4a2713aSLionel Sambuc loc(pointerType(pointee(builtinType())))));
4103f4a2713aSLionel Sambuc
4104f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4105f4a2713aSLionel Sambuc "int const *A;",
4106f4a2713aSLionel Sambuc pointerType(pointee(isConstQualified(), builtinType()))));
4107f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4108f4a2713aSLionel Sambuc "int *A;",
4109f4a2713aSLionel Sambuc pointerType(pointee(isConstQualified(), builtinType()))));
4110f4a2713aSLionel Sambuc }
4111f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesPointersToConstTypes)4112f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesPointersToConstTypes) {
4113f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int b; int * const a = &b;",
4114f4a2713aSLionel Sambuc loc(pointerType())));
4115f4a2713aSLionel Sambuc EXPECT_TRUE(matches("int b; int * const a = &b;",
4116f4a2713aSLionel Sambuc loc(pointerType())));
4117f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4118f4a2713aSLionel Sambuc "int b; const int * a = &b;",
4119f4a2713aSLionel Sambuc loc(pointerType(pointee(builtinType())))));
4120f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4121f4a2713aSLionel Sambuc "int b; const int * a = &b;",
4122f4a2713aSLionel Sambuc pointerType(pointee(builtinType()))));
4123f4a2713aSLionel Sambuc }
4124f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesTypedefTypes)4125f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesTypedefTypes) {
4126f4a2713aSLionel Sambuc EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"),
4127f4a2713aSLionel Sambuc hasType(typedefType()))));
4128f4a2713aSLionel Sambuc }
4129f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesTemplateSpecializationType)4130f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesTemplateSpecializationType) {
4131f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template <typename T> class A{}; A<int> a;",
4132f4a2713aSLionel Sambuc templateSpecializationType()));
4133f4a2713aSLionel Sambuc }
4134f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesRecordType)4135f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesRecordType) {
4136f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class C{}; C c;", recordType()));
4137f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct S{}; S s;",
4138f4a2713aSLionel Sambuc recordType(hasDeclaration(recordDecl(hasName("S"))))));
4139f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i;",
4140f4a2713aSLionel Sambuc recordType(hasDeclaration(recordDecl(hasName("S"))))));
4141f4a2713aSLionel Sambuc }
4142f4a2713aSLionel Sambuc
TEST(TypeMatching,MatchesElaboratedType)4143f4a2713aSLionel Sambuc TEST(TypeMatching, MatchesElaboratedType) {
4144f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4145f4a2713aSLionel Sambuc "namespace N {"
4146f4a2713aSLionel Sambuc " namespace M {"
4147f4a2713aSLionel Sambuc " class D {};"
4148f4a2713aSLionel Sambuc " }"
4149f4a2713aSLionel Sambuc "}"
4150f4a2713aSLionel Sambuc "N::M::D d;", elaboratedType()));
4151f4a2713aSLionel Sambuc EXPECT_TRUE(matches("class C {} c;", elaboratedType()));
4152f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class C {}; C c;", elaboratedType()));
4153f4a2713aSLionel Sambuc }
4154f4a2713aSLionel Sambuc
TEST(ElaboratedTypeNarrowing,hasQualifier)4155f4a2713aSLionel Sambuc TEST(ElaboratedTypeNarrowing, hasQualifier) {
4156f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4157f4a2713aSLionel Sambuc "namespace N {"
4158f4a2713aSLionel Sambuc " namespace M {"
4159f4a2713aSLionel Sambuc " class D {};"
4160f4a2713aSLionel Sambuc " }"
4161f4a2713aSLionel Sambuc "}"
4162f4a2713aSLionel Sambuc "N::M::D d;",
4163f4a2713aSLionel Sambuc elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
4164f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4165f4a2713aSLionel Sambuc "namespace M {"
4166f4a2713aSLionel Sambuc " class D {};"
4167f4a2713aSLionel Sambuc "}"
4168f4a2713aSLionel Sambuc "M::D d;",
4169f4a2713aSLionel Sambuc elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
4170f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4171f4a2713aSLionel Sambuc "struct D {"
4172f4a2713aSLionel Sambuc "} d;",
4173f4a2713aSLionel Sambuc elaboratedType(hasQualifier(nestedNameSpecifier()))));
4174f4a2713aSLionel Sambuc }
4175f4a2713aSLionel Sambuc
TEST(ElaboratedTypeNarrowing,namesType)4176f4a2713aSLionel Sambuc TEST(ElaboratedTypeNarrowing, namesType) {
4177f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4178f4a2713aSLionel Sambuc "namespace N {"
4179f4a2713aSLionel Sambuc " namespace M {"
4180f4a2713aSLionel Sambuc " class D {};"
4181f4a2713aSLionel Sambuc " }"
4182f4a2713aSLionel Sambuc "}"
4183f4a2713aSLionel Sambuc "N::M::D d;",
4184f4a2713aSLionel Sambuc elaboratedType(elaboratedType(namesType(recordType(
4185f4a2713aSLionel Sambuc hasDeclaration(namedDecl(hasName("D")))))))));
4186f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4187f4a2713aSLionel Sambuc "namespace M {"
4188f4a2713aSLionel Sambuc " class D {};"
4189f4a2713aSLionel Sambuc "}"
4190f4a2713aSLionel Sambuc "M::D d;",
4191f4a2713aSLionel Sambuc elaboratedType(elaboratedType(namesType(typedefType())))));
4192f4a2713aSLionel Sambuc }
4193f4a2713aSLionel Sambuc
TEST(NNS,MatchesNestedNameSpecifiers)4194f4a2713aSLionel Sambuc TEST(NNS, MatchesNestedNameSpecifiers) {
4195f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;",
4196f4a2713aSLionel Sambuc nestedNameSpecifier()));
4197f4a2713aSLionel Sambuc EXPECT_TRUE(matches("template <typename T> class A { typename T::B b; };",
4198f4a2713aSLionel Sambuc nestedNameSpecifier()));
4199f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct A { void f(); }; void A::f() {}",
4200f4a2713aSLionel Sambuc nestedNameSpecifier()));
4201f4a2713aSLionel Sambuc
4202f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4203f4a2713aSLionel Sambuc "struct A { static void f() {} }; void g() { A::f(); }",
4204f4a2713aSLionel Sambuc nestedNameSpecifier()));
4205f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4206f4a2713aSLionel Sambuc "struct A { static void f() {} }; void g(A* a) { a->f(); }",
4207f4a2713aSLionel Sambuc nestedNameSpecifier()));
4208f4a2713aSLionel Sambuc }
4209f4a2713aSLionel Sambuc
TEST(NullStatement,SimpleCases)4210f4a2713aSLionel Sambuc TEST(NullStatement, SimpleCases) {
4211f4a2713aSLionel Sambuc EXPECT_TRUE(matches("void f() {int i;;}", nullStmt()));
4212f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt()));
4213f4a2713aSLionel Sambuc }
4214f4a2713aSLionel Sambuc
TEST(NNS,MatchesTypes)4215f4a2713aSLionel Sambuc TEST(NNS, MatchesTypes) {
4216f4a2713aSLionel Sambuc NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
4217f4a2713aSLionel Sambuc specifiesType(hasDeclaration(recordDecl(hasName("A")))));
4218f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct A { struct B {}; }; A::B b;", Matcher));
4219f4a2713aSLionel Sambuc EXPECT_TRUE(matches("struct A { struct B { struct C {}; }; }; A::B::C c;",
4220f4a2713aSLionel Sambuc Matcher));
4221f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace A { struct B {}; } A::B b;", Matcher));
4222f4a2713aSLionel Sambuc }
4223f4a2713aSLionel Sambuc
TEST(NNS,MatchesNamespaceDecls)4224f4a2713aSLionel Sambuc TEST(NNS, MatchesNamespaceDecls) {
4225f4a2713aSLionel Sambuc NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
4226f4a2713aSLionel Sambuc specifiesNamespace(hasName("ns")));
4227f4a2713aSLionel Sambuc EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;", Matcher));
4228f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("namespace xx { struct A {}; } xx::A a;", Matcher));
4229f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("struct ns { struct A {}; }; ns::A a;", Matcher));
4230f4a2713aSLionel Sambuc }
4231f4a2713aSLionel Sambuc
TEST(NNS,BindsNestedNameSpecifiers)4232f4a2713aSLionel Sambuc TEST(NNS, BindsNestedNameSpecifiers) {
4233f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4234f4a2713aSLionel Sambuc "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
4235f4a2713aSLionel Sambuc nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
4236f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<NestedNameSpecifier>("nns", "ns::struct E::")));
4237f4a2713aSLionel Sambuc }
4238f4a2713aSLionel Sambuc
TEST(NNS,BindsNestedNameSpecifierLocs)4239f4a2713aSLionel Sambuc TEST(NNS, BindsNestedNameSpecifierLocs) {
4240f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4241f4a2713aSLionel Sambuc "namespace ns { struct B {}; } ns::B b;",
4242f4a2713aSLionel Sambuc loc(nestedNameSpecifier()).bind("loc"),
4243f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<NestedNameSpecifierLoc>("loc", 1)));
4244f4a2713aSLionel Sambuc }
4245f4a2713aSLionel Sambuc
TEST(NNS,MatchesNestedNameSpecifierPrefixes)4246f4a2713aSLionel Sambuc TEST(NNS, MatchesNestedNameSpecifierPrefixes) {
4247f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4248f4a2713aSLionel Sambuc "struct A { struct B { struct C {}; }; }; A::B::C c;",
4249f4a2713aSLionel Sambuc nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A"))))));
4250f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4251f4a2713aSLionel Sambuc "struct A { struct B { struct C {}; }; }; A::B::C c;",
4252f4a2713aSLionel Sambuc nestedNameSpecifierLoc(hasPrefix(
4253f4a2713aSLionel Sambuc specifiesTypeLoc(loc(qualType(asString("struct A"))))))));
4254f4a2713aSLionel Sambuc }
4255f4a2713aSLionel Sambuc
TEST(NNS,DescendantsOfNestedNameSpecifiers)4256f4a2713aSLionel Sambuc TEST(NNS, DescendantsOfNestedNameSpecifiers) {
4257f4a2713aSLionel Sambuc std::string Fragment =
4258f4a2713aSLionel Sambuc "namespace a { struct A { struct B { struct C {}; }; }; };"
4259f4a2713aSLionel Sambuc "void f() { a::A::B::C c; }";
4260f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4261f4a2713aSLionel Sambuc Fragment,
4262f4a2713aSLionel Sambuc nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
4263f4a2713aSLionel Sambuc hasDescendant(nestedNameSpecifier(
4264f4a2713aSLionel Sambuc specifiesNamespace(hasName("a")))))));
4265f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4266f4a2713aSLionel Sambuc Fragment,
4267f4a2713aSLionel Sambuc nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
4268f4a2713aSLionel Sambuc has(nestedNameSpecifier(
4269f4a2713aSLionel Sambuc specifiesNamespace(hasName("a")))))));
4270f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4271f4a2713aSLionel Sambuc Fragment,
4272f4a2713aSLionel Sambuc nestedNameSpecifier(specifiesType(asString("struct a::A")),
4273f4a2713aSLionel Sambuc has(nestedNameSpecifier(
4274f4a2713aSLionel Sambuc specifiesNamespace(hasName("a")))))));
4275f4a2713aSLionel Sambuc
4276f4a2713aSLionel Sambuc // Not really useful because a NestedNameSpecifier can af at most one child,
4277f4a2713aSLionel Sambuc // but to complete the interface.
4278f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4279f4a2713aSLionel Sambuc Fragment,
4280f4a2713aSLionel Sambuc nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
4281f4a2713aSLionel Sambuc forEach(nestedNameSpecifier().bind("x"))),
4282f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<NestedNameSpecifier>("x", 1)));
4283f4a2713aSLionel Sambuc }
4284f4a2713aSLionel Sambuc
TEST(NNS,NestedNameSpecifiersAsDescendants)4285f4a2713aSLionel Sambuc TEST(NNS, NestedNameSpecifiersAsDescendants) {
4286f4a2713aSLionel Sambuc std::string Fragment =
4287f4a2713aSLionel Sambuc "namespace a { struct A { struct B { struct C {}; }; }; };"
4288f4a2713aSLionel Sambuc "void f() { a::A::B::C c; }";
4289f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4290f4a2713aSLionel Sambuc Fragment,
4291f4a2713aSLionel Sambuc decl(hasDescendant(nestedNameSpecifier(specifiesType(
4292f4a2713aSLionel Sambuc asString("struct a::A")))))));
4293f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4294f4a2713aSLionel Sambuc Fragment,
4295f4a2713aSLionel Sambuc functionDecl(hasName("f"),
4296f4a2713aSLionel Sambuc forEachDescendant(nestedNameSpecifier().bind("x"))),
4297f4a2713aSLionel Sambuc // Nested names: a, a::A and a::A::B.
4298f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<NestedNameSpecifier>("x", 3)));
4299f4a2713aSLionel Sambuc }
4300f4a2713aSLionel Sambuc
TEST(NNSLoc,DescendantsOfNestedNameSpecifierLocs)4301f4a2713aSLionel Sambuc TEST(NNSLoc, DescendantsOfNestedNameSpecifierLocs) {
4302f4a2713aSLionel Sambuc std::string Fragment =
4303f4a2713aSLionel Sambuc "namespace a { struct A { struct B { struct C {}; }; }; };"
4304f4a2713aSLionel Sambuc "void f() { a::A::B::C c; }";
4305f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4306f4a2713aSLionel Sambuc Fragment,
4307f4a2713aSLionel Sambuc nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
4308f4a2713aSLionel Sambuc hasDescendant(loc(nestedNameSpecifier(
4309f4a2713aSLionel Sambuc specifiesNamespace(hasName("a"))))))));
4310f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4311f4a2713aSLionel Sambuc Fragment,
4312f4a2713aSLionel Sambuc nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
4313f4a2713aSLionel Sambuc has(loc(nestedNameSpecifier(
4314f4a2713aSLionel Sambuc specifiesNamespace(hasName("a"))))))));
4315f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4316f4a2713aSLionel Sambuc Fragment,
4317f4a2713aSLionel Sambuc nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
4318f4a2713aSLionel Sambuc has(loc(nestedNameSpecifier(
4319f4a2713aSLionel Sambuc specifiesNamespace(hasName("a"))))))));
4320f4a2713aSLionel Sambuc
4321f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4322f4a2713aSLionel Sambuc Fragment,
4323f4a2713aSLionel Sambuc nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
4324f4a2713aSLionel Sambuc forEach(nestedNameSpecifierLoc().bind("x"))),
4325f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<NestedNameSpecifierLoc>("x", 1)));
4326f4a2713aSLionel Sambuc }
4327f4a2713aSLionel Sambuc
TEST(NNSLoc,NestedNameSpecifierLocsAsDescendants)4328f4a2713aSLionel Sambuc TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) {
4329f4a2713aSLionel Sambuc std::string Fragment =
4330f4a2713aSLionel Sambuc "namespace a { struct A { struct B { struct C {}; }; }; };"
4331f4a2713aSLionel Sambuc "void f() { a::A::B::C c; }";
4332f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4333f4a2713aSLionel Sambuc Fragment,
4334f4a2713aSLionel Sambuc decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
4335f4a2713aSLionel Sambuc asString("struct a::A"))))))));
4336f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4337f4a2713aSLionel Sambuc Fragment,
4338f4a2713aSLionel Sambuc functionDecl(hasName("f"),
4339f4a2713aSLionel Sambuc forEachDescendant(nestedNameSpecifierLoc().bind("x"))),
4340f4a2713aSLionel Sambuc // Nested names: a, a::A and a::A::B.
4341f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<NestedNameSpecifierLoc>("x", 3)));
4342f4a2713aSLionel Sambuc }
4343f4a2713aSLionel Sambuc
4344f4a2713aSLionel Sambuc template <typename T> class VerifyMatchOnNode : public BoundNodesCallback {
4345f4a2713aSLionel Sambuc public:
VerifyMatchOnNode(StringRef Id,const internal::Matcher<T> & InnerMatcher,StringRef InnerId)4346f4a2713aSLionel Sambuc VerifyMatchOnNode(StringRef Id, const internal::Matcher<T> &InnerMatcher,
4347f4a2713aSLionel Sambuc StringRef InnerId)
4348f4a2713aSLionel Sambuc : Id(Id), InnerMatcher(InnerMatcher), InnerId(InnerId) {
4349f4a2713aSLionel Sambuc }
4350f4a2713aSLionel Sambuc
run(const BoundNodes * Nodes)4351f4a2713aSLionel Sambuc virtual bool run(const BoundNodes *Nodes) { return false; }
4352f4a2713aSLionel Sambuc
run(const BoundNodes * Nodes,ASTContext * Context)4353f4a2713aSLionel Sambuc virtual bool run(const BoundNodes *Nodes, ASTContext *Context) {
4354f4a2713aSLionel Sambuc const T *Node = Nodes->getNodeAs<T>(Id);
4355*0a6a1f1dSLionel Sambuc return selectFirst<T>(InnerId, match(InnerMatcher, *Node, *Context)) !=
4356*0a6a1f1dSLionel Sambuc nullptr;
4357f4a2713aSLionel Sambuc }
4358f4a2713aSLionel Sambuc private:
4359f4a2713aSLionel Sambuc std::string Id;
4360f4a2713aSLionel Sambuc internal::Matcher<T> InnerMatcher;
4361f4a2713aSLionel Sambuc std::string InnerId;
4362f4a2713aSLionel Sambuc };
4363f4a2713aSLionel Sambuc
TEST(MatchFinder,CanMatchDeclarationsRecursively)4364f4a2713aSLionel Sambuc TEST(MatchFinder, CanMatchDeclarationsRecursively) {
4365f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4366f4a2713aSLionel Sambuc "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
4367f4a2713aSLionel Sambuc new VerifyMatchOnNode<clang::Decl>(
4368f4a2713aSLionel Sambuc "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),
4369f4a2713aSLionel Sambuc "Y")));
4370f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse(
4371f4a2713aSLionel Sambuc "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
4372f4a2713aSLionel Sambuc new VerifyMatchOnNode<clang::Decl>(
4373f4a2713aSLionel Sambuc "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),
4374f4a2713aSLionel Sambuc "Z")));
4375f4a2713aSLionel Sambuc }
4376f4a2713aSLionel Sambuc
TEST(MatchFinder,CanMatchStatementsRecursively)4377f4a2713aSLionel Sambuc TEST(MatchFinder, CanMatchStatementsRecursively) {
4378f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4379f4a2713aSLionel Sambuc "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
4380f4a2713aSLionel Sambuc new VerifyMatchOnNode<clang::Stmt>(
4381f4a2713aSLionel Sambuc "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));
4382f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse(
4383f4a2713aSLionel Sambuc "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
4384f4a2713aSLionel Sambuc new VerifyMatchOnNode<clang::Stmt>(
4385f4a2713aSLionel Sambuc "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));
4386f4a2713aSLionel Sambuc }
4387f4a2713aSLionel Sambuc
TEST(MatchFinder,CanMatchSingleNodesRecursively)4388f4a2713aSLionel Sambuc TEST(MatchFinder, CanMatchSingleNodesRecursively) {
4389f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4390f4a2713aSLionel Sambuc "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
4391f4a2713aSLionel Sambuc new VerifyMatchOnNode<clang::Decl>(
4392f4a2713aSLionel Sambuc "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));
4393f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultFalse(
4394f4a2713aSLionel Sambuc "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
4395f4a2713aSLionel Sambuc new VerifyMatchOnNode<clang::Decl>(
4396f4a2713aSLionel Sambuc "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));
4397f4a2713aSLionel Sambuc }
4398f4a2713aSLionel Sambuc
4399f4a2713aSLionel Sambuc template <typename T>
4400f4a2713aSLionel Sambuc class VerifyAncestorHasChildIsEqual : public BoundNodesCallback {
4401f4a2713aSLionel Sambuc public:
run(const BoundNodes * Nodes)4402f4a2713aSLionel Sambuc virtual bool run(const BoundNodes *Nodes) { return false; }
4403f4a2713aSLionel Sambuc
run(const BoundNodes * Nodes,ASTContext * Context)4404f4a2713aSLionel Sambuc virtual bool run(const BoundNodes *Nodes, ASTContext *Context) {
4405f4a2713aSLionel Sambuc const T *Node = Nodes->getNodeAs<T>("");
4406f4a2713aSLionel Sambuc return verify(*Nodes, *Context, Node);
4407f4a2713aSLionel Sambuc }
4408f4a2713aSLionel Sambuc
verify(const BoundNodes & Nodes,ASTContext & Context,const Stmt * Node)4409f4a2713aSLionel Sambuc bool verify(const BoundNodes &Nodes, ASTContext &Context, const Stmt *Node) {
4410*0a6a1f1dSLionel Sambuc // Use the original typed pointer to verify we can pass pointers to subtypes
4411*0a6a1f1dSLionel Sambuc // to equalsNode.
4412*0a6a1f1dSLionel Sambuc const T *TypedNode = cast<T>(Node);
4413*0a6a1f1dSLionel Sambuc return selectFirst<T>(
4414*0a6a1f1dSLionel Sambuc "", match(stmt(hasParent(
4415*0a6a1f1dSLionel Sambuc stmt(has(stmt(equalsNode(TypedNode)))).bind(""))),
4416*0a6a1f1dSLionel Sambuc *Node, Context)) != nullptr;
4417f4a2713aSLionel Sambuc }
verify(const BoundNodes & Nodes,ASTContext & Context,const Decl * Node)4418f4a2713aSLionel Sambuc bool verify(const BoundNodes &Nodes, ASTContext &Context, const Decl *Node) {
4419*0a6a1f1dSLionel Sambuc // Use the original typed pointer to verify we can pass pointers to subtypes
4420*0a6a1f1dSLionel Sambuc // to equalsNode.
4421*0a6a1f1dSLionel Sambuc const T *TypedNode = cast<T>(Node);
4422*0a6a1f1dSLionel Sambuc return selectFirst<T>(
4423*0a6a1f1dSLionel Sambuc "", match(decl(hasParent(
4424*0a6a1f1dSLionel Sambuc decl(has(decl(equalsNode(TypedNode)))).bind(""))),
4425*0a6a1f1dSLionel Sambuc *Node, Context)) != nullptr;
4426f4a2713aSLionel Sambuc }
4427f4a2713aSLionel Sambuc };
4428f4a2713aSLionel Sambuc
TEST(IsEqualTo,MatchesNodesByIdentity)4429f4a2713aSLionel Sambuc TEST(IsEqualTo, MatchesNodesByIdentity) {
4430f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4431f4a2713aSLionel Sambuc "class X { class Y {}; };", recordDecl(hasName("::X::Y")).bind(""),
4432*0a6a1f1dSLionel Sambuc new VerifyAncestorHasChildIsEqual<CXXRecordDecl>()));
4433*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4434*0a6a1f1dSLionel Sambuc "void f() { if (true) if(true) {} }", ifStmt().bind(""),
4435*0a6a1f1dSLionel Sambuc new VerifyAncestorHasChildIsEqual<IfStmt>()));
4436*0a6a1f1dSLionel Sambuc }
4437*0a6a1f1dSLionel Sambuc
TEST(MatchFinder,CheckProfiling)4438*0a6a1f1dSLionel Sambuc TEST(MatchFinder, CheckProfiling) {
4439*0a6a1f1dSLionel Sambuc MatchFinder::MatchFinderOptions Options;
4440*0a6a1f1dSLionel Sambuc llvm::StringMap<llvm::TimeRecord> Records;
4441*0a6a1f1dSLionel Sambuc Options.CheckProfiling.emplace(Records);
4442*0a6a1f1dSLionel Sambuc MatchFinder Finder(std::move(Options));
4443*0a6a1f1dSLionel Sambuc
4444*0a6a1f1dSLionel Sambuc struct NamedCallback : public MatchFinder::MatchCallback {
4445*0a6a1f1dSLionel Sambuc void run(const MatchFinder::MatchResult &Result) override {}
4446*0a6a1f1dSLionel Sambuc StringRef getID() const override { return "MyID"; }
4447*0a6a1f1dSLionel Sambuc } Callback;
4448*0a6a1f1dSLionel Sambuc Finder.addMatcher(decl(), &Callback);
4449*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Factory(
4450*0a6a1f1dSLionel Sambuc newFrontendActionFactory(&Finder));
4451*0a6a1f1dSLionel Sambuc ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
4452*0a6a1f1dSLionel Sambuc
4453*0a6a1f1dSLionel Sambuc EXPECT_EQ(1u, Records.size());
4454*0a6a1f1dSLionel Sambuc EXPECT_EQ("MyID", Records.begin()->getKey());
4455f4a2713aSLionel Sambuc }
4456f4a2713aSLionel Sambuc
4457f4a2713aSLionel Sambuc class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback {
4458f4a2713aSLionel Sambuc public:
VerifyStartOfTranslationUnit()4459f4a2713aSLionel Sambuc VerifyStartOfTranslationUnit() : Called(false) {}
run(const MatchFinder::MatchResult & Result)4460f4a2713aSLionel Sambuc virtual void run(const MatchFinder::MatchResult &Result) {
4461f4a2713aSLionel Sambuc EXPECT_TRUE(Called);
4462f4a2713aSLionel Sambuc }
onStartOfTranslationUnit()4463f4a2713aSLionel Sambuc virtual void onStartOfTranslationUnit() {
4464f4a2713aSLionel Sambuc Called = true;
4465f4a2713aSLionel Sambuc }
4466f4a2713aSLionel Sambuc bool Called;
4467f4a2713aSLionel Sambuc };
4468f4a2713aSLionel Sambuc
TEST(MatchFinder,InterceptsStartOfTranslationUnit)4469f4a2713aSLionel Sambuc TEST(MatchFinder, InterceptsStartOfTranslationUnit) {
4470f4a2713aSLionel Sambuc MatchFinder Finder;
4471f4a2713aSLionel Sambuc VerifyStartOfTranslationUnit VerifyCallback;
4472f4a2713aSLionel Sambuc Finder.addMatcher(decl(), &VerifyCallback);
4473*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Factory(
4474*0a6a1f1dSLionel Sambuc newFrontendActionFactory(&Finder));
4475f4a2713aSLionel Sambuc ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
4476f4a2713aSLionel Sambuc EXPECT_TRUE(VerifyCallback.Called);
4477f4a2713aSLionel Sambuc
4478f4a2713aSLionel Sambuc VerifyCallback.Called = false;
4479*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTUnit> AST(tooling::buildASTFromCode("int x;"));
4480f4a2713aSLionel Sambuc ASSERT_TRUE(AST.get());
4481f4a2713aSLionel Sambuc Finder.matchAST(AST->getASTContext());
4482f4a2713aSLionel Sambuc EXPECT_TRUE(VerifyCallback.Called);
4483f4a2713aSLionel Sambuc }
4484f4a2713aSLionel Sambuc
4485f4a2713aSLionel Sambuc class VerifyEndOfTranslationUnit : public MatchFinder::MatchCallback {
4486f4a2713aSLionel Sambuc public:
VerifyEndOfTranslationUnit()4487f4a2713aSLionel Sambuc VerifyEndOfTranslationUnit() : Called(false) {}
run(const MatchFinder::MatchResult & Result)4488f4a2713aSLionel Sambuc virtual void run(const MatchFinder::MatchResult &Result) {
4489f4a2713aSLionel Sambuc EXPECT_FALSE(Called);
4490f4a2713aSLionel Sambuc }
onEndOfTranslationUnit()4491f4a2713aSLionel Sambuc virtual void onEndOfTranslationUnit() {
4492f4a2713aSLionel Sambuc Called = true;
4493f4a2713aSLionel Sambuc }
4494f4a2713aSLionel Sambuc bool Called;
4495f4a2713aSLionel Sambuc };
4496f4a2713aSLionel Sambuc
TEST(MatchFinder,InterceptsEndOfTranslationUnit)4497f4a2713aSLionel Sambuc TEST(MatchFinder, InterceptsEndOfTranslationUnit) {
4498f4a2713aSLionel Sambuc MatchFinder Finder;
4499f4a2713aSLionel Sambuc VerifyEndOfTranslationUnit VerifyCallback;
4500f4a2713aSLionel Sambuc Finder.addMatcher(decl(), &VerifyCallback);
4501*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Factory(
4502*0a6a1f1dSLionel Sambuc newFrontendActionFactory(&Finder));
4503f4a2713aSLionel Sambuc ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
4504f4a2713aSLionel Sambuc EXPECT_TRUE(VerifyCallback.Called);
4505f4a2713aSLionel Sambuc
4506f4a2713aSLionel Sambuc VerifyCallback.Called = false;
4507*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTUnit> AST(tooling::buildASTFromCode("int x;"));
4508f4a2713aSLionel Sambuc ASSERT_TRUE(AST.get());
4509f4a2713aSLionel Sambuc Finder.matchAST(AST->getASTContext());
4510f4a2713aSLionel Sambuc EXPECT_TRUE(VerifyCallback.Called);
4511f4a2713aSLionel Sambuc }
4512f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,QualType)4513f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, QualType) {
4514f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4515f4a2713aSLionel Sambuc "int i = 1;", varDecl(hasType(qualType().bind("type")),
4516f4a2713aSLionel Sambuc hasInitializer(ignoringParenImpCasts(
4517f4a2713aSLionel Sambuc hasType(qualType(equalsBoundNode("type"))))))));
4518f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("int i = 1.f;",
4519f4a2713aSLionel Sambuc varDecl(hasType(qualType().bind("type")),
4520f4a2713aSLionel Sambuc hasInitializer(ignoringParenImpCasts(hasType(
4521f4a2713aSLionel Sambuc qualType(equalsBoundNode("type"))))))));
4522f4a2713aSLionel Sambuc }
4523f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,NonMatchingTypes)4524f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, NonMatchingTypes) {
4525f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4526f4a2713aSLionel Sambuc "int i = 1;", varDecl(namedDecl(hasName("i")).bind("name"),
4527f4a2713aSLionel Sambuc hasInitializer(ignoringParenImpCasts(
4528f4a2713aSLionel Sambuc hasType(qualType(equalsBoundNode("type"))))))));
4529f4a2713aSLionel Sambuc }
4530f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,Stmt)4531f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, Stmt) {
4532f4a2713aSLionel Sambuc EXPECT_TRUE(
4533f4a2713aSLionel Sambuc matches("void f() { if(true) {} }",
4534f4a2713aSLionel Sambuc stmt(allOf(ifStmt().bind("if"),
4535f4a2713aSLionel Sambuc hasParent(stmt(has(stmt(equalsBoundNode("if")))))))));
4536f4a2713aSLionel Sambuc
4537f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4538f4a2713aSLionel Sambuc "void f() { if(true) { if (true) {} } }",
4539f4a2713aSLionel Sambuc stmt(allOf(ifStmt().bind("if"), has(stmt(equalsBoundNode("if")))))));
4540f4a2713aSLionel Sambuc }
4541f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,Decl)4542f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, Decl) {
4543f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4544f4a2713aSLionel Sambuc "class X { class Y {}; };",
4545f4a2713aSLionel Sambuc decl(allOf(recordDecl(hasName("::X::Y")).bind("record"),
4546f4a2713aSLionel Sambuc hasParent(decl(has(decl(equalsBoundNode("record")))))))));
4547f4a2713aSLionel Sambuc
4548f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches("class X { class Y {}; };",
4549f4a2713aSLionel Sambuc decl(allOf(recordDecl(hasName("::X")).bind("record"),
4550f4a2713aSLionel Sambuc has(decl(equalsBoundNode("record")))))));
4551f4a2713aSLionel Sambuc }
4552f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,Type)4553f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, Type) {
4554f4a2713aSLionel Sambuc EXPECT_TRUE(matches(
4555f4a2713aSLionel Sambuc "class X { int a; int b; };",
4556f4a2713aSLionel Sambuc recordDecl(
4557f4a2713aSLionel Sambuc has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
4558f4a2713aSLionel Sambuc has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
4559f4a2713aSLionel Sambuc
4560f4a2713aSLionel Sambuc EXPECT_TRUE(notMatches(
4561f4a2713aSLionel Sambuc "class X { int a; double b; };",
4562f4a2713aSLionel Sambuc recordDecl(
4563f4a2713aSLionel Sambuc has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
4564f4a2713aSLionel Sambuc has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
4565f4a2713aSLionel Sambuc }
4566f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,UsingForEachDescendant)4567f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, UsingForEachDescendant) {
4568f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4569f4a2713aSLionel Sambuc "int f() {"
4570f4a2713aSLionel Sambuc " if (1) {"
4571f4a2713aSLionel Sambuc " int i = 9;"
4572f4a2713aSLionel Sambuc " }"
4573f4a2713aSLionel Sambuc " int j = 10;"
4574f4a2713aSLionel Sambuc " {"
4575f4a2713aSLionel Sambuc " float k = 9.0;"
4576f4a2713aSLionel Sambuc " }"
4577f4a2713aSLionel Sambuc " return 0;"
4578f4a2713aSLionel Sambuc "}",
4579f4a2713aSLionel Sambuc // Look for variable declarations within functions whose type is the same
4580f4a2713aSLionel Sambuc // as the function return type.
4581f4a2713aSLionel Sambuc functionDecl(returns(qualType().bind("type")),
4582f4a2713aSLionel Sambuc forEachDescendant(varDecl(hasType(
4583f4a2713aSLionel Sambuc qualType(equalsBoundNode("type")))).bind("decl"))),
4584f4a2713aSLionel Sambuc // Only i and j should match, not k.
4585f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<VarDecl>("decl", 2)));
4586f4a2713aSLionel Sambuc }
4587f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,FiltersMatchedCombinations)4588f4a2713aSLionel Sambuc TEST(EqualsBoundNodeMatcher, FiltersMatchedCombinations) {
4589f4a2713aSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4590f4a2713aSLionel Sambuc "void f() {"
4591f4a2713aSLionel Sambuc " int x;"
4592f4a2713aSLionel Sambuc " double d;"
4593f4a2713aSLionel Sambuc " x = d + x - d + x;"
4594f4a2713aSLionel Sambuc "}",
4595f4a2713aSLionel Sambuc functionDecl(
4596f4a2713aSLionel Sambuc hasName("f"), forEachDescendant(varDecl().bind("d")),
4597f4a2713aSLionel Sambuc forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))),
4598f4a2713aSLionel Sambuc new VerifyIdIsBoundTo<VarDecl>("d", 5)));
4599f4a2713aSLionel Sambuc }
4600f4a2713aSLionel Sambuc
TEST(EqualsBoundNodeMatcher,UnlessDescendantsOfAncestorsMatch)4601*0a6a1f1dSLionel Sambuc TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
4602*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchAndVerifyResultTrue(
4603*0a6a1f1dSLionel Sambuc "struct StringRef { int size() const; const char* data() const; };"
4604*0a6a1f1dSLionel Sambuc "void f(StringRef v) {"
4605*0a6a1f1dSLionel Sambuc " v.data();"
4606*0a6a1f1dSLionel Sambuc "}",
4607*0a6a1f1dSLionel Sambuc memberCallExpr(
4608*0a6a1f1dSLionel Sambuc callee(methodDecl(hasName("data"))),
4609*0a6a1f1dSLionel Sambuc on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
4610*0a6a1f1dSLionel Sambuc .bind("var")))),
4611*0a6a1f1dSLionel Sambuc unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
4612*0a6a1f1dSLionel Sambuc callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
4613*0a6a1f1dSLionel Sambuc on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
4614*0a6a1f1dSLionel Sambuc .bind("data"),
4615*0a6a1f1dSLionel Sambuc new VerifyIdIsBoundTo<Expr>("data", 1)));
4616*0a6a1f1dSLionel Sambuc
4617*0a6a1f1dSLionel Sambuc EXPECT_FALSE(matches(
4618*0a6a1f1dSLionel Sambuc "struct StringRef { int size() const; const char* data() const; };"
4619*0a6a1f1dSLionel Sambuc "void f(StringRef v) {"
4620*0a6a1f1dSLionel Sambuc " v.data();"
4621*0a6a1f1dSLionel Sambuc " v.size();"
4622*0a6a1f1dSLionel Sambuc "}",
4623*0a6a1f1dSLionel Sambuc memberCallExpr(
4624*0a6a1f1dSLionel Sambuc callee(methodDecl(hasName("data"))),
4625*0a6a1f1dSLionel Sambuc on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
4626*0a6a1f1dSLionel Sambuc .bind("var")))),
4627*0a6a1f1dSLionel Sambuc unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
4628*0a6a1f1dSLionel Sambuc callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
4629*0a6a1f1dSLionel Sambuc on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
4630*0a6a1f1dSLionel Sambuc .bind("data")));
4631*0a6a1f1dSLionel Sambuc }
4632*0a6a1f1dSLionel Sambuc
TEST(TypeDefDeclMatcher,Match)4633*0a6a1f1dSLionel Sambuc TEST(TypeDefDeclMatcher, Match) {
4634*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("typedef int typedefDeclTest;",
4635*0a6a1f1dSLionel Sambuc typedefDecl(hasName("typedefDeclTest"))));
4636*0a6a1f1dSLionel Sambuc }
4637*0a6a1f1dSLionel Sambuc
4638*0a6a1f1dSLionel Sambuc // FIXME: Figure out how to specify paths so the following tests pass on Windows.
4639*0a6a1f1dSLionel Sambuc #ifndef LLVM_ON_WIN32
4640*0a6a1f1dSLionel Sambuc
TEST(Matcher,IsExpansionInMainFileMatcher)4641*0a6a1f1dSLionel Sambuc TEST(Matcher, IsExpansionInMainFileMatcher) {
4642*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matches("class X {};",
4643*0a6a1f1dSLionel Sambuc recordDecl(hasName("X"), isExpansionInMainFile())));
4644*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("", recordDecl(isExpansionInMainFile())));
4645*0a6a1f1dSLionel Sambuc FileContentMappings M;
4646*0a6a1f1dSLionel Sambuc M.push_back(std::make_pair("/other", "class X {};"));
4647*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesConditionally("#include <other>\n",
4648*0a6a1f1dSLionel Sambuc recordDecl(isExpansionInMainFile()), false,
4649*0a6a1f1dSLionel Sambuc "-isystem/", M));
4650*0a6a1f1dSLionel Sambuc }
4651*0a6a1f1dSLionel Sambuc
TEST(Matcher,IsExpansionInSystemHeader)4652*0a6a1f1dSLionel Sambuc TEST(Matcher, IsExpansionInSystemHeader) {
4653*0a6a1f1dSLionel Sambuc FileContentMappings M;
4654*0a6a1f1dSLionel Sambuc M.push_back(std::make_pair("/other", "class X {};"));
4655*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesConditionally(
4656*0a6a1f1dSLionel Sambuc "#include \"other\"\n", recordDecl(isExpansionInSystemHeader()), true,
4657*0a6a1f1dSLionel Sambuc "-isystem/", M));
4658*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesConditionally("#include \"other\"\n",
4659*0a6a1f1dSLionel Sambuc recordDecl(isExpansionInSystemHeader()),
4660*0a6a1f1dSLionel Sambuc false, "-I/", M));
4661*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("class X {};",
4662*0a6a1f1dSLionel Sambuc recordDecl(isExpansionInSystemHeader())));
4663*0a6a1f1dSLionel Sambuc EXPECT_TRUE(notMatches("", recordDecl(isExpansionInSystemHeader())));
4664*0a6a1f1dSLionel Sambuc }
4665*0a6a1f1dSLionel Sambuc
TEST(Matcher,IsExpansionInFileMatching)4666*0a6a1f1dSLionel Sambuc TEST(Matcher, IsExpansionInFileMatching) {
4667*0a6a1f1dSLionel Sambuc FileContentMappings M;
4668*0a6a1f1dSLionel Sambuc M.push_back(std::make_pair("/foo", "class A {};"));
4669*0a6a1f1dSLionel Sambuc M.push_back(std::make_pair("/bar", "class B {};"));
4670*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesConditionally(
4671*0a6a1f1dSLionel Sambuc "#include <foo>\n"
4672*0a6a1f1dSLionel Sambuc "#include <bar>\n"
4673*0a6a1f1dSLionel Sambuc "class X {};",
4674*0a6a1f1dSLionel Sambuc recordDecl(isExpansionInFileMatching("b.*"), hasName("B")), true,
4675*0a6a1f1dSLionel Sambuc "-isystem/", M));
4676*0a6a1f1dSLionel Sambuc EXPECT_TRUE(matchesConditionally(
4677*0a6a1f1dSLionel Sambuc "#include <foo>\n"
4678*0a6a1f1dSLionel Sambuc "#include <bar>\n"
4679*0a6a1f1dSLionel Sambuc "class X {};",
4680*0a6a1f1dSLionel Sambuc recordDecl(isExpansionInFileMatching("f.*"), hasName("X")), false,
4681*0a6a1f1dSLionel Sambuc "-isystem/", M));
4682*0a6a1f1dSLionel Sambuc }
4683*0a6a1f1dSLionel Sambuc
4684*0a6a1f1dSLionel Sambuc #endif // LLVM_ON_WIN32
4685*0a6a1f1dSLionel Sambuc
4686f4a2713aSLionel Sambuc } // end namespace ast_matchers
4687f4a2713aSLionel Sambuc } // end namespace clang
4688