1#include "clang/AST/ASTContext.h"
2#include "clang/AST/ASTStructuralEquivalence.h"
3#include "clang/AST/Decl.h"
4#include "clang/AST/DeclTemplate.h"
5#include "clang/ASTMatchers/ASTMatchers.h"
6#include "clang/Frontend/ASTUnit.h"
7#include "clang/Testing/CommandLineArgs.h"
8#include "clang/Tooling/Tooling.h"
9#include "llvm/TargetParser/Host.h"
10
11#include "DeclMatcher.h"
12
13#include "gtest/gtest.h"
14
15namespace clang {
16namespace ast_matchers {
17
18using std::get;
19
20struct StructuralEquivalenceTest : ::testing::Test {
21 std::unique_ptr<ASTUnit> AST0, AST1;
22 std::string Code0, Code1; // Buffers for SourceManager
23
24 // Parses the source code in the specified language and sets the ASTs of
25 // the current test instance to the parse result.
26 void makeASTUnits(const std::string &SrcCode0, const std::string &SrcCode1,
27 TestLanguage Lang) {
28 this->Code0 = SrcCode0;
29 this->Code1 = SrcCode1;
30 std::vector<std::string> Args = getCommandLineArgsForTesting(Lang);
31
32 const char *const InputFileName = "input.cc";
33
34 AST0 = tooling::buildASTFromCodeWithArgs(Code: Code0, Args, FileName: InputFileName);
35 AST1 = tooling::buildASTFromCodeWithArgs(Code: Code1, Args, FileName: InputFileName);
36 }
37
38 // Get a pair of node pointers into the synthesized AST from the given code
39 // snippets. To determine the returned node, a separate matcher is specified
40 // for both snippets. The first matching node is returned.
41 template <typename NodeType, typename MatcherType>
42 std::tuple<NodeType *, NodeType *>
43 makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,
44 TestLanguage Lang, const MatcherType &Matcher0,
45 const MatcherType &Matcher1) {
46 makeASTUnits(SrcCode0, SrcCode1, Lang);
47
48 NodeType *D0 = FirstDeclMatcher<NodeType>().match(
49 AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
50 NodeType *D1 = FirstDeclMatcher<NodeType>().match(
51 AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
52
53 return std::make_tuple(D0, D1);
54 }
55
56 std::tuple<TranslationUnitDecl *, TranslationUnitDecl *>
57 makeTuDecls(const std::string &SrcCode0, const std::string &SrcCode1,
58 TestLanguage Lang) {
59 makeASTUnits(SrcCode0, SrcCode1, Lang);
60
61 return std::make_tuple(args: AST0->getASTContext().getTranslationUnitDecl(),
62 args: AST1->getASTContext().getTranslationUnitDecl());
63 }
64
65 // Get a pair of node pointers into the synthesized AST from the given code
66 // snippets. The same matcher is used for both snippets.
67 template <typename NodeType, typename MatcherType>
68 std::tuple<NodeType *, NodeType *>
69 makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,
70 TestLanguage Lang, const MatcherType &AMatcher) {
71 return makeDecls<NodeType, MatcherType>(
72 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
73 }
74
75 // Get a pair of Decl pointers to the synthesized declarations from the given
76 // code snippets. We search for the first NamedDecl with given name in both
77 // snippets.
78 std::tuple<NamedDecl *, NamedDecl *>
79 makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1,
80 TestLanguage Lang, const char *const Identifier = "foo") {
81 auto Matcher = namedDecl(hasName(Name: Identifier));
82 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, AMatcher: Matcher);
83 }
84
85 // Wraps a Stmt and the ASTContext that contains it.
86 struct StmtWithASTContext {
87 Stmt *S;
88 ASTContext *Context;
89 explicit StmtWithASTContext(Stmt &S, ASTContext &Context)
90 : S(&S), Context(&Context) {}
91 explicit StmtWithASTContext(FunctionDecl *FD)
92 : S(FD->getBody()), Context(&FD->getASTContext()) {}
93 };
94
95 // Get a pair of node pointers into the synthesized AST from the given code
96 // snippets. To determine the returned node, a separate matcher is specified
97 // for both snippets. The first matching node is returned.
98 template <typename MatcherType>
99 std::tuple<StmtWithASTContext, StmtWithASTContext>
100 makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,
101 TestLanguage Lang, const MatcherType &Matcher0,
102 const MatcherType &Matcher1) {
103 makeASTUnits(SrcCode0, SrcCode1, Lang);
104
105 Stmt *S0 = FirstDeclMatcher<Stmt>().match(
106 AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
107 Stmt *S1 = FirstDeclMatcher<Stmt>().match(
108 AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
109
110 return std::make_tuple(args: StmtWithASTContext(*S0, AST0->getASTContext()),
111 args: StmtWithASTContext(*S1, AST1->getASTContext()));
112 }
113
114 // Get a pair of node pointers into the synthesized AST from the given code
115 // snippets. The same matcher is used for both snippets.
116 template <typename MatcherType>
117 std::tuple<StmtWithASTContext, StmtWithASTContext>
118 makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,
119 TestLanguage Lang, const MatcherType &AMatcher) {
120 return makeStmts(SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
121 }
122
123 // Convenience function for makeStmts that wraps the code inside a function
124 // body.
125 template <typename MatcherType>
126 std::tuple<StmtWithASTContext, StmtWithASTContext>
127 makeWrappedStmts(const std::string &SrcCode0, const std::string &SrcCode1,
128 TestLanguage Lang, const MatcherType &AMatcher) {
129 auto Wrap = [](const std::string &Src) {
130 return "void wrapped() {" + Src + ";}";
131 };
132 return makeStmts(Wrap(SrcCode0), Wrap(SrcCode1), Lang, AMatcher);
133 }
134
135 bool testStructuralMatch(Decl *D0, Decl *D1,
136 bool IgnoreTemplateParmDepth = false) {
137 StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01;
138 StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10;
139 StructuralEquivalenceContext Ctx01(
140 D0->getLangOpts(), D0->getASTContext(), D1->getASTContext(),
141 NonEquivalentDecls01, StructuralEquivalenceKind::Default,
142 /*StrictTypeSpelling=*/false,
143 /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,
144 IgnoreTemplateParmDepth);
145 StructuralEquivalenceContext Ctx10(
146 D1->getLangOpts(), D1->getASTContext(), D0->getASTContext(),
147 NonEquivalentDecls10, StructuralEquivalenceKind::Default,
148 /*StrictTypeSpelling=*/false,
149 /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,
150 IgnoreTemplateParmDepth);
151 bool Eq01 = Ctx01.IsEquivalent(D1: D0, D2: D1);
152 bool Eq10 = Ctx10.IsEquivalent(D1, D2: D0);
153 EXPECT_EQ(Eq01, Eq10);
154 return Eq01;
155 }
156
157 bool testStructuralMatch(StmtWithASTContext S0, StmtWithASTContext S1) {
158 StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01;
159 StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10;
160 StructuralEquivalenceContext Ctx01(S0.Context->getLangOpts(), *S0.Context,
161 *S1.Context, NonEquivalentDecls01,
162 StructuralEquivalenceKind::Default,
163 /*StrictTypeSpelling=*/false,
164 /*Complain=*/false);
165 StructuralEquivalenceContext Ctx10(S1.Context->getLangOpts(), *S1.Context,
166 *S0.Context, NonEquivalentDecls10,
167 StructuralEquivalenceKind::Default,
168 /*StrictTypeSpelling=*/false,
169 /*Complain=*/false);
170 bool Eq01 = Ctx01.IsEquivalent(S1: S0.S, S2: S1.S);
171 bool Eq10 = Ctx10.IsEquivalent(S1: S1.S, S2: S0.S);
172 EXPECT_EQ(Eq01, Eq10);
173 return Eq01;
174 }
175
176 bool
177 testStructuralMatch(std::tuple<StmtWithASTContext, StmtWithASTContext> t) {
178 return testStructuralMatch(S0: get<0>(t&: t), S1: get<1>(t&: t));
179 }
180
181 bool testStructuralMatch(std::tuple<Decl *, Decl *> t,
182 bool IgnoreTemplateParmDepth = false) {
183 return testStructuralMatch(D0: get<0>(t&: t), D1: get<1>(t&: t), IgnoreTemplateParmDepth);
184 }
185};
186
187TEST_F(StructuralEquivalenceTest, Int) {
188 auto Decls = makeNamedDecls(SrcCode0: "int foo;", SrcCode1: "int foo;", Lang: Lang_CXX03);
189 EXPECT_TRUE(testStructuralMatch(Decls));
190}
191
192TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
193 auto Decls = makeNamedDecls(SrcCode0: "int foo;", SrcCode1: "signed int foo;", Lang: Lang_CXX03);
194 EXPECT_TRUE(testStructuralMatch(Decls));
195}
196
197TEST_F(StructuralEquivalenceTest, Char) {
198 auto Decls = makeNamedDecls(SrcCode0: "char foo;", SrcCode1: "char foo;", Lang: Lang_CXX03);
199 EXPECT_TRUE(testStructuralMatch(Decls));
200}
201
202// This test is disabled for now.
203// FIXME Whether this is equivalent is dependent on the target.
204TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
205 auto Decls = makeNamedDecls(SrcCode0: "char foo;", SrcCode1: "signed char foo;", Lang: Lang_CXX03);
206 EXPECT_FALSE(testStructuralMatch(Decls));
207}
208
209TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
210 auto Decls = makeNamedDecls(SrcCode0: "struct foo;", SrcCode1: "struct foo;", Lang: Lang_CXX03);
211 EXPECT_TRUE(testStructuralMatch(Decls));
212}
213
214TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
215 auto Decls = makeNamedDecls(SrcCode0: "struct foo { int x; };",
216 SrcCode1: "struct foo { signed int x; };", Lang: Lang_CXX03);
217 EXPECT_TRUE(testStructuralMatch(Decls));
218}
219
220TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
221 auto Decls = makeNamedDecls(SrcCode0: "struct foo { char x; };",
222 SrcCode1: "struct foo { signed char x; };", Lang: Lang_CXX03);
223 EXPECT_FALSE(testStructuralMatch(Decls));
224}
225
226TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
227 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
228 SrcCode0: R"(template <class T> struct foo; template<> struct foo<int>{};)",
229 SrcCode1: R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
230 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl());
231 auto Spec0 = get<0>(t&: Decls);
232 auto Spec1 = get<1>(t&: Decls);
233 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
234}
235
236TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
237 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
238 SrcCode0: R"(template <class T> struct foo; template<> struct foo<char>{};)",
239 SrcCode1: R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
240 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl());
241 auto Spec0 = get<0>(t&: Decls);
242 auto Spec1 = get<1>(t&: Decls);
243 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
244}
245
246TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
247 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
248 SrcCode0: R"(
249 struct true_type{};
250 template <class T> struct foo;
251 template<> struct foo<char> : true_type {};
252 )",
253 SrcCode1: R"(
254 struct true_type{};
255 template <class T> struct foo;
256 template<> struct foo<signed char> : true_type {};
257 )",
258 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl());
259 EXPECT_FALSE(testStructuralMatch(Decls));
260}
261
262// This test is disabled for now.
263// FIXME Enable it, once the check is implemented.
264TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
265 auto Code =
266 R"(
267 namespace NS {
268 template <class T> class Base {
269 int a;
270 };
271 class Derived : Base<Derived> {
272 };
273 }
274 void foo(NS::Derived &);
275 )";
276 auto Decls = makeNamedDecls(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX03);
277
278 NamespaceDecl *NS =
279 LastDeclMatcher<NamespaceDecl>().match(get<1>(t&: Decls), namespaceDecl());
280 ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
281 get<1>(t&: Decls), classTemplateDecl(hasName(Name: "Base")));
282
283 // Reorder the decls, move the TD to the last place in the DC.
284 NS->removeDecl(TD);
285 NS->addDeclInternal(TD);
286
287 EXPECT_FALSE(testStructuralMatch(Decls));
288}
289
290TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
291 auto Code = "class X { int a; int b; };";
292 auto Decls = makeNamedDecls(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX03, Identifier: "X");
293
294 CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
295 get<1>(t&: Decls), cxxRecordDecl(hasName(Name: "X")));
296 FieldDecl *FD =
297 FirstDeclMatcher<FieldDecl>().match(get<1>(t&: Decls), fieldDecl(hasName(Name: "a")));
298
299 // Reorder the FieldDecls
300 RD->removeDecl(FD);
301 RD->addDeclInternal(FD);
302
303 EXPECT_FALSE(testStructuralMatch(Decls));
304}
305
306struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
307};
308
309TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {
310 auto t = makeNamedDecls(SrcCode0: "void foo();", SrcCode1: "template<class T> void foo();",
311 Lang: Lang_CXX03);
312 EXPECT_FALSE(testStructuralMatch(t));
313}
314
315TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) {
316 auto t = makeDecls<FunctionDecl>(
317 SrcCode0: "struct X{}; bool operator<(X, X);", SrcCode1: "struct X{}; bool operator==(X, X);",
318 Lang: Lang_CXX03, Matcher0: functionDecl(hasOverloadedOperatorName(Name: "<")),
319 Matcher1: functionDecl(hasOverloadedOperatorName(Name: "==")));
320 EXPECT_FALSE(testStructuralMatch(t));
321}
322
323TEST_F(StructuralEquivalenceFunctionTest, SameOperators) {
324 auto t = makeDecls<FunctionDecl>(
325 SrcCode0: "struct X{}; bool operator<(X, X);", SrcCode1: "struct X{}; bool operator<(X, X);",
326 Lang: Lang_CXX03, Matcher0: functionDecl(hasOverloadedOperatorName(Name: "<")),
327 Matcher1: functionDecl(hasOverloadedOperatorName(Name: "<")));
328 EXPECT_TRUE(testStructuralMatch(t));
329}
330
331TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) {
332 auto t = makeDecls<FunctionDecl>(SrcCode0: "struct X{ X(); };", SrcCode1: "struct X{ ~X(); };",
333 Lang: Lang_CXX03, Matcher0: cxxConstructorDecl(),
334 Matcher1: cxxDestructorDecl());
335 EXPECT_FALSE(testStructuralMatch(t));
336}
337
338TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
339 auto t =
340 makeNamedDecls(SrcCode0: "void foo(int&);", SrcCode1: "void foo(const int&);", Lang: Lang_CXX03);
341 EXPECT_FALSE(testStructuralMatch(t));
342}
343
344TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
345 auto t = makeNamedDecls(SrcCode0: "void foo(int);", SrcCode1: "void foo(const int);", Lang: Lang_CXX03);
346 EXPECT_TRUE(testStructuralMatch(t));
347 // consider this OK
348}
349
350TEST_F(StructuralEquivalenceFunctionTest, Throw) {
351 auto t = makeNamedDecls(SrcCode0: "void foo();", SrcCode1: "void foo() throw();", Lang: Lang_CXX03);
352 EXPECT_FALSE(testStructuralMatch(t));
353}
354
355TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
356 auto t = makeNamedDecls(SrcCode0: "void foo();",
357 SrcCode1: "void foo() noexcept;", Lang: Lang_CXX11);
358 EXPECT_FALSE(testStructuralMatch(t));
359}
360
361TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
362 auto t = makeNamedDecls(SrcCode0: "void foo() throw();",
363 SrcCode1: "void foo() noexcept;", Lang: Lang_CXX11);
364 EXPECT_FALSE(testStructuralMatch(t));
365}
366
367TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
368 auto t = makeNamedDecls(SrcCode0: "void foo() throw();",
369 SrcCode1: "void foo() noexcept(false);", Lang: Lang_CXX11);
370 EXPECT_FALSE(testStructuralMatch(t));
371}
372
373TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
374 auto t = makeNamedDecls(SrcCode0: "void foo() throw();",
375 SrcCode1: "void foo() noexcept(true);", Lang: Lang_CXX11);
376 EXPECT_FALSE(testStructuralMatch(t));
377}
378
379TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) {
380 auto t = makeNamedDecls(SrcCode0: "void foo() noexcept(false);",
381 SrcCode1: "void foo() noexcept(true);", Lang: Lang_CXX11);
382 EXPECT_FALSE(testStructuralMatch(t));
383}
384
385TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
386 auto t = makeNamedDecls(SrcCode0: "void foo() noexcept(false);",
387 SrcCode1: "void foo() noexcept(false);", Lang: Lang_CXX11);
388 EXPECT_TRUE(testStructuralMatch(t));
389}
390
391TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
392 auto t = makeNamedDecls(SrcCode0: "void foo() noexcept;",
393 SrcCode1: "void foo() noexcept(false);", Lang: Lang_CXX11);
394 EXPECT_FALSE(testStructuralMatch(t));
395}
396
397TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
398 auto t = makeNamedDecls(SrcCode0: "void foo() noexcept;",
399 SrcCode1: "void foo() noexcept(true);", Lang: Lang_CXX11);
400 EXPECT_FALSE(testStructuralMatch(t));
401}
402
403TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
404 auto t = makeNamedDecls(SrcCode0: "char foo();", SrcCode1: "int foo();", Lang: Lang_CXX03);
405 EXPECT_FALSE(testStructuralMatch(t));
406}
407
408TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
409 auto t = makeNamedDecls(SrcCode0: "char foo();", SrcCode1: "const char foo();", Lang: Lang_CXX03);
410 EXPECT_FALSE(testStructuralMatch(t));
411}
412
413TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
414 auto t = makeNamedDecls(SrcCode0: "char &foo();",
415 SrcCode1: "char &&foo();", Lang: Lang_CXX11);
416 EXPECT_FALSE(testStructuralMatch(t));
417}
418
419TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
420 auto t = makeNamedDecls(SrcCode0: "void foo(int);", SrcCode1: "void foo(int, int);", Lang: Lang_CXX03);
421 EXPECT_FALSE(testStructuralMatch(t));
422}
423
424TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
425 auto t = makeNamedDecls(SrcCode0: "void foo(int);", SrcCode1: "void foo(char);", Lang: Lang_CXX03);
426 EXPECT_FALSE(testStructuralMatch(t));
427}
428
429TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
430 auto t = makeNamedDecls(SrcCode0: "void foo(int a);", SrcCode1: "void foo(int b);", Lang: Lang_CXX03);
431 EXPECT_TRUE(testStructuralMatch(t));
432}
433
434TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
435 auto t =
436 makeNamedDecls(SrcCode0: "void foo(int x...);", SrcCode1: "void foo(int x);", Lang: Lang_CXX03);
437 EXPECT_FALSE(testStructuralMatch(t));
438}
439
440TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
441 auto t = makeNamedDecls(SrcCode0: "void foo(int *);", SrcCode1: "void foo(int);", Lang: Lang_CXX03);
442 EXPECT_FALSE(testStructuralMatch(t));
443}
444
445TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
446 auto t = makeNamedDecls(SrcCode0: "void ((foo))();", SrcCode1: "void foo();", Lang: Lang_CXX03);
447 EXPECT_TRUE(testStructuralMatch(t));
448}
449
450TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
451 auto t = makeNamedDecls(
452 SrcCode0: "void (foo)() throw(int);",
453 SrcCode1: "void (foo)() noexcept;",
454 Lang: Lang_CXX11);
455 EXPECT_FALSE(testStructuralMatch(t));
456}
457
458TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
459 auto t = makeNamedDecls(
460 SrcCode0: "struct A { void (foo)() const; };",
461 SrcCode1: "struct A { void (foo)(); };",
462 Lang: Lang_CXX11);
463 EXPECT_FALSE(testStructuralMatch(t));
464}
465
466TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
467 auto t = makeNamedDecls(SrcCode0: "__attribute__((noreturn)) void foo();",
468 SrcCode1: " void foo();", Lang: Lang_C99);
469 EXPECT_TRUE(testStructuralMatch(t));
470}
471
472TEST_F(StructuralEquivalenceFunctionTest,
473 FunctionsWithDifferentCallingConventions) {
474 // These attributes may not be available on certain platforms.
475 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
476 llvm::Triple::x86_64)
477 GTEST_SKIP();
478 auto t = makeNamedDecls(SrcCode0: "__attribute__((preserve_all)) void foo();",
479 SrcCode1: "__attribute__((ms_abi)) void foo();", Lang: Lang_C99);
480 EXPECT_FALSE(testStructuralMatch(t));
481}
482
483TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {
484 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
485 llvm::Triple::x86_64)
486 GTEST_SKIP();
487 auto t = makeNamedDecls(
488 SrcCode0: "__attribute__((no_caller_saved_registers)) void foo();",
489 SrcCode1: " void foo();", Lang: Lang_C99);
490 EXPECT_FALSE(testStructuralMatch(t));
491}
492
493struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
494};
495
496TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
497 auto t = makeDecls<CXXMethodDecl>(SrcCode0: "struct X { void foo(); };",
498 SrcCode1: "struct X { virtual void foo(); };",
499 Lang: Lang_CXX03, AMatcher: cxxMethodDecl(hasName(Name: "foo")));
500 EXPECT_FALSE(testStructuralMatch(t));
501}
502
503TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
504 auto t = makeNamedDecls(SrcCode0: "struct X { virtual void foo(); };",
505 SrcCode1: "struct X { virtual void foo() = 0; };", Lang: Lang_CXX03);
506 EXPECT_FALSE(testStructuralMatch(t));
507}
508
509TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
510 // The final-ness is not checked yet.
511 auto t =
512 makeNamedDecls(SrcCode0: "struct X { virtual void foo(); };",
513 SrcCode1: "struct X { virtual void foo() final; };", Lang: Lang_CXX03);
514 EXPECT_FALSE(testStructuralMatch(t));
515}
516
517TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
518 auto t = makeNamedDecls(SrcCode0: "struct X { void foo(); };",
519 SrcCode1: "struct X { void foo() const; };", Lang: Lang_CXX03);
520 EXPECT_FALSE(testStructuralMatch(t));
521}
522
523TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
524 auto t = makeNamedDecls(SrcCode0: "struct X { void foo(); };",
525 SrcCode1: "struct X { static void foo(); };", Lang: Lang_CXX03);
526 EXPECT_FALSE(testStructuralMatch(t));
527}
528
529TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
530 auto t = makeNamedDecls(SrcCode0: "struct X { void foo(); };",
531 SrcCode1: "struct X { void foo() &&; };", Lang: Lang_CXX11);
532 EXPECT_FALSE(testStructuralMatch(t));
533}
534
535TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
536 auto t = makeNamedDecls(SrcCode0: "struct X { void foo() &; };",
537 SrcCode1: "struct X { void foo() &&; };", Lang: Lang_CXX11);
538 EXPECT_FALSE(testStructuralMatch(t));
539}
540
541TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
542 auto t = makeDecls<CXXMethodDecl>(SrcCode0: "struct X { public: void foo(); };",
543 SrcCode1: "struct X { private: void foo(); };",
544 Lang: Lang_CXX03, AMatcher: cxxMethodDecl(hasName(Name: "foo")));
545 EXPECT_FALSE(testStructuralMatch(t));
546}
547
548TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
549 auto t = makeNamedDecls(SrcCode0: "struct X { void foo(); };",
550 SrcCode1: "struct X { void foo() = delete; };", Lang: Lang_CXX11);
551 EXPECT_FALSE(testStructuralMatch(t));
552}
553
554TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
555 auto t = makeDecls<FunctionDecl>(SrcCode0: "void foo();", SrcCode1: "struct foo { foo(); };",
556 Lang: Lang_CXX03, Matcher0: functionDecl(hasName(Name: "foo")),
557 Matcher1: cxxConstructorDecl(hasName(Name: "foo")));
558 EXPECT_FALSE(testStructuralMatch(t));
559}
560
561TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
562 auto t = makeDecls<CXXConstructorDecl>(SrcCode0: "struct X { X(); };",
563 SrcCode1: "struct X { X(int); };", Lang: Lang_CXX03,
564 AMatcher: cxxConstructorDecl(hasName(Name: "X")));
565 EXPECT_FALSE(testStructuralMatch(t));
566}
567
568TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
569 auto t = makeDecls<CXXConstructorDecl>(SrcCode0: "struct X { X(int); };",
570 SrcCode1: "struct X { explicit X(int); };",
571 Lang: Lang_CXX11,
572 AMatcher: cxxConstructorDecl(hasName(Name: "X")));
573 EXPECT_FALSE(testStructuralMatch(t));
574}
575
576TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
577 auto t = makeDecls<CXXConstructorDecl>(SrcCode0: "struct X { X(); };",
578 SrcCode1: "struct X { X() = default; };",
579 Lang: Lang_CXX11,
580 AMatcher: cxxConstructorDecl(hasName(Name: "X")));
581 EXPECT_FALSE(testStructuralMatch(t));
582}
583
584TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
585 auto t = makeDecls<CXXConversionDecl>(SrcCode0: "struct X { operator bool(); };",
586 SrcCode1: "struct X { operator char(); };",
587 Lang: Lang_CXX11,
588 AMatcher: cxxConversionDecl());
589 EXPECT_FALSE(testStructuralMatch(t));
590}
591
592TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
593 auto t =
594 makeDecls<FunctionDecl>(SrcCode0: "struct X { int operator +(int); };",
595 SrcCode1: "struct X { int operator -(int); };", Lang: Lang_CXX03,
596 Matcher0: functionDecl(hasOverloadedOperatorName(Name: "+")),
597 Matcher1: functionDecl(hasOverloadedOperatorName(Name: "-")));
598 EXPECT_FALSE(testStructuralMatch(t));
599}
600
601TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
602 auto t = makeDecls<FunctionDecl>(
603 SrcCode0: "struct X { virtual void f(); }; void X::f() { }",
604 SrcCode1: "struct X { virtual void f() { }; };", Lang: Lang_CXX03,
605 AMatcher: functionDecl(allOf(hasName(Name: "f"), isDefinition())));
606 EXPECT_TRUE(testStructuralMatch(t));
607}
608
609TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
610 auto t = makeDecls<FunctionDecl>(
611 SrcCode0: "struct X { virtual void f(); }; void X::f() { }",
612 SrcCode1: "struct X { void f(); }; void X::f() { }", Lang: Lang_CXX03,
613 AMatcher: functionDecl(allOf(hasName(Name: "f"), isDefinition())));
614 EXPECT_FALSE(testStructuralMatch(t));
615}
616
617struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
618 // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
619 RecordDecl *getRecordDecl(FieldDecl *FD) {
620 auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());
621 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
622 };
623};
624
625TEST_F(StructuralEquivalenceRecordTest, Name) {
626 auto t = makeDecls<CXXRecordDecl>(SrcCode0: "struct A{ };", SrcCode1: "struct B{ };", Lang: Lang_CXX03,
627 Matcher0: cxxRecordDecl(hasName(Name: "A")),
628 Matcher1: cxxRecordDecl(hasName(Name: "B")));
629 EXPECT_FALSE(testStructuralMatch(t));
630}
631
632TEST_F(StructuralEquivalenceRecordTest, Fields) {
633 auto t = makeNamedDecls(SrcCode0: "struct foo{ int x; };", SrcCode1: "struct foo{ char x; };",
634 Lang: Lang_CXX03);
635 EXPECT_FALSE(testStructuralMatch(t));
636}
637
638TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
639 // Currently, methods of a class are not checked at class equivalence.
640 auto t = makeNamedDecls(SrcCode0: "struct foo{ int x(); };", SrcCode1: "struct foo{ char x(); };",
641 Lang: Lang_CXX03);
642 EXPECT_FALSE(testStructuralMatch(t));
643}
644
645TEST_F(StructuralEquivalenceRecordTest, Bases) {
646 auto t = makeNamedDecls(SrcCode0: "struct A{ }; struct foo: A { };",
647 SrcCode1: "struct B{ }; struct foo: B { };", Lang: Lang_CXX03);
648 EXPECT_FALSE(testStructuralMatch(t));
649}
650
651TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
652 auto t =
653 makeNamedDecls(SrcCode0: "struct A{ }; struct foo: A { };",
654 SrcCode1: "struct A{ }; struct foo: virtual A { };", Lang: Lang_CXX03);
655 EXPECT_FALSE(testStructuralMatch(t));
656}
657
658TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
659 // Access specifier in inheritance is not checked yet.
660 auto t =
661 makeNamedDecls(SrcCode0: "struct A{ }; struct foo: public A { };",
662 SrcCode1: "struct A{ }; struct foo: private A { };", Lang: Lang_CXX03);
663 EXPECT_FALSE(testStructuralMatch(t));
664}
665
666TEST_F(StructuralEquivalenceRecordTest, Match) {
667 auto Code = R"(
668 struct A{ };
669 struct B{ };
670 struct foo: A, virtual B {
671 void x();
672 int a;
673 };
674 )";
675 auto t = makeNamedDecls(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX03);
676 EXPECT_TRUE(testStructuralMatch(t));
677}
678
679TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
680 auto t = makeTuDecls(
681 SrcCode0: R"(
682 struct A {
683 struct {
684 struct A *next;
685 } entry0;
686 struct {
687 struct A *next;
688 } entry1;
689 };
690 )",
691 SrcCode1: "", Lang: Lang_C99);
692 auto *TU = get<0>(t&: t);
693 auto *Entry0 =
694 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName(Name: "entry0")));
695 auto *Entry1 =
696 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName(Name: "entry1")));
697 auto *R0 = getRecordDecl(FD: Entry0);
698 auto *R1 = getRecordDecl(FD: Entry1);
699
700 ASSERT_NE(R0, R1);
701 EXPECT_TRUE(testStructuralMatch(R0, R0));
702 EXPECT_TRUE(testStructuralMatch(R1, R1));
703 EXPECT_FALSE(testStructuralMatch(R0, R1));
704}
705
706TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
707 auto t = makeTuDecls(
708 SrcCode0: R"(
709 struct X {
710 struct {
711 int a;
712 };
713 struct {
714 int b;
715 };
716 };
717 )",
718 SrcCode1: "", Lang: Lang_C99);
719 auto *TU = get<0>(t&: t);
720 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
721 TU, indirectFieldDecl(hasName(Name: "a")));
722 auto *FA = cast<FieldDecl>(A->chain().front());
723 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
724 auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(
725 TU, indirectFieldDecl(hasName(Name: "b")));
726 auto *FB = cast<FieldDecl>(B->chain().front());
727 RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();
728
729 ASSERT_NE(RA, RB);
730 EXPECT_TRUE(testStructuralMatch(RA, RA));
731 EXPECT_TRUE(testStructuralMatch(RB, RB));
732 EXPECT_FALSE(testStructuralMatch(RA, RB));
733}
734
735TEST_F(StructuralEquivalenceRecordTest,
736 RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
737 auto t = makeTuDecls(
738 SrcCode0: R"(
739 struct X {
740 struct { int a; };
741 struct { int b; };
742 };
743 )",
744 SrcCode1: R"(
745 struct X { // The order is reversed.
746 struct { int b; };
747 struct { int a; };
748 };
749 )",
750 Lang: Lang_C99);
751
752 auto *TU = get<0>(t&: t);
753 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
754 TU, indirectFieldDecl(hasName(Name: "a")));
755 auto *FA = cast<FieldDecl>(A->chain().front());
756 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
757
758 auto *TU1 = get<1>(t&: t);
759 auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(
760 TU1, indirectFieldDecl(hasName(Name: "a")));
761 auto *FA1 = cast<FieldDecl>(A1->chain().front());
762 RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();
763
764 RecordDecl *X =
765 FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName(Name: "X")));
766 RecordDecl *X1 =
767 FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName(Name: "X")));
768 ASSERT_NE(X, X1);
769 EXPECT_FALSE(testStructuralMatch(X, X1));
770
771 ASSERT_NE(RA, RA1);
772 EXPECT_TRUE(testStructuralMatch(RA, RA));
773 EXPECT_TRUE(testStructuralMatch(RA1, RA1));
774 EXPECT_FALSE(testStructuralMatch(RA1, RA));
775}
776
777TEST_F(StructuralEquivalenceRecordTest,
778 UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
779 auto Code =
780 R"(
781 struct A {
782 struct {
783 struct A *next;
784 } entry0;
785 struct {
786 struct A *next;
787 } entry1;
788 };
789 )";
790 auto t = makeTuDecls(SrcCode0: Code, SrcCode1: Code, Lang: Lang_C99);
791
792 auto *FromTU = get<0>(t&: t);
793 auto *Entry1 =
794 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName(Name: "entry1")));
795
796 auto *ToTU = get<1>(t&: t);
797 auto *Entry0 =
798 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName(Name: "entry0")));
799 auto *A =
800 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName(Name: "A")));
801 A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
802 // nullptr. This may be the case during ASTImport.
803
804 auto *R0 = getRecordDecl(FD: Entry0);
805 auto *R1 = getRecordDecl(FD: Entry1);
806
807 ASSERT_NE(R0, R1);
808 EXPECT_TRUE(testStructuralMatch(R0, R0));
809 EXPECT_TRUE(testStructuralMatch(R1, R1));
810 EXPECT_FALSE(testStructuralMatch(R0, R1));
811}
812
813TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {
814 auto t = makeDecls<CXXRecordDecl>(SrcCode0: "struct A { };",
815 SrcCode1: "template<class T> struct A { };",
816 Lang: Lang_CXX03, AMatcher: cxxRecordDecl(hasName(Name: "A")));
817 EXPECT_FALSE(testStructuralMatch(t));
818}
819
820TEST_F(StructuralEquivalenceRecordTest,
821 FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {
822 auto t = makeNamedDecls(SrcCode0: "class foo;", SrcCode1: "class foo;", Lang: Lang_CXX11);
823 EXPECT_TRUE(testStructuralMatch(t));
824}
825
826TEST_F(StructuralEquivalenceRecordTest,
827 FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {
828 auto t =
829 makeNamedDecls(SrcCode0: "class foo;", SrcCode1: "class foo { int A; };", Lang: Lang_CXX11);
830 EXPECT_TRUE(testStructuralMatch(t));
831}
832
833TEST_F(StructuralEquivalenceRecordTest,
834 RecordShouldBeEqualWithRecordWhichHasDefinition) {
835 auto t = makeNamedDecls(SrcCode0: "class foo { int A; };", SrcCode1: "class foo { int A; };",
836 Lang: Lang_CXX11);
837 EXPECT_TRUE(testStructuralMatch(t));
838}
839
840TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {
841 auto t = makeNamedDecls(SrcCode0: "class foo { int B; };", SrcCode1: "class foo { int A; };",
842 Lang: Lang_CXX11);
843 EXPECT_FALSE(testStructuralMatch(t));
844}
845
846TEST_F(StructuralEquivalenceRecordTest, SameFriendMultipleTimes) {
847 auto t = makeNamedDecls(SrcCode0: "struct foo { friend class X; };",
848 SrcCode1: "struct foo { friend class X; friend class X; };",
849 Lang: Lang_CXX11);
850 EXPECT_FALSE(testStructuralMatch(t));
851}
852
853TEST_F(StructuralEquivalenceRecordTest, SameFriendsDifferentOrder) {
854 auto t = makeNamedDecls(SrcCode0: "struct foo { friend class X; friend class Y; };",
855 SrcCode1: "struct foo { friend class Y; friend class X; };",
856 Lang: Lang_CXX11);
857 EXPECT_FALSE(testStructuralMatch(t));
858}
859
860TEST_F(StructuralEquivalenceRecordTest, SameFriendsSameOrder) {
861 auto t = makeNamedDecls(SrcCode0: "struct foo { friend class X; friend class Y; };",
862 SrcCode1: "struct foo { friend class X; friend class Y; };",
863 Lang: Lang_CXX11);
864 EXPECT_TRUE(testStructuralMatch(t));
865}
866
867struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {};
868
869TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) {
870 // Get the LambdaExprs, unfortunately we can't match directly the underlying
871 // implicit CXXRecordDecl of the Lambda classes.
872 auto t = makeDecls<LambdaExpr>(
873 SrcCode0: "void f() { auto L0 = [](int){}; }",
874 SrcCode1: "void f() { auto L1 = [](){}; }",
875 Lang: Lang_CXX11,
876 Matcher0: lambdaExpr(),
877 Matcher1: lambdaExpr());
878 CXXRecordDecl *L0 = get<0>(t&: t)->getLambdaClass();
879 CXXRecordDecl *L1 = get<1>(t&: t)->getLambdaClass();
880 EXPECT_FALSE(testStructuralMatch(L0, L1));
881}
882
883TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) {
884 auto t = makeDecls<LambdaExpr>(
885 SrcCode0: "void f() { auto L0 = [](int){}; }",
886 SrcCode1: "void f() { auto L1 = [](int){}; }",
887 Lang: Lang_CXX11,
888 Matcher0: lambdaExpr(),
889 Matcher1: lambdaExpr());
890 CXXRecordDecl *L0 = get<0>(t&: t)->getLambdaClass();
891 CXXRecordDecl *L1 = get<1>(t&: t)->getLambdaClass();
892 EXPECT_TRUE(testStructuralMatch(L0, L1));
893}
894
895TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) {
896 auto t = makeDecls<LambdaExpr>(
897 SrcCode0: "void f() { char* X; auto L0 = [X](){}; }",
898 SrcCode1: "void f() { float X; auto L1 = [X](){}; }",
899 Lang: Lang_CXX11,
900 Matcher0: lambdaExpr(),
901 Matcher1: lambdaExpr());
902 CXXRecordDecl *L0 = get<0>(t&: t)->getLambdaClass();
903 CXXRecordDecl *L1 = get<1>(t&: t)->getLambdaClass();
904 EXPECT_FALSE(testStructuralMatch(L0, L1));
905}
906
907TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) {
908 auto t = makeDecls<LambdaExpr>(
909 SrcCode0: "void f() { float X; auto L0 = [X](){}; }",
910 SrcCode1: "void f() { float X; auto L1 = [X](){}; }",
911 Lang: Lang_CXX11,
912 Matcher0: lambdaExpr(),
913 Matcher1: lambdaExpr());
914 CXXRecordDecl *L0 = get<0>(t&: t)->getLambdaClass();
915 CXXRecordDecl *L1 = get<1>(t&: t)->getLambdaClass();
916 EXPECT_TRUE(testStructuralMatch(L0, L1));
917}
918
919TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
920 auto t = makeNamedDecls(SrcCode0: "struct A{ }; struct B{ }; void foo(A a, A b);",
921 SrcCode1: "struct A{ }; struct B{ }; void foo(A a, B b);",
922 Lang: Lang_CXX03);
923 EXPECT_FALSE(testStructuralMatch(t));
924}
925
926TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {
927 auto Decls = makeNamedDecls(SrcCode0: "struct foo {explicit(false) foo(int);};",
928 SrcCode1: "struct foo {explicit(true) foo(int);};", Lang: Lang_CXX20);
929 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
930 get<0>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo")));
931 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
932 get<1>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo")));
933 EXPECT_FALSE(testStructuralMatch(First, Second));
934}
935
936TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {
937 auto Decls = makeNamedDecls(SrcCode0: "struct foo {explicit(true) foo(int);};",
938 SrcCode1: "struct foo {explicit(true) foo(int);};", Lang: Lang_CXX20);
939 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
940 get<0>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo")));
941 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
942 get<1>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo")));
943 EXPECT_TRUE(testStructuralMatch(First, Second));
944}
945
946struct StructuralEquivalenceRecordContextTest : StructuralEquivalenceTest {};
947
948TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsNamed) {
949 auto Decls =
950 makeNamedDecls(SrcCode0: "class X;", SrcCode1: "namespace N { class X; }", Lang: Lang_CXX03, Identifier: "X");
951 EXPECT_FALSE(testStructuralMatch(Decls));
952}
953
954TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsNamed) {
955 auto Decls = makeNamedDecls(SrcCode0: "namespace A { class X; }",
956 SrcCode1: "namespace B { class X; }", Lang: Lang_CXX03, Identifier: "X");
957 EXPECT_FALSE(testStructuralMatch(Decls));
958}
959
960TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsNamed) {
961 auto Decls = makeNamedDecls(SrcCode0: "namespace { class X; }",
962 SrcCode1: "namespace N { class X; }", Lang: Lang_CXX03, Identifier: "X");
963 EXPECT_FALSE(testStructuralMatch(Decls));
964}
965
966TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsAnon) {
967 auto Decls =
968 makeNamedDecls(SrcCode0: "class X;", SrcCode1: "namespace { class X; }", Lang: Lang_CXX03, Identifier: "X");
969 EXPECT_FALSE(testStructuralMatch(Decls));
970}
971
972TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnon) {
973 auto Decls = makeNamedDecls(SrcCode0: "namespace { class X; }",
974 SrcCode1: "namespace { class X; }", Lang: Lang_CXX03, Identifier: "X");
975 EXPECT_TRUE(testStructuralMatch(Decls));
976}
977
978TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnonAnon) {
979 auto Decls =
980 makeNamedDecls(SrcCode0: "namespace { class X; }",
981 SrcCode1: "namespace { namespace { class X; } }", Lang: Lang_CXX03, Identifier: "X");
982 EXPECT_FALSE(testStructuralMatch(Decls));
983}
984
985TEST_F(StructuralEquivalenceRecordContextTest,
986 NamespaceNamedNamedVsNamedNamed) {
987 auto Decls = makeNamedDecls(SrcCode0: "namespace A { namespace N { class X; } }",
988 SrcCode1: "namespace B { namespace N { class X; } }",
989 Lang: Lang_CXX03, Identifier: "X");
990 EXPECT_FALSE(testStructuralMatch(Decls));
991}
992
993TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsInline) {
994 auto Decls = makeNamedDecls(SrcCode0: "namespace A { namespace A { class X; } }",
995 SrcCode1: "namespace A { inline namespace A { class X; } }",
996 Lang: Lang_CXX17, Identifier: "X");
997 EXPECT_FALSE(testStructuralMatch(Decls));
998}
999
1000TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineVsInline) {
1001 auto Decls = makeNamedDecls(SrcCode0: "namespace A { inline namespace A { class X; } }",
1002 SrcCode1: "namespace A { inline namespace B { class X; } }",
1003 Lang: Lang_CXX17, Identifier: "X");
1004 EXPECT_TRUE(testStructuralMatch(Decls));
1005}
1006
1007TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineTopLevel) {
1008 auto Decls =
1009 makeNamedDecls(SrcCode0: "inline namespace A { class X; }",
1010 SrcCode1: "inline namespace B { class X; }", Lang: Lang_CXX17, Identifier: "X");
1011 EXPECT_TRUE(testStructuralMatch(Decls));
1012}
1013
1014TEST_F(StructuralEquivalenceRecordContextTest, TransparentContext) {
1015 auto Decls =
1016 makeNamedDecls(SrcCode0: "extern \"C\" { class X; }", SrcCode1: "class X;", Lang: Lang_CXX03, Identifier: "X");
1017 EXPECT_TRUE(testStructuralMatch(Decls));
1018}
1019
1020TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextNE) {
1021 auto Decls = makeNamedDecls(SrcCode0: "extern \"C\" { class X; }",
1022 SrcCode1: "namespace { class X; }", Lang: Lang_CXX03, Identifier: "X");
1023 EXPECT_FALSE(testStructuralMatch(Decls));
1024}
1025
1026TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextInNamespace) {
1027 auto Decls = makeNamedDecls(SrcCode0: "extern \"C\" { namespace N { class X; } }",
1028 SrcCode1: "namespace N { extern \"C\" { class X; } }",
1029 Lang: Lang_CXX03, Identifier: "X");
1030 EXPECT_TRUE(testStructuralMatch(Decls));
1031}
1032
1033TEST_F(StructuralEquivalenceRecordContextTest,
1034 ClassTemplateSpecializationContext) {
1035 std::string Code =
1036 R"(
1037 template <typename T> struct O {
1038 struct M {};
1039 };
1040 )";
1041 auto t = makeDecls<VarDecl>(SrcCode0: Code + R"(
1042 typedef O<int>::M MT1;
1043 MT1 A;
1044 )",
1045 SrcCode1: Code + R"(
1046 namespace {
1047 struct I {};
1048 } // namespace
1049 typedef O<I>::M MT2;
1050 MT2 A;
1051 )",
1052 Lang: Lang_CXX11, AMatcher: varDecl(hasName(Name: "A")));
1053 EXPECT_FALSE(testStructuralMatch(t));
1054}
1055
1056TEST_F(StructuralEquivalenceTest, NamespaceOfRecordMember) {
1057 auto Decls = makeNamedDecls(
1058 SrcCode0: R"(
1059 class X;
1060 class Y { X* x; };
1061 )",
1062 SrcCode1: R"(
1063 namespace N { class X; }
1064 class Y { N::X* x; };
1065 )",
1066 Lang: Lang_CXX03, Identifier: "Y");
1067 EXPECT_FALSE(testStructuralMatch(Decls));
1068}
1069
1070TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototype) {
1071 auto Decls =
1072 makeNamedDecls(SrcCode0: "struct Param { int a; }; void foo(struct Param *p);",
1073 SrcCode1: "void foo(struct Param { int a; } *p);", Lang: Lang_C89);
1074 EXPECT_TRUE(testStructuralMatch(Decls));
1075}
1076
1077TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototypeDifferentName) {
1078 auto Decls =
1079 makeNamedDecls(SrcCode0: "struct Param1 { int a; }; void foo(struct Param1 *p);",
1080 SrcCode1: "void foo(struct Param2 { int a; } *p);", Lang: Lang_C89);
1081 EXPECT_FALSE(testStructuralMatch(Decls));
1082}
1083
1084TEST_F(StructuralEquivalenceRecordContextTest, RecordInsideFunction) {
1085 auto Decls = makeNamedDecls(SrcCode0: "struct Param { int a; };",
1086 SrcCode1: "void f() { struct Param { int a; }; }", Lang: Lang_C89,
1087 Identifier: "Param");
1088 EXPECT_TRUE(testStructuralMatch(Decls));
1089}
1090
1091struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
1092
1093TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
1094 auto t = makeNamedDecls(SrcCode0: "enum class foo;", SrcCode1: "enum class foo;", Lang: Lang_CXX11);
1095 EXPECT_TRUE(testStructuralMatch(t));
1096}
1097
1098TEST_F(StructuralEquivalenceEnumTest,
1099 FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {
1100 auto t =
1101 makeNamedDecls(SrcCode0: "enum class foo;", SrcCode1: "enum class foo { A };", Lang: Lang_CXX11);
1102 EXPECT_TRUE(testStructuralMatch(t));
1103}
1104
1105TEST_F(StructuralEquivalenceEnumTest,
1106 EnumShouldBeEqualWithEnumWhichHasDefinition) {
1107 auto t = makeNamedDecls(SrcCode0: "enum class foo { A };", SrcCode1: "enum class foo { A };",
1108 Lang: Lang_CXX11);
1109 EXPECT_TRUE(testStructuralMatch(t));
1110}
1111
1112TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {
1113 auto t = makeNamedDecls(SrcCode0: "enum class foo { B };", SrcCode1: "enum class foo { A };",
1114 Lang: Lang_CXX11);
1115 EXPECT_FALSE(testStructuralMatch(t));
1116}
1117
1118TEST_F(StructuralEquivalenceEnumTest, AnonymousEnumsWithSameConsts) {
1119 // field x is required to trigger comparison of the anonymous enum
1120 auto t = makeNamedDecls(SrcCode0: "struct foo { enum { A } x; };",
1121 SrcCode1: "struct foo { enum { A } x;};", Lang: Lang_CXX11);
1122 EXPECT_TRUE(testStructuralMatch(t));
1123}
1124
1125TEST_F(StructuralEquivalenceEnumTest, AnonymousEnumsWithDiffConsts) {
1126 // field x is required to trigger comparison of the anonymous enum
1127 auto t = makeNamedDecls(SrcCode0: "struct foo { enum { A } x; };",
1128 SrcCode1: "struct foo { enum { B } x;};", Lang: Lang_CXX11);
1129 EXPECT_FALSE(testStructuralMatch(t));
1130}
1131
1132struct StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {};
1133
1134TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithSameValues) {
1135 auto t = makeNamedDecls(SrcCode0: "enum foo { foo = 1 };", SrcCode1: "enum foo { foo = 1 };",
1136 Lang: Lang_C89);
1137 EXPECT_TRUE(testStructuralMatch(t));
1138}
1139
1140TEST_F(StructuralEquivalenceEnumConstantTest,
1141 EnumConstantsWithDifferentValues) {
1142 auto t =
1143 makeNamedDecls(SrcCode0: "enum e { foo = 1 };", SrcCode1: "enum e { foo = 2 };", Lang: Lang_C89);
1144 EXPECT_FALSE(testStructuralMatch(t));
1145}
1146
1147TEST_F(StructuralEquivalenceEnumConstantTest,
1148 EnumConstantsWithDifferentExprsButSameValues) {
1149 auto t = makeNamedDecls(SrcCode0: "enum e { foo = 1 + 1 };", SrcCode1: "enum e { foo = 2 };",
1150 Lang: Lang_CXX11);
1151 EXPECT_FALSE(testStructuralMatch(t));
1152}
1153
1154TEST_F(StructuralEquivalenceEnumConstantTest,
1155 EnumConstantsWithDifferentSignedness) {
1156 auto t = makeNamedDecls(SrcCode0: "enum e : unsigned { foo = 1 };",
1157 SrcCode1: "enum e : int { foo = 1 };", Lang: Lang_CXX11);
1158 EXPECT_FALSE(testStructuralMatch(t));
1159}
1160
1161TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentWidth) {
1162 auto t = makeNamedDecls(SrcCode0: "enum e : short { foo = 1 };",
1163 SrcCode1: "enum e : int { foo = 1 };", Lang: Lang_CXX11);
1164 EXPECT_FALSE(testStructuralMatch(t));
1165}
1166
1167TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentName) {
1168 auto t =
1169 makeDecls<EnumConstantDecl>(SrcCode0: "enum e { foo = 1 };", SrcCode1: "enum e { bar = 1 };",
1170 Lang: Lang_CXX11, AMatcher: enumConstantDecl());
1171 EXPECT_FALSE(testStructuralMatch(t));
1172}
1173
1174struct StructuralEquivalenceObjCCategoryTest : StructuralEquivalenceTest {};
1175
1176TEST_F(StructuralEquivalenceObjCCategoryTest, MatchinCategoryNames) {
1177 auto t = makeDecls<ObjCCategoryDecl>(SrcCode0: "@interface A @end @interface A(X) @end",
1178 SrcCode1: "@interface A @end @interface A(X) @end",
1179 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1180 EXPECT_TRUE(testStructuralMatch(t));
1181}
1182
1183TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesForDifferentClasses) {
1184 auto t = makeDecls<ObjCCategoryDecl>(SrcCode0: "@interface A @end @interface A(X) @end",
1185 SrcCode1: "@interface B @end @interface B(X) @end",
1186 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1187 EXPECT_FALSE(testStructuralMatch(t));
1188}
1189
1190TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithDifferentNames) {
1191 auto t = makeDecls<ObjCCategoryDecl>(SrcCode0: "@interface A @end @interface A(X) @end",
1192 SrcCode1: "@interface A @end @interface A(Y) @end",
1193 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1194 EXPECT_FALSE(testStructuralMatch(t));
1195}
1196
1197TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithoutInterfaces) {
1198 auto t = makeDecls<ObjCCategoryDecl>(SrcCode0: " @interface A(X) @end",
1199 SrcCode1: "@interface A @end @interface A(X) @end",
1200 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1201 EXPECT_FALSE(testStructuralMatch(t));
1202
1203 auto t2 = makeDecls<ObjCCategoryDecl>(SrcCode0: "@interface A(X) @end",
1204 SrcCode1: "@interface A(X) @end",
1205 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1206 EXPECT_TRUE(testStructuralMatch(t2));
1207}
1208
1209TEST_F(StructuralEquivalenceObjCCategoryTest, CategoryAndExtension) {
1210 auto t = makeDecls<ObjCCategoryDecl>(SrcCode0: "@interface A @end @interface A(X) @end",
1211 SrcCode1: "@interface A @end @interface A() @end",
1212 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1213 EXPECT_FALSE(testStructuralMatch(t));
1214}
1215
1216TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingProtocols) {
1217 auto t = makeDecls<ObjCCategoryDecl>(
1218 SrcCode0: "@protocol P @end @interface A @end @interface A(X)<P> @end",
1219 SrcCode1: "@protocol P @end @interface A @end @interface A(X)<P> @end", Lang: Lang_OBJC,
1220 AMatcher: objcCategoryDecl());
1221 EXPECT_TRUE(testStructuralMatch(t));
1222}
1223
1224TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocols) {
1225 auto t = makeDecls<ObjCCategoryDecl>(
1226 SrcCode0: "@protocol P @end @interface A @end @interface A(X)<P> @end",
1227 SrcCode1: "@protocol Q @end @interface A @end @interface A(X)<Q> @end", Lang: Lang_OBJC,
1228 AMatcher: objcCategoryDecl());
1229 EXPECT_FALSE(testStructuralMatch(t));
1230}
1231
1232TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocolsOrder) {
1233 auto t = makeDecls<ObjCCategoryDecl>(
1234 SrcCode0: "@protocol P @end @protocol Q @end @interface A @end @interface A(X)<P, "
1235 "Q> @end",
1236 SrcCode1: "@protocol P @end @protocol Q @end @interface A @end @interface A(X)<Q, "
1237 "P> @end",
1238 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1239 EXPECT_FALSE(testStructuralMatch(t));
1240}
1241
1242TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingIvars) {
1243 auto t = makeDecls<ObjCCategoryDecl>(
1244 SrcCode0: "@interface A @end @interface A() { int x; } @end",
1245 SrcCode1: "@interface A @end @interface A() { int x; } @end", Lang: Lang_OBJC,
1246 AMatcher: objcCategoryDecl());
1247 EXPECT_TRUE(testStructuralMatch(t));
1248}
1249
1250TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarName) {
1251 auto t = makeDecls<ObjCCategoryDecl>(
1252 SrcCode0: "@interface A @end @interface A() { int x; } @end",
1253 SrcCode1: "@interface A @end @interface A() { int y; } @end", Lang: Lang_OBJC,
1254 AMatcher: objcCategoryDecl());
1255 EXPECT_FALSE(testStructuralMatch(t));
1256}
1257
1258TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarType) {
1259 auto t = makeDecls<ObjCCategoryDecl>(
1260 SrcCode0: "@interface A @end @interface A() { int x; } @end",
1261 SrcCode1: "@interface A @end @interface A() { float x; } @end", Lang: Lang_OBJC,
1262 AMatcher: objcCategoryDecl());
1263 EXPECT_FALSE(testStructuralMatch(t));
1264}
1265
1266TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarBitfieldWidth) {
1267 auto t = makeDecls<ObjCCategoryDecl>(
1268 SrcCode0: "@interface A @end @interface A() { int x: 1; } @end",
1269 SrcCode1: "@interface A @end @interface A() { int x: 2; } @end", Lang: Lang_OBJC,
1270 AMatcher: objcCategoryDecl());
1271 EXPECT_FALSE(testStructuralMatch(t));
1272}
1273
1274TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarVisibility) {
1275 auto t = makeDecls<ObjCCategoryDecl>(
1276 SrcCode0: "@interface A @end @interface A() { @public int x; } @end",
1277 SrcCode1: "@interface A @end @interface A() { @protected int x; } @end", Lang: Lang_OBJC,
1278 AMatcher: objcCategoryDecl());
1279 EXPECT_FALSE(testStructuralMatch(t));
1280}
1281
1282TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarNumber) {
1283 auto t = makeDecls<ObjCCategoryDecl>(
1284 SrcCode0: "@interface A @end @interface A() { int x; } @end",
1285 SrcCode1: "@interface A @end @interface A() {} @end", Lang: Lang_OBJC,
1286 AMatcher: objcCategoryDecl());
1287 EXPECT_FALSE(testStructuralMatch(t));
1288}
1289
1290TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarOrder) {
1291 auto t = makeDecls<ObjCCategoryDecl>(
1292 SrcCode0: "@interface A @end @interface A() { int x; int y; } @end",
1293 SrcCode1: "@interface A @end @interface A() { int y; int x; } @end", Lang: Lang_OBJC,
1294 AMatcher: objcCategoryDecl());
1295 EXPECT_FALSE(testStructuralMatch(t));
1296}
1297
1298TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingMethods) {
1299 auto t = makeDecls<ObjCCategoryDecl>(
1300 SrcCode0: "@interface A @end @interface A(X) -(void)test; @end",
1301 SrcCode1: "@interface A @end @interface A(X) -(void)test; @end", Lang: Lang_OBJC,
1302 AMatcher: objcCategoryDecl());
1303 EXPECT_TRUE(testStructuralMatch(t));
1304}
1305
1306TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodName) {
1307 auto t = makeDecls<ObjCCategoryDecl>(
1308 SrcCode0: "@interface A @end @interface A(X) -(void)test; @end",
1309 SrcCode1: "@interface A @end @interface A(X) -(void)wasd; @end", Lang: Lang_OBJC,
1310 AMatcher: objcCategoryDecl());
1311 EXPECT_FALSE(testStructuralMatch(t));
1312
1313 auto t2 = makeDecls<ObjCCategoryDecl>(
1314 SrcCode0: "@interface A @end @interface A(X) -(void)test:(int)x more:(int)y; @end",
1315 SrcCode1: "@interface A @end @interface A(X) -(void)test:(int)x :(int)y; @end",
1316 Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1317 EXPECT_FALSE(testStructuralMatch(t2));
1318}
1319
1320TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodClassInstance) {
1321 auto t = makeDecls<ObjCCategoryDecl>(
1322 SrcCode0: "@interface A @end @interface A(X) -(void)test; @end",
1323 SrcCode1: "@interface A @end @interface A(X) +(void)test; @end", Lang: Lang_OBJC,
1324 AMatcher: objcCategoryDecl());
1325 EXPECT_FALSE(testStructuralMatch(t));
1326}
1327
1328TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodReturnType) {
1329 auto t = makeDecls<ObjCCategoryDecl>(
1330 SrcCode0: "@interface A @end @interface A(X) -(void)test; @end",
1331 SrcCode1: "@interface A @end @interface A(X) -(int)test; @end", Lang: Lang_OBJC,
1332 AMatcher: objcCategoryDecl());
1333 EXPECT_FALSE(testStructuralMatch(t));
1334}
1335
1336TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterType) {
1337 auto t = makeDecls<ObjCCategoryDecl>(
1338 SrcCode0: "@interface A @end @interface A(X) -(void)test:(int)x; @end",
1339 SrcCode1: "@interface A @end @interface A(X) -(void)test:(float)x; @end", Lang: Lang_OBJC,
1340 AMatcher: objcCategoryDecl());
1341 EXPECT_FALSE(testStructuralMatch(t));
1342}
1343
1344TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterName) {
1345 auto t = makeDecls<ObjCCategoryDecl>(
1346 SrcCode0: "@interface A @end @interface A(X) -(void)test:(int)x; @end",
1347 SrcCode1: "@interface A @end @interface A(X) -(void)test:(int)y; @end", Lang: Lang_OBJC,
1348 AMatcher: objcCategoryDecl());
1349 EXPECT_TRUE(testStructuralMatch(t));
1350}
1351
1352TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodNumber) {
1353 auto t = makeDecls<ObjCCategoryDecl>(
1354 SrcCode0: "@interface A @end @interface A(X) -(void)test; @end",
1355 SrcCode1: "@interface A @end @interface A(X) @end", Lang: Lang_OBJC, AMatcher: objcCategoryDecl());
1356 EXPECT_FALSE(testStructuralMatch(t));
1357}
1358
1359TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodOrder) {
1360 auto t = makeDecls<ObjCCategoryDecl>(
1361 SrcCode0: "@interface A @end @interface A(X) -(void)u; -(void)v; @end",
1362 SrcCode1: "@interface A @end @interface A(X) -(void)v; -(void)u; @end", Lang: Lang_OBJC,
1363 AMatcher: objcCategoryDecl());
1364 EXPECT_FALSE(testStructuralMatch(t));
1365}
1366
1367struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};
1368
1369TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {
1370 auto t = makeNamedDecls(SrcCode0: "template <class T> struct foo;",
1371 SrcCode1: "template <class T> struct foo;", Lang: Lang_CXX03);
1372 EXPECT_TRUE(testStructuralMatch(t));
1373}
1374
1375TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {
1376 auto t = makeNamedDecls(SrcCode0: "template <class T> struct foo;",
1377 SrcCode1: "template <class U> struct foo;", Lang: Lang_CXX03);
1378 EXPECT_TRUE(testStructuralMatch(t));
1379}
1380
1381TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {
1382 auto t = makeNamedDecls(SrcCode0: "template <class T> struct foo;",
1383 SrcCode1: "template <int T> struct foo;", Lang: Lang_CXX03);
1384 EXPECT_FALSE(testStructuralMatch(t));
1385}
1386
1387TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) {
1388 const char *Code = "class foo { int a : 2; };";
1389 auto t = makeNamedDecls(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX03);
1390 EXPECT_TRUE(testStructuralMatch(t));
1391}
1392
1393TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) {
1394 auto t = makeNamedDecls(SrcCode0: "class foo { int a : 2; };",
1395 SrcCode1: "class foo { int a : 4; };", Lang: Lang_CXX03);
1396 EXPECT_FALSE(testStructuralMatch(t));
1397}
1398
1399TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) {
1400 const char *Code = "template <class T> class foo { int a : sizeof(T); };";
1401 auto t = makeNamedDecls(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX03);
1402 EXPECT_TRUE(testStructuralMatch(t));
1403}
1404
1405TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) {
1406 auto t = makeNamedDecls(
1407 SrcCode0: "template <class A, class B> class foo { int a : sizeof(A); };",
1408 SrcCode1: "template <class A, class B> class foo { int a : sizeof(B); };",
1409 Lang: Lang_CXX03);
1410 EXPECT_FALSE(testStructuralMatch(t));
1411}
1412
1413TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) {
1414 auto t = makeNamedDecls(
1415 SrcCode0: "template <class A> class foo { int a : sizeof(A); };",
1416 SrcCode1: "template <class A> class foo { int a : sizeof(A) + 1; };", Lang: Lang_CXX03);
1417 EXPECT_FALSE(testStructuralMatch(t));
1418}
1419
1420TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
1421 auto Decls = makeNamedDecls(
1422 SrcCode0: "template <bool b> struct foo {explicit(b) foo(int);};",
1423 SrcCode1: "template <bool b> struct foo {explicit(b) foo(int);};", Lang: Lang_CXX20);
1424 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
1425 get<0>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo<b>")));
1426 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
1427 get<1>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo<b>")));
1428 EXPECT_TRUE(testStructuralMatch(First, Second));
1429}
1430
1431TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
1432 auto Decls = makeNamedDecls(
1433 SrcCode0: "template <bool b> struct foo {explicit(b) foo(int);};",
1434 SrcCode1: "template <bool b> struct foo {explicit(!b) foo(int);};", Lang: Lang_CXX20);
1435 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
1436 get<0>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo<b>")));
1437 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
1438 get<1>(t&: Decls), cxxConstructorDecl(hasName(Name: "foo<b>")));
1439 EXPECT_FALSE(testStructuralMatch(First, Second));
1440}
1441
1442TEST_F(StructuralEquivalenceTemplateTest,
1443 TemplateVsSubstTemplateTemplateParmInArgEq) {
1444 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1445 SrcCode0: R"(
1446template <typename P1> class Arg { };
1447template <template <typename PP1> class P1> class Primary { };
1448
1449void f() {
1450 // Make specialization with simple template.
1451 Primary <Arg> A;
1452}
1453 )",
1454 SrcCode1: R"(
1455template <typename P1> class Arg { };
1456template <template <typename PP1> class P1> class Primary { };
1457
1458template <template <typename PP1> class P1> class Templ {
1459 void f() {
1460 // Make specialization with substituted template template param.
1461 Primary <P1> A;
1462 };
1463};
1464
1465// Instantiate with substitution Arg into P1.
1466template class Templ <Arg>;
1467 )",
1468 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1469 EXPECT_TRUE(testStructuralMatch(t));
1470}
1471
1472TEST_F(StructuralEquivalenceTemplateTest,
1473 TemplateVsSubstTemplateTemplateParmInArgNotEq) {
1474 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1475 SrcCode0: R"(
1476template <typename P1> class Arg { };
1477template <template <typename PP1> class P1> class Primary { };
1478
1479void f() {
1480 // Make specialization with simple template.
1481 Primary <Arg> A;
1482}
1483 )",
1484 SrcCode1: R"(
1485// Arg is different from the other, this should cause non-equivalence.
1486template <typename P1> class Arg { int X; };
1487template <template <typename PP1> class P1> class Primary { };
1488
1489template <template <typename PP1> class P1> class Templ {
1490 void f() {
1491 // Make specialization with substituted template template param.
1492 Primary <P1> A;
1493 };
1494};
1495
1496// Instantiate with substitution Arg into P1.
1497template class Templ <Arg>;
1498 )",
1499 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1500 EXPECT_FALSE(testStructuralMatch(t));
1501}
1502
1503struct StructuralEquivalenceDependentTemplateArgsTest
1504 : StructuralEquivalenceTemplateTest {};
1505
1506TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1507 SameStructsInDependentArgs) {
1508 std::string Code =
1509 R"(
1510 template <typename>
1511 struct S1;
1512
1513 template <typename>
1514 struct enable_if;
1515
1516 struct S
1517 {
1518 template <typename T, typename enable_if<S1<T>>::type>
1519 void f();
1520 };
1521 )";
1522 auto t = makeDecls<FunctionTemplateDecl>(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX11,
1523 AMatcher: functionTemplateDecl(hasName(Name: "f")));
1524 EXPECT_TRUE(testStructuralMatch(t));
1525}
1526
1527TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1528 DifferentStructsInDependentArgs) {
1529 std::string Code =
1530 R"(
1531 template <typename>
1532 struct S1;
1533
1534 template <typename>
1535 struct S2;
1536
1537 template <typename>
1538 struct enable_if;
1539 )";
1540 auto t = makeDecls<FunctionTemplateDecl>(SrcCode0: Code + R"(
1541 struct S
1542 {
1543 template <typename T, typename enable_if<S1<T>>::type>
1544 void f();
1545 };
1546 )",
1547 SrcCode1: Code + R"(
1548 struct S
1549 {
1550 template <typename T, typename enable_if<S2<T>>::type>
1551 void f();
1552 };
1553 )",
1554 Lang: Lang_CXX11,
1555 AMatcher: functionTemplateDecl(hasName(Name: "f")));
1556 EXPECT_FALSE(testStructuralMatch(t));
1557}
1558
1559TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1560 SameStructsInDependentScopeDeclRefExpr) {
1561 std::string Code =
1562 R"(
1563 template <typename>
1564 struct S1;
1565
1566 template <bool>
1567 struct enable_if;
1568
1569 struct S
1570 {
1571 template <typename T, typename enable_if<S1<T>::value>::type>
1572 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1573 };
1574 )";
1575 auto t = makeDecls<FunctionTemplateDecl>(SrcCode0: Code, SrcCode1: Code, Lang: Lang_CXX11,
1576 AMatcher: functionTemplateDecl(hasName(Name: "f")));
1577 EXPECT_TRUE(testStructuralMatch(t));
1578}
1579
1580TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1581 DifferentStructsInDependentScopeDeclRefExpr) {
1582 std::string Code =
1583 R"(
1584 template <typename>
1585 struct S1;
1586
1587 template <typename>
1588 struct S2;
1589
1590 template <bool>
1591 struct enable_if;
1592 )";
1593 auto t = makeDecls<FunctionTemplateDecl>(SrcCode0: Code + R"(
1594 struct S
1595 {
1596 template <typename T, typename enable_if<S1<T>::value>::type>
1597 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1598 };
1599 )",
1600 SrcCode1: Code + R"(
1601 struct S
1602 {
1603 template <typename T, typename enable_if<S2<T>::value>::type>
1604 void f();
1605 };
1606 )",
1607 Lang: Lang_CXX03,
1608 AMatcher: functionTemplateDecl(hasName(Name: "f")));
1609 EXPECT_FALSE(testStructuralMatch(t));
1610}
1611
1612TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1613 DifferentValueInDependentScopeDeclRefExpr) {
1614 std::string Code =
1615 R"(
1616 template <typename>
1617 struct S1;
1618
1619 template <bool>
1620 struct enable_if;
1621 )";
1622 auto t = makeDecls<FunctionTemplateDecl>(SrcCode0: Code + R"(
1623 struct S
1624 {
1625 template <typename T, typename enable_if<S1<T>::value1>::type>
1626 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1627 };
1628 )",
1629 SrcCode1: Code + R"(
1630 struct S
1631 {
1632 template <typename T, typename enable_if<S1<T>::value2>::type>
1633 void f();
1634 };
1635 )",
1636 Lang: Lang_CXX03,
1637 AMatcher: functionTemplateDecl(hasName(Name: "f")));
1638 EXPECT_FALSE(testStructuralMatch(t));
1639}
1640
1641TEST_F(
1642 StructuralEquivalenceTemplateTest,
1643 ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) {
1644 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1645 SrcCode0: R"(
1646 template <class T> struct Primary {};
1647 namespace N {
1648 struct Arg;
1649 }
1650 // Explicit instantiation with qualified name.
1651 template struct Primary<N::Arg>;
1652 )",
1653 SrcCode1: R"(
1654 template <class T> struct Primary {};
1655 namespace N {
1656 struct Arg;
1657 }
1658 using namespace N;
1659 // Explicit instantiation with UNqualified name.
1660 template struct Primary<Arg>;
1661 )",
1662 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1663 EXPECT_TRUE(testStructuralMatch(t));
1664}
1665
1666TEST_F(
1667 StructuralEquivalenceTemplateTest,
1668 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) {
1669 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1670 SrcCode0: R"(
1671 template <class T> struct Primary {};
1672 namespace N {
1673 struct Arg { int a; };
1674 }
1675 // Explicit instantiation with qualified name.
1676 template struct Primary<N::Arg>;
1677 )",
1678 SrcCode1: R"(
1679 template <class T> struct Primary {};
1680 namespace N {
1681 // This struct is not equivalent with the other in the prev TU.
1682 struct Arg { double b; }; // -- Field mismatch.
1683 }
1684 using namespace N;
1685 // Explicit instantiation with UNqualified name.
1686 template struct Primary<Arg>;
1687 )",
1688 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1689 EXPECT_FALSE(testStructuralMatch(t));
1690}
1691
1692TEST_F(
1693 StructuralEquivalenceTemplateTest,
1694 ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) {
1695 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1696 SrcCode0: R"(
1697 template <template <class> class T> struct Primary {};
1698 namespace N {
1699 template <class T> struct Arg;
1700 }
1701 // Explicit instantiation with qualified name.
1702 template struct Primary<N::Arg>;
1703 )",
1704 SrcCode1: R"(
1705 template <template <class> class T> struct Primary {};
1706 namespace N {
1707 template <class T> struct Arg;
1708 }
1709 using namespace N;
1710 // Explicit instantiation with UNqualified name.
1711 template struct Primary<Arg>;
1712 )",
1713 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1714 EXPECT_TRUE(testStructuralMatch(t));
1715}
1716
1717TEST_F(
1718 StructuralEquivalenceTemplateTest,
1719 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) {
1720 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1721 SrcCode0: R"(
1722 template <template <class> class T> struct Primary {};
1723 namespace N {
1724 template <class T> struct Arg { int a; };
1725 }
1726 // Explicit instantiation with qualified name.
1727 template struct Primary<N::Arg>;
1728 )",
1729 SrcCode1: R"(
1730 template <template <class> class T> struct Primary {};
1731 namespace N {
1732 // This template is not equivalent with the other in the prev TU.
1733 template <class T> struct Arg { double b; }; // -- Field mismatch.
1734 }
1735 using namespace N;
1736 // Explicit instantiation with UNqualified name.
1737 template struct Primary<Arg>;
1738 )",
1739 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1740 EXPECT_FALSE(testStructuralMatch(t));
1741}
1742
1743TEST_F(StructuralEquivalenceTemplateTest,
1744 IgnoreTemplateParmDepthAtTemplateTypeParmDecl) {
1745 auto Decls = makeDecls<ClassTemplateDecl>(
1746 SrcCode0: R"(
1747 template<class> struct A;
1748 )",
1749 SrcCode1: R"(
1750 template<class> struct S {
1751 template<class> friend struct A;
1752 };
1753 )",
1754 Lang: Lang_CXX03, Matcher0: classTemplateDecl(hasName(Name: "A")),
1755 Matcher1: classTemplateDecl(hasName(Name: "A")));
1756 EXPECT_TRUE(testStructuralMatch(Decls));
1757 EXPECT_TRUE(testStructuralMatch(Decls, true));
1758}
1759
1760TEST_F(StructuralEquivalenceTemplateTest,
1761 IgnoreTemplateParmDepthAtNonTypeTemplateParmDecl) {
1762 auto Decls = makeDecls<ClassTemplateDecl>(
1763 SrcCode0: R"(
1764 template<class T, T U> struct A;
1765 )",
1766 SrcCode1: R"(
1767 template<class T> struct S {
1768 template<class P, P Q> friend struct A;
1769 };
1770 )",
1771 Lang: Lang_CXX03, Matcher0: classTemplateDecl(hasName(Name: "A")),
1772 Matcher1: classTemplateDecl(hasName(Name: "A")));
1773 EXPECT_FALSE(testStructuralMatch(Decls));
1774 EXPECT_TRUE(testStructuralMatch(Decls, /*IgnoreTemplateParmDepth=*/true));
1775}
1776
1777TEST_F(
1778 StructuralEquivalenceTemplateTest,
1779 ClassTemplSpecWithInequivalentShadowedTemplArg) {
1780 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1781 SrcCode0: R"(
1782 template <template <class> class T> struct Primary {};
1783 template <class T> struct Arg { int a; };
1784 // Explicit instantiation with ::Arg
1785 template struct Primary<Arg>;
1786 )",
1787 SrcCode1: R"(
1788 template <template <class> class T> struct Primary {};
1789 template <class T> struct Arg { int a; };
1790 namespace N {
1791 // This template is not equivalent with the other in the global scope.
1792 template <class T> struct Arg { double b; }; // -- Field mismatch.
1793 // Explicit instantiation with N::Arg which shadows ::Arg
1794 template struct Primary<Arg>;
1795 }
1796 )",
1797 Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary")));
1798 EXPECT_FALSE(testStructuralMatch(t));
1799}
1800struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {
1801 StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls;
1802
1803 template <typename NodeType, typename MatcherType>
1804 std::pair<NodeType *, NodeType *>
1805 findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU,
1806 MatcherType M) {
1807 NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(t&: TU), M);
1808 NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(t&: TU), M);
1809 return {D0, D1};
1810 }
1811
1812 template <typename NodeType>
1813 bool isInNonEqCache(std::pair<NodeType *, NodeType *> D,
1814 bool IgnoreTemplateParmDepth = false) {
1815 return NonEquivalentDecls.count(
1816 V: std::make_tuple(D.first, D.second, IgnoreTemplateParmDepth)) > 0;
1817 }
1818};
1819
1820TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {
1821 auto TU = makeTuDecls(
1822 SrcCode0: R"(
1823 class A {};
1824 class B {};
1825 void x(A, A);
1826 )",
1827 SrcCode1: R"(
1828 class A {};
1829 class B {};
1830 void x(A, B);
1831 )",
1832 Lang: Lang_CXX03);
1833
1834 StructuralEquivalenceContext Ctx(
1835 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1836 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1837 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1838 /*Complain=*/false);
1839
1840 auto X = findDeclPair<FunctionDecl>(TU, M: functionDecl(hasName(Name: "x")));
1841 EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second));
1842
1843 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1844 TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1845 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1846 TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
1847}
1848
1849TEST_F(StructuralEquivalenceCacheTest, ReturnStmtNonEq) {
1850 auto TU = makeTuDecls(
1851 SrcCode0: R"(
1852 bool x() { return true; }
1853 )",
1854 SrcCode1: R"(
1855 bool x() { return false; }
1856 )",
1857 Lang: Lang_CXX03);
1858
1859 StructuralEquivalenceContext Ctx(
1860 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1861 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1862 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1863 /*Complain=*/false);
1864
1865 auto X = findDeclPair<FunctionDecl>(TU, M: functionDecl(hasName(Name: "x")));
1866 EXPECT_FALSE(Ctx.IsEquivalent(X.first->getBody(), X.second->getBody()));
1867
1868}
1869
1870TEST_F(StructuralEquivalenceCacheTest, VarDeclNoEq) {
1871 auto TU = makeTuDecls(
1872 SrcCode0: R"(
1873 int p;
1874 )",
1875 SrcCode1: R"(
1876 int q;
1877 )",
1878 Lang: Lang_CXX03);
1879
1880 StructuralEquivalenceContext Ctx(
1881 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1882 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1883 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1884 /*Complain=*/false);
1885
1886 auto Var = findDeclPair<VarDecl>(TU, M: varDecl());
1887 EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
1888}
1889
1890TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) {
1891 auto TU = makeTuDecls(
1892 SrcCode0: R"(
1893 int p;
1894 )",
1895 SrcCode1: R"(
1896 static int p;
1897 )",
1898 Lang: Lang_CXX03);
1899
1900 StructuralEquivalenceContext Ctx(
1901 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1902 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1903 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1904 /*Complain=*/false);
1905
1906 auto Var = findDeclPair<VarDecl>(TU, M: varDecl());
1907 EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
1908}
1909
1910TEST_F(StructuralEquivalenceCacheTest,
1911 NonTypeTemplateParmWithDifferentPositionNoEq) {
1912 auto TU = makeTuDecls(
1913 SrcCode0: R"(
1914 template<int T>
1915 struct A {
1916 template<int U>
1917 void foo() {}
1918 };
1919 )",
1920 SrcCode1: R"(
1921 template<int U>
1922 struct A {
1923 template<int V, int T>
1924 void foo() {}
1925 };
1926 )",
1927 Lang: Lang_CXX03);
1928
1929 StructuralEquivalenceContext Ctx(
1930 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1931 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1932 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1933 /*Complain=*/false);
1934
1935 auto NTTP = findDeclPair<NonTypeTemplateParmDecl>(
1936 TU, M: nonTypeTemplateParmDecl(hasName(Name: "T")));
1937 EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second));
1938}
1939
1940TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) {
1941 auto TU = makeTuDecls(
1942 SrcCode0: R"(
1943 int p = 1;
1944 )",
1945 SrcCode1: R"(
1946 int p = 2;
1947 )",
1948 Lang: Lang_CXX03);
1949
1950 StructuralEquivalenceContext Ctx(
1951 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1952 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1953 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1954 /*Complain=*/false);
1955
1956 auto Var = findDeclPair<VarDecl>(TU, M: varDecl());
1957 EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));
1958}
1959
1960TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {
1961 auto TU = makeTuDecls(
1962 SrcCode0: R"(
1963 class A {};
1964 class B { int i; };
1965 void x(A *);
1966 void y(A *);
1967 class C {
1968 friend void x(A *);
1969 friend void y(A *);
1970 };
1971 )",
1972 SrcCode1: R"(
1973 class A {};
1974 class B { int i; };
1975 void x(A *);
1976 void y(B *);
1977 class C {
1978 friend void x(A *);
1979 friend void y(B *);
1980 };
1981 )",
1982 Lang: Lang_CXX03);
1983
1984 StructuralEquivalenceContext Ctx(
1985 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
1986 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
1987 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
1988 /*Complain=*/false);
1989
1990 auto C = findDeclPair<CXXRecordDecl>(
1991 TU, M: cxxRecordDecl(hasName(Name: "C"), unless(isImplicit())));
1992 EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second));
1993
1994 EXPECT_FALSE(isInNonEqCache(C));
1995 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1996 TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1997 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1998 TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
1999 EXPECT_FALSE(isInNonEqCache(
2000 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
2001 EXPECT_FALSE(isInNonEqCache(
2002 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y")))));
2003}
2004
2005TEST_F(StructuralEquivalenceCacheTest, Cycle) {
2006 auto TU = makeTuDecls(
2007 SrcCode0: R"(
2008 class C;
2009 class A { C *c; };
2010 void x(A *);
2011 class C {
2012 friend void x(A *);
2013 };
2014 )",
2015 SrcCode1: R"(
2016 class C;
2017 class A { C *c; };
2018 void x(A *);
2019 class C {
2020 friend void x(A *);
2021 };
2022 )",
2023 Lang: Lang_CXX03);
2024
2025 StructuralEquivalenceContext Ctx(
2026 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
2027 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
2028 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
2029 /*Complain=*/false);
2030
2031 auto C = findDeclPair<CXXRecordDecl>(
2032 TU, M: cxxRecordDecl(hasName(Name: "C"), unless(isImplicit())));
2033 EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second));
2034
2035 EXPECT_FALSE(isInNonEqCache(C));
2036 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
2037 TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
2038 EXPECT_FALSE(isInNonEqCache(
2039 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
2040}
2041
2042TEST_F(StructuralEquivalenceCacheTest, TemplateParmDepth) {
2043 // In 'friend struct Y' ClassTemplateDecl has the TU as parent context.
2044 // This declaration has template depth 1 (it is already inside a template).
2045 // It has not a previous declaration and is an "undeclared" friend.
2046 //
2047 // Second TU has a specialization of 'struct X'.
2048 // In this case 'friend struct Y' has the ClassTemplateSpecializationDecl as
2049 // parent. It has template depth 0 (it is in the specialization). It has the
2050 // first 'struct Y' declaration as previous declaration and canonical
2051 // declaration.
2052 //
2053 // When these two 'friend struct Y' are compared, only the template depth is
2054 // different.
2055 // FIXME: Structural equivalence checks the depth only in types, not in
2056 // TemplateParmDecl. For this reason the second 'A1' argument is needed (as a
2057 // type) in the template to make the check fail.
2058 auto TU = makeTuDecls(
2059 SrcCode0: R"(
2060 template <class A1, A1>
2061 struct Y;
2062
2063 template <class A>
2064 struct X {
2065 template <class A1, A1>
2066 friend struct Y;
2067 };
2068 )",
2069 SrcCode1: R"(
2070 template <class A1, A1>
2071 struct Y;
2072
2073 template <class A>
2074 struct X {
2075 template <class A1, A1>
2076 friend struct Y;
2077 };
2078
2079 X<int> x;
2080 )",
2081 Lang: Lang_CXX03);
2082
2083 auto *D0 = LastDeclMatcher<ClassTemplateDecl>().match(
2084 get<0>(t&: TU), classTemplateDecl(hasName(Name: "Y"), unless(isImplicit())));
2085 auto *D1 = LastDeclMatcher<ClassTemplateDecl>().match(
2086 get<1>(t&: TU), classTemplateDecl(hasName(Name: "Y"), unless(isImplicit())));
2087 ASSERT_EQ(D0->getTemplateDepth(), 1u);
2088 ASSERT_EQ(D1->getTemplateDepth(), 0u);
2089
2090 StructuralEquivalenceContext Ctx_NoIgnoreTemplateParmDepth(
2091 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
2092 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
2093 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
2094 /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,
2095 /*IgnoreTemplateParmDepth=*/false);
2096
2097 EXPECT_FALSE(Ctx_NoIgnoreTemplateParmDepth.IsEquivalent(D0, D1));
2098
2099 Decl *NonEqDecl0 =
2100 D0->getCanonicalDecl()->getTemplateParameters()->getParam(1);
2101 Decl *NonEqDecl1 =
2102 D1->getCanonicalDecl()->getTemplateParameters()->getParam(1);
2103 EXPECT_TRUE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), false));
2104 EXPECT_FALSE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), true));
2105
2106 StructuralEquivalenceContext Ctx_IgnoreTemplateParmDepth(
2107 get<0>(t&: TU)->getASTContext().getLangOpts(), get<0>(t&: TU)->getASTContext(),
2108 get<1>(t&: TU)->getASTContext(), NonEquivalentDecls,
2109 StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,
2110 /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,
2111 /*IgnoreTemplateParmDepth=*/true);
2112
2113 EXPECT_TRUE(Ctx_IgnoreTemplateParmDepth.IsEquivalent(D0, D1));
2114
2115 EXPECT_FALSE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), true));
2116}
2117
2118struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {};
2119
2120/// Fallback matcher to be used only when there is no specific matcher for a
2121/// Expr subclass. Remove this once all Expr subclasses have their own matcher.
2122static auto &fallbackExprMatcher = expr;
2123
2124TEST_F(StructuralEquivalenceStmtTest, AddrLabelExpr) {
2125 auto t = makeWrappedStmts(SrcCode0: "lbl: &&lbl;", SrcCode1: "lbl: &&lbl;", Lang: Lang_CXX03,
2126 AMatcher: addrLabelExpr());
2127 EXPECT_TRUE(testStructuralMatch(t));
2128}
2129
2130TEST_F(StructuralEquivalenceStmtTest, AddrLabelExprDifferentLabel) {
2131 auto t = makeWrappedStmts(SrcCode0: "lbl1: lbl2: &&lbl1;", SrcCode1: "lbl1: lbl2: &&lbl2;",
2132 Lang: Lang_CXX03, AMatcher: addrLabelExpr());
2133 // FIXME: Should be false. LabelDecl are incorrectly matched.
2134 EXPECT_TRUE(testStructuralMatch(t));
2135}
2136
2137static const std::string MemoryOrderSrc = R"(
2138enum memory_order {
2139 memory_order_relaxed,
2140 memory_order_consume,
2141 memory_order_acquire,
2142 memory_order_release,
2143 memory_order_acq_rel,
2144 memory_order_seq_cst
2145};
2146)";
2147
2148TEST_F(StructuralEquivalenceStmtTest, AtomicExpr) {
2149 std::string Prefix = "char a, b; " + MemoryOrderSrc;
2150 auto t = makeStmts(
2151 SrcCode0: Prefix +
2152 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",
2153 SrcCode1: Prefix +
2154 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",
2155 Lang: Lang_CXX03, AMatcher: atomicExpr());
2156 EXPECT_TRUE(testStructuralMatch(t));
2157}
2158
2159TEST_F(StructuralEquivalenceStmtTest, AtomicExprDifferentOp) {
2160 std::string Prefix = "char a, b; " + MemoryOrderSrc;
2161 auto t = makeStmts(
2162 SrcCode0: Prefix +
2163 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",
2164 SrcCode1: Prefix +
2165 "void wrapped() { __atomic_store(&a, &b, memory_order_seq_cst); }",
2166 Lang: Lang_CXX03, AMatcher: atomicExpr());
2167 EXPECT_FALSE(testStructuralMatch(t));
2168}
2169
2170TEST_F(StructuralEquivalenceStmtTest, BinaryOperator) {
2171 auto t = makeWrappedStmts(SrcCode0: "1 + 1", SrcCode1: "1 + 1", Lang: Lang_CXX03, AMatcher: binaryOperator());
2172 EXPECT_TRUE(testStructuralMatch(t));
2173}
2174
2175TEST_F(StructuralEquivalenceStmtTest, BinaryOperatorDifferentOps) {
2176 auto t = makeWrappedStmts(SrcCode0: "1 + 1", SrcCode1: "1 - 1", Lang: Lang_CXX03, AMatcher: binaryOperator());
2177 EXPECT_FALSE(testStructuralMatch(t));
2178}
2179
2180TEST_F(StructuralEquivalenceStmtTest, CallExpr) {
2181 std::string Src = "int call(); int wrapped() { call(); }";
2182 auto t = makeStmts(SrcCode0: Src, SrcCode1: Src, Lang: Lang_CXX03, AMatcher: callExpr());
2183 EXPECT_TRUE(testStructuralMatch(t));
2184}
2185
2186TEST_F(StructuralEquivalenceStmtTest, CallExprDifferentCallee) {
2187 std::string FunctionSrc = "int func1(); int func2();\n";
2188 auto t = makeStmts(SrcCode0: FunctionSrc + "void wrapper() { func1(); }",
2189 SrcCode1: FunctionSrc + "void wrapper() { func2(); }", Lang: Lang_CXX03,
2190 AMatcher: callExpr());
2191 EXPECT_FALSE(testStructuralMatch(t));
2192}
2193
2194TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) {
2195 auto t = makeWrappedStmts(SrcCode0: "'a'", SrcCode1: "'a'", Lang: Lang_CXX03, AMatcher: characterLiteral());
2196 EXPECT_TRUE(testStructuralMatch(t));
2197}
2198
2199TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) {
2200 auto t = makeWrappedStmts(SrcCode0: "'a'", SrcCode1: "'b'", Lang: Lang_CXX03, AMatcher: characterLiteral());
2201 EXPECT_FALSE(testStructuralMatch(t));
2202}
2203
2204TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExpr) {
2205 auto t = makeWrappedStmts(SrcCode0: "__is_lvalue_expr(1)", SrcCode1: "__is_lvalue_expr(1)",
2206 Lang: Lang_CXX03, AMatcher: fallbackExprMatcher());
2207 EXPECT_TRUE(testStructuralMatch(t));
2208}
2209
2210TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExprDifferentKind) {
2211 auto t = makeWrappedStmts(SrcCode0: "__is_lvalue_expr(1)", SrcCode1: "__is_rvalue_expr(1)",
2212 Lang: Lang_CXX03, AMatcher: fallbackExprMatcher());
2213 EXPECT_FALSE(testStructuralMatch(t));
2214}
2215
2216TEST_F(StructuralEquivalenceStmtTest, FloatingLiteral) {
2217 auto t = makeWrappedStmts(SrcCode0: "1.0", SrcCode1: "1.0", Lang: Lang_CXX03, AMatcher: fallbackExprMatcher());
2218 EXPECT_TRUE(testStructuralMatch(t));
2219}
2220
2221TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentSpelling) {
2222 auto t = makeWrappedStmts(SrcCode0: "0x10.1p0", SrcCode1: "16.0625", Lang: Lang_CXX17,
2223 AMatcher: fallbackExprMatcher());
2224 // Same value but with different spelling is equivalent.
2225 EXPECT_TRUE(testStructuralMatch(t));
2226}
2227
2228TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentType) {
2229 auto t = makeWrappedStmts(SrcCode0: "1.0", SrcCode1: "1.0f", Lang: Lang_CXX03, AMatcher: fallbackExprMatcher());
2230 EXPECT_FALSE(testStructuralMatch(t));
2231}
2232
2233TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentValue) {
2234 auto t = makeWrappedStmts(SrcCode0: "1.01", SrcCode1: "1.0", Lang: Lang_CXX03, AMatcher: fallbackExprMatcher());
2235 EXPECT_FALSE(testStructuralMatch(t));
2236}
2237
2238TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) {
2239 auto t = makeWrappedStmts(SrcCode0: "_Generic(0u, unsigned int: 0, float: 1)",
2240 SrcCode1: "_Generic(0u, unsigned int: 0, float: 1)", Lang: Lang_C99,
2241 AMatcher: genericSelectionExpr());
2242 EXPECT_TRUE(testStructuralMatch(t));
2243}
2244
2245TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) {
2246 auto t = makeWrappedStmts(SrcCode0: "_Generic(0u, unsigned int: 0, float: 1)",
2247 SrcCode1: "_Generic(0, int: 0, float: 1)", Lang: Lang_C99,
2248 AMatcher: genericSelectionExpr());
2249 EXPECT_FALSE(testStructuralMatch(t));
2250}
2251
2252TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) {
2253 auto t = makeWrappedStmts(SrcCode0: "_Generic(0u, unsigned int: 0, float: 1)",
2254 SrcCode1: "_Generic(0u, float: 1, unsigned int: 0)", Lang: Lang_C99,
2255 AMatcher: genericSelectionExpr());
2256 EXPECT_FALSE(testStructuralMatch(t));
2257}
2258
2259TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) {
2260 auto t = makeStmts(
2261 SrcCode0: R"(
2262 template <typename T>
2263 void f() {
2264 T x;
2265 (void)_Generic(x, int: 0, float: 1);
2266 }
2267 void g() { f<int>(); }
2268 )",
2269 SrcCode1: R"(
2270 template <typename T>
2271 void f() {
2272 T x;
2273 (void)_Generic(x, int: 0, float: 1);
2274 }
2275 void g() { f<int>(); }
2276 )",
2277 Lang: Lang_CXX03, AMatcher: genericSelectionExpr());
2278 EXPECT_TRUE(testStructuralMatch(t));
2279}
2280
2281TEST_F(StructuralEquivalenceStmtTest,
2282 GenericSelectionExprDependentResultOrderDiffers) {
2283 auto t = makeStmts(
2284 SrcCode0: R"(
2285 template <typename T>
2286 void f() {
2287 T x;
2288 (void)_Generic(x, float: 1, int: 0);
2289 }
2290 void g() { f<int>(); }
2291 )",
2292 SrcCode1: R"(
2293 template <typename T>
2294 void f() {
2295 T x;
2296 (void)_Generic(x, int: 0, float: 1);
2297 }
2298 void g() { f<int>(); }
2299 )",
2300 Lang: Lang_CXX03, AMatcher: genericSelectionExpr());
2301
2302 EXPECT_FALSE(testStructuralMatch(t));
2303}
2304TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) {
2305 auto t = makeWrappedStmts(SrcCode0: "1", SrcCode1: "1", Lang: Lang_CXX03, AMatcher: integerLiteral());
2306 EXPECT_TRUE(testStructuralMatch(t));
2307}
2308
2309TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentSpelling) {
2310 auto t = makeWrappedStmts(SrcCode0: "1", SrcCode1: "0x1", Lang: Lang_CXX03, AMatcher: integerLiteral());
2311 // Same value but with different spelling is equivalent.
2312 EXPECT_TRUE(testStructuralMatch(t));
2313}
2314
2315TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) {
2316 auto t = makeWrappedStmts(SrcCode0: "1", SrcCode1: "2", Lang: Lang_CXX03, AMatcher: integerLiteral());
2317 EXPECT_FALSE(testStructuralMatch(t));
2318}
2319
2320TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) {
2321 auto t = makeWrappedStmts(SrcCode0: "1", SrcCode1: "1L", Lang: Lang_CXX03, AMatcher: integerLiteral());
2322 EXPECT_FALSE(testStructuralMatch(t));
2323}
2324
2325TEST_F(StructuralEquivalenceStmtTest, MemberExpr) {
2326 std::string ClassSrc = "struct C { int a; int b; };";
2327 auto t = makeStmts(SrcCode0: ClassSrc + "int wrapper() { C c; return c.a; }",
2328 SrcCode1: ClassSrc + "int wrapper() { C c; return c.a; }",
2329 Lang: Lang_CXX03, AMatcher: memberExpr());
2330 EXPECT_TRUE(testStructuralMatch(t));
2331}
2332
2333TEST_F(StructuralEquivalenceStmtTest, MemberExprDifferentMember) {
2334 std::string ClassSrc = "struct C { int a; int b; };";
2335 auto t = makeStmts(SrcCode0: ClassSrc + "int wrapper() { C c; return c.a; }",
2336 SrcCode1: ClassSrc + "int wrapper() { C c; return c.b; }",
2337 Lang: Lang_CXX03, AMatcher: memberExpr());
2338 EXPECT_FALSE(testStructuralMatch(t));
2339}
2340
2341TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) {
2342 auto t =
2343 makeWrappedStmts(SrcCode0: "@\"a\"", SrcCode1: "@\"a\"", Lang: Lang_OBJCXX, AMatcher: fallbackExprMatcher());
2344 EXPECT_TRUE(testStructuralMatch(t));
2345}
2346
2347TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) {
2348 auto t =
2349 makeWrappedStmts(SrcCode0: "@\"a\"", SrcCode1: "@\"b\"", Lang: Lang_OBJCXX, AMatcher: fallbackExprMatcher());
2350 EXPECT_FALSE(testStructuralMatch(t));
2351}
2352
2353TEST_F(StructuralEquivalenceStmtTest, StringLiteral) {
2354 auto t = makeWrappedStmts(SrcCode0: "\"a\"", SrcCode1: "\"a\"", Lang: Lang_CXX03, AMatcher: stringLiteral());
2355 EXPECT_TRUE(testStructuralMatch(t));
2356}
2357
2358TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) {
2359 auto t = makeWrappedStmts(SrcCode0: "\"a\"", SrcCode1: "\"b\"", Lang: Lang_CXX03, AMatcher: stringLiteral());
2360 EXPECT_FALSE(testStructuralMatch(t));
2361}
2362
2363TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) {
2364 auto t = makeWrappedStmts(SrcCode0: "\"a\"", SrcCode1: "\"aa\"", Lang: Lang_CXX03, AMatcher: stringLiteral());
2365 EXPECT_FALSE(testStructuralMatch(t));
2366}
2367
2368TEST_F(StructuralEquivalenceStmtTest, TypeTraitExpr) {
2369 auto t = makeWrappedStmts(SrcCode0: "__is_pod(int)", SrcCode1: "__is_pod(int)", Lang: Lang_CXX03,
2370 AMatcher: fallbackExprMatcher());
2371 EXPECT_TRUE(testStructuralMatch(t));
2372}
2373
2374TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentType) {
2375 auto t = makeWrappedStmts(SrcCode0: "__is_pod(int)", SrcCode1: "__is_pod(long)", Lang: Lang_CXX03,
2376 AMatcher: fallbackExprMatcher());
2377 EXPECT_FALSE(testStructuralMatch(t));
2378}
2379
2380TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTrait) {
2381 auto t = makeWrappedStmts(
2382 SrcCode0: "__is_pod(int)", SrcCode1: "__is_trivially_constructible(int)", Lang: Lang_CXX03, AMatcher: expr());
2383 EXPECT_FALSE(testStructuralMatch(t));
2384}
2385
2386TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTraits) {
2387 auto t = makeWrappedStmts(SrcCode0: "__is_constructible(int)",
2388 SrcCode1: "__is_constructible(int, int)", Lang: Lang_CXX03, AMatcher: expr());
2389 EXPECT_FALSE(testStructuralMatch(t));
2390}
2391
2392TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExpr) {
2393 auto t = makeWrappedStmts(SrcCode0: "sizeof(int)", SrcCode1: "sizeof(int)", Lang: Lang_CXX03,
2394 AMatcher: unaryExprOrTypeTraitExpr());
2395 EXPECT_TRUE(testStructuralMatch(t));
2396}
2397
2398TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentKind) {
2399 auto t = makeWrappedStmts(SrcCode0: "sizeof(int)", SrcCode1: "alignof(long)", Lang: Lang_CXX11,
2400 AMatcher: unaryExprOrTypeTraitExpr());
2401 EXPECT_FALSE(testStructuralMatch(t));
2402}
2403
2404TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentType) {
2405 auto t = makeWrappedStmts(SrcCode0: "sizeof(int)", SrcCode1: "sizeof(long)", Lang: Lang_CXX03,
2406 AMatcher: unaryExprOrTypeTraitExpr());
2407 EXPECT_FALSE(testStructuralMatch(t));
2408}
2409
2410TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) {
2411 auto t = makeWrappedStmts(SrcCode0: "+1", SrcCode1: "+1", Lang: Lang_CXX03, AMatcher: unaryOperator());
2412 EXPECT_TRUE(testStructuralMatch(t));
2413}
2414
2415TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) {
2416 auto t = makeWrappedStmts(SrcCode0: "+1", SrcCode1: "-1", Lang: Lang_CXX03, AMatcher: unaryOperator());
2417 EXPECT_FALSE(testStructuralMatch(t));
2418}
2419
2420TEST_F(StructuralEquivalenceStmtTest,
2421 CXXOperatorCallExprVsUnaryBinaryOperator) {
2422 auto t = makeNamedDecls(
2423 SrcCode0: R"(
2424 template <typename T, T x>
2425 class A;
2426 template <typename T, T x, T y>
2427 void foo(
2428 A<T, x + y>,
2429 A<T, x - y>,
2430 A<T, -x>,
2431 A<T, x * y>,
2432 A<T, *x>,
2433 A<T, x / y>,
2434 A<T, x % y>,
2435 A<T, x ^ y>,
2436 A<T, x & y>,
2437 A<T, &x>,
2438 A<T, x | y>,
2439 A<T, ~x>,
2440 A<T, !x>,
2441 A<T, x < y>,
2442 A<T, (x > y)>,
2443 A<T, x << y>,
2444 A<T, (x >> y)>,
2445 A<T, x == y>,
2446 A<T, x != y>,
2447 A<T, x <= y>,
2448 A<T, x >= y>,
2449 A<T, x <=> y>,
2450 A<T, x && y>,
2451 A<T, x || y>,
2452 A<T, ++x>,
2453 A<T, --x>,
2454 A<T, (x , y)>,
2455 A<T, x ->* y>,
2456 A<T, x -> y>
2457 );
2458 )",
2459 SrcCode1: R"(
2460 struct Bar {
2461 Bar& operator=(Bar&);
2462 Bar& operator->();
2463 };
2464
2465 Bar& operator+(Bar&, Bar&);
2466 Bar& operator+(Bar&);
2467 Bar& operator-(Bar&, Bar&);
2468 Bar& operator-(Bar&);
2469 Bar& operator*(Bar&, Bar&);
2470 Bar& operator*(Bar&);
2471 Bar& operator/(Bar&, Bar&);
2472 Bar& operator%(Bar&, Bar&);
2473 Bar& operator^(Bar&, Bar&);
2474 Bar& operator&(Bar&, Bar&);
2475 Bar& operator&(Bar&);
2476 Bar& operator|(Bar&, Bar&);
2477 Bar& operator~(Bar&);
2478 Bar& operator!(Bar&);
2479 Bar& operator<(Bar&, Bar&);
2480 Bar& operator>(Bar&, Bar&);
2481 Bar& operator+=(Bar&, Bar&);
2482 Bar& operator-=(Bar&, Bar&);
2483 Bar& operator*=(Bar&, Bar&);
2484 Bar& operator/=(Bar&, Bar&);
2485 Bar& operator%=(Bar&, Bar&);
2486 Bar& operator^=(Bar&, Bar&);
2487 Bar& operator&=(Bar&, Bar&);
2488 Bar& operator|=(Bar&, Bar&);
2489 Bar& operator<<(Bar&, Bar&);
2490 Bar& operator>>(Bar&, Bar&);
2491 Bar& operator<<=(Bar&, Bar&);
2492 Bar& operator>>=(Bar&, Bar&);
2493 Bar& operator==(Bar&, Bar&);
2494 Bar& operator!=(Bar&, Bar&);
2495 Bar& operator<=(Bar&, Bar&);
2496 Bar& operator>=(Bar&, Bar&);
2497 Bar& operator<=>(Bar&, Bar&);
2498 Bar& operator&&(Bar&, Bar&);
2499 Bar& operator||(Bar&, Bar&);
2500 Bar& operator++(Bar&);
2501 Bar& operator--(Bar&);
2502 Bar& operator,(Bar&, Bar&);
2503 Bar& operator->*(Bar&, Bar&);
2504
2505 template <typename T, T x>
2506 class A;
2507 template <typename T, T x, T y>
2508 void foo(
2509 A<T, x + y>,
2510 A<T, x - y>,
2511 A<T, -x>,
2512 A<T, x * y>,
2513 A<T, *x>,
2514 A<T, x / y>,
2515 A<T, x % y>,
2516 A<T, x ^ y>,
2517 A<T, x & y>,
2518 A<T, &x>,
2519 A<T, x | y>,
2520 A<T, ~x>,
2521 A<T, !x>,
2522 A<T, x < y>,
2523 A<T, (x > y)>,
2524 A<T, x << y>,
2525 A<T, (x >> y)>,
2526 A<T, x == y>,
2527 A<T, x != y>,
2528 A<T, x <= y>,
2529 A<T, x >= y>,
2530 A<T, x <=> y>,
2531 A<T, x && y>,
2532 A<T, x || y>,
2533 A<T, ++x>,
2534 A<T, --x>,
2535 A<T, (x , y)>,
2536 A<T, x ->* y>,
2537 A<T, x -> y>
2538 );
2539 )",
2540 Lang: Lang_CXX20);
2541 EXPECT_TRUE(testStructuralMatch(t));
2542}
2543
2544TEST_F(StructuralEquivalenceStmtTest,
2545 CXXOperatorCallExprVsUnaryBinaryOperatorNe) {
2546 auto t = makeNamedDecls(
2547 SrcCode0: R"(
2548 template <typename T, T x>
2549 class A;
2550 template <typename T, T x, T y>
2551 void foo(
2552 A<T, x + y>
2553 );
2554 )",
2555 SrcCode1: R"(
2556 struct Bar;
2557
2558 Bar& operator-(Bar&, Bar&);
2559
2560 template <typename T, T x>
2561 class A;
2562 template <typename T, T x, T y>
2563 void foo(
2564 A<T, x - y>
2565 );
2566 )",
2567 Lang: Lang_CXX11);
2568 EXPECT_FALSE(testStructuralMatch(t));
2569}
2570
2571TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) {
2572 auto t = makeNamedDecls(
2573 SrcCode0: R"(
2574 template <typename T, T x>
2575 class A;
2576 template <typename T, T x, T y>
2577 void foo(A<T, x>);
2578 )",
2579 SrcCode1: R"(
2580 template <typename T, T x>
2581 class A;
2582 template <typename T, T x, T y>
2583 void foo(A<T, y>);
2584 )",
2585 Lang: Lang_CXX11);
2586 EXPECT_FALSE(testStructuralMatch(t));
2587}
2588
2589TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) {
2590 auto t = makeStmts(
2591 SrcCode0: R"(
2592 void f1(int);
2593 template <typename T>
2594 void f(T t) {
2595 f1(t);
2596 }
2597 void g() { f<int>(1); }
2598 )",
2599 SrcCode1: R"(
2600 void f2(int);
2601 template <typename T>
2602 void f(T t) {
2603 f2(t);
2604 }
2605 void g() { f<int>(1); }
2606 )",
2607 Lang: Lang_CXX03, AMatcher: unresolvedLookupExpr());
2608 EXPECT_FALSE(testStructuralMatch(t));
2609}
2610
2611TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentQualifier) {
2612 auto t = makeStmts(
2613 SrcCode0: R"(
2614 struct X {
2615 static void g(int);
2616 static void g(char);
2617 };
2618
2619 template <typename T>
2620 void f(T t) {
2621 X::g(t);
2622 }
2623
2624 void g() { f<int>(1); }
2625 )",
2626 SrcCode1: R"(
2627 struct Y {
2628 static void g(int);
2629 static void g(char);
2630 };
2631
2632 template <typename T>
2633 void f(T t) {
2634 Y::g(t);
2635 }
2636
2637 void g() { f<int>(1); }
2638 )",
2639 Lang: Lang_CXX03, AMatcher: unresolvedLookupExpr());
2640 EXPECT_FALSE(testStructuralMatch(t));
2641}
2642
2643TEST_F(StructuralEquivalenceStmtTest,
2644 UnresolvedLookupDifferentTemplateArgument) {
2645 auto t = makeStmts(
2646 SrcCode0: R"(
2647 struct A {};
2648 template<typename T1, typename T2>
2649 void g() {}
2650
2651 template <typename T>
2652 void f() {
2653 g<A, T>();
2654 }
2655
2656 void h() { f<int>(); }
2657 )",
2658 SrcCode1: R"(
2659 struct B {};
2660 template<typename T1, typename T2>
2661 void g() {}
2662
2663 template <typename T>
2664 void f() {
2665 g<B, T>();
2666 }
2667
2668 void h() { f<int>(); }
2669 )",
2670 Lang: Lang_CXX03, AMatcher: unresolvedLookupExpr());
2671 EXPECT_FALSE(testStructuralMatch(t));
2672}
2673
2674TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookup) {
2675 auto t = makeStmts(
2676 SrcCode0: R"(
2677 struct A {};
2678 struct B {
2679 template<typename T1, typename T2>
2680 static void g(int) {};
2681 template<typename T1, typename T2>
2682 static void g(char) {};
2683 };
2684
2685 template <typename T1, typename T2>
2686 void f(T2 x) {
2687 B::g<A, T1>(x);
2688 }
2689
2690 void g() { f<char, int>(1); }
2691 )",
2692 SrcCode1: R"(
2693 struct A {};
2694 struct B {
2695 template<typename T1, typename T2>
2696 static void g(int) {};
2697 template<typename T1, typename T2>
2698 static void g(char) {};
2699 };
2700
2701 template <typename T1, typename T2>
2702 void f(T2 x) {
2703 B::g<A, T1>(x);
2704 }
2705
2706 void g() { f<char, int>(1); }
2707 )",
2708 Lang: Lang_CXX03, AMatcher: unresolvedLookupExpr());
2709 EXPECT_TRUE(testStructuralMatch(t));
2710}
2711
2712TEST_F(StructuralEquivalenceCacheTest, GotoStmtNoEq) {
2713 auto S = makeStmts(
2714 SrcCode0: R"(
2715 void foo() {
2716 goto L1;
2717 L1: foo();
2718 }
2719 )",
2720 SrcCode1: R"(
2721 void foo() {
2722 goto L2;
2723 L2: foo();
2724 }
2725 )",
2726 Lang: Lang_CXX03, AMatcher: gotoStmt());
2727 EXPECT_FALSE(testStructuralMatch(S));
2728}
2729
2730TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) {
2731 std::string Prefix = "enum Test { AAA, BBB };";
2732 auto t = makeStmts(
2733 SrcCode0: Prefix + "void foo(int i) {if (i > 0) {i = AAA;} else {i = BBB;}}",
2734 SrcCode1: Prefix + "void foo(int i) {if (i > 0) {i = BBB;} else {i = AAA;}}",
2735 Lang: Lang_CXX03, AMatcher: ifStmt());
2736 EXPECT_FALSE(testStructuralMatch(t));
2737}
2738
2739TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) {
2740 auto S = makeStmts(
2741 SrcCode0: R"(
2742 template <class T>
2743 void foo() {
2744 (void)T().x;
2745 }
2746 struct A { int x; };
2747 void bar() {
2748 foo<A>();
2749 }
2750 )",
2751 SrcCode1: R"(
2752 template <class T>
2753 void foo() {
2754 (void)T().y;
2755 }
2756 struct A { int y; };
2757 void bar() {
2758 foo<A>();
2759 }
2760 )",
2761 Lang: Lang_CXX11, AMatcher: cxxDependentScopeMemberExpr());
2762 EXPECT_FALSE(testStructuralMatch(S));
2763}
2764
2765} // end namespace ast_matchers
2766} // end namespace clang
2767

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/AST/StructuralEquivalenceTest.cpp