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

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