blob: 19d2e334fc7e628259852224dfc1fa425b94ea12 [file] [log] [blame]
Gabor Marton1f667532018-05-24 08:41:07 +00001#include "clang/AST/ASTContext.h"
2#include "clang/ASTMatchers/ASTMatchers.h"
3#include "clang/AST/ASTStructuralEquivalence.h"
4#include "clang/Frontend/ASTUnit.h"
5#include "clang/Tooling/Tooling.h"
6
7#include "Language.h"
8#include "DeclMatcher.h"
9
10#include "gtest/gtest.h"
11
12namespace clang {
13namespace ast_matchers {
14
15using std::get;
16
17struct StructuralEquivalenceTest : ::testing::Test {
18 std::unique_ptr<ASTUnit> AST0, AST1;
19 std::string Code0, Code1; // Buffers for SourceManager
20
Balazs Keric7797c42018-07-11 09:37:24 +000021 // Get a pair of node pointers into the synthesized AST from the given code
22 // snippets. To determine the returned node, a separate matcher is specified
23 // for both snippets. The first matching node is returned.
24 template <typename NodeType, typename MatcherType>
25 std::tuple<NodeType *, NodeType *> makeDecls(
26 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
27 const MatcherType &Matcher0, const MatcherType &Matcher1) {
Gabor Marton1f667532018-05-24 08:41:07 +000028 this->Code0 = SrcCode0;
29 this->Code1 = SrcCode1;
30 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
31
32 const char *const InputFileName = "input.cc";
33
34 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
35 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
36
Balazs Keric7797c42018-07-11 09:37:24 +000037 NodeType *D0 = FirstDeclMatcher<NodeType>().match(
38 AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
39 NodeType *D1 = FirstDeclMatcher<NodeType>().match(
40 AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
Gabor Marton1f667532018-05-24 08:41:07 +000041
Gabor Marton1f667532018-05-24 08:41:07 +000042 return std::make_tuple(D0, D1);
43 }
44
Gabor Martonf086fa82018-07-17 12:06:36 +000045 std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> makeTuDecls(
46 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang) {
47 this->Code0 = SrcCode0;
48 this->Code1 = SrcCode1;
49 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
50
51 const char *const InputFileName = "input.cc";
52
53 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
54 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
55
56 return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),
57 AST1->getASTContext().getTranslationUnitDecl());
58 }
59
Balazs Keric7797c42018-07-11 09:37:24 +000060 // Get a pair of node pointers into the synthesized AST from the given code
61 // snippets. The same matcher is used for both snippets.
62 template <typename NodeType, typename MatcherType>
63 std::tuple<NodeType *, NodeType *> makeDecls(
64 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
65 const MatcherType &AMatcher) {
66 return makeDecls<NodeType, MatcherType>(
67 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
68 }
69
70 // Get a pair of Decl pointers to the synthesized declarations from the given
71 // code snippets. We search for the first NamedDecl with given name in both
72 // snippets.
73 std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls(
74 const std::string &SrcCode0, const std::string &SrcCode1,
75 Language Lang, const char *const Identifier = "foo") {
76 auto Matcher = namedDecl(hasName(Identifier));
77 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);
78 }
79
Gabor Martonf086fa82018-07-17 12:06:36 +000080 bool testStructuralMatch(Decl *D0, Decl *D1) {
Gabor Marton1f667532018-05-24 08:41:07 +000081 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
Gabor Marton26f72a92018-07-12 09:42:05 +000082 StructuralEquivalenceContext Ctx(
83 D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
84 StructuralEquivalenceKind::Default, false, false);
Gabor Marton1f667532018-05-24 08:41:07 +000085 return Ctx.IsStructurallyEquivalent(D0, D1);
86 }
87
Gabor Martonf086fa82018-07-17 12:06:36 +000088 bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
Gabor Marton1f667532018-05-24 08:41:07 +000089 return testStructuralMatch(get<0>(t), get<1>(t));
90 }
91};
92
93TEST_F(StructuralEquivalenceTest, Int) {
94 auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
95 EXPECT_TRUE(testStructuralMatch(Decls));
96}
97
98TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
99 auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
100 EXPECT_TRUE(testStructuralMatch(Decls));
101}
102
103TEST_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.
110TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
111 auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
112 EXPECT_FALSE(testStructuralMatch(Decls));
113}
114
115TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
116 auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
117 EXPECT_TRUE(testStructuralMatch(Decls));
118}
119
120TEST_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
126TEST_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
132TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
Balazs Keric7797c42018-07-11 09:37:24 +0000133 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);
Gabor Marton1f667532018-05-24 08:41:07 +0000140 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
141}
142
143TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
Balazs Keric7797c42018-07-11 09:37:24 +0000144 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);
Gabor Marton1f667532018-05-24 08:41:07 +0000151 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
152}
153
154TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
Balazs Keric7797c42018-07-11 09:37:24 +0000155 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
Gabor Marton1f667532018-05-24 08:41:07 +0000156 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 )",
Balazs Keric7797c42018-07-11 09:37:24 +0000166 Lang_CXX,
167 classTemplateSpecializationDecl());
168 EXPECT_FALSE(testStructuralMatch(Decls));
Gabor Marton1f667532018-05-24 08:41:07 +0000169}
170
171// This test is disabled for now.
172// FIXME Enable it, once the check is implemented.
173TEST_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
199TEST_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
Balazs Keric7797c42018-07-11 09:37:24 +0000215struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
216};
217
218TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
219 auto t = makeNamedDecls("void foo(int&);",
220 "void foo(const int&);", Lang_CXX);
221 EXPECT_FALSE(testStructuralMatch(t));
222}
223
224TEST_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
231TEST_F(StructuralEquivalenceFunctionTest, Throw) {
232 auto t = makeNamedDecls("void foo();",
233 "void foo() throw();", Lang_CXX);
234 EXPECT_FALSE(testStructuralMatch(t));
235}
236
237TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
238 auto t = makeNamedDecls("void foo();",
239 "void foo() noexcept;", Lang_CXX11);
240 EXPECT_FALSE(testStructuralMatch(t));
241}
242
243TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
244 auto t = makeNamedDecls("void foo() throw();",
245 "void foo() noexcept;", Lang_CXX11);
246 EXPECT_FALSE(testStructuralMatch(t));
247}
248
249TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
250 auto t = makeNamedDecls("void foo() throw();",
251 "void foo() noexcept(false);", Lang_CXX11);
252 EXPECT_FALSE(testStructuralMatch(t));
253}
254
255TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
256 auto t = makeNamedDecls("void foo() throw();",
257 "void foo() noexcept(true);", Lang_CXX11);
258 EXPECT_FALSE(testStructuralMatch(t));
259}
260
261TEST_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
268TEST_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
274TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
275 auto t = makeNamedDecls("void foo() noexcept;",
276 "void foo() noexcept(false);", Lang_CXX11);
277 EXPECT_FALSE(testStructuralMatch(t));
278}
279
280TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
281 auto t = makeNamedDecls("void foo() noexcept;",
282 "void foo() noexcept(true);", Lang_CXX11);
283 EXPECT_FALSE(testStructuralMatch(t));
284}
285
286TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
287 auto t = makeNamedDecls("char foo();",
288 "int foo();", Lang_CXX);
289 EXPECT_FALSE(testStructuralMatch(t));
290}
291
292TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
293 auto t = makeNamedDecls("char foo();",
294 "const char foo();", Lang_CXX);
295 EXPECT_FALSE(testStructuralMatch(t));
296}
297
298TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
299 auto t = makeNamedDecls("char &foo();",
300 "char &&foo();", Lang_CXX11);
301 EXPECT_FALSE(testStructuralMatch(t));
302}
303
304TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
305 auto t = makeNamedDecls("void foo(int);",
306 "void foo(int, int);", Lang_CXX);
307 EXPECT_FALSE(testStructuralMatch(t));
308}
309
310TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
311 auto t = makeNamedDecls("void foo(int);",
312 "void foo(char);", Lang_CXX);
313 EXPECT_FALSE(testStructuralMatch(t));
314}
315
316TEST_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
322TEST_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
328TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
329 auto t = makeNamedDecls("void foo(int *);",
330 "void foo(int);", Lang_CXX);
331 EXPECT_FALSE(testStructuralMatch(t));
332}
333
334TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
335 auto t = makeNamedDecls(
336 "void ((foo))();",
337 "void foo();",
338 Lang_CXX);
339 EXPECT_TRUE(testStructuralMatch(t));
340}
341
342TEST_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
350TEST_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
358struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
359};
360
361TEST_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
369TEST_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
375TEST_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
382TEST_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
388TEST_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
394TEST_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
400TEST_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
406TEST_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
414TEST_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
420TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
421 auto t = makeDecls<FunctionDecl>(
422 "void foo();", "struct foo { foo(); };", Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000423 functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo")));
Balazs Keric7797c42018-07-11 09:37:24 +0000424 EXPECT_FALSE(testStructuralMatch(t));
425}
426
427TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
428 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
429 "struct X { X(int); };", Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000430 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000431 EXPECT_FALSE(testStructuralMatch(t));
432}
433
434TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
435 auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
436 "struct X { explicit X(int); };",
437 Lang_CXX11,
Balazs Keri36883d32018-07-11 15:26:26 +0000438 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000439 EXPECT_FALSE(testStructuralMatch(t));
440}
441
442TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
443 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
444 "struct X { X() = default; };",
445 Lang_CXX11,
Balazs Keri36883d32018-07-11 15:26:26 +0000446 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000447 EXPECT_FALSE(testStructuralMatch(t));
448}
449
450TEST_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
458TEST_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
467TEST_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
476TEST_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
485struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
Gabor Martonf086fa82018-07-17 12:06:36 +0000486 // 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 };
Balazs Keric7797c42018-07-11 09:37:24 +0000491};
492
493TEST_F(StructuralEquivalenceRecordTest, Name) {
494 auto t = makeDecls<CXXRecordDecl>(
495 "struct A{ };",
496 "struct B{ };",
497 Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000498 cxxRecordDecl(hasName("A")),
499 cxxRecordDecl(hasName("B")));
Balazs Keric7797c42018-07-11 09:37:24 +0000500 EXPECT_FALSE(testStructuralMatch(t));
501}
502
503TEST_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
511TEST_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
520TEST_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
528TEST_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
536TEST_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
545TEST_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
Gabor Martonf086fa82018-07-17 12:06:36 +0000558TEST_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
585TEST_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
Balazs Keric7797c42018-07-11 09:37:24 +0000622TEST_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
Gabor Marton1f667532018-05-24 08:41:07 +0000630} // end namespace ast_matchers
631} // end namespace clang