1 #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 
12 namespace clang {
13 namespace ast_matchers {
14 
15 using std::get;
16 
17 struct StructuralEquivalenceTest : ::testing::Test {
18   std::unique_ptr<ASTUnit> AST0, AST1;
19   std::string Code0, Code1; // Buffers for SourceManager
20 
21   // 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) {
28     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 
37     NodeType *D0 = FirstDeclMatcher<NodeType>().match(
38         AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
39     NodeType *D1 = FirstDeclMatcher<NodeType>().match(
40         AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
41 
42     return std::make_tuple(D0, D1);
43   }
44 
45   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 
60   // 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 
80   bool testStructuralMatch(Decl *D0, Decl *D1) {
81     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;
93   }
94 
95   bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
96     return testStructuralMatch(get<0>(t), get<1>(t));
97   }
98 };
99 
100 TEST_F(StructuralEquivalenceTest, Int) {
101   auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
102   EXPECT_TRUE(testStructuralMatch(Decls));
103 }
104 
105 TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
106   auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
107   EXPECT_TRUE(testStructuralMatch(Decls));
108 }
109 
110 TEST_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.
117 TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
118   auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
119   EXPECT_FALSE(testStructuralMatch(Decls));
120 }
121 
122 TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
123   auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
124   EXPECT_TRUE(testStructuralMatch(Decls));
125 }
126 
127 TEST_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 
133 TEST_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 
139 TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
140   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);
147   EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
148 }
149 
150 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
151   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);
158   EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
159 }
160 
161 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
162   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
163       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       )",
173       Lang_CXX,
174       classTemplateSpecializationDecl());
175   EXPECT_FALSE(testStructuralMatch(Decls));
176 }
177 
178 // This test is disabled for now.
179 // FIXME Enable it, once the check is implemented.
180 TEST_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 
206 TEST_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 
222 struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
223 };
224 
225 TEST_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 
233 TEST_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 
242 TEST_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 
251 TEST_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 
260 TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
261   auto t = makeNamedDecls("void foo(int&);",
262                           "void foo(const int&);", Lang_CXX);
263   EXPECT_FALSE(testStructuralMatch(t));
264 }
265 
266 TEST_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 
273 TEST_F(StructuralEquivalenceFunctionTest, Throw) {
274   auto t = makeNamedDecls("void foo();",
275                           "void foo() throw();", Lang_CXX);
276   EXPECT_FALSE(testStructuralMatch(t));
277 }
278 
279 TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
280   auto t = makeNamedDecls("void foo();",
281                           "void foo() noexcept;", Lang_CXX11);
282   EXPECT_FALSE(testStructuralMatch(t));
283 }
284 
285 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
286   auto t = makeNamedDecls("void foo() throw();",
287                           "void foo() noexcept;", Lang_CXX11);
288   EXPECT_FALSE(testStructuralMatch(t));
289 }
290 
291 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
292   auto t = makeNamedDecls("void foo() throw();",
293                           "void foo() noexcept(false);", Lang_CXX11);
294   EXPECT_FALSE(testStructuralMatch(t));
295 }
296 
297 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
298   auto t = makeNamedDecls("void foo() throw();",
299                           "void foo() noexcept(true);", Lang_CXX11);
300   EXPECT_FALSE(testStructuralMatch(t));
301 }
302 
303 TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) {
304   // The expression is not checked yet.
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 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
802   auto t = makeNamedDecls(
803       "struct A{ }; struct B{ }; void foo(A a, A b);",
804       "struct A{ }; struct B{ }; void foo(A a, B b);",
805       Lang_CXX);
806   EXPECT_FALSE(testStructuralMatch(t));
807 }
808 
809 struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
810 
811 TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
812   auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);
813   EXPECT_TRUE(testStructuralMatch(t));
814 }
815 
816 TEST_F(StructuralEquivalenceEnumTest,
817        FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {
818   auto t =
819       makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);
820   EXPECT_TRUE(testStructuralMatch(t));
821 }
822 
823 TEST_F(StructuralEquivalenceEnumTest,
824        EnumShouldBeEqualWithEnumWhichHasDefinition) {
825   auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",
826                           Lang_CXX11);
827   EXPECT_TRUE(testStructuralMatch(t));
828 }
829 
830 TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {
831   auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",
832                           Lang_CXX11);
833   EXPECT_FALSE(testStructuralMatch(t));
834 }
835 
836 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};
837 
838 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {
839   auto t = makeNamedDecls("template <class T> struct foo;",
840                           "template <class T> struct foo;", Lang_CXX);
841   EXPECT_TRUE(testStructuralMatch(t));
842 }
843 
844 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {
845   auto t = makeNamedDecls("template <class T> struct foo;",
846                           "template <class U> struct foo;", Lang_CXX);
847   EXPECT_TRUE(testStructuralMatch(t));
848 }
849 
850 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {
851   auto t = makeNamedDecls("template <class T> struct foo;",
852                           "template <int T> struct foo;", Lang_CXX);
853   EXPECT_FALSE(testStructuralMatch(t));
854 }
855 
856 } // end namespace ast_matchers
857 } // end namespace clang
858