blob: 551986fc1c90511077f069654280d9dd37e6ee62 [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
Balazs Keric7797c42018-07-11 09:37:24 +000045 // Get a pair of node pointers into the synthesized AST from the given code
46 // snippets. The same matcher is used for both snippets.
47 template <typename NodeType, typename MatcherType>
48 std::tuple<NodeType *, NodeType *> makeDecls(
49 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang,
50 const MatcherType &AMatcher) {
51 return makeDecls<NodeType, MatcherType>(
52 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
53 }
54
55 // Get a pair of Decl pointers to the synthesized declarations from the given
56 // code snippets. We search for the first NamedDecl with given name in both
57 // snippets.
58 std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls(
59 const std::string &SrcCode0, const std::string &SrcCode1,
60 Language Lang, const char *const Identifier = "foo") {
61 auto Matcher = namedDecl(hasName(Identifier));
62 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);
63 }
64
Gabor Marton1f667532018-05-24 08:41:07 +000065 bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) {
66 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
Gabor Marton26f72a92018-07-12 09:42:05 +000067 StructuralEquivalenceContext Ctx(
68 D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
69 StructuralEquivalenceKind::Default, false, false);
Gabor Marton1f667532018-05-24 08:41:07 +000070 return Ctx.IsStructurallyEquivalent(D0, D1);
71 }
72
73 bool testStructuralMatch(std::tuple<NamedDecl *, NamedDecl *> t) {
74 return testStructuralMatch(get<0>(t), get<1>(t));
75 }
76};
77
78TEST_F(StructuralEquivalenceTest, Int) {
79 auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
80 EXPECT_TRUE(testStructuralMatch(Decls));
81}
82
83TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
84 auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
85 EXPECT_TRUE(testStructuralMatch(Decls));
86}
87
88TEST_F(StructuralEquivalenceTest, Char) {
89 auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX);
90 EXPECT_TRUE(testStructuralMatch(Decls));
91}
92
93// This test is disabled for now.
94// FIXME Whether this is equivalent is dependendant on the target.
95TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
96 auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
97 EXPECT_FALSE(testStructuralMatch(Decls));
98}
99
100TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
101 auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
102 EXPECT_TRUE(testStructuralMatch(Decls));
103}
104
105TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
106 auto Decls = makeNamedDecls("struct foo { int x; };",
107 "struct foo { signed int x; };", Lang_CXX);
108 EXPECT_TRUE(testStructuralMatch(Decls));
109}
110
111TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
112 auto Decls = makeNamedDecls("struct foo { char x; };",
113 "struct foo { signed char x; };", Lang_CXX);
114 EXPECT_FALSE(testStructuralMatch(Decls));
115}
116
117TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
Balazs Keric7797c42018-07-11 09:37:24 +0000118 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
119 R"(template <class T> struct foo; template<> struct foo<int>{};)",
120 R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
121 Lang_CXX,
122 classTemplateSpecializationDecl());
123 auto Spec0 = get<0>(Decls);
124 auto Spec1 = get<1>(Decls);
Gabor Marton1f667532018-05-24 08:41:07 +0000125 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
126}
127
128TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
Balazs Keric7797c42018-07-11 09:37:24 +0000129 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
130 R"(template <class T> struct foo; template<> struct foo<char>{};)",
131 R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
132 Lang_CXX,
133 classTemplateSpecializationDecl());
134 auto Spec0 = get<0>(Decls);
135 auto Spec1 = get<1>(Decls);
Gabor Marton1f667532018-05-24 08:41:07 +0000136 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
137}
138
139TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
Balazs Keric7797c42018-07-11 09:37:24 +0000140 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
Gabor Marton1f667532018-05-24 08:41:07 +0000141 R"(
142 struct true_type{};
143 template <class T> struct foo;
144 template<> struct foo<char> : true_type {};
145 )",
146 R"(
147 struct true_type{};
148 template <class T> struct foo;
149 template<> struct foo<signed char> : true_type {};
150 )",
Balazs Keric7797c42018-07-11 09:37:24 +0000151 Lang_CXX,
152 classTemplateSpecializationDecl());
153 EXPECT_FALSE(testStructuralMatch(Decls));
Gabor Marton1f667532018-05-24 08:41:07 +0000154}
155
156// This test is disabled for now.
157// FIXME Enable it, once the check is implemented.
158TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
159 auto Code =
160 R"(
161 namespace NS {
162 template <class T> class Base {
163 int a;
164 };
165 class Derived : Base<Derived> {
166 };
167 }
168 void foo(NS::Derived &);
169 )";
170 auto Decls = makeNamedDecls(Code, Code, Lang_CXX);
171
172 NamespaceDecl *NS =
173 LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
174 ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
175 get<1>(Decls), classTemplateDecl(hasName("Base")));
176
177 // Reorder the decls, move the TD to the last place in the DC.
178 NS->removeDecl(TD);
179 NS->addDeclInternal(TD);
180
181 EXPECT_FALSE(testStructuralMatch(Decls));
182}
183
184TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
185 auto Code = "class X { int a; int b; };";
186 auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");
187
188 CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
189 get<1>(Decls), cxxRecordDecl(hasName("X")));
190 FieldDecl *FD =
191 FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
192
193 // Reorder the FieldDecls
194 RD->removeDecl(FD);
195 RD->addDeclInternal(FD);
196
197 EXPECT_FALSE(testStructuralMatch(Decls));
198}
199
Balazs Keric7797c42018-07-11 09:37:24 +0000200struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
201};
202
203TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
204 auto t = makeNamedDecls("void foo(int&);",
205 "void foo(const int&);", Lang_CXX);
206 EXPECT_FALSE(testStructuralMatch(t));
207}
208
209TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
210 auto t = makeNamedDecls("void foo(int);",
211 "void foo(const int);", Lang_CXX);
212 EXPECT_TRUE(testStructuralMatch(t));
213 // consider this OK
214}
215
216TEST_F(StructuralEquivalenceFunctionTest, Throw) {
217 auto t = makeNamedDecls("void foo();",
218 "void foo() throw();", Lang_CXX);
219 EXPECT_FALSE(testStructuralMatch(t));
220}
221
222TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
223 auto t = makeNamedDecls("void foo();",
224 "void foo() noexcept;", Lang_CXX11);
225 EXPECT_FALSE(testStructuralMatch(t));
226}
227
228TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
229 auto t = makeNamedDecls("void foo() throw();",
230 "void foo() noexcept;", Lang_CXX11);
231 EXPECT_FALSE(testStructuralMatch(t));
232}
233
234TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
235 auto t = makeNamedDecls("void foo() throw();",
236 "void foo() noexcept(false);", Lang_CXX11);
237 EXPECT_FALSE(testStructuralMatch(t));
238}
239
240TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
241 auto t = makeNamedDecls("void foo() throw();",
242 "void foo() noexcept(true);", Lang_CXX11);
243 EXPECT_FALSE(testStructuralMatch(t));
244}
245
246TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) {
247 // The expression is not checked yet.
248 auto t = makeNamedDecls("void foo() noexcept(false);",
249 "void foo() noexcept(true);", Lang_CXX11);
250 EXPECT_FALSE(testStructuralMatch(t));
251}
252
253TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
254 auto t = makeNamedDecls("void foo() noexcept(false);",
255 "void foo() noexcept(false);", Lang_CXX11);
256 EXPECT_TRUE(testStructuralMatch(t));
257}
258
259TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
260 auto t = makeNamedDecls("void foo() noexcept;",
261 "void foo() noexcept(false);", Lang_CXX11);
262 EXPECT_FALSE(testStructuralMatch(t));
263}
264
265TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
266 auto t = makeNamedDecls("void foo() noexcept;",
267 "void foo() noexcept(true);", Lang_CXX11);
268 EXPECT_FALSE(testStructuralMatch(t));
269}
270
271TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
272 auto t = makeNamedDecls("char foo();",
273 "int foo();", Lang_CXX);
274 EXPECT_FALSE(testStructuralMatch(t));
275}
276
277TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
278 auto t = makeNamedDecls("char foo();",
279 "const char foo();", Lang_CXX);
280 EXPECT_FALSE(testStructuralMatch(t));
281}
282
283TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
284 auto t = makeNamedDecls("char &foo();",
285 "char &&foo();", Lang_CXX11);
286 EXPECT_FALSE(testStructuralMatch(t));
287}
288
289TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
290 auto t = makeNamedDecls("void foo(int);",
291 "void foo(int, int);", Lang_CXX);
292 EXPECT_FALSE(testStructuralMatch(t));
293}
294
295TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
296 auto t = makeNamedDecls("void foo(int);",
297 "void foo(char);", Lang_CXX);
298 EXPECT_FALSE(testStructuralMatch(t));
299}
300
301TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
302 auto t = makeNamedDecls("void foo(int a);",
303 "void foo(int b);", Lang_CXX);
304 EXPECT_TRUE(testStructuralMatch(t));
305}
306
307TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
308 auto t = makeNamedDecls("void foo(int x...);",
309 "void foo(int x);", Lang_CXX);
310 EXPECT_FALSE(testStructuralMatch(t));
311}
312
313TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
314 auto t = makeNamedDecls("void foo(int *);",
315 "void foo(int);", Lang_CXX);
316 EXPECT_FALSE(testStructuralMatch(t));
317}
318
319TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
320 auto t = makeNamedDecls(
321 "void ((foo))();",
322 "void foo();",
323 Lang_CXX);
324 EXPECT_TRUE(testStructuralMatch(t));
325}
326
327TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
328 auto t = makeNamedDecls(
329 "void (foo)() throw(int);",
330 "void (foo)() noexcept;",
331 Lang_CXX11);
332 EXPECT_FALSE(testStructuralMatch(t));
333}
334
335TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
336 auto t = makeNamedDecls(
337 "struct A { void (foo)() const; };",
338 "struct A { void (foo)(); };",
339 Lang_CXX11);
340 EXPECT_FALSE(testStructuralMatch(t));
341}
342
343struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
344};
345
346TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
347 auto t = makeDecls<CXXMethodDecl>(
348 "struct X { void foo(); };",
349 "struct X { virtual void foo(); };", Lang_CXX,
350 cxxMethodDecl(hasName("foo")));
351 EXPECT_FALSE(testStructuralMatch(t));
352}
353
354TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
355 auto t = makeNamedDecls("struct X { virtual void foo(); };",
356 "struct X { virtual void foo() = 0; };", Lang_CXX);
357 EXPECT_FALSE(testStructuralMatch(t));
358}
359
360TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
361 // The final-ness is not checked yet.
362 auto t = makeNamedDecls("struct X { virtual void foo(); };",
363 "struct X { virtual void foo() final; };", Lang_CXX);
364 EXPECT_FALSE(testStructuralMatch(t));
365}
366
367TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
368 auto t = makeNamedDecls("struct X { void foo(); };",
369 "struct X { void foo() const; };", Lang_CXX);
370 EXPECT_FALSE(testStructuralMatch(t));
371}
372
373TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
374 auto t = makeNamedDecls("struct X { void foo(); };",
375 "struct X { static void foo(); };", Lang_CXX);
376 EXPECT_FALSE(testStructuralMatch(t));
377}
378
379TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
380 auto t = makeNamedDecls("struct X { void foo(); };",
381 "struct X { void foo() &&; };", Lang_CXX11);
382 EXPECT_FALSE(testStructuralMatch(t));
383}
384
385TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
386 auto t = makeNamedDecls("struct X { void foo() &; };",
387 "struct X { void foo() &&; };", Lang_CXX11);
388 EXPECT_FALSE(testStructuralMatch(t));
389}
390
391TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
392 auto t = makeDecls<CXXMethodDecl>(
393 "struct X { public: void foo(); };",
394 "struct X { private: void foo(); };", Lang_CXX,
395 cxxMethodDecl(hasName("foo")));
396 EXPECT_FALSE(testStructuralMatch(t));
397}
398
399TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
400 auto t = makeNamedDecls("struct X { void foo(); };",
401 "struct X { void foo() = delete; };", Lang_CXX11);
402 EXPECT_FALSE(testStructuralMatch(t));
403}
404
405TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
406 auto t = makeDecls<FunctionDecl>(
407 "void foo();", "struct foo { foo(); };", Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000408 functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo")));
Balazs Keric7797c42018-07-11 09:37:24 +0000409 EXPECT_FALSE(testStructuralMatch(t));
410}
411
412TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
413 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
414 "struct X { X(int); };", Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000415 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000416 EXPECT_FALSE(testStructuralMatch(t));
417}
418
419TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
420 auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
421 "struct X { explicit X(int); };",
422 Lang_CXX11,
Balazs Keri36883d32018-07-11 15:26:26 +0000423 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000424 EXPECT_FALSE(testStructuralMatch(t));
425}
426
427TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
428 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
429 "struct X { X() = default; };",
430 Lang_CXX11,
Balazs Keri36883d32018-07-11 15:26:26 +0000431 cxxConstructorDecl(hasName("X")));
Balazs Keric7797c42018-07-11 09:37:24 +0000432 EXPECT_FALSE(testStructuralMatch(t));
433}
434
435TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
436 auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",
437 "struct X { operator char(); };",
438 Lang_CXX11,
439 cxxConversionDecl());
440 EXPECT_FALSE(testStructuralMatch(t));
441}
442
443TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
444 auto t = makeDecls<FunctionDecl>(
445 "struct X { int operator +(int); };",
446 "struct X { int operator -(int); };", Lang_CXX,
447 functionDecl(hasOverloadedOperatorName("+")),
448 functionDecl(hasOverloadedOperatorName("-")));
449 EXPECT_FALSE(testStructuralMatch(t));
450}
451
452TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
453 auto t = makeDecls<FunctionDecl>(
454 "struct X { virtual void f(); }; void X::f() { }",
455 "struct X { virtual void f() { }; };",
456 Lang_CXX,
457 functionDecl(allOf(hasName("f"), isDefinition())));
458 EXPECT_TRUE(testStructuralMatch(t));
459}
460
461TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
462 auto t = makeDecls<FunctionDecl>(
463 "struct X { virtual void f(); }; void X::f() { }",
464 "struct X { void f(); }; void X::f() { }",
465 Lang_CXX,
466 functionDecl(allOf(hasName("f"), isDefinition())));
467 EXPECT_FALSE(testStructuralMatch(t));
468}
469
470struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
471};
472
473TEST_F(StructuralEquivalenceRecordTest, Name) {
474 auto t = makeDecls<CXXRecordDecl>(
475 "struct A{ };",
476 "struct B{ };",
477 Lang_CXX,
Balazs Keri36883d32018-07-11 15:26:26 +0000478 cxxRecordDecl(hasName("A")),
479 cxxRecordDecl(hasName("B")));
Balazs Keric7797c42018-07-11 09:37:24 +0000480 EXPECT_FALSE(testStructuralMatch(t));
481}
482
483TEST_F(StructuralEquivalenceRecordTest, Fields) {
484 auto t = makeNamedDecls(
485 "struct foo{ int x; };",
486 "struct foo{ char x; };",
487 Lang_CXX);
488 EXPECT_FALSE(testStructuralMatch(t));
489}
490
491TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
492 // Currently, methods of a class are not checked at class equivalence.
493 auto t = makeNamedDecls(
494 "struct foo{ int x(); };",
495 "struct foo{ char x(); };",
496 Lang_CXX);
497 EXPECT_FALSE(testStructuralMatch(t));
498}
499
500TEST_F(StructuralEquivalenceRecordTest, Bases) {
501 auto t = makeNamedDecls(
502 "struct A{ }; struct foo: A { };",
503 "struct B{ }; struct foo: B { };",
504 Lang_CXX);
505 EXPECT_FALSE(testStructuralMatch(t));
506}
507
508TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
509 auto t = makeNamedDecls(
510 "struct A{ }; struct foo: A { };",
511 "struct A{ }; struct foo: virtual A { };",
512 Lang_CXX);
513 EXPECT_FALSE(testStructuralMatch(t));
514}
515
516TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
517 // Access specifier in inheritance is not checked yet.
518 auto t = makeNamedDecls(
519 "struct A{ }; struct foo: public A { };",
520 "struct A{ }; struct foo: private A { };",
521 Lang_CXX);
522 EXPECT_FALSE(testStructuralMatch(t));
523}
524
525TEST_F(StructuralEquivalenceRecordTest, Match) {
526 auto Code = R"(
527 struct A{ };
528 struct B{ };
529 struct foo: A, virtual B {
530 void x();
531 int a;
532 };
533 )";
534 auto t = makeNamedDecls(Code, Code, Lang_CXX);
535 EXPECT_TRUE(testStructuralMatch(t));
536}
537
538TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
539 auto t = makeNamedDecls(
540 "struct A{ }; struct B{ }; void foo(A a, A b);",
541 "struct A{ }; struct B{ }; void foo(A a, B b);",
542 Lang_CXX);
543 EXPECT_FALSE(testStructuralMatch(t));
544}
545
Gabor Marton1f667532018-05-24 08:41:07 +0000546} // end namespace ast_matchers
547} // end namespace clang