1 #include "clang/AST/ASTContext.h"
2 #include "clang/AST/ASTStructuralEquivalence.h"
3 #include "clang/ASTMatchers/ASTMatchers.h"
4 #include "clang/Frontend/ASTUnit.h"
5 #include "clang/Tooling/Tooling.h"
6 #include "llvm/Support/Host.h"
7 
8 #include "Language.h"
9 #include "DeclMatcher.h"
10 
11 #include "gtest/gtest.h"
12 
13 namespace clang {
14 namespace ast_matchers {
15 
16 using std::get;
17 
18 struct StructuralEquivalenceTest : ::testing::Test {
19   std::unique_ptr<ASTUnit> AST0, AST1;
20   std::string Code0, Code1; // Buffers for SourceManager
21 
22   // Get a pair of node pointers into the synthesized AST from the given code
23   // snippets. To determine the returned node, a separate matcher is specified
24   // for both snippets. The first matching node is returned.
25   template <typename NodeType, typename MatcherType>
26   std::tuple<NodeType *, NodeType *> makeDecls(
27       const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
28       const MatcherType &Matcher0, const MatcherType &Matcher1) {
29     this->Code0 = SrcCode0;
30     this->Code1 = SrcCode1;
31     ArgVector Args = getBasicRunOptionsForLanguage(Lang);
32 
33     const char *const InputFileName = "input.cc";
34 
35     AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
36     AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
37 
38     NodeType *D0 = FirstDeclMatcher<NodeType>().match(
39         AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
40     NodeType *D1 = FirstDeclMatcher<NodeType>().match(
41         AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
42 
43     return std::make_tuple(D0, D1);
44   }
45 
46   std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> makeTuDecls(
47       const std::string &SrcCode0, const std::string &SrcCode1, Language Lang) {
48     this->Code0 = SrcCode0;
49     this->Code1 = SrcCode1;
50     ArgVector Args = getBasicRunOptionsForLanguage(Lang);
51 
52     const char *const InputFileName = "input.cc";
53 
54     AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
55     AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
56 
57     return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),
58                            AST1->getASTContext().getTranslationUnitDecl());
59   }
60 
61   // Get a pair of node pointers into the synthesized AST from the given code
62   // snippets. The same matcher is used for both snippets.
63   template <typename NodeType, typename MatcherType>
64   std::tuple<NodeType *, NodeType *> makeDecls(
65       const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
66       const MatcherType &AMatcher) {
67     return makeDecls<NodeType, MatcherType>(
68           SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
69   }
70 
71   // Get a pair of Decl pointers to the synthesized declarations from the given
72   // code snippets. We search for the first NamedDecl with given name in both
73   // snippets.
74   std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls(
75       const std::string &SrcCode0, const std::string &SrcCode1,
76       Language Lang, const char *const Identifier = "foo") {
77     auto Matcher = namedDecl(hasName(Identifier));
78     return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);
79   }
80 
81   bool testStructuralMatch(Decl *D0, Decl *D1) {
82     llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
83     llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
84     StructuralEquivalenceContext Ctx01(
85         D0->getASTContext(), D1->getASTContext(),
86         NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false);
87     StructuralEquivalenceContext Ctx10(
88         D1->getASTContext(), D0->getASTContext(),
89         NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false);
90     bool Eq01 = Ctx01.IsEquivalent(D0, D1);
91     bool Eq10 = Ctx10.IsEquivalent(D1, D0);
92     EXPECT_EQ(Eq01, Eq10);
93     return Eq01;
94   }
95 
96   bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
97     return testStructuralMatch(get<0>(t), get<1>(t));
98   }
99 };
100 
101 TEST_F(StructuralEquivalenceTest, Int) {
102   auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
103   EXPECT_TRUE(testStructuralMatch(Decls));
104 }
105 
106 TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
107   auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
108   EXPECT_TRUE(testStructuralMatch(Decls));
109 }
110 
111 TEST_F(StructuralEquivalenceTest, Char) {
112   auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX);
113   EXPECT_TRUE(testStructuralMatch(Decls));
114 }
115 
116 // This test is disabled for now.
117 // FIXME Whether this is equivalent is dependendant on the target.
118 TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
119   auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
120   EXPECT_FALSE(testStructuralMatch(Decls));
121 }
122 
123 TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
124   auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
125   EXPECT_TRUE(testStructuralMatch(Decls));
126 }
127 
128 TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
129   auto Decls = makeNamedDecls("struct foo { int x; };",
130                               "struct foo { signed int x; };", Lang_CXX);
131   EXPECT_TRUE(testStructuralMatch(Decls));
132 }
133 
134 TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
135   auto Decls = makeNamedDecls("struct foo { char x; };",
136                               "struct foo { signed char x; };", Lang_CXX);
137   EXPECT_FALSE(testStructuralMatch(Decls));
138 }
139 
140 TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
141   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
142       R"(template <class T> struct foo; template<> struct foo<int>{};)",
143       R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
144       Lang_CXX,
145       classTemplateSpecializationDecl());
146   auto Spec0 = get<0>(Decls);
147   auto Spec1 = get<1>(Decls);
148   EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
149 }
150 
151 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
152   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
153       R"(template <class T> struct foo; template<> struct foo<char>{};)",
154       R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
155       Lang_CXX,
156       classTemplateSpecializationDecl());
157   auto Spec0 = get<0>(Decls);
158   auto Spec1 = get<1>(Decls);
159   EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
160 }
161 
162 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
163   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
164       R"(
165       struct true_type{};
166       template <class T> struct foo;
167       template<> struct foo<char> : true_type {};
168       )",
169       R"(
170       struct true_type{};
171       template <class T> struct foo;
172       template<> struct foo<signed char> : true_type {};
173       )",
174       Lang_CXX,
175       classTemplateSpecializationDecl());
176   EXPECT_FALSE(testStructuralMatch(Decls));
177 }
178 
179 // This test is disabled for now.
180 // FIXME Enable it, once the check is implemented.
181 TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
182   auto Code =
183       R"(
184       namespace NS {
185       template <class T> class Base {
186           int a;
187       };
188       class Derived : Base<Derived> {
189       };
190       }
191       void foo(NS::Derived &);
192       )";
193   auto Decls = makeNamedDecls(Code, Code, Lang_CXX);
194 
195   NamespaceDecl *NS =
196       LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
197   ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
198       get<1>(Decls), classTemplateDecl(hasName("Base")));
199 
200   // Reorder the decls, move the TD to the last place in the DC.
201   NS->removeDecl(TD);
202   NS->addDeclInternal(TD);
203 
204   EXPECT_FALSE(testStructuralMatch(Decls));
205 }
206 
207 TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
208   auto Code = "class X { int a; int b; };";
209   auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");
210 
211   CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
212       get<1>(Decls), cxxRecordDecl(hasName("X")));
213   FieldDecl *FD =
214       FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
215 
216   // Reorder the FieldDecls
217   RD->removeDecl(FD);
218   RD->addDeclInternal(FD);
219 
220   EXPECT_FALSE(testStructuralMatch(Decls));
221 }
222 
223 struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
224 };
225 
226 TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {
227   auto t = makeNamedDecls(
228       "void foo();",
229       "template<class T> void foo();",
230       Lang_CXX);
231   EXPECT_FALSE(testStructuralMatch(t));
232 }
233 
234 TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) {
235   auto t = makeDecls<FunctionDecl>(
236       "struct X{}; bool operator<(X, X);",
237       "struct X{}; bool operator==(X, X);", Lang_CXX,
238       functionDecl(hasOverloadedOperatorName("<")),
239       functionDecl(hasOverloadedOperatorName("==")));
240   EXPECT_FALSE(testStructuralMatch(t));
241 }
242 
243 TEST_F(StructuralEquivalenceFunctionTest, SameOperators) {
244   auto t = makeDecls<FunctionDecl>(
245       "struct X{}; bool operator<(X, X);",
246       "struct X{}; bool operator<(X, X);", Lang_CXX,
247       functionDecl(hasOverloadedOperatorName("<")),
248       functionDecl(hasOverloadedOperatorName("<")));
249   EXPECT_TRUE(testStructuralMatch(t));
250 }
251 
252 TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) {
253   auto t = makeDecls<FunctionDecl>(
254       "struct X{ X(); };",
255       "struct X{ ~X(); };", Lang_CXX,
256       cxxConstructorDecl(),
257       cxxDestructorDecl());
258   EXPECT_FALSE(testStructuralMatch(t));
259 }
260 
261 TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
262   auto t = makeNamedDecls("void foo(int&);",
263                           "void foo(const int&);", Lang_CXX);
264   EXPECT_FALSE(testStructuralMatch(t));
265 }
266 
267 TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
268   auto t = makeNamedDecls("void foo(int);",
269                           "void foo(const int);", Lang_CXX);
270   EXPECT_TRUE(testStructuralMatch(t));
271   // consider this OK
272 }
273 
274 TEST_F(StructuralEquivalenceFunctionTest, Throw) {
275   auto t = makeNamedDecls("void foo();",
276                           "void foo() throw();", Lang_CXX);
277   EXPECT_FALSE(testStructuralMatch(t));
278 }
279 
280 TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
281   auto t = makeNamedDecls("void foo();",
282                           "void foo() noexcept;", Lang_CXX11);
283   EXPECT_FALSE(testStructuralMatch(t));
284 }
285 
286 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
287   auto t = makeNamedDecls("void foo() throw();",
288                           "void foo() noexcept;", Lang_CXX11);
289   EXPECT_FALSE(testStructuralMatch(t));
290 }
291 
292 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
293   auto t = makeNamedDecls("void foo() throw();",
294                           "void foo() noexcept(false);", Lang_CXX11);
295   EXPECT_FALSE(testStructuralMatch(t));
296 }
297 
298 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
299   auto t = makeNamedDecls("void foo() throw();",
300                           "void foo() noexcept(true);", Lang_CXX11);
301   EXPECT_FALSE(testStructuralMatch(t));
302 }
303 
304 TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) {
305   auto t = makeNamedDecls("void foo() noexcept(false);",
306                           "void foo() noexcept(true);", Lang_CXX11);
307   EXPECT_FALSE(testStructuralMatch(t));
308 }
309 
310 TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
311   auto t = makeNamedDecls("void foo() noexcept(false);",
312                           "void foo() noexcept(false);", Lang_CXX11);
313   EXPECT_TRUE(testStructuralMatch(t));
314 }
315 
316 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
317   auto t = makeNamedDecls("void foo() noexcept;",
318                           "void foo() noexcept(false);", Lang_CXX11);
319   EXPECT_FALSE(testStructuralMatch(t));
320 }
321 
322 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
323   auto t = makeNamedDecls("void foo() noexcept;",
324                           "void foo() noexcept(true);", Lang_CXX11);
325   EXPECT_FALSE(testStructuralMatch(t));
326 }
327 
328 TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
329   auto t = makeNamedDecls("char foo();",
330                           "int foo();", Lang_CXX);
331   EXPECT_FALSE(testStructuralMatch(t));
332 }
333 
334 TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
335   auto t = makeNamedDecls("char foo();",
336                           "const char foo();", Lang_CXX);
337   EXPECT_FALSE(testStructuralMatch(t));
338 }
339 
340 TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
341   auto t = makeNamedDecls("char &foo();",
342                           "char &&foo();", Lang_CXX11);
343   EXPECT_FALSE(testStructuralMatch(t));
344 }
345 
346 TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
347   auto t = makeNamedDecls("void foo(int);",
348                           "void foo(int, int);", Lang_CXX);
349   EXPECT_FALSE(testStructuralMatch(t));
350 }
351 
352 TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
353   auto t = makeNamedDecls("void foo(int);",
354                           "void foo(char);", Lang_CXX);
355   EXPECT_FALSE(testStructuralMatch(t));
356 }
357 
358 TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
359   auto t = makeNamedDecls("void foo(int a);",
360                           "void foo(int b);", Lang_CXX);
361   EXPECT_TRUE(testStructuralMatch(t));
362 }
363 
364 TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
365   auto t = makeNamedDecls("void foo(int x...);",
366                           "void foo(int x);", Lang_CXX);
367   EXPECT_FALSE(testStructuralMatch(t));
368 }
369 
370 TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
371   auto t = makeNamedDecls("void foo(int *);",
372                           "void foo(int);", Lang_CXX);
373   EXPECT_FALSE(testStructuralMatch(t));
374 }
375 
376 TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
377   auto t = makeNamedDecls(
378       "void ((foo))();",
379       "void foo();",
380       Lang_CXX);
381   EXPECT_TRUE(testStructuralMatch(t));
382 }
383 
384 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
385   auto t = makeNamedDecls(
386       "void (foo)() throw(int);",
387       "void (foo)() noexcept;",
388       Lang_CXX11);
389   EXPECT_FALSE(testStructuralMatch(t));
390 }
391 
392 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
393   auto t = makeNamedDecls(
394       "struct A { void (foo)() const; };",
395       "struct A { void (foo)(); };",
396       Lang_CXX11);
397   EXPECT_FALSE(testStructuralMatch(t));
398 }
399 
400 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
401   auto t = makeNamedDecls(
402       "__attribute__((noreturn)) void foo();",
403       "                          void foo();",
404       Lang_C);
405   EXPECT_TRUE(testStructuralMatch(t));
406 }
407 
408 TEST_F(StructuralEquivalenceFunctionTest,
409     FunctionsWithDifferentCallingConventions) {
410   // These attributes may not be available on certain platforms.
411   if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
412       llvm::Triple::x86_64)
413     return;
414   auto t = makeNamedDecls(
415       "__attribute__((preserve_all)) void foo();",
416       "__attribute__((ms_abi))   void foo();",
417       Lang_C);
418   EXPECT_FALSE(testStructuralMatch(t));
419 }
420 
421 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {
422   if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
423       llvm::Triple::x86_64)
424     return;
425   auto t = makeNamedDecls(
426       "__attribute__((no_caller_saved_registers)) void foo();",
427       "                                           void foo();",
428       Lang_C);
429   EXPECT_FALSE(testStructuralMatch(t));
430 }
431 
432 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
433 };
434 
435 TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
436   auto t = makeDecls<CXXMethodDecl>(
437       "struct X { void foo(); };",
438       "struct X { virtual void foo(); };", Lang_CXX,
439       cxxMethodDecl(hasName("foo")));
440   EXPECT_FALSE(testStructuralMatch(t));
441 }
442 
443 TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
444   auto t = makeNamedDecls("struct X { virtual void foo(); };",
445                           "struct X { virtual void foo() = 0; };", Lang_CXX);
446   EXPECT_FALSE(testStructuralMatch(t));
447 }
448 
449 TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
450   // The final-ness is not checked yet.
451   auto t = makeNamedDecls("struct X { virtual void foo(); };",
452                           "struct X { virtual void foo() final; };", Lang_CXX);
453   EXPECT_FALSE(testStructuralMatch(t));
454 }
455 
456 TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
457   auto t = makeNamedDecls("struct X { void foo(); };",
458                           "struct X { void foo() const; };", Lang_CXX);
459   EXPECT_FALSE(testStructuralMatch(t));
460 }
461 
462 TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
463   auto t = makeNamedDecls("struct X { void foo(); };",
464                           "struct X { static void foo(); };", Lang_CXX);
465   EXPECT_FALSE(testStructuralMatch(t));
466 }
467 
468 TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
469   auto t = makeNamedDecls("struct X { void foo(); };",
470                           "struct X { void foo() &&; };", Lang_CXX11);
471   EXPECT_FALSE(testStructuralMatch(t));
472 }
473 
474 TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
475   auto t = makeNamedDecls("struct X { void foo() &; };",
476                           "struct X { void foo() &&; };", Lang_CXX11);
477   EXPECT_FALSE(testStructuralMatch(t));
478 }
479 
480 TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
481   auto t = makeDecls<CXXMethodDecl>(
482       "struct X { public: void foo(); };",
483       "struct X { private: void foo(); };", Lang_CXX,
484       cxxMethodDecl(hasName("foo")));
485   EXPECT_FALSE(testStructuralMatch(t));
486 }
487 
488 TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
489   auto t = makeNamedDecls("struct X { void foo(); };",
490                           "struct X { void foo() = delete; };", Lang_CXX11);
491   EXPECT_FALSE(testStructuralMatch(t));
492 }
493 
494 TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
495   auto t = makeDecls<FunctionDecl>(
496       "void foo();", "struct foo { foo(); };", Lang_CXX,
497       functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo")));
498   EXPECT_FALSE(testStructuralMatch(t));
499 }
500 
501 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
502   auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
503                                          "struct X { X(int); };", Lang_CXX,
504                                          cxxConstructorDecl(hasName("X")));
505   EXPECT_FALSE(testStructuralMatch(t));
506 }
507 
508 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
509   auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
510                                          "struct X { explicit X(int); };",
511                                          Lang_CXX11,
512                                          cxxConstructorDecl(hasName("X")));
513   EXPECT_FALSE(testStructuralMatch(t));
514 }
515 
516 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
517   auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
518                                          "struct X { X() = default; };",
519                                          Lang_CXX11,
520                                          cxxConstructorDecl(hasName("X")));
521   EXPECT_FALSE(testStructuralMatch(t));
522 }
523 
524 TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
525   auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",
526                                         "struct X { operator char(); };",
527                                          Lang_CXX11,
528                                          cxxConversionDecl());
529   EXPECT_FALSE(testStructuralMatch(t));
530 }
531 
532 TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
533   auto t = makeDecls<FunctionDecl>(
534       "struct X { int operator +(int); };",
535       "struct X { int operator -(int); };", Lang_CXX,
536       functionDecl(hasOverloadedOperatorName("+")),
537       functionDecl(hasOverloadedOperatorName("-")));
538   EXPECT_FALSE(testStructuralMatch(t));
539 }
540 
541 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
542   auto t = makeDecls<FunctionDecl>(
543       "struct X { virtual void f(); }; void X::f() { }",
544       "struct X { virtual void f() { }; };",
545       Lang_CXX,
546       functionDecl(allOf(hasName("f"), isDefinition())));
547   EXPECT_TRUE(testStructuralMatch(t));
548 }
549 
550 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
551   auto t = makeDecls<FunctionDecl>(
552       "struct X { virtual void f(); }; void X::f() { }",
553       "struct X { void f(); }; void X::f() { }",
554       Lang_CXX,
555       functionDecl(allOf(hasName("f"), isDefinition())));
556   EXPECT_FALSE(testStructuralMatch(t));
557 }
558 
559 struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
560   // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
561   RecordDecl *getRecordDecl(FieldDecl *FD) {
562     auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());
563     return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
564   };
565 };
566 
567 TEST_F(StructuralEquivalenceRecordTest, Name) {
568   auto t = makeDecls<CXXRecordDecl>(
569       "struct A{ };",
570       "struct B{ };",
571       Lang_CXX,
572       cxxRecordDecl(hasName("A")),
573       cxxRecordDecl(hasName("B")));
574   EXPECT_FALSE(testStructuralMatch(t));
575 }
576 
577 TEST_F(StructuralEquivalenceRecordTest, Fields) {
578   auto t = makeNamedDecls(
579       "struct foo{ int x; };",
580       "struct foo{ char x; };",
581       Lang_CXX);
582   EXPECT_FALSE(testStructuralMatch(t));
583 }
584 
585 TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
586   // Currently, methods of a class are not checked at class equivalence.
587   auto t = makeNamedDecls(
588       "struct foo{ int x(); };",
589       "struct foo{ char x(); };",
590       Lang_CXX);
591   EXPECT_FALSE(testStructuralMatch(t));
592 }
593 
594 TEST_F(StructuralEquivalenceRecordTest, Bases) {
595   auto t = makeNamedDecls(
596       "struct A{ }; struct foo: A { };",
597       "struct B{ }; struct foo: B { };",
598       Lang_CXX);
599   EXPECT_FALSE(testStructuralMatch(t));
600 }
601 
602 TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
603   auto t = makeNamedDecls(
604       "struct A{ }; struct foo: A { };",
605       "struct A{ }; struct foo: virtual A { };",
606       Lang_CXX);
607   EXPECT_FALSE(testStructuralMatch(t));
608 }
609 
610 TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
611   // Access specifier in inheritance is not checked yet.
612   auto t = makeNamedDecls(
613       "struct A{ }; struct foo: public A { };",
614       "struct A{ }; struct foo: private A { };",
615       Lang_CXX);
616   EXPECT_FALSE(testStructuralMatch(t));
617 }
618 
619 TEST_F(StructuralEquivalenceRecordTest, Match) {
620   auto Code = R"(
621       struct A{ };
622       struct B{ };
623       struct foo: A, virtual B {
624         void x();
625         int a;
626       };
627       )";
628   auto t = makeNamedDecls(Code, Code, Lang_CXX);
629   EXPECT_TRUE(testStructuralMatch(t));
630 }
631 
632 TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
633   auto t = makeTuDecls(
634       R"(
635       struct A {
636         struct {
637           struct A *next;
638         } entry0;
639         struct {
640           struct A *next;
641         } entry1;
642       };
643       )",
644       "", Lang_C);
645   auto *TU = get<0>(t);
646   auto *Entry0 =
647       FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));
648   auto *Entry1 =
649       FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));
650   auto *R0 = getRecordDecl(Entry0);
651   auto *R1 = getRecordDecl(Entry1);
652 
653   ASSERT_NE(R0, R1);
654   EXPECT_TRUE(testStructuralMatch(R0, R0));
655   EXPECT_TRUE(testStructuralMatch(R1, R1));
656   EXPECT_FALSE(testStructuralMatch(R0, R1));
657 }
658 
659 TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
660   auto t = makeTuDecls(
661       R"(
662       struct X {
663         struct {
664           int a;
665         };
666         struct {
667           int b;
668         };
669       };
670       )",
671       "", Lang_C);
672   auto *TU = get<0>(t);
673   auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
674       TU, indirectFieldDecl(hasName("a")));
675   auto *FA = cast<FieldDecl>(A->chain().front());
676   RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
677   auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(
678       TU, indirectFieldDecl(hasName("b")));
679   auto *FB = cast<FieldDecl>(B->chain().front());
680   RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();
681 
682   ASSERT_NE(RA, RB);
683   EXPECT_TRUE(testStructuralMatch(RA, RA));
684   EXPECT_TRUE(testStructuralMatch(RB, RB));
685   EXPECT_FALSE(testStructuralMatch(RA, RB));
686 }
687 
688 TEST_F(StructuralEquivalenceRecordTest,
689        RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
690   auto t = makeTuDecls(
691       R"(
692       struct X {
693         struct { int a; };
694         struct { int b; };
695       };
696       )",
697       R"(
698       struct X { // The order is reversed.
699         struct { int b; };
700         struct { int a; };
701       };
702       )",
703       Lang_C);
704 
705   auto *TU = get<0>(t);
706   auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
707       TU, indirectFieldDecl(hasName("a")));
708   auto *FA = cast<FieldDecl>(A->chain().front());
709   RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
710 
711   auto *TU1 = get<1>(t);
712   auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(
713       TU1, indirectFieldDecl(hasName("a")));
714   auto *FA1 = cast<FieldDecl>(A1->chain().front());
715   RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();
716 
717   RecordDecl *X =
718       FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X")));
719   RecordDecl *X1 =
720       FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X")));
721   ASSERT_NE(X, X1);
722   EXPECT_FALSE(testStructuralMatch(X, X1));
723 
724   ASSERT_NE(RA, RA1);
725   EXPECT_TRUE(testStructuralMatch(RA, RA));
726   EXPECT_TRUE(testStructuralMatch(RA1, RA1));
727   EXPECT_FALSE(testStructuralMatch(RA1, RA));
728 }
729 
730 TEST_F(StructuralEquivalenceRecordTest,
731        UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
732   auto Code =
733       R"(
734       struct A {
735         struct {
736           struct A *next;
737         } entry0;
738         struct {
739           struct A *next;
740         } entry1;
741       };
742       )";
743   auto t = makeTuDecls(Code, Code, Lang_C);
744 
745   auto *FromTU = get<0>(t);
746   auto *Entry1 =
747       FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));
748 
749   auto *ToTU = get<1>(t);
750   auto *Entry0 =
751       FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
752   auto *A =
753       FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
754   A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
755                         // nullptr. This may be the case during ASTImport.
756 
757   auto *R0 = getRecordDecl(Entry0);
758   auto *R1 = getRecordDecl(Entry1);
759 
760   ASSERT_NE(R0, R1);
761   EXPECT_TRUE(testStructuralMatch(R0, R0));
762   EXPECT_TRUE(testStructuralMatch(R1, R1));
763   EXPECT_FALSE(testStructuralMatch(R0, R1));
764 }
765 
766 TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {
767   auto t = makeDecls<CXXRecordDecl>(
768       "struct A { };",
769       "template<class T> struct A { };",
770       Lang_CXX,
771       cxxRecordDecl(hasName("A")));
772   EXPECT_FALSE(testStructuralMatch(t));
773 }
774 
775 TEST_F(StructuralEquivalenceRecordTest,
776     FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {
777   auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11);
778   EXPECT_TRUE(testStructuralMatch(t));
779 }
780 
781 TEST_F(StructuralEquivalenceRecordTest,
782        FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {
783   auto t =
784       makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11);
785   EXPECT_TRUE(testStructuralMatch(t));
786 }
787 
788 TEST_F(StructuralEquivalenceRecordTest,
789        RecordShouldBeEqualWithRecordWhichHasDefinition) {
790   auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };",
791                           Lang_CXX11);
792   EXPECT_TRUE(testStructuralMatch(t));
793 }
794 
795 TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {
796   auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };",
797                           Lang_CXX11);
798   EXPECT_FALSE(testStructuralMatch(t));
799 }
800 
801 struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {};
802 
803 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) {
804   // Get the LambdaExprs, unfortunately we can't match directly the underlying
805   // implicit CXXRecordDecl of the Lambda classes.
806   auto t = makeDecls<LambdaExpr>(
807       "void f() { auto L0 = [](int){}; }",
808       "void f() { auto L1 = [](){}; }",
809       Lang_CXX11,
810       lambdaExpr(),
811       lambdaExpr());
812   CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
813   CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
814   EXPECT_FALSE(testStructuralMatch(L0, L1));
815 }
816 
817 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) {
818   auto t = makeDecls<LambdaExpr>(
819       "void f() { auto L0 = [](int){}; }",
820       "void f() { auto L1 = [](int){}; }",
821       Lang_CXX11,
822       lambdaExpr(),
823       lambdaExpr());
824   CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
825   CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
826   EXPECT_TRUE(testStructuralMatch(L0, L1));
827 }
828 
829 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) {
830   auto t = makeDecls<LambdaExpr>(
831       "void f() { char* X; auto L0 = [X](){}; }",
832       "void f() { float X; auto L1 = [X](){}; }",
833       Lang_CXX11,
834       lambdaExpr(),
835       lambdaExpr());
836   CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
837   CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
838   EXPECT_FALSE(testStructuralMatch(L0, L1));
839 }
840 
841 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) {
842   auto t = makeDecls<LambdaExpr>(
843       "void f() { float X; auto L0 = [X](){}; }",
844       "void f() { float X; auto L1 = [X](){}; }",
845       Lang_CXX11,
846       lambdaExpr(),
847       lambdaExpr());
848   CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
849   CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
850   EXPECT_TRUE(testStructuralMatch(L0, L1));
851 }
852 
853 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
854   auto t = makeNamedDecls(
855       "struct A{ }; struct B{ }; void foo(A a, A b);",
856       "struct A{ }; struct B{ }; void foo(A a, B b);",
857       Lang_CXX);
858   EXPECT_FALSE(testStructuralMatch(t));
859 }
860 
861 TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {
862   auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};",
863                               "struct foo {explicit(true) foo(int);};", Lang_CXX2a);
864   CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
865       get<0>(Decls), cxxConstructorDecl(hasName("foo")));
866   CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
867       get<1>(Decls), cxxConstructorDecl(hasName("foo")));
868   EXPECT_FALSE(testStructuralMatch(First, Second));
869 }
870 
871 TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {
872   auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};",
873                               "struct foo {explicit(true) foo(int);};", Lang_CXX2a);
874   CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
875       get<0>(Decls), cxxConstructorDecl(hasName("foo")));
876   CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
877       get<1>(Decls), cxxConstructorDecl(hasName("foo")));
878   EXPECT_TRUE(testStructuralMatch(First, Second));
879 }
880 
881 struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
882 
883 TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
884   auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);
885   EXPECT_TRUE(testStructuralMatch(t));
886 }
887 
888 TEST_F(StructuralEquivalenceEnumTest,
889        FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {
890   auto t =
891       makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);
892   EXPECT_TRUE(testStructuralMatch(t));
893 }
894 
895 TEST_F(StructuralEquivalenceEnumTest,
896        EnumShouldBeEqualWithEnumWhichHasDefinition) {
897   auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",
898                           Lang_CXX11);
899   EXPECT_TRUE(testStructuralMatch(t));
900 }
901 
902 TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {
903   auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",
904                           Lang_CXX11);
905   EXPECT_FALSE(testStructuralMatch(t));
906 }
907 
908 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};
909 
910 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {
911   auto t = makeNamedDecls("template <class T> struct foo;",
912                           "template <class T> struct foo;", Lang_CXX);
913   EXPECT_TRUE(testStructuralMatch(t));
914 }
915 
916 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {
917   auto t = makeNamedDecls("template <class T> struct foo;",
918                           "template <class U> struct foo;", Lang_CXX);
919   EXPECT_TRUE(testStructuralMatch(t));
920 }
921 
922 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {
923   auto t = makeNamedDecls("template <class T> struct foo;",
924                           "template <int T> struct foo;", Lang_CXX);
925   EXPECT_FALSE(testStructuralMatch(t));
926 }
927 
928 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
929   auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};",
930                               "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX2a);
931   CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
932       get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
933   CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
934       get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
935   EXPECT_TRUE(testStructuralMatch(First, Second));
936 }
937 
938 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
939   auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};",
940                               "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX2a);
941   CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
942       get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
943   CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
944       get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
945   EXPECT_FALSE(testStructuralMatch(First, Second));
946 }
947 
948 TEST_F(StructuralEquivalenceTemplateTest,
949        TemplateVsSubstTemplateTemplateParmInArgEq) {
950   auto t = makeDecls<ClassTemplateSpecializationDecl>(
951       R"(
952 template <typename P1> class Arg { };
953 template <template <typename PP1> class P1> class Primary { };
954 
955 void f() {
956   // Make specialization with simple template.
957   Primary <Arg> A;
958 }
959       )",
960       R"(
961 template <typename P1> class Arg { };
962 template <template <typename PP1> class P1> class Primary { };
963 
964 template <template <typename PP1> class P1> class Templ {
965   void f() {
966     // Make specialization with substituted template template param.
967     Primary <P1> A;
968   };
969 };
970 
971 // Instantiate with substitution Arg into P1.
972 template class Templ <Arg>;
973       )",
974       Lang_CXX, classTemplateSpecializationDecl(hasName("Primary")));
975   EXPECT_TRUE(testStructuralMatch(t));
976 }
977 
978 TEST_F(StructuralEquivalenceTemplateTest,
979        TemplateVsSubstTemplateTemplateParmInArgNotEq) {
980   auto t = makeDecls<ClassTemplateSpecializationDecl>(
981       R"(
982 template <typename P1> class Arg { };
983 template <template <typename PP1> class P1> class Primary { };
984 
985 void f() {
986   // Make specialization with simple template.
987   Primary <Arg> A;
988 }
989       )",
990       R"(
991 // Arg is different from the other, this should cause non-equivalence.
992 template <typename P1> class Arg { int X; };
993 template <template <typename PP1> class P1> class Primary { };
994 
995 template <template <typename PP1> class P1> class Templ {
996   void f() {
997     // Make specialization with substituted template template param.
998     Primary <P1> A;
999   };
1000 };
1001 
1002 // Instantiate with substitution Arg into P1.
1003 template class Templ <Arg>;
1004       )",
1005       Lang_CXX, classTemplateSpecializationDecl(hasName("Primary")));
1006   EXPECT_FALSE(testStructuralMatch(t));
1007 }
1008 
1009 struct StructuralEquivalenceDependentTemplateArgsTest
1010     : StructuralEquivalenceTemplateTest {};
1011 
1012 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1013        SameStructsInDependentArgs) {
1014   std::string Code =
1015       R"(
1016       template <typename>
1017       struct S1;
1018 
1019       template <typename>
1020       struct enable_if;
1021 
1022       struct S
1023       {
1024         template <typename T, typename enable_if<S1<T>>::type>
1025         void f();
1026       };
1027       )";
1028   auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
1029                                            functionTemplateDecl(hasName("f")));
1030   EXPECT_TRUE(testStructuralMatch(t));
1031 }
1032 
1033 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1034        DifferentStructsInDependentArgs) {
1035   std::string Code =
1036       R"(
1037       template <typename>
1038       struct S1;
1039 
1040       template <typename>
1041       struct S2;
1042 
1043       template <typename>
1044       struct enable_if;
1045       )";
1046   auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1047       struct S
1048       {
1049         template <typename T, typename enable_if<S1<T>>::type>
1050         void f();
1051       };
1052       )",
1053                                            Code + R"(
1054       struct S
1055       {
1056         template <typename T, typename enable_if<S2<T>>::type>
1057         void f();
1058       };
1059       )",
1060                                            Lang_CXX11,
1061                                            functionTemplateDecl(hasName("f")));
1062   EXPECT_FALSE(testStructuralMatch(t));
1063 }
1064 
1065 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1066        SameStructsInDependentScopeDeclRefExpr) {
1067   std::string Code =
1068       R"(
1069       template <typename>
1070       struct S1;
1071 
1072       template <bool>
1073       struct enable_if;
1074 
1075       struct S
1076       {
1077         template <typename T, typename enable_if<S1<T>::value>::type>
1078         void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1079       };
1080       )";
1081   auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
1082                                            functionTemplateDecl(hasName("f")));
1083   EXPECT_TRUE(testStructuralMatch(t));
1084 }
1085 
1086 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1087        DifferentStructsInDependentScopeDeclRefExpr) {
1088   std::string Code =
1089       R"(
1090       template <typename>
1091       struct S1;
1092 
1093       template <typename>
1094       struct S2;
1095 
1096       template <bool>
1097       struct enable_if;
1098       )";
1099   auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1100       struct S
1101       {
1102         template <typename T, typename enable_if<S1<T>::value>::type>
1103         void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1104       };
1105       )",
1106                                            Code + R"(
1107       struct S
1108       {
1109         template <typename T, typename enable_if<S2<T>::value>::type>
1110         void f();
1111       };
1112       )",
1113                                            Lang_CXX,
1114                                            functionTemplateDecl(hasName("f")));
1115   EXPECT_FALSE(testStructuralMatch(t));
1116 }
1117 
1118 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1119        DifferentValueInDependentScopeDeclRefExpr) {
1120   std::string Code =
1121       R"(
1122       template <typename>
1123       struct S1;
1124 
1125       template <bool>
1126       struct enable_if;
1127       )";
1128   auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1129       struct S
1130       {
1131         template <typename T, typename enable_if<S1<T>::value1>::type>
1132         void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1133       };
1134       )",
1135                                            Code + R"(
1136       struct S
1137       {
1138         template <typename T, typename enable_if<S1<T>::value2>::type>
1139         void f();
1140       };
1141       )",
1142                                            Lang_CXX,
1143                                            functionTemplateDecl(hasName("f")));
1144   EXPECT_FALSE(testStructuralMatch(t));
1145 }
1146 
1147 TEST_F(
1148     StructuralEquivalenceTemplateTest,
1149     ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) {
1150   auto t = makeDecls<ClassTemplateSpecializationDecl>(
1151       R"(
1152       template <class T> struct Primary {};
1153       namespace N {
1154         struct Arg;
1155       }
1156       // Explicit instantiation with qualified name.
1157       template struct Primary<N::Arg>;
1158       )",
1159       R"(
1160       template <class T> struct Primary {};
1161       namespace N {
1162         struct Arg;
1163       }
1164       using namespace N;
1165       // Explicit instantiation with UNqualified name.
1166       template struct Primary<Arg>;
1167       )",
1168       Lang_CXX,
1169       classTemplateSpecializationDecl(hasName("Primary")));
1170   EXPECT_TRUE(testStructuralMatch(t));
1171 }
1172 
1173 TEST_F(
1174     StructuralEquivalenceTemplateTest,
1175     ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) {
1176   auto t = makeDecls<ClassTemplateSpecializationDecl>(
1177       R"(
1178       template <class T> struct Primary {};
1179       namespace N {
1180         struct Arg { int a; };
1181       }
1182       // Explicit instantiation with qualified name.
1183       template struct Primary<N::Arg>;
1184       )",
1185       R"(
1186       template <class T> struct Primary {};
1187       namespace N {
1188         // This struct is not equivalent with the other in the prev TU.
1189         struct Arg { double b; }; // -- Field mismatch.
1190       }
1191       using namespace N;
1192       // Explicit instantiation with UNqualified name.
1193       template struct Primary<Arg>;
1194       )",
1195       Lang_CXX,
1196       classTemplateSpecializationDecl(hasName("Primary")));
1197   EXPECT_FALSE(testStructuralMatch(t));
1198 }
1199 
1200 TEST_F(
1201     StructuralEquivalenceTemplateTest,
1202     ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) {
1203   auto t = makeDecls<ClassTemplateSpecializationDecl>(
1204       R"(
1205       template <template <class> class T> struct Primary {};
1206       namespace N {
1207         template <class T> struct Arg;
1208       }
1209       // Explicit instantiation with qualified name.
1210       template struct Primary<N::Arg>;
1211       )",
1212       R"(
1213       template <template <class> class T> struct Primary {};
1214       namespace N {
1215         template <class T> struct Arg;
1216       }
1217       using namespace N;
1218       // Explicit instantiation with UNqualified name.
1219       template struct Primary<Arg>;
1220       )",
1221       Lang_CXX,
1222       classTemplateSpecializationDecl(hasName("Primary")));
1223   EXPECT_TRUE(testStructuralMatch(t));
1224 }
1225 
1226 TEST_F(
1227     StructuralEquivalenceTemplateTest,
1228     ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) {
1229   auto t = makeDecls<ClassTemplateSpecializationDecl>(
1230       R"(
1231       template <template <class> class T> struct Primary {};
1232       namespace N {
1233         template <class T> struct Arg { int a; };
1234       }
1235       // Explicit instantiation with qualified name.
1236       template struct Primary<N::Arg>;
1237       )",
1238       R"(
1239       template <template <class> class T> struct Primary {};
1240       namespace N {
1241         // This template is not equivalent with the other in the prev TU.
1242         template <class T> struct Arg { double b; }; // -- Field mismatch.
1243       }
1244       using namespace N;
1245       // Explicit instantiation with UNqualified name.
1246       template struct Primary<Arg>;
1247       )",
1248       Lang_CXX,
1249       classTemplateSpecializationDecl(hasName("Primary")));
1250   EXPECT_FALSE(testStructuralMatch(t));
1251 }
1252 
1253 TEST_F(
1254     StructuralEquivalenceTemplateTest,
1255     ClassTemplSpecWithInequivalentShadowedTemplArg) {
1256   auto t = makeDecls<ClassTemplateSpecializationDecl>(
1257       R"(
1258       template <template <class> class T> struct Primary {};
1259       template <class T> struct Arg { int a; };
1260       // Explicit instantiation with ::Arg
1261       template struct Primary<Arg>;
1262       )",
1263       R"(
1264       template <template <class> class T> struct Primary {};
1265       template <class T> struct Arg { int a; };
1266       namespace N {
1267         // This template is not equivalent with the other in the global scope.
1268         template <class T> struct Arg { double b; }; // -- Field mismatch.
1269         // Explicit instantiation with N::Arg which shadows ::Arg
1270         template struct Primary<Arg>;
1271       }
1272       )",
1273       Lang_CXX,
1274       classTemplateSpecializationDecl(hasName("Primary")));
1275   EXPECT_FALSE(testStructuralMatch(t));
1276 }
1277 struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {
1278   llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
1279 
1280   template <typename NodeType, typename MatcherType>
1281   std::pair<NodeType *, NodeType *>
1282   findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU,
1283                MatcherType M) {
1284     NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M);
1285     NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M);
1286     return {D0, D1};
1287   }
1288 
1289   template <typename NodeType>
1290   bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) {
1291     return NonEquivalentDecls.count(D) > 0;
1292   }
1293 };
1294 
1295 TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {
1296   auto TU = makeTuDecls(
1297       R"(
1298       class A {};
1299       class B {};
1300       void x(A, A);
1301       )",
1302       R"(
1303       class A {};
1304       class B {};
1305       void x(A, B);
1306       )",
1307       Lang_CXX);
1308 
1309   StructuralEquivalenceContext Ctx(
1310       get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
1311       NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
1312 
1313   auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));
1314   EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second));
1315 
1316   EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1317       TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1318   EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1319       TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
1320 }
1321 
1322 TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {
1323   auto TU = makeTuDecls(
1324       R"(
1325       class A {};
1326       class B { int i; };
1327       void x(A *);
1328       void y(A *);
1329       class C {
1330         friend void x(A *);
1331         friend void y(A *);
1332       };
1333       )",
1334       R"(
1335       class A {};
1336       class B { int i; };
1337       void x(A *);
1338       void y(B *);
1339       class C {
1340         friend void x(A *);
1341         friend void y(B *);
1342       };
1343       )",
1344       Lang_CXX);
1345 
1346   StructuralEquivalenceContext Ctx(
1347       get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
1348       NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
1349 
1350   auto C = findDeclPair<CXXRecordDecl>(
1351       TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));
1352   EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second));
1353 
1354   EXPECT_FALSE(isInNonEqCache(C));
1355   EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1356       TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1357   EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1358       TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
1359   EXPECT_FALSE(isInNonEqCache(
1360       findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
1361   EXPECT_FALSE(isInNonEqCache(
1362       findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y")))));
1363 }
1364 
1365 TEST_F(StructuralEquivalenceCacheTest, Cycle) {
1366   auto TU = makeTuDecls(
1367       R"(
1368       class C;
1369       class A { C *c; };
1370       void x(A *);
1371       class C {
1372         friend void x(A *);
1373       };
1374       )",
1375       R"(
1376       class C;
1377       class A { C *c; };
1378       void x(A *);
1379       class C {
1380         friend void x(A *);
1381       };
1382       )",
1383       Lang_CXX);
1384 
1385   StructuralEquivalenceContext Ctx(
1386       get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
1387       NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
1388 
1389   auto C = findDeclPair<CXXRecordDecl>(
1390       TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));
1391   EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second));
1392 
1393   EXPECT_FALSE(isInNonEqCache(C));
1394   EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1395       TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1396   EXPECT_FALSE(isInNonEqCache(
1397       findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
1398 }
1399 
1400 } // end namespace ast_matchers
1401 } // end namespace clang
1402