blob: cdb55d90b9dfbe4c477bce9350e9728870886087 [file] [log] [blame]
Gabor Marton1f667532018-05-24 08:41:07 +00001#include "clang/AST/ASTContext.h"
2#include "clang/ASTMatchers/ASTMatchers.h"
3#include "clang/AST/ASTStructuralEquivalence.h"
4#include "clang/Frontend/ASTUnit.h"
5#include "clang/Tooling/Tooling.h"
6
7#include "Language.h"
8#include "DeclMatcher.h"
9
10#include "gtest/gtest.h"
11
12namespace clang {
13namespace ast_matchers {
14
15using std::get;
16
17struct StructuralEquivalenceTest : ::testing::Test {
18 std::unique_ptr<ASTUnit> AST0, AST1;
19 std::string Code0, Code1; // Buffers for SourceManager
20
Balazs Keric7797c42018-07-11 09:37:24 +000021 // Get a pair of node pointers into the synthesized AST from the given code
22 // snippets. To determine the returned node, a separate matcher is specified
23 // for both snippets. The first matching node is returned.
24 template <typename NodeType, typename MatcherType>
25 std::tuple<NodeType *, NodeType *> makeDecls(
26 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
27 const MatcherType &Matcher0, const MatcherType &Matcher1) {
Gabor Marton1f667532018-05-24 08:41:07 +000028 this->Code0 = SrcCode0;
29 this->Code1 = SrcCode1;
30 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
31
32 const char *const InputFileName = "input.cc";
33
34 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
35 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
36
Balazs Keric7797c42018-07-11 09:37:24 +000037 NodeType *D0 = FirstDeclMatcher<NodeType>().match(
38 AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
39 NodeType *D1 = FirstDeclMatcher<NodeType>().match(
40 AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
Gabor Marton1f667532018-05-24 08:41:07 +000041
Gabor Marton1f667532018-05-24 08:41:07 +000042 return std::make_tuple(D0, D1);
43 }
44
Gabor Martonf086fa82018-07-17 12:06:36 +000045 std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> makeTuDecls(
46 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang) {
47 this->Code0 = SrcCode0;
48 this->Code1 = SrcCode1;
49 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
50
51 const char *const InputFileName = "input.cc";
52
53 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
54 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
55
56 return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),
57 AST1->getASTContext().getTranslationUnitDecl());
58 }
59
Balazs Keric7797c42018-07-11 09:37:24 +000060 // Get a pair of node pointers into the synthesized AST from the given code
61 // snippets. The same matcher is used for both snippets.
62 template <typename NodeType, typename MatcherType>
63 std::tuple<NodeType *, NodeType *> makeDecls(
64 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
65 const MatcherType &AMatcher) {
66 return makeDecls<NodeType, MatcherType>(
67 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
68 }
69
70 // Get a pair of Decl pointers to the synthesized declarations from the given
71 // code snippets. We search for the first NamedDecl with given name in both
72 // snippets.
73 std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls(
74 const std::string &SrcCode0, const std::string &SrcCode1,
75 Language Lang, const char *const Identifier = "foo") {
76 auto Matcher = namedDecl(hasName(Identifier));
77 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);
78 }
79
Gabor Martonf086fa82018-07-17 12:06:36 +000080 bool testStructuralMatch(Decl *D0, Decl *D1) {
Balazs Keria0a81b12018-08-08 15:04:27 +000081 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
82 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
83 StructuralEquivalenceContext Ctx01(
84 D0->getASTContext(), D1->getASTContext(),
85 NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false);
86 StructuralEquivalenceContext Ctx10(
87 D1->getASTContext(), D0->getASTContext(),
88 NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false);
89 bool Eq01 = Ctx01.IsEquivalent(D0, D1);
90 bool Eq10 = Ctx10.IsEquivalent(D1, D0);
91 EXPECT_EQ(Eq01, Eq10);
92 return Eq01;
Gabor Marton1f667532018-05-24 08:41:07 +000093 }
94
Gabor Martonf086fa82018-07-17 12:06:36 +000095 bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
Gabor Marton1f667532018-05-24 08:41:07 +000096 return testStructuralMatch(get<0>(t), get<1>(t));
97 }
98};
99
100TEST_F(StructuralEquivalenceTest, Int) {
101 auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
102 EXPECT_TRUE(testStructuralMatch(Decls));
103}
104
105TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
106 auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
107 EXPECT_TRUE(testStructuralMatch(Decls));
108}
109
110TEST_F(StructuralEquivalenceTest, Char) {
111 auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX);
112 EXPECT_TRUE(testStructuralMatch(Decls));
113}
114
115// This test is disabled for now.
116// FIXME Whether this is equivalent is dependendant on the target.
117TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
118 auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
119 EXPECT_FALSE(testStructuralMatch(Decls));
120}
121
122TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
123 auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
124 EXPECT_TRUE(testStructuralMatch(Decls));
125}
126
127TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
128 auto Decls = makeNamedDecls("struct foo { int x; };",
129 "struct foo { signed int x; };", Lang_CXX);
130 EXPECT_TRUE(testStructuralMatch(Decls));
131}
132
133TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
134 auto Decls = makeNamedDecls("struct foo { char x; };",
135 "struct foo { signed char x; };", Lang_CXX);
136 EXPECT_FALSE(testStructuralMatch(Decls));
137}
138
139TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
Balazs Keric7797c42018-07-11 09:37:24 +0000140 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
141 R"(template <class T> struct foo; template<> struct foo<int>{};)",
142 R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
143 Lang_CXX,
144 classTemplateSpecializationDecl());
145 auto Spec0 = get<0>(Decls);
146 auto Spec1 = get<1>(Decls);
Gabor Marton1f667532018-05-24 08:41:07 +0000147 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
148}
149
150TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
Balazs Keric7797c42018-07-11 09:37:24 +0000151 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
152 R"(template <class T> struct foo; template<> struct foo<char>{};)",
153 R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
154 Lang_CXX,
155 classTemplateSpecializationDecl());
156 auto Spec0 = get<0>(Decls);
157 auto Spec1 = get<1>(Decls);
Gabor Marton1f667532018-05-24 08:41:07 +0000158 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
159}
160
161TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
Balazs Keric7797c42018-07-11 09:37:24 +0000162 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
Gabor Marton1f667532018-05-24 08:41:07 +0000163 R"(
164 struct true_type{};
165 template <class T> struct foo;
166 template<> struct foo<char> : true_type {};
167 )",
168 R"(
169 struct true_type{};
170 template <class T> struct foo;
171 template<> struct foo<signed char> : true_type {};
172 )",
Balazs Keric7797c42018-07-11 09:37:24 +0000173 Lang_CXX,
174 classTemplateSpecializationDecl());
175 EXPECT_FALSE(testStructuralMatch(Decls));
Gabor Marton1f667532018-05-24 08:41:07 +0000176}
177
178// This test is disabled for now.
179// FIXME Enable it, once the check is implemented.
180TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
181 auto Code =
182 R"(
183 namespace NS {
184 template <class T> class Base {
185 int a;
186 };
187 class Derived : Base<Derived> {
188 };
189 }
190 void foo(NS::Derived &);
191 )";
192 auto Decls = makeNamedDecls(Code, Code, Lang_CXX);
193
194 NamespaceDecl *NS =
195 LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
196 ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
197 get<1>(Decls), classTemplateDecl(hasName("Base")));
198
199 // Reorder the decls, move the TD to the last place in the DC.
200 NS->removeDecl(TD);
201 NS->addDeclInternal(TD);
202
203 EXPECT_FALSE(testStructuralMatch(Decls));
204}
205
206TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
207 auto Code = "class X { int a; int b; };";
208 auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");
209
210 CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
211 get<1>(Decls), cxxRecordDecl(hasName("X")));
212 FieldDecl *FD =
213 FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
214
215 // Reorder the FieldDecls
216 RD->removeDecl(FD);
217 RD->addDeclInternal(FD);
218
219 EXPECT_FALSE(testStructuralMatch(Decls));
220}
221
Balazs Keric7797c42018-07-11 09:37:24 +0000222struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
223};
224
Balazs Keria0a81b12018-08-08 15:04:27 +0000225TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {
226 auto t = makeNamedDecls(
227 "void foo();",
228 "template<class T> void foo();",
229 Lang_CXX);
230 EXPECT_FALSE(testStructuralMatch(t));
231}
232
Gabor Martonfc638d62019-02-08 08:55:32 +0000233TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) {
234 auto t = makeDecls<FunctionDecl>(
235 "struct X{}; bool operator<(X, X);",
236 "struct X{}; bool operator==(X, X);", Lang_CXX,
237 functionDecl(hasOverloadedOperatorName("<")),
238 functionDecl(hasOverloadedOperatorName("==")));
239 EXPECT_FALSE(testStructuralMatch(t));
240}
241
242TEST_F(StructuralEquivalenceFunctionTest, SameOperators) {
243 auto t = makeDecls<FunctionDecl>(
244 "struct X{}; bool operator<(X, X);",
245 "struct X{}; bool operator<(X, X);", Lang_CXX,
246 functionDecl(hasOverloadedOperatorName("<")),
247 functionDecl(hasOverloadedOperatorName("<")));
248 EXPECT_TRUE(testStructuralMatch(t));
249}
250
251TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) {
252 auto t = makeDecls<FunctionDecl>(
253 "struct X{ X(); };",
254 "struct X{ ~X(); };", Lang_CXX,
255 cxxConstructorDecl(),
256 cxxDestructorDecl());
257 EXPECT_FALSE(testStructuralMatch(t));
258}
259
Balazs Keric7797c42018-07-11 09:37:24 +0000260TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
261 auto t = makeNamedDecls("void foo(int&);",
262 "void foo(const int&);", Lang_CXX);
263 EXPECT_FALSE(testStructuralMatch(t));
264}
265
266TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
267 auto t = makeNamedDecls("void foo(int);",
268 "void foo(const int);", Lang_CXX);
269 EXPECT_TRUE(testStructuralMatch(t));
270 // consider this OK
271}
272
273TEST_F(StructuralEquivalenceFunctionTest, Throw) {
274 auto t = makeNamedDecls("void foo();",
275 "void foo() throw();", Lang_CXX);
276 EXPECT_FALSE(testStructuralMatch(t));
277}
278
279TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
280 auto t = makeNamedDecls("void foo();",
281 "void foo() noexcept;", Lang_CXX11);
282 EXPECT_FALSE(testStructuralMatch(t));
283}
284
285TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
286 auto t = makeNamedDecls("void foo() throw();",
287 "void foo() noexcept;", Lang_CXX11);
288 EXPECT_FALSE(testStructuralMatch(t));
289}
290
291TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
292 auto t = makeNamedDecls("void foo() throw();",
293 "void foo() noexcept(false);", Lang_CXX11);
294 EXPECT_FALSE(testStructuralMatch(t));
295}
296
297TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
298 auto t = makeNamedDecls("void foo() throw();",
299 "void foo() noexcept(true);", Lang_CXX11);
300 EXPECT_FALSE(testStructuralMatch(t));
301}
302
Gabor Marton1d51e3e2019-05-20 10:38:14 +0000303TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) {
Balazs Keric7797c42018-07-11 09:37:24 +0000304 auto t = makeNamedDecls("void foo() noexcept(false);",
305 "void foo() noexcept(true);", Lang_CXX11);
306 EXPECT_FALSE(testStructuralMatch(t));
307}
308
309TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
310 auto t = makeNamedDecls("void foo() noexcept(false);",
311 "void foo() noexcept(false);", Lang_CXX11);
312 EXPECT_TRUE(testStructuralMatch(t));
313}
314
315TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
316 auto t = makeNamedDecls("void foo() noexcept;",
317 "void foo() noexcept(false);", Lang_CXX11);
318 EXPECT_FALSE(testStructuralMatch(t));
319}
320
321TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
322 auto t = makeNamedDecls("void foo() noexcept;",
323 "void foo() noexcept(true);", Lang_CXX11);
324 EXPECT_FALSE(testStructuralMatch(t));
325}
326
327TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
328 auto t = makeNamedDecls("char foo();",
329 "int foo();", Lang_CXX);
330 EXPECT_FALSE(testStructuralMatch(t));
331}
332
333TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
334 auto t = makeNamedDecls("char foo();",
335 "const char foo();", Lang_CXX);
336 EXPECT_FALSE(testStructuralMatch(t));
337}
338
339TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
340 auto t = makeNamedDecls("char &foo();",
341 "char &&foo();", Lang_CXX11);
342 EXPECT_FALSE(testStructuralMatch(t));
343}
344
345TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
346 auto t = makeNamedDecls("void foo(int);",
347 "void foo(int, int);", Lang_CXX);
348 EXPECT_FALSE(testStructuralMatch(t));
349}
350
351TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
352 auto t = makeNamedDecls("void foo(int);",
353 "void foo(char);", Lang_CXX);
354 EXPECT_FALSE(testStructuralMatch(t));
355}
356
357TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
358 auto t = makeNamedDecls("void foo(int a);",
359 "void foo(int b);", Lang_CXX);
360 EXPECT_TRUE(testStructuralMatch(t));
361}
362
363TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
364 auto t = makeNamedDecls("void foo(int x...);",
365 "void foo(int x);", Lang_CXX);
366 EXPECT_FALSE(testStructuralMatch(t));
367}
368
369TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
370 auto t = makeNamedDecls("void foo(int *);",
371 "void foo(int);", Lang_CXX);
372 EXPECT_FALSE(testStructuralMatch(t));
373}
374
375TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
376 auto t = makeNamedDecls(
377 "void ((foo))();",
378 "void foo();",
379 Lang_CXX);
380 EXPECT_TRUE(testStructuralMatch(t));
381}
382
383TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
384 auto t = makeNamedDecls(
385 "void (foo)() throw(int);",
386 "void (foo)() noexcept;",
387 Lang_CXX11);
388 EXPECT_FALSE(testStructuralMatch(t));
389}
390
391TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
392 auto t = makeNamedDecls(
393 "struct A { void (foo)() const; };",
394 "struct A { void (foo)(); };",
395 Lang_CXX11);
396 EXPECT_FALSE(testStructuralMatch(t));
397}
398
Gabor Marton41f20462019-01-24 14:47:44 +0000399TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
400 auto t = makeNamedDecls(
401 "__attribute__((noreturn)) void foo();",
402 " void foo();",
403 Lang_C);
404 EXPECT_TRUE(testStructuralMatch(t));
405}
406
407TEST_F(StructuralEquivalenceFunctionTest,
408 FunctionsWithDifferentCallingConventions) {
David Green1be906a2019-02-02 08:31:22 +0000409 // These attributes may not be available on certain platforms.
410 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
411 llvm::Triple::x86_64)
412 return;
Gabor Marton41f20462019-01-24 14:47:44 +0000413 auto t = makeNamedDecls(
Gabor Marton23a06fb2019-01-24 15:42:20 +0000414 "__attribute__((preserve_all)) void foo();",
Gabor Marton41f20462019-01-24 14:47:44 +0000415 "__attribute__((ms_abi)) void foo();",
416 Lang_C);
417 EXPECT_FALSE(testStructuralMatch(t));
418}
419
420TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {
David Green1be906a2019-02-02 08:31:22 +0000421 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
422 llvm::Triple::x86_64)
423 return;
Gabor Marton41f20462019-01-24 14:47:44 +0000424 auto t = makeNamedDecls(
425 "__attribute__((no_caller_saved_registers)) void foo();",
426 " void foo();",
427 Lang_C);
428 EXPECT_FALSE(testStructuralMatch(t));
429}
430
Balazs Keric7797c42018-07-11 09:37:24 +0000431struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
432};
433
434TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
435 auto t = makeDecls<CXXMethodDecl>(
436 "struct X { void foo(); };",
437 "struct X { virtual void foo(); };", Lang_CXX,
438 cxxMethodDecl(hasName("foo")));
439 EXPECT_FALSE(testStructuralMatch(t));
440}
441
442TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
443 auto t = makeNamedDecls("struct X { virtual void foo(); };",
444 "struct X { virtual void foo() = 0; };", Lang_CXX);
445 EXPECT_FALSE(testStructuralMatch(t));
446}
447
448TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
449 // The final-ness is not checked yet.
450 auto t = makeNamedDecls("struct X { virtual void foo(); };",
451 "struct X { virtual void foo() final; };", Lang_CXX);
452 EXPECT_FALSE(testStructuralMatch(t));
453}
454
455TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
456 auto t = makeNamedDecls("struct X { void foo(); };",
457 "struct X { void foo() const; };", Lang_CXX);
458 EXPECT_FALSE(testStructuralMatch(t));
459}
460
461TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
462 auto t = makeNamedDecls("struct X { void foo(); };",
463 "struct X { static void foo(); };", Lang_CXX);
464 EXPECT_FALSE(testStructuralMatch(t));
465}
466
467TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
468 auto t = makeNamedDecls("struct X { void foo(); };",
469 "struct X { void foo() &&; };", Lang_CXX11);
470 EXPECT_FALSE(testStructuralMatch(t));
471}
472
473TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
474 auto t = makeNamedDecls("struct X { void foo() &; };",
475 "struct X { void foo() &&; };", Lang_CXX11);
476 EXPECT_FALSE(testStructuralMatch(t));
477}
478
479TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
480 auto t = makeDecls<CXXMethodDecl>(
481 "struct X { public: void foo(); };",
482 "struct X { private: void foo(); };", Lang_CXX,
483 cxxMethodDecl(hasName("foo")));
484 EXPECT_FALSE(testStructuralMatch(t));
485}
486
487TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
488 auto t = makeNamedDecls("struct X { void foo(); };",
489 "struct X { void foo() = delete; };", Lang_CXX11);
490 EXPECT_FALSE(testStructuralMatch(t));
491}
492
493TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
494 auto t = makeDecls<FunctionDecl>(
495 "void foo();", "struct foo { foo(); };", Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000496 functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo")));
Balazs Keric7797c42018-07-11 09:37:24 +0000497 EXPECT_FALSE(testStructuralMatch(t));
498}
499
500TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
501 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
502 "struct X { X(int); };", Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000503 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000504 EXPECT_FALSE(testStructuralMatch(t));
505}
506
507TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
508 auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
509 "struct X { explicit X(int); };",
510 Lang_CXX11,
Balazs Keri36883d32018-07-11 15:26:26 +0000511 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000512 EXPECT_FALSE(testStructuralMatch(t));
513}
514
515TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
516 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
517 "struct X { X() = default; };",
518 Lang_CXX11,
Balazs Keri36883d32018-07-11 15:26:26 +0000519 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000520 EXPECT_FALSE(testStructuralMatch(t));
521}
522
523TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
524 auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",
525 "struct X { operator char(); };",
526 Lang_CXX11,
527 cxxConversionDecl());
528 EXPECT_FALSE(testStructuralMatch(t));
529}
530
531TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
532 auto t = makeDecls<FunctionDecl>(
533 "struct X { int operator +(int); };",
534 "struct X { int operator -(int); };", Lang_CXX,
535 functionDecl(hasOverloadedOperatorName("+")),
536 functionDecl(hasOverloadedOperatorName("-")));
537 EXPECT_FALSE(testStructuralMatch(t));
538}
539
540TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
541 auto t = makeDecls<FunctionDecl>(
542 "struct X { virtual void f(); }; void X::f() { }",
543 "struct X { virtual void f() { }; };",
544 Lang_CXX,
545 functionDecl(allOf(hasName("f"), isDefinition())));
546 EXPECT_TRUE(testStructuralMatch(t));
547}
548
549TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
550 auto t = makeDecls<FunctionDecl>(
551 "struct X { virtual void f(); }; void X::f() { }",
552 "struct X { void f(); }; void X::f() { }",
553 Lang_CXX,
554 functionDecl(allOf(hasName("f"), isDefinition())));
555 EXPECT_FALSE(testStructuralMatch(t));
556}
557
558struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
Gabor Martonf086fa82018-07-17 12:06:36 +0000559 // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
560 RecordDecl *getRecordDecl(FieldDecl *FD) {
561 auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());
562 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
563 };
Balazs Keric7797c42018-07-11 09:37:24 +0000564};
565
566TEST_F(StructuralEquivalenceRecordTest, Name) {
567 auto t = makeDecls<CXXRecordDecl>(
568 "struct A{ };",
569 "struct B{ };",
570 Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000571 cxxRecordDecl(hasName("A")),
572 cxxRecordDecl(hasName("B")));
Balazs Keric7797c42018-07-11 09:37:24 +0000573 EXPECT_FALSE(testStructuralMatch(t));
574}
575
576TEST_F(StructuralEquivalenceRecordTest, Fields) {
577 auto t = makeNamedDecls(
578 "struct foo{ int x; };",
579 "struct foo{ char x; };",
580 Lang_CXX);
581 EXPECT_FALSE(testStructuralMatch(t));
582}
583
584TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
585 // Currently, methods of a class are not checked at class equivalence.
586 auto t = makeNamedDecls(
587 "struct foo{ int x(); };",
588 "struct foo{ char x(); };",
589 Lang_CXX);
590 EXPECT_FALSE(testStructuralMatch(t));
591}
592
593TEST_F(StructuralEquivalenceRecordTest, Bases) {
594 auto t = makeNamedDecls(
595 "struct A{ }; struct foo: A { };",
596 "struct B{ }; struct foo: B { };",
597 Lang_CXX);
598 EXPECT_FALSE(testStructuralMatch(t));
599}
600
601TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
602 auto t = makeNamedDecls(
603 "struct A{ }; struct foo: A { };",
604 "struct A{ }; struct foo: virtual A { };",
605 Lang_CXX);
606 EXPECT_FALSE(testStructuralMatch(t));
607}
608
609TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
610 // Access specifier in inheritance is not checked yet.
611 auto t = makeNamedDecls(
612 "struct A{ }; struct foo: public A { };",
613 "struct A{ }; struct foo: private A { };",
614 Lang_CXX);
615 EXPECT_FALSE(testStructuralMatch(t));
616}
617
618TEST_F(StructuralEquivalenceRecordTest, Match) {
619 auto Code = R"(
620 struct A{ };
621 struct B{ };
622 struct foo: A, virtual B {
623 void x();
624 int a;
625 };
626 )";
627 auto t = makeNamedDecls(Code, Code, Lang_CXX);
628 EXPECT_TRUE(testStructuralMatch(t));
629}
630
Gabor Martonf086fa82018-07-17 12:06:36 +0000631TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
632 auto t = makeTuDecls(
633 R"(
634 struct A {
635 struct {
636 struct A *next;
637 } entry0;
638 struct {
639 struct A *next;
640 } entry1;
641 };
642 )",
643 "", Lang_C);
644 auto *TU = get<0>(t);
645 auto *Entry0 =
646 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));
647 auto *Entry1 =
648 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));
649 auto *R0 = getRecordDecl(Entry0);
650 auto *R1 = getRecordDecl(Entry1);
651
652 ASSERT_NE(R0, R1);
653 EXPECT_TRUE(testStructuralMatch(R0, R0));
654 EXPECT_TRUE(testStructuralMatch(R1, R1));
655 EXPECT_FALSE(testStructuralMatch(R0, R1));
656}
657
Gabor Marton7df342a2018-12-17 12:42:12 +0000658TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
659 auto t = makeTuDecls(
660 R"(
661 struct X {
662 struct {
663 int a;
664 };
665 struct {
666 int b;
667 };
668 };
669 )",
670 "", Lang_C);
671 auto *TU = get<0>(t);
672 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
673 TU, indirectFieldDecl(hasName("a")));
674 auto *FA = cast<FieldDecl>(A->chain().front());
675 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
676 auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(
677 TU, indirectFieldDecl(hasName("b")));
678 auto *FB = cast<FieldDecl>(B->chain().front());
679 RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();
680
681 ASSERT_NE(RA, RB);
682 EXPECT_TRUE(testStructuralMatch(RA, RA));
683 EXPECT_TRUE(testStructuralMatch(RB, RB));
684 EXPECT_FALSE(testStructuralMatch(RA, RB));
685}
686
687TEST_F(StructuralEquivalenceRecordTest,
688 RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
689 auto t = makeTuDecls(
690 R"(
691 struct X {
692 struct { int a; };
693 struct { int b; };
694 };
695 )",
696 R"(
697 struct X { // The order is reversed.
698 struct { int b; };
699 struct { int a; };
700 };
701 )",
702 Lang_C);
703
704 auto *TU = get<0>(t);
705 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
706 TU, indirectFieldDecl(hasName("a")));
707 auto *FA = cast<FieldDecl>(A->chain().front());
708 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
709
710 auto *TU1 = get<1>(t);
711 auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(
712 TU1, indirectFieldDecl(hasName("a")));
713 auto *FA1 = cast<FieldDecl>(A1->chain().front());
714 RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();
715
716 RecordDecl *X =
717 FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X")));
718 RecordDecl *X1 =
719 FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X")));
720 ASSERT_NE(X, X1);
721 EXPECT_FALSE(testStructuralMatch(X, X1));
722
723 ASSERT_NE(RA, RA1);
724 EXPECT_TRUE(testStructuralMatch(RA, RA));
725 EXPECT_TRUE(testStructuralMatch(RA1, RA1));
726 EXPECT_FALSE(testStructuralMatch(RA1, RA));
727}
728
Gabor Martonf086fa82018-07-17 12:06:36 +0000729TEST_F(StructuralEquivalenceRecordTest,
730 UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
731 auto Code =
732 R"(
733 struct A {
734 struct {
735 struct A *next;
736 } entry0;
737 struct {
738 struct A *next;
739 } entry1;
740 };
741 )";
742 auto t = makeTuDecls(Code, Code, Lang_C);
743
744 auto *FromTU = get<0>(t);
745 auto *Entry1 =
746 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));
747
748 auto *ToTU = get<1>(t);
749 auto *Entry0 =
750 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
751 auto *A =
752 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
753 A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
754 // nullptr. This may be the case during ASTImport.
755
756 auto *R0 = getRecordDecl(Entry0);
757 auto *R1 = getRecordDecl(Entry1);
758
759 ASSERT_NE(R0, R1);
760 EXPECT_TRUE(testStructuralMatch(R0, R0));
761 EXPECT_TRUE(testStructuralMatch(R1, R1));
762 EXPECT_FALSE(testStructuralMatch(R0, R1));
763}
764
Balazs Keria0a81b12018-08-08 15:04:27 +0000765TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {
766 auto t = makeDecls<CXXRecordDecl>(
767 "struct A { };",
768 "template<class T> struct A { };",
769 Lang_CXX,
770 cxxRecordDecl(hasName("A")));
771 EXPECT_FALSE(testStructuralMatch(t));
772}
Gabor Martonf086fa82018-07-17 12:06:36 +0000773
Gabor Marton6b01e1c2018-08-09 12:36:25 +0000774TEST_F(StructuralEquivalenceRecordTest,
775 FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {
776 auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11);
777 EXPECT_TRUE(testStructuralMatch(t));
778}
779
780TEST_F(StructuralEquivalenceRecordTest,
781 FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {
782 auto t =
783 makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11);
784 EXPECT_TRUE(testStructuralMatch(t));
785}
786
787TEST_F(StructuralEquivalenceRecordTest,
788 RecordShouldBeEqualWithRecordWhichHasDefinition) {
789 auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };",
790 Lang_CXX11);
791 EXPECT_TRUE(testStructuralMatch(t));
792}
793
794TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {
795 auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };",
796 Lang_CXX11);
797 EXPECT_FALSE(testStructuralMatch(t));
798}
799
Gabor Martonae512b82019-07-17 14:40:09 +0000800struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {};
801
802TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) {
803 // Get the LambdaExprs, unfortunately we can't match directly the underlying
804 // implicit CXXRecordDecl of the Lambda classes.
805 auto t = makeDecls<LambdaExpr>(
806 "void f() { auto L0 = [](int){}; }",
807 "void f() { auto L1 = [](){}; }",
808 Lang_CXX11,
809 lambdaExpr(),
810 lambdaExpr());
811 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
812 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
813 EXPECT_FALSE(testStructuralMatch(L0, L1));
814}
815
816TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) {
817 auto t = makeDecls<LambdaExpr>(
818 "void f() { auto L0 = [](int){}; }",
819 "void f() { auto L1 = [](int){}; }",
820 Lang_CXX11,
821 lambdaExpr(),
822 lambdaExpr());
823 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
824 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
825 EXPECT_TRUE(testStructuralMatch(L0, L1));
826}
827
828TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) {
829 auto t = makeDecls<LambdaExpr>(
830 "void f() { char* X; auto L0 = [X](){}; }",
831 "void f() { float X; auto L1 = [X](){}; }",
832 Lang_CXX11,
833 lambdaExpr(),
834 lambdaExpr());
835 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
836 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
837 EXPECT_FALSE(testStructuralMatch(L0, L1));
838}
839
840TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) {
841 auto t = makeDecls<LambdaExpr>(
842 "void f() { float X; auto L0 = [X](){}; }",
843 "void f() { float X; auto L1 = [X](){}; }",
844 Lang_CXX11,
845 lambdaExpr(),
846 lambdaExpr());
847 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
848 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
849 EXPECT_TRUE(testStructuralMatch(L0, L1));
850}
851
Balazs Keric7797c42018-07-11 09:37:24 +0000852TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
853 auto t = makeNamedDecls(
854 "struct A{ }; struct B{ }; void foo(A a, A b);",
855 "struct A{ }; struct B{ }; void foo(A a, B b);",
856 Lang_CXX);
857 EXPECT_FALSE(testStructuralMatch(t));
858}
859
Richard Smith76b90272019-05-09 03:59:21 +0000860TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {
861 auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};",
862 "struct foo {explicit(true) foo(int);};", Lang_CXX2a);
863 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
864 get<0>(Decls), cxxConstructorDecl(hasName("foo")));
865 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
866 get<1>(Decls), cxxConstructorDecl(hasName("foo")));
867 EXPECT_FALSE(testStructuralMatch(First, Second));
868}
869
870TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {
871 auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};",
872 "struct foo {explicit(true) foo(int);};", Lang_CXX2a);
873 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
874 get<0>(Decls), cxxConstructorDecl(hasName("foo")));
875 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
876 get<1>(Decls), cxxConstructorDecl(hasName("foo")));
877 EXPECT_TRUE(testStructuralMatch(First, Second));
878}
879
Gabor Marton6b01e1c2018-08-09 12:36:25 +0000880struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
881
882TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
883 auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);
884 EXPECT_TRUE(testStructuralMatch(t));
885}
886
887TEST_F(StructuralEquivalenceEnumTest,
888 FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {
889 auto t =
890 makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);
891 EXPECT_TRUE(testStructuralMatch(t));
892}
893
894TEST_F(StructuralEquivalenceEnumTest,
895 EnumShouldBeEqualWithEnumWhichHasDefinition) {
896 auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",
897 Lang_CXX11);
898 EXPECT_TRUE(testStructuralMatch(t));
899}
900
901TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {
902 auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",
903 Lang_CXX11);
904 EXPECT_FALSE(testStructuralMatch(t));
905}
906
Gabor Marton059c1d82019-01-28 10:01:11 +0000907struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};
908
909TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {
910 auto t = makeNamedDecls("template <class T> struct foo;",
911 "template <class T> struct foo;", Lang_CXX);
912 EXPECT_TRUE(testStructuralMatch(t));
913}
914
915TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {
916 auto t = makeNamedDecls("template <class T> struct foo;",
917 "template <class U> struct foo;", Lang_CXX);
918 EXPECT_TRUE(testStructuralMatch(t));
919}
920
921TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {
922 auto t = makeNamedDecls("template <class T> struct foo;",
923 "template <int T> struct foo;", Lang_CXX);
924 EXPECT_FALSE(testStructuralMatch(t));
925}
Gabor Marton6b01e1c2018-08-09 12:36:25 +0000926
Richard Smith76b90272019-05-09 03:59:21 +0000927TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
928 auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};",
929 "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX2a);
930 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
931 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
932 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
933 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
934 EXPECT_TRUE(testStructuralMatch(First, Second));
935}
936
937TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
938 auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};",
939 "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX2a);
940 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
941 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
942 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
943 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
944 EXPECT_FALSE(testStructuralMatch(First, Second));
945}
946
Gabor Marton4f883f12019-07-02 07:36:39 +0000947struct StructuralEquivalenceDependentTemplateArgsTest
948 : StructuralEquivalenceTemplateTest {};
949
950TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
951 SameStructsInDependentArgs) {
952 std::string Code =
953 R"(
954 template <typename>
955 struct S1;
956
957 template <typename>
958 struct enable_if;
959
960 struct S
961 {
962 template <typename T, typename enable_if<S1<T>>::type>
963 void f();
964 };
965 )";
966 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
967 functionTemplateDecl(hasName("f")));
968 EXPECT_TRUE(testStructuralMatch(t));
969}
970
971TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
972 DifferentStructsInDependentArgs) {
973 std::string Code =
974 R"(
975 template <typename>
976 struct S1;
977
978 template <typename>
979 struct S2;
980
981 template <typename>
982 struct enable_if;
983 )";
984 auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
985 struct S
986 {
987 template <typename T, typename enable_if<S1<T>>::type>
988 void f();
989 };
990 )",
991 Code + R"(
992 struct S
993 {
994 template <typename T, typename enable_if<S2<T>>::type>
995 void f();
996 };
997 )",
998 Lang_CXX11,
999 functionTemplateDecl(hasName("f")));
1000 EXPECT_FALSE(testStructuralMatch(t));
1001}
1002
1003TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1004 SameStructsInDependentScopeDeclRefExpr) {
1005 std::string Code =
1006 R"(
1007 template <typename>
1008 struct S1;
1009
1010 template <bool>
1011 struct enable_if;
1012
1013 struct S
1014 {
1015 template <typename T, typename enable_if<S1<T>::value>::type>
1016 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1017 };
1018 )";
1019 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
1020 functionTemplateDecl(hasName("f")));
1021 EXPECT_TRUE(testStructuralMatch(t));
1022}
1023
1024TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1025 DifferentStructsInDependentScopeDeclRefExpr) {
1026 std::string Code =
1027 R"(
1028 template <typename>
1029 struct S1;
1030
1031 template <typename>
1032 struct S2;
1033
1034 template <bool>
1035 struct enable_if;
1036 )";
1037 auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1038 struct S
1039 {
1040 template <typename T, typename enable_if<S1<T>::value>::type>
1041 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1042 };
1043 )",
1044 Code + R"(
1045 struct S
1046 {
1047 template <typename T, typename enable_if<S2<T>::value>::type>
1048 void f();
1049 };
1050 )",
1051 Lang_CXX,
1052 functionTemplateDecl(hasName("f")));
1053 EXPECT_FALSE(testStructuralMatch(t));
1054}
1055
1056TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1057 DifferentValueInDependentScopeDeclRefExpr) {
1058 std::string Code =
1059 R"(
1060 template <typename>
1061 struct S1;
1062
1063 template <bool>
1064 struct enable_if;
1065 )";
1066 auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1067 struct S
1068 {
1069 template <typename T, typename enable_if<S1<T>::value1>::type>
1070 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1071 };
1072 )",
1073 Code + R"(
1074 struct S
1075 {
1076 template <typename T, typename enable_if<S1<T>::value2>::type>
1077 void f();
1078 };
1079 )",
1080 Lang_CXX,
1081 functionTemplateDecl(hasName("f")));
1082 EXPECT_FALSE(testStructuralMatch(t));
1083}
1084
Gabor Marton1f667532018-05-24 08:41:07 +00001085} // end namespace ast_matchers
1086} // end namespace clang