]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unittests/AST/StructuralEquivalenceTest.cpp
Vendor import of clang trunk r338150:
[FreeBSD/FreeBSD.git] / unittests / AST / StructuralEquivalenceTest.cpp
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 *>> NonEquivalentDecls;
82     StructuralEquivalenceContext Ctx(
83         D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
84         StructuralEquivalenceKind::Default, false, false);
85     return Ctx.IsEquivalent(D0, D1);
86   }
87
88   bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
89     return testStructuralMatch(get<0>(t), get<1>(t));
90   }
91 };
92
93 TEST_F(StructuralEquivalenceTest, Int) {
94   auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
95   EXPECT_TRUE(testStructuralMatch(Decls));
96 }
97
98 TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
99   auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
100   EXPECT_TRUE(testStructuralMatch(Decls));
101 }
102
103 TEST_F(StructuralEquivalenceTest, Char) {
104   auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX);
105   EXPECT_TRUE(testStructuralMatch(Decls));
106 }
107
108 // This test is disabled for now.
109 // FIXME Whether this is equivalent is dependendant on the target.
110 TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
111   auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
112   EXPECT_FALSE(testStructuralMatch(Decls));
113 }
114
115 TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
116   auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
117   EXPECT_TRUE(testStructuralMatch(Decls));
118 }
119
120 TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
121   auto Decls = makeNamedDecls("struct foo { int x; };",
122                               "struct foo { signed int x; };", Lang_CXX);
123   EXPECT_TRUE(testStructuralMatch(Decls));
124 }
125
126 TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
127   auto Decls = makeNamedDecls("struct foo { char x; };",
128                               "struct foo { signed char x; };", Lang_CXX);
129   EXPECT_FALSE(testStructuralMatch(Decls));
130 }
131
132 TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
133   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
134       R"(template <class T> struct foo; template<> struct foo<int>{};)",
135       R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
136       Lang_CXX,
137       classTemplateSpecializationDecl());
138   auto Spec0 = get<0>(Decls);
139   auto Spec1 = get<1>(Decls);
140   EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
141 }
142
143 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
144   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
145       R"(template <class T> struct foo; template<> struct foo<char>{};)",
146       R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
147       Lang_CXX,
148       classTemplateSpecializationDecl());
149   auto Spec0 = get<0>(Decls);
150   auto Spec1 = get<1>(Decls);
151   EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
152 }
153
154 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
155   auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
156       R"(
157       struct true_type{};
158       template <class T> struct foo;
159       template<> struct foo<char> : true_type {};
160       )",
161       R"(
162       struct true_type{};
163       template <class T> struct foo;
164       template<> struct foo<signed char> : true_type {};
165       )",
166       Lang_CXX,
167       classTemplateSpecializationDecl());
168   EXPECT_FALSE(testStructuralMatch(Decls));
169 }
170
171 // This test is disabled for now.
172 // FIXME Enable it, once the check is implemented.
173 TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
174   auto Code =
175       R"(
176       namespace NS {
177       template <class T> class Base {
178           int a;
179       };
180       class Derived : Base<Derived> {
181       };
182       }
183       void foo(NS::Derived &);
184       )";
185   auto Decls = makeNamedDecls(Code, Code, Lang_CXX);
186
187   NamespaceDecl *NS =
188       LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
189   ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
190       get<1>(Decls), classTemplateDecl(hasName("Base")));
191
192   // Reorder the decls, move the TD to the last place in the DC.
193   NS->removeDecl(TD);
194   NS->addDeclInternal(TD);
195
196   EXPECT_FALSE(testStructuralMatch(Decls));
197 }
198
199 TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
200   auto Code = "class X { int a; int b; };";
201   auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");
202
203   CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
204       get<1>(Decls), cxxRecordDecl(hasName("X")));
205   FieldDecl *FD =
206       FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
207
208   // Reorder the FieldDecls
209   RD->removeDecl(FD);
210   RD->addDeclInternal(FD);
211
212   EXPECT_FALSE(testStructuralMatch(Decls));
213 }
214
215 struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
216 };
217
218 TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
219   auto t = makeNamedDecls("void foo(int&);",
220                           "void foo(const int&);", Lang_CXX);
221   EXPECT_FALSE(testStructuralMatch(t));
222 }
223
224 TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
225   auto t = makeNamedDecls("void foo(int);",
226                           "void foo(const int);", Lang_CXX);
227   EXPECT_TRUE(testStructuralMatch(t));
228   // consider this OK
229 }
230
231 TEST_F(StructuralEquivalenceFunctionTest, Throw) {
232   auto t = makeNamedDecls("void foo();",
233                           "void foo() throw();", Lang_CXX);
234   EXPECT_FALSE(testStructuralMatch(t));
235 }
236
237 TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
238   auto t = makeNamedDecls("void foo();",
239                           "void foo() noexcept;", Lang_CXX11);
240   EXPECT_FALSE(testStructuralMatch(t));
241 }
242
243 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
244   auto t = makeNamedDecls("void foo() throw();",
245                           "void foo() noexcept;", Lang_CXX11);
246   EXPECT_FALSE(testStructuralMatch(t));
247 }
248
249 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
250   auto t = makeNamedDecls("void foo() throw();",
251                           "void foo() noexcept(false);", Lang_CXX11);
252   EXPECT_FALSE(testStructuralMatch(t));
253 }
254
255 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
256   auto t = makeNamedDecls("void foo() throw();",
257                           "void foo() noexcept(true);", Lang_CXX11);
258   EXPECT_FALSE(testStructuralMatch(t));
259 }
260
261 TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) {
262   // The expression is not checked yet.
263   auto t = makeNamedDecls("void foo() noexcept(false);",
264                           "void foo() noexcept(true);", Lang_CXX11);
265   EXPECT_FALSE(testStructuralMatch(t));
266 }
267
268 TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
269   auto t = makeNamedDecls("void foo() noexcept(false);",
270                           "void foo() noexcept(false);", Lang_CXX11);
271   EXPECT_TRUE(testStructuralMatch(t));
272 }
273
274 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
275   auto t = makeNamedDecls("void foo() noexcept;",
276                           "void foo() noexcept(false);", Lang_CXX11);
277   EXPECT_FALSE(testStructuralMatch(t));
278 }
279
280 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
281   auto t = makeNamedDecls("void foo() noexcept;",
282                           "void foo() noexcept(true);", Lang_CXX11);
283   EXPECT_FALSE(testStructuralMatch(t));
284 }
285
286 TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
287   auto t = makeNamedDecls("char foo();",
288                           "int foo();", Lang_CXX);
289   EXPECT_FALSE(testStructuralMatch(t));
290 }
291
292 TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
293   auto t = makeNamedDecls("char foo();",
294                           "const char foo();", Lang_CXX);
295   EXPECT_FALSE(testStructuralMatch(t));
296 }
297
298 TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
299   auto t = makeNamedDecls("char &foo();",
300                           "char &&foo();", Lang_CXX11);
301   EXPECT_FALSE(testStructuralMatch(t));
302 }
303
304 TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
305   auto t = makeNamedDecls("void foo(int);",
306                           "void foo(int, int);", Lang_CXX);
307   EXPECT_FALSE(testStructuralMatch(t));
308 }
309
310 TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
311   auto t = makeNamedDecls("void foo(int);",
312                           "void foo(char);", Lang_CXX);
313   EXPECT_FALSE(testStructuralMatch(t));
314 }
315
316 TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
317   auto t = makeNamedDecls("void foo(int a);",
318                           "void foo(int b);", Lang_CXX);
319   EXPECT_TRUE(testStructuralMatch(t));
320 }
321
322 TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
323   auto t = makeNamedDecls("void foo(int x...);",
324                           "void foo(int x);", Lang_CXX);
325   EXPECT_FALSE(testStructuralMatch(t));
326 }
327
328 TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
329   auto t = makeNamedDecls("void foo(int *);",
330                           "void foo(int);", Lang_CXX);
331   EXPECT_FALSE(testStructuralMatch(t));
332 }
333
334 TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
335   auto t = makeNamedDecls(
336       "void ((foo))();",
337       "void foo();",
338       Lang_CXX);
339   EXPECT_TRUE(testStructuralMatch(t));
340 }
341
342 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
343   auto t = makeNamedDecls(
344       "void (foo)() throw(int);",
345       "void (foo)() noexcept;",
346       Lang_CXX11);
347   EXPECT_FALSE(testStructuralMatch(t));
348 }
349
350 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
351   auto t = makeNamedDecls(
352       "struct A { void (foo)() const; };",
353       "struct A { void (foo)(); };",
354       Lang_CXX11);
355   EXPECT_FALSE(testStructuralMatch(t));
356 }
357
358 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
359 };
360
361 TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
362   auto t = makeDecls<CXXMethodDecl>(
363       "struct X { void foo(); };",
364       "struct X { virtual void foo(); };", Lang_CXX,
365       cxxMethodDecl(hasName("foo")));
366   EXPECT_FALSE(testStructuralMatch(t));
367 }
368
369 TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
370   auto t = makeNamedDecls("struct X { virtual void foo(); };",
371                           "struct X { virtual void foo() = 0; };", Lang_CXX);
372   EXPECT_FALSE(testStructuralMatch(t));
373 }
374
375 TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
376   // The final-ness is not checked yet.
377   auto t = makeNamedDecls("struct X { virtual void foo(); };",
378                           "struct X { virtual void foo() final; };", Lang_CXX);
379   EXPECT_FALSE(testStructuralMatch(t));
380 }
381
382 TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
383   auto t = makeNamedDecls("struct X { void foo(); };",
384                           "struct X { void foo() const; };", Lang_CXX);
385   EXPECT_FALSE(testStructuralMatch(t));
386 }
387
388 TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
389   auto t = makeNamedDecls("struct X { void foo(); };",
390                           "struct X { static void foo(); };", Lang_CXX);
391   EXPECT_FALSE(testStructuralMatch(t));
392 }
393
394 TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
395   auto t = makeNamedDecls("struct X { void foo(); };",
396                           "struct X { void foo() &&; };", Lang_CXX11);
397   EXPECT_FALSE(testStructuralMatch(t));
398 }
399
400 TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
401   auto t = makeNamedDecls("struct X { void foo() &; };",
402                           "struct X { void foo() &&; };", Lang_CXX11);
403   EXPECT_FALSE(testStructuralMatch(t));
404 }
405
406 TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
407   auto t = makeDecls<CXXMethodDecl>(
408       "struct X { public: void foo(); };",
409       "struct X { private: void foo(); };", Lang_CXX,
410       cxxMethodDecl(hasName("foo")));
411   EXPECT_FALSE(testStructuralMatch(t));
412 }
413
414 TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
415   auto t = makeNamedDecls("struct X { void foo(); };",
416                           "struct X { void foo() = delete; };", Lang_CXX11);
417   EXPECT_FALSE(testStructuralMatch(t));
418 }
419
420 TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
421   auto t = makeDecls<FunctionDecl>(
422       "void foo();", "struct foo { foo(); };", Lang_CXX,
423       functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo")));
424   EXPECT_FALSE(testStructuralMatch(t));
425 }
426
427 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
428   auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
429                                          "struct X { X(int); };", Lang_CXX,
430                                          cxxConstructorDecl(hasName("X")));
431   EXPECT_FALSE(testStructuralMatch(t));
432 }
433
434 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
435   auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
436                                          "struct X { explicit X(int); };",
437                                          Lang_CXX11,
438                                          cxxConstructorDecl(hasName("X")));
439   EXPECT_FALSE(testStructuralMatch(t));
440 }
441
442 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
443   auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
444                                          "struct X { X() = default; };",
445                                          Lang_CXX11,
446                                          cxxConstructorDecl(hasName("X")));
447   EXPECT_FALSE(testStructuralMatch(t));
448 }
449
450 TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
451   auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",
452                                         "struct X { operator char(); };",
453                                          Lang_CXX11,
454                                          cxxConversionDecl());
455   EXPECT_FALSE(testStructuralMatch(t));
456 }
457
458 TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
459   auto t = makeDecls<FunctionDecl>(
460       "struct X { int operator +(int); };",
461       "struct X { int operator -(int); };", Lang_CXX,
462       functionDecl(hasOverloadedOperatorName("+")),
463       functionDecl(hasOverloadedOperatorName("-")));
464   EXPECT_FALSE(testStructuralMatch(t));
465 }
466
467 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
468   auto t = makeDecls<FunctionDecl>(
469       "struct X { virtual void f(); }; void X::f() { }",
470       "struct X { virtual void f() { }; };",
471       Lang_CXX,
472       functionDecl(allOf(hasName("f"), isDefinition())));
473   EXPECT_TRUE(testStructuralMatch(t));
474 }
475
476 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
477   auto t = makeDecls<FunctionDecl>(
478       "struct X { virtual void f(); }; void X::f() { }",
479       "struct X { void f(); }; void X::f() { }",
480       Lang_CXX,
481       functionDecl(allOf(hasName("f"), isDefinition())));
482   EXPECT_FALSE(testStructuralMatch(t));
483 }
484
485 struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
486   // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
487   RecordDecl *getRecordDecl(FieldDecl *FD) {
488     auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());
489     return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
490   };
491 };
492
493 TEST_F(StructuralEquivalenceRecordTest, Name) {
494   auto t = makeDecls<CXXRecordDecl>(
495       "struct A{ };",
496       "struct B{ };",
497       Lang_CXX,
498       cxxRecordDecl(hasName("A")),
499       cxxRecordDecl(hasName("B")));
500   EXPECT_FALSE(testStructuralMatch(t));
501 }
502
503 TEST_F(StructuralEquivalenceRecordTest, Fields) {
504   auto t = makeNamedDecls(
505       "struct foo{ int x; };",
506       "struct foo{ char x; };",
507       Lang_CXX);
508   EXPECT_FALSE(testStructuralMatch(t));
509 }
510
511 TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
512   // Currently, methods of a class are not checked at class equivalence.
513   auto t = makeNamedDecls(
514       "struct foo{ int x(); };",
515       "struct foo{ char x(); };",
516       Lang_CXX);
517   EXPECT_FALSE(testStructuralMatch(t));
518 }
519
520 TEST_F(StructuralEquivalenceRecordTest, Bases) {
521   auto t = makeNamedDecls(
522       "struct A{ }; struct foo: A { };",
523       "struct B{ }; struct foo: B { };",
524       Lang_CXX);
525   EXPECT_FALSE(testStructuralMatch(t));
526 }
527
528 TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
529   auto t = makeNamedDecls(
530       "struct A{ }; struct foo: A { };",
531       "struct A{ }; struct foo: virtual A { };",
532       Lang_CXX);
533   EXPECT_FALSE(testStructuralMatch(t));
534 }
535
536 TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
537   // Access specifier in inheritance is not checked yet.
538   auto t = makeNamedDecls(
539       "struct A{ }; struct foo: public A { };",
540       "struct A{ }; struct foo: private A { };",
541       Lang_CXX);
542   EXPECT_FALSE(testStructuralMatch(t));
543 }
544
545 TEST_F(StructuralEquivalenceRecordTest, Match) {
546   auto Code = R"(
547       struct A{ };
548       struct B{ };
549       struct foo: A, virtual B {
550         void x();
551         int a;
552       };
553       )";
554   auto t = makeNamedDecls(Code, Code, Lang_CXX);
555   EXPECT_TRUE(testStructuralMatch(t));
556 }
557
558 TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
559   auto t = makeTuDecls(
560       R"(
561       struct A {
562         struct {
563           struct A *next;
564         } entry0;
565         struct {
566           struct A *next;
567         } entry1;
568       };
569       )",
570       "", Lang_C);
571   auto *TU = get<0>(t);
572   auto *Entry0 =
573       FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));
574   auto *Entry1 =
575       FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));
576   auto *R0 = getRecordDecl(Entry0);
577   auto *R1 = getRecordDecl(Entry1);
578
579   ASSERT_NE(R0, R1);
580   EXPECT_TRUE(testStructuralMatch(R0, R0));
581   EXPECT_TRUE(testStructuralMatch(R1, R1));
582   EXPECT_FALSE(testStructuralMatch(R0, R1));
583 }
584
585 TEST_F(StructuralEquivalenceRecordTest,
586        UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
587   auto Code =
588       R"(
589       struct A {
590         struct {
591           struct A *next;
592         } entry0;
593         struct {
594           struct A *next;
595         } entry1;
596       };
597       )";
598   auto t = makeTuDecls(Code, Code, Lang_C);
599
600   auto *FromTU = get<0>(t);
601   auto *Entry1 =
602       FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));
603
604   auto *ToTU = get<1>(t);
605   auto *Entry0 =
606       FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
607   auto *A =
608       FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
609   A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
610                         // nullptr. This may be the case during ASTImport.
611
612   auto *R0 = getRecordDecl(Entry0);
613   auto *R1 = getRecordDecl(Entry1);
614
615   ASSERT_NE(R0, R1);
616   EXPECT_TRUE(testStructuralMatch(R0, R0));
617   EXPECT_TRUE(testStructuralMatch(R1, R1));
618   EXPECT_FALSE(testStructuralMatch(R0, R1));
619 }
620
621
622 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
623   auto t = makeNamedDecls(
624       "struct A{ }; struct B{ }; void foo(A a, A b);",
625       "struct A{ }; struct B{ }; void foo(A a, B b);",
626       Lang_CXX);
627   EXPECT_FALSE(testStructuralMatch(t));
628 }
629
630 } // end namespace ast_matchers
631 } // end namespace clang