1 #include "clang/AST/ASTContext.h"
2 #include "clang/AST/ASTStructuralEquivalence.h"
3 #include "clang/ASTMatchers/ASTMatchers.h"
4 #include "clang/Frontend/ASTUnit.h"
5 #include "clang/Testing/CommandLineArgs.h"
6 #include "clang/Tooling/Tooling.h"
7 #include "llvm/Support/Host.h"
8
9 #include "DeclMatcher.h"
10
11 #include "gtest/gtest.h"
12
13 namespace clang {
14 namespace ast_matchers {
15
16 using std::get;
17
18 struct StructuralEquivalenceTest : ::testing::Test {
19 std::unique_ptr<ASTUnit> AST0, AST1;
20 std::string Code0, Code1; // Buffers for SourceManager
21
22 // Parses the source code in the specified language and sets the ASTs of
23 // the current test instance to the parse result.
makeASTUnitsclang::ast_matchers::StructuralEquivalenceTest24 void makeASTUnits(const std::string &SrcCode0, const std::string &SrcCode1,
25 TestLanguage Lang) {
26 this->Code0 = SrcCode0;
27 this->Code1 = SrcCode1;
28 std::vector<std::string> Args = getCommandLineArgsForTesting(Lang);
29
30 const char *const InputFileName = "input.cc";
31
32 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
33 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
34 }
35
36 // Get a pair of node pointers into the synthesized AST from the given code
37 // snippets. To determine the returned node, a separate matcher is specified
38 // for both snippets. The first matching node is returned.
39 template <typename NodeType, typename MatcherType>
40 std::tuple<NodeType *, NodeType *>
makeDeclsclang::ast_matchers::StructuralEquivalenceTest41 makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,
42 TestLanguage Lang, const MatcherType &Matcher0,
43 const MatcherType &Matcher1) {
44 makeASTUnits(SrcCode0, SrcCode1, Lang);
45
46 NodeType *D0 = FirstDeclMatcher<NodeType>().match(
47 AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
48 NodeType *D1 = FirstDeclMatcher<NodeType>().match(
49 AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
50
51 return std::make_tuple(D0, D1);
52 }
53
54 std::tuple<TranslationUnitDecl *, TranslationUnitDecl *>
makeTuDeclsclang::ast_matchers::StructuralEquivalenceTest55 makeTuDecls(const std::string &SrcCode0, const std::string &SrcCode1,
56 TestLanguage Lang) {
57 makeASTUnits(SrcCode0, SrcCode1, Lang);
58
59 return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),
60 AST1->getASTContext().getTranslationUnitDecl());
61 }
62
63 // Get a pair of node pointers into the synthesized AST from the given code
64 // snippets. The same matcher is used for both snippets.
65 template <typename NodeType, typename MatcherType>
66 std::tuple<NodeType *, NodeType *>
makeDeclsclang::ast_matchers::StructuralEquivalenceTest67 makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,
68 TestLanguage Lang, const MatcherType &AMatcher) {
69 return makeDecls<NodeType, MatcherType>(
70 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
71 }
72
73 // Get a pair of Decl pointers to the synthesized declarations from the given
74 // code snippets. We search for the first NamedDecl with given name in both
75 // snippets.
76 std::tuple<NamedDecl *, NamedDecl *>
makeNamedDeclsclang::ast_matchers::StructuralEquivalenceTest77 makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1,
78 TestLanguage Lang, const char *const Identifier = "foo") {
79 auto Matcher = namedDecl(hasName(Identifier));
80 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);
81 }
82
83 // Wraps a Stmt and the ASTContext that contains it.
84 struct StmtWithASTContext {
85 Stmt *S;
86 ASTContext *Context;
StmtWithASTContextclang::ast_matchers::StructuralEquivalenceTest::StmtWithASTContext87 explicit StmtWithASTContext(Stmt &S, ASTContext &Context)
88 : S(&S), Context(&Context) {}
StmtWithASTContextclang::ast_matchers::StructuralEquivalenceTest::StmtWithASTContext89 explicit StmtWithASTContext(FunctionDecl *FD)
90 : S(FD->getBody()), Context(&FD->getASTContext()) {}
91 };
92
93 // Get a pair of node pointers into the synthesized AST from the given code
94 // snippets. To determine the returned node, a separate matcher is specified
95 // for both snippets. The first matching node is returned.
96 template <typename MatcherType>
97 std::tuple<StmtWithASTContext, StmtWithASTContext>
makeStmtsclang::ast_matchers::StructuralEquivalenceTest98 makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,
99 TestLanguage Lang, const MatcherType &Matcher0,
100 const MatcherType &Matcher1) {
101 makeASTUnits(SrcCode0, SrcCode1, Lang);
102
103 Stmt *S0 = FirstDeclMatcher<Stmt>().match(
104 AST0->getASTContext().getTranslationUnitDecl(), Matcher0);
105 Stmt *S1 = FirstDeclMatcher<Stmt>().match(
106 AST1->getASTContext().getTranslationUnitDecl(), Matcher1);
107
108 return std::make_tuple(StmtWithASTContext(*S0, AST0->getASTContext()),
109 StmtWithASTContext(*S1, AST1->getASTContext()));
110 }
111
112 // Get a pair of node pointers into the synthesized AST from the given code
113 // snippets. The same matcher is used for both snippets.
114 template <typename MatcherType>
115 std::tuple<StmtWithASTContext, StmtWithASTContext>
makeStmtsclang::ast_matchers::StructuralEquivalenceTest116 makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,
117 TestLanguage Lang, const MatcherType &AMatcher) {
118 return makeStmts(SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);
119 }
120
121 // Convenience function for makeStmts that wraps the code inside a function
122 // body.
123 template <typename MatcherType>
124 std::tuple<StmtWithASTContext, StmtWithASTContext>
makeWrappedStmtsclang::ast_matchers::StructuralEquivalenceTest125 makeWrappedStmts(const std::string &SrcCode0, const std::string &SrcCode1,
126 TestLanguage Lang, const MatcherType &AMatcher) {
127 auto Wrap = [](const std::string &Src) {
128 return "void wrapped() {" + Src + ";}";
129 };
130 return makeStmts(Wrap(SrcCode0), Wrap(SrcCode1), Lang, AMatcher);
131 }
132
testStructuralMatchclang::ast_matchers::StructuralEquivalenceTest133 bool testStructuralMatch(Decl *D0, Decl *D1) {
134 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
135 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
136 StructuralEquivalenceContext Ctx01(
137 D0->getASTContext(), D1->getASTContext(),
138 NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false);
139 StructuralEquivalenceContext Ctx10(
140 D1->getASTContext(), D0->getASTContext(),
141 NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false);
142 bool Eq01 = Ctx01.IsEquivalent(D0, D1);
143 bool Eq10 = Ctx10.IsEquivalent(D1, D0);
144 EXPECT_EQ(Eq01, Eq10);
145 return Eq01;
146 }
147
testStructuralMatchclang::ast_matchers::StructuralEquivalenceTest148 bool testStructuralMatch(StmtWithASTContext S0, StmtWithASTContext S1) {
149 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
150 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
151 StructuralEquivalenceContext Ctx01(
152 *S0.Context, *S1.Context, NonEquivalentDecls01,
153 StructuralEquivalenceKind::Default, false, false);
154 StructuralEquivalenceContext Ctx10(
155 *S1.Context, *S0.Context, NonEquivalentDecls10,
156 StructuralEquivalenceKind::Default, false, false);
157 bool Eq01 = Ctx01.IsEquivalent(S0.S, S1.S);
158 bool Eq10 = Ctx10.IsEquivalent(S1.S, S0.S);
159 EXPECT_EQ(Eq01, Eq10);
160 return Eq01;
161 }
162
163 bool
testStructuralMatchclang::ast_matchers::StructuralEquivalenceTest164 testStructuralMatch(std::tuple<StmtWithASTContext, StmtWithASTContext> t) {
165 return testStructuralMatch(get<0>(t), get<1>(t));
166 }
167
testStructuralMatchclang::ast_matchers::StructuralEquivalenceTest168 bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
169 return testStructuralMatch(get<0>(t), get<1>(t));
170 }
171 };
172
TEST_F(StructuralEquivalenceTest,Int)173 TEST_F(StructuralEquivalenceTest, Int) {
174 auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX03);
175 EXPECT_TRUE(testStructuralMatch(Decls));
176 }
177
TEST_F(StructuralEquivalenceTest,IntVsSignedInt)178 TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
179 auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX03);
180 EXPECT_TRUE(testStructuralMatch(Decls));
181 }
182
TEST_F(StructuralEquivalenceTest,Char)183 TEST_F(StructuralEquivalenceTest, Char) {
184 auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX03);
185 EXPECT_TRUE(testStructuralMatch(Decls));
186 }
187
188 // This test is disabled for now.
189 // FIXME Whether this is equivalent is dependendant on the target.
TEST_F(StructuralEquivalenceTest,DISABLED_CharVsSignedChar)190 TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
191 auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX03);
192 EXPECT_FALSE(testStructuralMatch(Decls));
193 }
194
TEST_F(StructuralEquivalenceTest,ForwardRecordDecl)195 TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
196 auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX03);
197 EXPECT_TRUE(testStructuralMatch(Decls));
198 }
199
TEST_F(StructuralEquivalenceTest,IntVsSignedIntInStruct)200 TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
201 auto Decls = makeNamedDecls("struct foo { int x; };",
202 "struct foo { signed int x; };", Lang_CXX03);
203 EXPECT_TRUE(testStructuralMatch(Decls));
204 }
205
TEST_F(StructuralEquivalenceTest,CharVsSignedCharInStruct)206 TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
207 auto Decls = makeNamedDecls("struct foo { char x; };",
208 "struct foo { signed char x; };", Lang_CXX03);
209 EXPECT_FALSE(testStructuralMatch(Decls));
210 }
211
TEST_F(StructuralEquivalenceTest,IntVsSignedIntTemplateSpec)212 TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
213 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
214 R"(template <class T> struct foo; template<> struct foo<int>{};)",
215 R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
216 Lang_CXX03, classTemplateSpecializationDecl());
217 auto Spec0 = get<0>(Decls);
218 auto Spec1 = get<1>(Decls);
219 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
220 }
221
TEST_F(StructuralEquivalenceTest,CharVsSignedCharTemplateSpec)222 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
223 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
224 R"(template <class T> struct foo; template<> struct foo<char>{};)",
225 R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
226 Lang_CXX03, classTemplateSpecializationDecl());
227 auto Spec0 = get<0>(Decls);
228 auto Spec1 = get<1>(Decls);
229 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
230 }
231
TEST_F(StructuralEquivalenceTest,CharVsSignedCharTemplateSpecWithInheritance)232 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
233 auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
234 R"(
235 struct true_type{};
236 template <class T> struct foo;
237 template<> struct foo<char> : true_type {};
238 )",
239 R"(
240 struct true_type{};
241 template <class T> struct foo;
242 template<> struct foo<signed char> : true_type {};
243 )",
244 Lang_CXX03, classTemplateSpecializationDecl());
245 EXPECT_FALSE(testStructuralMatch(Decls));
246 }
247
248 // This test is disabled for now.
249 // FIXME Enable it, once the check is implemented.
TEST_F(StructuralEquivalenceTest,DISABLED_WrongOrderInNamespace)250 TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
251 auto Code =
252 R"(
253 namespace NS {
254 template <class T> class Base {
255 int a;
256 };
257 class Derived : Base<Derived> {
258 };
259 }
260 void foo(NS::Derived &);
261 )";
262 auto Decls = makeNamedDecls(Code, Code, Lang_CXX03);
263
264 NamespaceDecl *NS =
265 LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
266 ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
267 get<1>(Decls), classTemplateDecl(hasName("Base")));
268
269 // Reorder the decls, move the TD to the last place in the DC.
270 NS->removeDecl(TD);
271 NS->addDeclInternal(TD);
272
273 EXPECT_FALSE(testStructuralMatch(Decls));
274 }
275
TEST_F(StructuralEquivalenceTest,WrongOrderOfFieldsInClass)276 TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
277 auto Code = "class X { int a; int b; };";
278 auto Decls = makeNamedDecls(Code, Code, Lang_CXX03, "X");
279
280 CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
281 get<1>(Decls), cxxRecordDecl(hasName("X")));
282 FieldDecl *FD =
283 FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
284
285 // Reorder the FieldDecls
286 RD->removeDecl(FD);
287 RD->addDeclInternal(FD);
288
289 EXPECT_FALSE(testStructuralMatch(Decls));
290 }
291
292 struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
293 };
294
TEST_F(StructuralEquivalenceFunctionTest,TemplateVsNonTemplate)295 TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {
296 auto t = makeNamedDecls("void foo();", "template<class T> void foo();",
297 Lang_CXX03);
298 EXPECT_FALSE(testStructuralMatch(t));
299 }
300
TEST_F(StructuralEquivalenceFunctionTest,DifferentOperators)301 TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) {
302 auto t = makeDecls<FunctionDecl>(
303 "struct X{}; bool operator<(X, X);", "struct X{}; bool operator==(X, X);",
304 Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")),
305 functionDecl(hasOverloadedOperatorName("==")));
306 EXPECT_FALSE(testStructuralMatch(t));
307 }
308
TEST_F(StructuralEquivalenceFunctionTest,SameOperators)309 TEST_F(StructuralEquivalenceFunctionTest, SameOperators) {
310 auto t = makeDecls<FunctionDecl>(
311 "struct X{}; bool operator<(X, X);", "struct X{}; bool operator<(X, X);",
312 Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")),
313 functionDecl(hasOverloadedOperatorName("<")));
314 EXPECT_TRUE(testStructuralMatch(t));
315 }
316
TEST_F(StructuralEquivalenceFunctionTest,CtorVsDtor)317 TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) {
318 auto t = makeDecls<FunctionDecl>("struct X{ X(); };", "struct X{ ~X(); };",
319 Lang_CXX03, cxxConstructorDecl(),
320 cxxDestructorDecl());
321 EXPECT_FALSE(testStructuralMatch(t));
322 }
323
TEST_F(StructuralEquivalenceFunctionTest,ParamConstWithRef)324 TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
325 auto t =
326 makeNamedDecls("void foo(int&);", "void foo(const int&);", Lang_CXX03);
327 EXPECT_FALSE(testStructuralMatch(t));
328 }
329
TEST_F(StructuralEquivalenceFunctionTest,ParamConstSimple)330 TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {
331 auto t = makeNamedDecls("void foo(int);", "void foo(const int);", Lang_CXX03);
332 EXPECT_TRUE(testStructuralMatch(t));
333 // consider this OK
334 }
335
TEST_F(StructuralEquivalenceFunctionTest,Throw)336 TEST_F(StructuralEquivalenceFunctionTest, Throw) {
337 auto t = makeNamedDecls("void foo();", "void foo() throw();", Lang_CXX03);
338 EXPECT_FALSE(testStructuralMatch(t));
339 }
340
TEST_F(StructuralEquivalenceFunctionTest,Noexcept)341 TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {
342 auto t = makeNamedDecls("void foo();",
343 "void foo() noexcept;", Lang_CXX11);
344 EXPECT_FALSE(testStructuralMatch(t));
345 }
346
TEST_F(StructuralEquivalenceFunctionTest,ThrowVsNoexcept)347 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {
348 auto t = makeNamedDecls("void foo() throw();",
349 "void foo() noexcept;", Lang_CXX11);
350 EXPECT_FALSE(testStructuralMatch(t));
351 }
352
TEST_F(StructuralEquivalenceFunctionTest,ThrowVsNoexceptFalse)353 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {
354 auto t = makeNamedDecls("void foo() throw();",
355 "void foo() noexcept(false);", Lang_CXX11);
356 EXPECT_FALSE(testStructuralMatch(t));
357 }
358
TEST_F(StructuralEquivalenceFunctionTest,ThrowVsNoexceptTrue)359 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {
360 auto t = makeNamedDecls("void foo() throw();",
361 "void foo() noexcept(true);", Lang_CXX11);
362 EXPECT_FALSE(testStructuralMatch(t));
363 }
364
TEST_F(StructuralEquivalenceFunctionTest,NoexceptNonMatch)365 TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) {
366 auto t = makeNamedDecls("void foo() noexcept(false);",
367 "void foo() noexcept(true);", Lang_CXX11);
368 EXPECT_FALSE(testStructuralMatch(t));
369 }
370
TEST_F(StructuralEquivalenceFunctionTest,NoexceptMatch)371 TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {
372 auto t = makeNamedDecls("void foo() noexcept(false);",
373 "void foo() noexcept(false);", Lang_CXX11);
374 EXPECT_TRUE(testStructuralMatch(t));
375 }
376
TEST_F(StructuralEquivalenceFunctionTest,NoexceptVsNoexceptFalse)377 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {
378 auto t = makeNamedDecls("void foo() noexcept;",
379 "void foo() noexcept(false);", Lang_CXX11);
380 EXPECT_FALSE(testStructuralMatch(t));
381 }
382
TEST_F(StructuralEquivalenceFunctionTest,NoexceptVsNoexceptTrue)383 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {
384 auto t = makeNamedDecls("void foo() noexcept;",
385 "void foo() noexcept(true);", Lang_CXX11);
386 EXPECT_FALSE(testStructuralMatch(t));
387 }
388
TEST_F(StructuralEquivalenceFunctionTest,ReturnType)389 TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {
390 auto t = makeNamedDecls("char foo();", "int foo();", Lang_CXX03);
391 EXPECT_FALSE(testStructuralMatch(t));
392 }
393
TEST_F(StructuralEquivalenceFunctionTest,ReturnConst)394 TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {
395 auto t = makeNamedDecls("char foo();", "const char foo();", Lang_CXX03);
396 EXPECT_FALSE(testStructuralMatch(t));
397 }
398
TEST_F(StructuralEquivalenceFunctionTest,ReturnRef)399 TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {
400 auto t = makeNamedDecls("char &foo();",
401 "char &&foo();", Lang_CXX11);
402 EXPECT_FALSE(testStructuralMatch(t));
403 }
404
TEST_F(StructuralEquivalenceFunctionTest,ParamCount)405 TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {
406 auto t = makeNamedDecls("void foo(int);", "void foo(int, int);", Lang_CXX03);
407 EXPECT_FALSE(testStructuralMatch(t));
408 }
409
TEST_F(StructuralEquivalenceFunctionTest,ParamType)410 TEST_F(StructuralEquivalenceFunctionTest, ParamType) {
411 auto t = makeNamedDecls("void foo(int);", "void foo(char);", Lang_CXX03);
412 EXPECT_FALSE(testStructuralMatch(t));
413 }
414
TEST_F(StructuralEquivalenceFunctionTest,ParamName)415 TEST_F(StructuralEquivalenceFunctionTest, ParamName) {
416 auto t = makeNamedDecls("void foo(int a);", "void foo(int b);", Lang_CXX03);
417 EXPECT_TRUE(testStructuralMatch(t));
418 }
419
TEST_F(StructuralEquivalenceFunctionTest,Variadic)420 TEST_F(StructuralEquivalenceFunctionTest, Variadic) {
421 auto t =
422 makeNamedDecls("void foo(int x...);", "void foo(int x);", Lang_CXX03);
423 EXPECT_FALSE(testStructuralMatch(t));
424 }
425
TEST_F(StructuralEquivalenceFunctionTest,ParamPtr)426 TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {
427 auto t = makeNamedDecls("void foo(int *);", "void foo(int);", Lang_CXX03);
428 EXPECT_FALSE(testStructuralMatch(t));
429 }
430
TEST_F(StructuralEquivalenceFunctionTest,NameInParen)431 TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {
432 auto t = makeNamedDecls("void ((foo))();", "void foo();", Lang_CXX03);
433 EXPECT_TRUE(testStructuralMatch(t));
434 }
435
TEST_F(StructuralEquivalenceFunctionTest,NameInParenWithExceptionSpec)436 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {
437 auto t = makeNamedDecls(
438 "void (foo)() throw(int);",
439 "void (foo)() noexcept;",
440 Lang_CXX11);
441 EXPECT_FALSE(testStructuralMatch(t));
442 }
443
TEST_F(StructuralEquivalenceFunctionTest,NameInParenWithConst)444 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
445 auto t = makeNamedDecls(
446 "struct A { void (foo)() const; };",
447 "struct A { void (foo)(); };",
448 Lang_CXX11);
449 EXPECT_FALSE(testStructuralMatch(t));
450 }
451
TEST_F(StructuralEquivalenceFunctionTest,FunctionsWithDifferentNoreturnAttr)452 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
453 auto t = makeNamedDecls("__attribute__((noreturn)) void foo();",
454 " void foo();", Lang_C99);
455 EXPECT_TRUE(testStructuralMatch(t));
456 }
457
TEST_F(StructuralEquivalenceFunctionTest,FunctionsWithDifferentCallingConventions)458 TEST_F(StructuralEquivalenceFunctionTest,
459 FunctionsWithDifferentCallingConventions) {
460 // These attributes may not be available on certain platforms.
461 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
462 llvm::Triple::x86_64)
463 return;
464 auto t = makeNamedDecls("__attribute__((preserve_all)) void foo();",
465 "__attribute__((ms_abi)) void foo();", Lang_C99);
466 EXPECT_FALSE(testStructuralMatch(t));
467 }
468
TEST_F(StructuralEquivalenceFunctionTest,FunctionsWithDifferentSavedRegsAttr)469 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {
470 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=
471 llvm::Triple::x86_64)
472 return;
473 auto t = makeNamedDecls(
474 "__attribute__((no_caller_saved_registers)) void foo();",
475 " void foo();", Lang_C99);
476 EXPECT_FALSE(testStructuralMatch(t));
477 }
478
479 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
480 };
481
TEST_F(StructuralEquivalenceCXXMethodTest,Virtual)482 TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {
483 auto t = makeDecls<CXXMethodDecl>("struct X { void foo(); };",
484 "struct X { virtual void foo(); };",
485 Lang_CXX03, cxxMethodDecl(hasName("foo")));
486 EXPECT_FALSE(testStructuralMatch(t));
487 }
488
TEST_F(StructuralEquivalenceCXXMethodTest,Pure)489 TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {
490 auto t = makeNamedDecls("struct X { virtual void foo(); };",
491 "struct X { virtual void foo() = 0; };", Lang_CXX03);
492 EXPECT_FALSE(testStructuralMatch(t));
493 }
494
TEST_F(StructuralEquivalenceCXXMethodTest,DISABLED_Final)495 TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {
496 // The final-ness is not checked yet.
497 auto t =
498 makeNamedDecls("struct X { virtual void foo(); };",
499 "struct X { virtual void foo() final; };", Lang_CXX03);
500 EXPECT_FALSE(testStructuralMatch(t));
501 }
502
TEST_F(StructuralEquivalenceCXXMethodTest,Const)503 TEST_F(StructuralEquivalenceCXXMethodTest, Const) {
504 auto t = makeNamedDecls("struct X { void foo(); };",
505 "struct X { void foo() const; };", Lang_CXX03);
506 EXPECT_FALSE(testStructuralMatch(t));
507 }
508
TEST_F(StructuralEquivalenceCXXMethodTest,Static)509 TEST_F(StructuralEquivalenceCXXMethodTest, Static) {
510 auto t = makeNamedDecls("struct X { void foo(); };",
511 "struct X { static void foo(); };", Lang_CXX03);
512 EXPECT_FALSE(testStructuralMatch(t));
513 }
514
TEST_F(StructuralEquivalenceCXXMethodTest,Ref1)515 TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {
516 auto t = makeNamedDecls("struct X { void foo(); };",
517 "struct X { void foo() &&; };", Lang_CXX11);
518 EXPECT_FALSE(testStructuralMatch(t));
519 }
520
TEST_F(StructuralEquivalenceCXXMethodTest,Ref2)521 TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {
522 auto t = makeNamedDecls("struct X { void foo() &; };",
523 "struct X { void foo() &&; };", Lang_CXX11);
524 EXPECT_FALSE(testStructuralMatch(t));
525 }
526
TEST_F(StructuralEquivalenceCXXMethodTest,AccessSpecifier)527 TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {
528 auto t = makeDecls<CXXMethodDecl>("struct X { public: void foo(); };",
529 "struct X { private: void foo(); };",
530 Lang_CXX03, cxxMethodDecl(hasName("foo")));
531 EXPECT_FALSE(testStructuralMatch(t));
532 }
533
TEST_F(StructuralEquivalenceCXXMethodTest,Delete)534 TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {
535 auto t = makeNamedDecls("struct X { void foo(); };",
536 "struct X { void foo() = delete; };", Lang_CXX11);
537 EXPECT_FALSE(testStructuralMatch(t));
538 }
539
TEST_F(StructuralEquivalenceCXXMethodTest,Constructor)540 TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {
541 auto t = makeDecls<FunctionDecl>("void foo();", "struct foo { foo(); };",
542 Lang_CXX03, functionDecl(hasName("foo")),
543 cxxConstructorDecl(hasName("foo")));
544 EXPECT_FALSE(testStructuralMatch(t));
545 }
546
TEST_F(StructuralEquivalenceCXXMethodTest,ConstructorParam)547 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {
548 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
549 "struct X { X(int); };", Lang_CXX03,
550 cxxConstructorDecl(hasName("X")));
551 EXPECT_FALSE(testStructuralMatch(t));
552 }
553
TEST_F(StructuralEquivalenceCXXMethodTest,ConstructorExplicit)554 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {
555 auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",
556 "struct X { explicit X(int); };",
557 Lang_CXX11,
558 cxxConstructorDecl(hasName("X")));
559 EXPECT_FALSE(testStructuralMatch(t));
560 }
561
TEST_F(StructuralEquivalenceCXXMethodTest,ConstructorDefault)562 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {
563 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",
564 "struct X { X() = default; };",
565 Lang_CXX11,
566 cxxConstructorDecl(hasName("X")));
567 EXPECT_FALSE(testStructuralMatch(t));
568 }
569
TEST_F(StructuralEquivalenceCXXMethodTest,Conversion)570 TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {
571 auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",
572 "struct X { operator char(); };",
573 Lang_CXX11,
574 cxxConversionDecl());
575 EXPECT_FALSE(testStructuralMatch(t));
576 }
577
TEST_F(StructuralEquivalenceCXXMethodTest,Operator)578 TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {
579 auto t =
580 makeDecls<FunctionDecl>("struct X { int operator +(int); };",
581 "struct X { int operator -(int); };", Lang_CXX03,
582 functionDecl(hasOverloadedOperatorName("+")),
583 functionDecl(hasOverloadedOperatorName("-")));
584 EXPECT_FALSE(testStructuralMatch(t));
585 }
586
TEST_F(StructuralEquivalenceCXXMethodTest,OutOfClass1)587 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {
588 auto t = makeDecls<FunctionDecl>(
589 "struct X { virtual void f(); }; void X::f() { }",
590 "struct X { virtual void f() { }; };", Lang_CXX03,
591 functionDecl(allOf(hasName("f"), isDefinition())));
592 EXPECT_TRUE(testStructuralMatch(t));
593 }
594
TEST_F(StructuralEquivalenceCXXMethodTest,OutOfClass2)595 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
596 auto t = makeDecls<FunctionDecl>(
597 "struct X { virtual void f(); }; void X::f() { }",
598 "struct X { void f(); }; void X::f() { }", Lang_CXX03,
599 functionDecl(allOf(hasName("f"), isDefinition())));
600 EXPECT_FALSE(testStructuralMatch(t));
601 }
602
603 struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
604 // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
getRecordDeclclang::ast_matchers::StructuralEquivalenceRecordTest605 RecordDecl *getRecordDecl(FieldDecl *FD) {
606 auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());
607 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
608 };
609 };
610
TEST_F(StructuralEquivalenceRecordTest,Name)611 TEST_F(StructuralEquivalenceRecordTest, Name) {
612 auto t = makeDecls<CXXRecordDecl>("struct A{ };", "struct B{ };", Lang_CXX03,
613 cxxRecordDecl(hasName("A")),
614 cxxRecordDecl(hasName("B")));
615 EXPECT_FALSE(testStructuralMatch(t));
616 }
617
TEST_F(StructuralEquivalenceRecordTest,Fields)618 TEST_F(StructuralEquivalenceRecordTest, Fields) {
619 auto t = makeNamedDecls("struct foo{ int x; };", "struct foo{ char x; };",
620 Lang_CXX03);
621 EXPECT_FALSE(testStructuralMatch(t));
622 }
623
TEST_F(StructuralEquivalenceRecordTest,DISABLED_Methods)624 TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {
625 // Currently, methods of a class are not checked at class equivalence.
626 auto t = makeNamedDecls("struct foo{ int x(); };", "struct foo{ char x(); };",
627 Lang_CXX03);
628 EXPECT_FALSE(testStructuralMatch(t));
629 }
630
TEST_F(StructuralEquivalenceRecordTest,Bases)631 TEST_F(StructuralEquivalenceRecordTest, Bases) {
632 auto t = makeNamedDecls("struct A{ }; struct foo: A { };",
633 "struct B{ }; struct foo: B { };", Lang_CXX03);
634 EXPECT_FALSE(testStructuralMatch(t));
635 }
636
TEST_F(StructuralEquivalenceRecordTest,InheritanceVirtual)637 TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {
638 auto t =
639 makeNamedDecls("struct A{ }; struct foo: A { };",
640 "struct A{ }; struct foo: virtual A { };", Lang_CXX03);
641 EXPECT_FALSE(testStructuralMatch(t));
642 }
643
TEST_F(StructuralEquivalenceRecordTest,DISABLED_InheritanceType)644 TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {
645 // Access specifier in inheritance is not checked yet.
646 auto t =
647 makeNamedDecls("struct A{ }; struct foo: public A { };",
648 "struct A{ }; struct foo: private A { };", Lang_CXX03);
649 EXPECT_FALSE(testStructuralMatch(t));
650 }
651
TEST_F(StructuralEquivalenceRecordTest,Match)652 TEST_F(StructuralEquivalenceRecordTest, Match) {
653 auto Code = R"(
654 struct A{ };
655 struct B{ };
656 struct foo: A, virtual B {
657 void x();
658 int a;
659 };
660 )";
661 auto t = makeNamedDecls(Code, Code, Lang_CXX03);
662 EXPECT_TRUE(testStructuralMatch(t));
663 }
664
TEST_F(StructuralEquivalenceRecordTest,UnnamedRecordsShouldBeInequivalent)665 TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
666 auto t = makeTuDecls(
667 R"(
668 struct A {
669 struct {
670 struct A *next;
671 } entry0;
672 struct {
673 struct A *next;
674 } entry1;
675 };
676 )",
677 "", Lang_C99);
678 auto *TU = get<0>(t);
679 auto *Entry0 =
680 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));
681 auto *Entry1 =
682 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));
683 auto *R0 = getRecordDecl(Entry0);
684 auto *R1 = getRecordDecl(Entry1);
685
686 ASSERT_NE(R0, R1);
687 EXPECT_TRUE(testStructuralMatch(R0, R0));
688 EXPECT_TRUE(testStructuralMatch(R1, R1));
689 EXPECT_FALSE(testStructuralMatch(R0, R1));
690 }
691
TEST_F(StructuralEquivalenceRecordTest,AnonymousRecordsShouldBeInequivalent)692 TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
693 auto t = makeTuDecls(
694 R"(
695 struct X {
696 struct {
697 int a;
698 };
699 struct {
700 int b;
701 };
702 };
703 )",
704 "", Lang_C99);
705 auto *TU = get<0>(t);
706 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
707 TU, indirectFieldDecl(hasName("a")));
708 auto *FA = cast<FieldDecl>(A->chain().front());
709 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
710 auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(
711 TU, indirectFieldDecl(hasName("b")));
712 auto *FB = cast<FieldDecl>(B->chain().front());
713 RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();
714
715 ASSERT_NE(RA, RB);
716 EXPECT_TRUE(testStructuralMatch(RA, RA));
717 EXPECT_TRUE(testStructuralMatch(RB, RB));
718 EXPECT_FALSE(testStructuralMatch(RA, RB));
719 }
720
TEST_F(StructuralEquivalenceRecordTest,RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent)721 TEST_F(StructuralEquivalenceRecordTest,
722 RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
723 auto t = makeTuDecls(
724 R"(
725 struct X {
726 struct { int a; };
727 struct { int b; };
728 };
729 )",
730 R"(
731 struct X { // The order is reversed.
732 struct { int b; };
733 struct { int a; };
734 };
735 )",
736 Lang_C99);
737
738 auto *TU = get<0>(t);
739 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
740 TU, indirectFieldDecl(hasName("a")));
741 auto *FA = cast<FieldDecl>(A->chain().front());
742 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
743
744 auto *TU1 = get<1>(t);
745 auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(
746 TU1, indirectFieldDecl(hasName("a")));
747 auto *FA1 = cast<FieldDecl>(A1->chain().front());
748 RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();
749
750 RecordDecl *X =
751 FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X")));
752 RecordDecl *X1 =
753 FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X")));
754 ASSERT_NE(X, X1);
755 EXPECT_FALSE(testStructuralMatch(X, X1));
756
757 ASSERT_NE(RA, RA1);
758 EXPECT_TRUE(testStructuralMatch(RA, RA));
759 EXPECT_TRUE(testStructuralMatch(RA1, RA1));
760 EXPECT_FALSE(testStructuralMatch(RA1, RA));
761 }
762
TEST_F(StructuralEquivalenceRecordTest,UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined)763 TEST_F(StructuralEquivalenceRecordTest,
764 UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
765 auto Code =
766 R"(
767 struct A {
768 struct {
769 struct A *next;
770 } entry0;
771 struct {
772 struct A *next;
773 } entry1;
774 };
775 )";
776 auto t = makeTuDecls(Code, Code, Lang_C99);
777
778 auto *FromTU = get<0>(t);
779 auto *Entry1 =
780 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));
781
782 auto *ToTU = get<1>(t);
783 auto *Entry0 =
784 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
785 auto *A =
786 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
787 A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
788 // nullptr. This may be the case during ASTImport.
789
790 auto *R0 = getRecordDecl(Entry0);
791 auto *R1 = getRecordDecl(Entry1);
792
793 ASSERT_NE(R0, R1);
794 EXPECT_TRUE(testStructuralMatch(R0, R0));
795 EXPECT_TRUE(testStructuralMatch(R1, R1));
796 EXPECT_FALSE(testStructuralMatch(R0, R1));
797 }
798
TEST_F(StructuralEquivalenceRecordTest,TemplateVsNonTemplate)799 TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {
800 auto t = makeDecls<CXXRecordDecl>("struct A { };",
801 "template<class T> struct A { };",
802 Lang_CXX03, cxxRecordDecl(hasName("A")));
803 EXPECT_FALSE(testStructuralMatch(t));
804 }
805
TEST_F(StructuralEquivalenceRecordTest,FwdDeclRecordShouldBeEqualWithFwdDeclRecord)806 TEST_F(StructuralEquivalenceRecordTest,
807 FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {
808 auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11);
809 EXPECT_TRUE(testStructuralMatch(t));
810 }
811
TEST_F(StructuralEquivalenceRecordTest,FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition)812 TEST_F(StructuralEquivalenceRecordTest,
813 FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {
814 auto t =
815 makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11);
816 EXPECT_TRUE(testStructuralMatch(t));
817 }
818
TEST_F(StructuralEquivalenceRecordTest,RecordShouldBeEqualWithRecordWhichHasDefinition)819 TEST_F(StructuralEquivalenceRecordTest,
820 RecordShouldBeEqualWithRecordWhichHasDefinition) {
821 auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };",
822 Lang_CXX11);
823 EXPECT_TRUE(testStructuralMatch(t));
824 }
825
TEST_F(StructuralEquivalenceRecordTest,RecordsWithDifferentBody)826 TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {
827 auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };",
828 Lang_CXX11);
829 EXPECT_FALSE(testStructuralMatch(t));
830 }
831
TEST_F(StructuralEquivalenceRecordTest,SameFriendMultipleTimes)832 TEST_F(StructuralEquivalenceRecordTest, SameFriendMultipleTimes) {
833 auto t = makeNamedDecls("struct foo { friend class X; };",
834 "struct foo { friend class X; friend class X; };",
835 Lang_CXX11);
836 EXPECT_FALSE(testStructuralMatch(t));
837 }
838
TEST_F(StructuralEquivalenceRecordTest,SameFriendsDifferentOrder)839 TEST_F(StructuralEquivalenceRecordTest, SameFriendsDifferentOrder) {
840 auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };",
841 "struct foo { friend class Y; friend class X; };",
842 Lang_CXX11);
843 EXPECT_FALSE(testStructuralMatch(t));
844 }
845
TEST_F(StructuralEquivalenceRecordTest,SameFriendsSameOrder)846 TEST_F(StructuralEquivalenceRecordTest, SameFriendsSameOrder) {
847 auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };",
848 "struct foo { friend class X; friend class Y; };",
849 Lang_CXX11);
850 EXPECT_TRUE(testStructuralMatch(t));
851 }
852
853 struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {};
854
TEST_F(StructuralEquivalenceLambdaTest,LambdaClassesWithDifferentMethods)855 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) {
856 // Get the LambdaExprs, unfortunately we can't match directly the underlying
857 // implicit CXXRecordDecl of the Lambda classes.
858 auto t = makeDecls<LambdaExpr>(
859 "void f() { auto L0 = [](int){}; }",
860 "void f() { auto L1 = [](){}; }",
861 Lang_CXX11,
862 lambdaExpr(),
863 lambdaExpr());
864 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
865 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
866 EXPECT_FALSE(testStructuralMatch(L0, L1));
867 }
868
TEST_F(StructuralEquivalenceLambdaTest,LambdaClassesWithEqMethods)869 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) {
870 auto t = makeDecls<LambdaExpr>(
871 "void f() { auto L0 = [](int){}; }",
872 "void f() { auto L1 = [](int){}; }",
873 Lang_CXX11,
874 lambdaExpr(),
875 lambdaExpr());
876 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
877 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
878 EXPECT_TRUE(testStructuralMatch(L0, L1));
879 }
880
TEST_F(StructuralEquivalenceLambdaTest,LambdaClassesWithDifferentFields)881 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) {
882 auto t = makeDecls<LambdaExpr>(
883 "void f() { char* X; auto L0 = [X](){}; }",
884 "void f() { float X; auto L1 = [X](){}; }",
885 Lang_CXX11,
886 lambdaExpr(),
887 lambdaExpr());
888 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
889 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
890 EXPECT_FALSE(testStructuralMatch(L0, L1));
891 }
892
TEST_F(StructuralEquivalenceLambdaTest,LambdaClassesWithEqFields)893 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) {
894 auto t = makeDecls<LambdaExpr>(
895 "void f() { float X; auto L0 = [X](){}; }",
896 "void f() { float X; auto L1 = [X](){}; }",
897 Lang_CXX11,
898 lambdaExpr(),
899 lambdaExpr());
900 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();
901 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();
902 EXPECT_TRUE(testStructuralMatch(L0, L1));
903 }
904
TEST_F(StructuralEquivalenceTest,CompareSameDeclWithMultiple)905 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
906 auto t = makeNamedDecls("struct A{ }; struct B{ }; void foo(A a, A b);",
907 "struct A{ }; struct B{ }; void foo(A a, B b);",
908 Lang_CXX03);
909 EXPECT_FALSE(testStructuralMatch(t));
910 }
911
TEST_F(StructuralEquivalenceTest,ExplicitBoolDifferent)912 TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {
913 auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};",
914 "struct foo {explicit(true) foo(int);};", Lang_CXX20);
915 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
916 get<0>(Decls), cxxConstructorDecl(hasName("foo")));
917 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
918 get<1>(Decls), cxxConstructorDecl(hasName("foo")));
919 EXPECT_FALSE(testStructuralMatch(First, Second));
920 }
921
TEST_F(StructuralEquivalenceTest,ExplicitBoolSame)922 TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {
923 auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};",
924 "struct foo {explicit(true) foo(int);};", Lang_CXX20);
925 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
926 get<0>(Decls), cxxConstructorDecl(hasName("foo")));
927 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
928 get<1>(Decls), cxxConstructorDecl(hasName("foo")));
929 EXPECT_TRUE(testStructuralMatch(First, Second));
930 }
931
932 struct StructuralEquivalenceRecordContextTest : StructuralEquivalenceTest {};
933
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceNoVsNamed)934 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsNamed) {
935 auto Decls =
936 makeNamedDecls("class X;", "namespace N { class X; }", Lang_CXX03, "X");
937 EXPECT_FALSE(testStructuralMatch(Decls));
938 }
939
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceNamedVsNamed)940 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsNamed) {
941 auto Decls = makeNamedDecls("namespace A { class X; }",
942 "namespace B { class X; }", Lang_CXX03, "X");
943 EXPECT_FALSE(testStructuralMatch(Decls));
944 }
945
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceAnonVsNamed)946 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsNamed) {
947 auto Decls = makeNamedDecls("namespace { class X; }",
948 "namespace N { class X; }", Lang_CXX03, "X");
949 EXPECT_FALSE(testStructuralMatch(Decls));
950 }
951
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceNoVsAnon)952 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsAnon) {
953 auto Decls =
954 makeNamedDecls("class X;", "namespace { class X; }", Lang_CXX03, "X");
955 EXPECT_FALSE(testStructuralMatch(Decls));
956 }
957
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceAnonVsAnon)958 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnon) {
959 auto Decls = makeNamedDecls("namespace { class X; }",
960 "namespace { class X; }", Lang_CXX03, "X");
961 EXPECT_TRUE(testStructuralMatch(Decls));
962 }
963
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceAnonVsAnonAnon)964 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnonAnon) {
965 auto Decls =
966 makeNamedDecls("namespace { class X; }",
967 "namespace { namespace { class X; } }", Lang_CXX03, "X");
968 EXPECT_FALSE(testStructuralMatch(Decls));
969 }
970
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceNamedNamedVsNamedNamed)971 TEST_F(StructuralEquivalenceRecordContextTest,
972 NamespaceNamedNamedVsNamedNamed) {
973 auto Decls = makeNamedDecls("namespace A { namespace N { class X; } }",
974 "namespace B { namespace N { class X; } }",
975 Lang_CXX03, "X");
976 EXPECT_FALSE(testStructuralMatch(Decls));
977 }
978
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceNamedVsInline)979 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsInline) {
980 auto Decls = makeNamedDecls("namespace A { namespace A { class X; } }",
981 "namespace A { inline namespace A { class X; } }",
982 Lang_CXX17, "X");
983 EXPECT_FALSE(testStructuralMatch(Decls));
984 }
985
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceInlineVsInline)986 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineVsInline) {
987 auto Decls = makeNamedDecls("namespace A { inline namespace A { class X; } }",
988 "namespace A { inline namespace B { class X; } }",
989 Lang_CXX17, "X");
990 EXPECT_TRUE(testStructuralMatch(Decls));
991 }
992
TEST_F(StructuralEquivalenceRecordContextTest,NamespaceInlineTopLevel)993 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineTopLevel) {
994 auto Decls =
995 makeNamedDecls("inline namespace A { class X; } }",
996 "inline namespace B { class X; } }", Lang_CXX17, "X");
997 EXPECT_TRUE(testStructuralMatch(Decls));
998 }
999
TEST_F(StructuralEquivalenceRecordContextTest,TransparentContext)1000 TEST_F(StructuralEquivalenceRecordContextTest, TransparentContext) {
1001 auto Decls =
1002 makeNamedDecls("extern \"C\" { class X; }", "class X;", Lang_CXX03, "X");
1003 EXPECT_TRUE(testStructuralMatch(Decls));
1004 }
1005
TEST_F(StructuralEquivalenceRecordContextTest,TransparentContextNE)1006 TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextNE) {
1007 auto Decls = makeNamedDecls("extern \"C\" { class X; }",
1008 "namespace { class X; }", Lang_CXX03, "X");
1009 EXPECT_FALSE(testStructuralMatch(Decls));
1010 }
1011
TEST_F(StructuralEquivalenceRecordContextTest,TransparentContextInNamespace)1012 TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextInNamespace) {
1013 auto Decls = makeNamedDecls("extern \"C\" { namespace N { class X; } }",
1014 "namespace N { extern \"C\" { class X; } }",
1015 Lang_CXX03, "X");
1016 EXPECT_TRUE(testStructuralMatch(Decls));
1017 }
1018
TEST_F(StructuralEquivalenceTest,NamespaceOfRecordMember)1019 TEST_F(StructuralEquivalenceTest, NamespaceOfRecordMember) {
1020 auto Decls = makeNamedDecls(
1021 R"(
1022 class X;
1023 class Y { X* x; };
1024 )",
1025 R"(
1026 namespace N { class X; }
1027 class Y { N::X* x; };
1028 )",
1029 Lang_CXX03, "Y");
1030 EXPECT_FALSE(testStructuralMatch(Decls));
1031 }
1032
TEST_F(StructuralEquivalenceTest,StructDefinitionInPrototype)1033 TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototype) {
1034 auto Decls =
1035 makeNamedDecls("struct Param { int a; }; void foo(struct Param *p);",
1036 "void foo(struct Param { int a; } *p);", Lang_C89);
1037 EXPECT_TRUE(testStructuralMatch(Decls));
1038 }
1039
TEST_F(StructuralEquivalenceTest,StructDefinitionInPrototypeDifferentName)1040 TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototypeDifferentName) {
1041 auto Decls =
1042 makeNamedDecls("struct Param1 { int a; }; void foo(struct Param1 *p);",
1043 "void foo(struct Param2 { int a; } *p);", Lang_C89);
1044 EXPECT_FALSE(testStructuralMatch(Decls));
1045 }
1046
TEST_F(StructuralEquivalenceRecordContextTest,RecordInsideFunction)1047 TEST_F(StructuralEquivalenceRecordContextTest, RecordInsideFunction) {
1048 auto Decls = makeNamedDecls("struct Param { int a; };",
1049 "void f() { struct Param { int a; }; }", Lang_C89,
1050 "Param");
1051 EXPECT_TRUE(testStructuralMatch(Decls));
1052 }
1053
1054 struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
1055
TEST_F(StructuralEquivalenceEnumTest,FwdDeclEnumShouldBeEqualWithFwdDeclEnum)1056 TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
1057 auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);
1058 EXPECT_TRUE(testStructuralMatch(t));
1059 }
1060
TEST_F(StructuralEquivalenceEnumTest,FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition)1061 TEST_F(StructuralEquivalenceEnumTest,
1062 FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {
1063 auto t =
1064 makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);
1065 EXPECT_TRUE(testStructuralMatch(t));
1066 }
1067
TEST_F(StructuralEquivalenceEnumTest,EnumShouldBeEqualWithEnumWhichHasDefinition)1068 TEST_F(StructuralEquivalenceEnumTest,
1069 EnumShouldBeEqualWithEnumWhichHasDefinition) {
1070 auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",
1071 Lang_CXX11);
1072 EXPECT_TRUE(testStructuralMatch(t));
1073 }
1074
TEST_F(StructuralEquivalenceEnumTest,EnumsWithDifferentBody)1075 TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {
1076 auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",
1077 Lang_CXX11);
1078 EXPECT_FALSE(testStructuralMatch(t));
1079 }
1080
1081 struct StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {};
1082
TEST_F(StructuralEquivalenceEnumConstantTest,EnumConstantsWithSameValues)1083 TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithSameValues) {
1084 auto t = makeNamedDecls("enum foo { foo = 1 };", "enum foo { foo = 1 };",
1085 Lang_C89);
1086 EXPECT_TRUE(testStructuralMatch(t));
1087 }
1088
TEST_F(StructuralEquivalenceEnumConstantTest,EnumConstantsWithDifferentValues)1089 TEST_F(StructuralEquivalenceEnumConstantTest,
1090 EnumConstantsWithDifferentValues) {
1091 auto t =
1092 makeNamedDecls("enum e { foo = 1 };", "enum e { foo = 2 };", Lang_C89);
1093 EXPECT_FALSE(testStructuralMatch(t));
1094 }
1095
TEST_F(StructuralEquivalenceEnumConstantTest,EnumConstantsWithDifferentExprsButSameValues)1096 TEST_F(StructuralEquivalenceEnumConstantTest,
1097 EnumConstantsWithDifferentExprsButSameValues) {
1098 auto t = makeNamedDecls("enum e { foo = 1 + 1 };", "enum e { foo = 2 };",
1099 Lang_CXX11);
1100 EXPECT_FALSE(testStructuralMatch(t));
1101 }
1102
TEST_F(StructuralEquivalenceEnumConstantTest,EnumConstantsWithDifferentSignedness)1103 TEST_F(StructuralEquivalenceEnumConstantTest,
1104 EnumConstantsWithDifferentSignedness) {
1105 auto t = makeNamedDecls("enum e : unsigned { foo = 1 };",
1106 "enum e : int { foo = 1 };", Lang_CXX11);
1107 EXPECT_FALSE(testStructuralMatch(t));
1108 }
1109
TEST_F(StructuralEquivalenceEnumConstantTest,EnumConstantsWithDifferentWidth)1110 TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentWidth) {
1111 auto t = makeNamedDecls("enum e : short { foo = 1 };",
1112 "enum e : int { foo = 1 };", Lang_CXX11);
1113 EXPECT_FALSE(testStructuralMatch(t));
1114 }
1115
TEST_F(StructuralEquivalenceEnumConstantTest,EnumConstantsWithDifferentName)1116 TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentName) {
1117 auto t =
1118 makeDecls<EnumConstantDecl>("enum e { foo = 1 };", "enum e { bar = 1 };",
1119 Lang_CXX11, enumConstantDecl());
1120 EXPECT_FALSE(testStructuralMatch(t));
1121 }
1122
1123 struct StructuralEquivalenceObjCCategoryTest : StructuralEquivalenceTest {};
1124
TEST_F(StructuralEquivalenceObjCCategoryTest,MatchinCategoryNames)1125 TEST_F(StructuralEquivalenceObjCCategoryTest, MatchinCategoryNames) {
1126 auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",
1127 "@interface A @end @interface A(X) @end",
1128 Lang_OBJC, objcCategoryDecl());
1129 EXPECT_TRUE(testStructuralMatch(t));
1130 }
1131
TEST_F(StructuralEquivalenceObjCCategoryTest,CategoriesForDifferentClasses)1132 TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesForDifferentClasses) {
1133 auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",
1134 "@interface B @end @interface B(X) @end",
1135 Lang_OBJC, objcCategoryDecl());
1136 EXPECT_FALSE(testStructuralMatch(t));
1137 }
1138
TEST_F(StructuralEquivalenceObjCCategoryTest,CategoriesWithDifferentNames)1139 TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithDifferentNames) {
1140 auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",
1141 "@interface A @end @interface A(Y) @end",
1142 Lang_OBJC, objcCategoryDecl());
1143 EXPECT_FALSE(testStructuralMatch(t));
1144 }
1145
TEST_F(StructuralEquivalenceObjCCategoryTest,CategoryAndExtension)1146 TEST_F(StructuralEquivalenceObjCCategoryTest, CategoryAndExtension) {
1147 auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",
1148 "@interface A @end @interface A() @end",
1149 Lang_OBJC, objcCategoryDecl());
1150 EXPECT_FALSE(testStructuralMatch(t));
1151 }
1152
TEST_F(StructuralEquivalenceObjCCategoryTest,MatchingProtocols)1153 TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingProtocols) {
1154 auto t = makeDecls<ObjCCategoryDecl>(
1155 "@protocol P @end @interface A @end @interface A(X)<P> @end",
1156 "@protocol P @end @interface A @end @interface A(X)<P> @end", Lang_OBJC,
1157 objcCategoryDecl());
1158 EXPECT_TRUE(testStructuralMatch(t));
1159 }
1160
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentProtocols)1161 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocols) {
1162 auto t = makeDecls<ObjCCategoryDecl>(
1163 "@protocol P @end @interface A @end @interface A(X)<P> @end",
1164 "@protocol Q @end @interface A @end @interface A(X)<Q> @end", Lang_OBJC,
1165 objcCategoryDecl());
1166 EXPECT_FALSE(testStructuralMatch(t));
1167 }
1168
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentProtocolsOrder)1169 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocolsOrder) {
1170 auto t = makeDecls<ObjCCategoryDecl>(
1171 "@protocol P @end @protocol Q @end @interface A @end @interface A(X)<P, "
1172 "Q> @end",
1173 "@protocol P @end @protocol Q @end @interface A @end @interface A(X)<Q, "
1174 "P> @end",
1175 Lang_OBJC, objcCategoryDecl());
1176 EXPECT_FALSE(testStructuralMatch(t));
1177 }
1178
TEST_F(StructuralEquivalenceObjCCategoryTest,MatchingIvars)1179 TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingIvars) {
1180 auto t = makeDecls<ObjCCategoryDecl>(
1181 "@interface A @end @interface A() { int x; } @end",
1182 "@interface A @end @interface A() { int x; } @end", Lang_OBJC,
1183 objcCategoryDecl());
1184 EXPECT_TRUE(testStructuralMatch(t));
1185 }
1186
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentIvarName)1187 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarName) {
1188 auto t = makeDecls<ObjCCategoryDecl>(
1189 "@interface A @end @interface A() { int x; } @end",
1190 "@interface A @end @interface A() { int y; } @end", Lang_OBJC,
1191 objcCategoryDecl());
1192 EXPECT_FALSE(testStructuralMatch(t));
1193 }
1194
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentIvarType)1195 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarType) {
1196 auto t = makeDecls<ObjCCategoryDecl>(
1197 "@interface A @end @interface A() { int x; } @end",
1198 "@interface A @end @interface A() { float x; } @end", Lang_OBJC,
1199 objcCategoryDecl());
1200 EXPECT_FALSE(testStructuralMatch(t));
1201 }
1202
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentIvarBitfieldWidth)1203 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarBitfieldWidth) {
1204 auto t = makeDecls<ObjCCategoryDecl>(
1205 "@interface A @end @interface A() { int x: 1; } @end",
1206 "@interface A @end @interface A() { int x: 2; } @end", Lang_OBJC,
1207 objcCategoryDecl());
1208 EXPECT_FALSE(testStructuralMatch(t));
1209 }
1210
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentIvarVisibility)1211 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarVisibility) {
1212 auto t = makeDecls<ObjCCategoryDecl>(
1213 "@interface A @end @interface A() { @public int x; } @end",
1214 "@interface A @end @interface A() { @protected int x; } @end", Lang_OBJC,
1215 objcCategoryDecl());
1216 EXPECT_FALSE(testStructuralMatch(t));
1217 }
1218
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentIvarNumber)1219 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarNumber) {
1220 auto t = makeDecls<ObjCCategoryDecl>(
1221 "@interface A @end @interface A() { int x; } @end",
1222 "@interface A @end @interface A() {} @end", Lang_OBJC,
1223 objcCategoryDecl());
1224 EXPECT_FALSE(testStructuralMatch(t));
1225 }
1226
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentIvarOrder)1227 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarOrder) {
1228 auto t = makeDecls<ObjCCategoryDecl>(
1229 "@interface A @end @interface A() { int x; int y; } @end",
1230 "@interface A @end @interface A() { int y; int x; } @end", Lang_OBJC,
1231 objcCategoryDecl());
1232 EXPECT_FALSE(testStructuralMatch(t));
1233 }
1234
TEST_F(StructuralEquivalenceObjCCategoryTest,MatchingMethods)1235 TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingMethods) {
1236 auto t = makeDecls<ObjCCategoryDecl>(
1237 "@interface A @end @interface A(X) -(void)test; @end",
1238 "@interface A @end @interface A(X) -(void)test; @end", Lang_OBJC,
1239 objcCategoryDecl());
1240 EXPECT_TRUE(testStructuralMatch(t));
1241 }
1242
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodName)1243 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodName) {
1244 auto t = makeDecls<ObjCCategoryDecl>(
1245 "@interface A @end @interface A(X) -(void)test; @end",
1246 "@interface A @end @interface A(X) -(void)wasd; @end", Lang_OBJC,
1247 objcCategoryDecl());
1248 EXPECT_FALSE(testStructuralMatch(t));
1249
1250 auto t2 = makeDecls<ObjCCategoryDecl>(
1251 "@interface A @end @interface A(X) -(void)test:(int)x more:(int)y; @end",
1252 "@interface A @end @interface A(X) -(void)test:(int)x :(int)y; @end",
1253 Lang_OBJC, objcCategoryDecl());
1254 EXPECT_FALSE(testStructuralMatch(t2));
1255 }
1256
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodClassInstance)1257 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodClassInstance) {
1258 auto t = makeDecls<ObjCCategoryDecl>(
1259 "@interface A @end @interface A(X) -(void)test; @end",
1260 "@interface A @end @interface A(X) +(void)test; @end", Lang_OBJC,
1261 objcCategoryDecl());
1262 EXPECT_FALSE(testStructuralMatch(t));
1263 }
1264
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodReturnType)1265 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodReturnType) {
1266 auto t = makeDecls<ObjCCategoryDecl>(
1267 "@interface A @end @interface A(X) -(void)test; @end",
1268 "@interface A @end @interface A(X) -(int)test; @end", Lang_OBJC,
1269 objcCategoryDecl());
1270 EXPECT_FALSE(testStructuralMatch(t));
1271 }
1272
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodParameterType)1273 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterType) {
1274 auto t = makeDecls<ObjCCategoryDecl>(
1275 "@interface A @end @interface A(X) -(void)test:(int)x; @end",
1276 "@interface A @end @interface A(X) -(void)test:(float)x; @end", Lang_OBJC,
1277 objcCategoryDecl());
1278 EXPECT_FALSE(testStructuralMatch(t));
1279 }
1280
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodParameterName)1281 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterName) {
1282 auto t = makeDecls<ObjCCategoryDecl>(
1283 "@interface A @end @interface A(X) -(void)test:(int)x; @end",
1284 "@interface A @end @interface A(X) -(void)test:(int)y; @end", Lang_OBJC,
1285 objcCategoryDecl());
1286 EXPECT_TRUE(testStructuralMatch(t));
1287 }
1288
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodNumber)1289 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodNumber) {
1290 auto t = makeDecls<ObjCCategoryDecl>(
1291 "@interface A @end @interface A(X) -(void)test; @end",
1292 "@interface A @end @interface A(X) @end", Lang_OBJC, objcCategoryDecl());
1293 EXPECT_FALSE(testStructuralMatch(t));
1294 }
1295
TEST_F(StructuralEquivalenceObjCCategoryTest,DifferentMethodOrder)1296 TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodOrder) {
1297 auto t = makeDecls<ObjCCategoryDecl>(
1298 "@interface A @end @interface A(X) -(void)u; -(void)v; @end",
1299 "@interface A @end @interface A(X) -(void)v; -(void)u; @end", Lang_OBJC,
1300 objcCategoryDecl());
1301 EXPECT_FALSE(testStructuralMatch(t));
1302 }
1303
1304 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};
1305
TEST_F(StructuralEquivalenceTemplateTest,ExactlySameTemplates)1306 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {
1307 auto t = makeNamedDecls("template <class T> struct foo;",
1308 "template <class T> struct foo;", Lang_CXX03);
1309 EXPECT_TRUE(testStructuralMatch(t));
1310 }
1311
TEST_F(StructuralEquivalenceTemplateTest,DifferentTemplateArgName)1312 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {
1313 auto t = makeNamedDecls("template <class T> struct foo;",
1314 "template <class U> struct foo;", Lang_CXX03);
1315 EXPECT_TRUE(testStructuralMatch(t));
1316 }
1317
TEST_F(StructuralEquivalenceTemplateTest,DifferentTemplateArgKind)1318 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {
1319 auto t = makeNamedDecls("template <class T> struct foo;",
1320 "template <int T> struct foo;", Lang_CXX03);
1321 EXPECT_FALSE(testStructuralMatch(t));
1322 }
1323
TEST_F(StructuralEquivalenceTemplateTest,BitFieldDecl)1324 TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) {
1325 const char *Code = "class foo { int a : 2; };";
1326 auto t = makeNamedDecls(Code, Code, Lang_CXX03);
1327 EXPECT_TRUE(testStructuralMatch(t));
1328 }
1329
TEST_F(StructuralEquivalenceTemplateTest,BitFieldDeclDifferentWidth)1330 TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) {
1331 auto t = makeNamedDecls("class foo { int a : 2; };",
1332 "class foo { int a : 4; };", Lang_CXX03);
1333 EXPECT_FALSE(testStructuralMatch(t));
1334 }
1335
TEST_F(StructuralEquivalenceTemplateTest,DependentBitFieldDecl)1336 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) {
1337 const char *Code = "template <class T> class foo { int a : sizeof(T); };";
1338 auto t = makeNamedDecls(Code, Code, Lang_CXX03);
1339 EXPECT_TRUE(testStructuralMatch(t));
1340 }
1341
TEST_F(StructuralEquivalenceTemplateTest,DependentBitFieldDeclDifferentVal)1342 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) {
1343 auto t = makeNamedDecls(
1344 "template <class A, class B> class foo { int a : sizeof(A); };",
1345 "template <class A, class B> class foo { int a : sizeof(B); };",
1346 Lang_CXX03);
1347 EXPECT_FALSE(testStructuralMatch(t));
1348 }
1349
TEST_F(StructuralEquivalenceTemplateTest,DependentBitFieldDeclDifferentVal2)1350 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) {
1351 auto t = makeNamedDecls(
1352 "template <class A> class foo { int a : sizeof(A); };",
1353 "template <class A> class foo { int a : sizeof(A) + 1; };", Lang_CXX03);
1354 EXPECT_FALSE(testStructuralMatch(t));
1355 }
1356
TEST_F(StructuralEquivalenceTemplateTest,ExplicitBoolSame)1357 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
1358 auto Decls = makeNamedDecls(
1359 "template <bool b> struct foo {explicit(b) foo(int);};",
1360 "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX20);
1361 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
1362 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
1363 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
1364 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
1365 EXPECT_TRUE(testStructuralMatch(First, Second));
1366 }
1367
TEST_F(StructuralEquivalenceTemplateTest,ExplicitBoolDifference)1368 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
1369 auto Decls = makeNamedDecls(
1370 "template <bool b> struct foo {explicit(b) foo(int);};",
1371 "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX20);
1372 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
1373 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
1374 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
1375 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
1376 EXPECT_FALSE(testStructuralMatch(First, Second));
1377 }
1378
TEST_F(StructuralEquivalenceTemplateTest,TemplateVsSubstTemplateTemplateParmInArgEq)1379 TEST_F(StructuralEquivalenceTemplateTest,
1380 TemplateVsSubstTemplateTemplateParmInArgEq) {
1381 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1382 R"(
1383 template <typename P1> class Arg { };
1384 template <template <typename PP1> class P1> class Primary { };
1385
1386 void f() {
1387 // Make specialization with simple template.
1388 Primary <Arg> A;
1389 }
1390 )",
1391 R"(
1392 template <typename P1> class Arg { };
1393 template <template <typename PP1> class P1> class Primary { };
1394
1395 template <template <typename PP1> class P1> class Templ {
1396 void f() {
1397 // Make specialization with substituted template template param.
1398 Primary <P1> A;
1399 };
1400 };
1401
1402 // Instantiate with substitution Arg into P1.
1403 template class Templ <Arg>;
1404 )",
1405 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1406 EXPECT_TRUE(testStructuralMatch(t));
1407 }
1408
TEST_F(StructuralEquivalenceTemplateTest,TemplateVsSubstTemplateTemplateParmInArgNotEq)1409 TEST_F(StructuralEquivalenceTemplateTest,
1410 TemplateVsSubstTemplateTemplateParmInArgNotEq) {
1411 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1412 R"(
1413 template <typename P1> class Arg { };
1414 template <template <typename PP1> class P1> class Primary { };
1415
1416 void f() {
1417 // Make specialization with simple template.
1418 Primary <Arg> A;
1419 }
1420 )",
1421 R"(
1422 // Arg is different from the other, this should cause non-equivalence.
1423 template <typename P1> class Arg { int X; };
1424 template <template <typename PP1> class P1> class Primary { };
1425
1426 template <template <typename PP1> class P1> class Templ {
1427 void f() {
1428 // Make specialization with substituted template template param.
1429 Primary <P1> A;
1430 };
1431 };
1432
1433 // Instantiate with substitution Arg into P1.
1434 template class Templ <Arg>;
1435 )",
1436 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1437 EXPECT_FALSE(testStructuralMatch(t));
1438 }
1439
1440 struct StructuralEquivalenceDependentTemplateArgsTest
1441 : StructuralEquivalenceTemplateTest {};
1442
TEST_F(StructuralEquivalenceDependentTemplateArgsTest,SameStructsInDependentArgs)1443 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1444 SameStructsInDependentArgs) {
1445 std::string Code =
1446 R"(
1447 template <typename>
1448 struct S1;
1449
1450 template <typename>
1451 struct enable_if;
1452
1453 struct S
1454 {
1455 template <typename T, typename enable_if<S1<T>>::type>
1456 void f();
1457 };
1458 )";
1459 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
1460 functionTemplateDecl(hasName("f")));
1461 EXPECT_TRUE(testStructuralMatch(t));
1462 }
1463
TEST_F(StructuralEquivalenceDependentTemplateArgsTest,DifferentStructsInDependentArgs)1464 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1465 DifferentStructsInDependentArgs) {
1466 std::string Code =
1467 R"(
1468 template <typename>
1469 struct S1;
1470
1471 template <typename>
1472 struct S2;
1473
1474 template <typename>
1475 struct enable_if;
1476 )";
1477 auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1478 struct S
1479 {
1480 template <typename T, typename enable_if<S1<T>>::type>
1481 void f();
1482 };
1483 )",
1484 Code + R"(
1485 struct S
1486 {
1487 template <typename T, typename enable_if<S2<T>>::type>
1488 void f();
1489 };
1490 )",
1491 Lang_CXX11,
1492 functionTemplateDecl(hasName("f")));
1493 EXPECT_FALSE(testStructuralMatch(t));
1494 }
1495
TEST_F(StructuralEquivalenceDependentTemplateArgsTest,SameStructsInDependentScopeDeclRefExpr)1496 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1497 SameStructsInDependentScopeDeclRefExpr) {
1498 std::string Code =
1499 R"(
1500 template <typename>
1501 struct S1;
1502
1503 template <bool>
1504 struct enable_if;
1505
1506 struct S
1507 {
1508 template <typename T, typename enable_if<S1<T>::value>::type>
1509 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1510 };
1511 )";
1512 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
1513 functionTemplateDecl(hasName("f")));
1514 EXPECT_TRUE(testStructuralMatch(t));
1515 }
1516
TEST_F(StructuralEquivalenceDependentTemplateArgsTest,DifferentStructsInDependentScopeDeclRefExpr)1517 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1518 DifferentStructsInDependentScopeDeclRefExpr) {
1519 std::string Code =
1520 R"(
1521 template <typename>
1522 struct S1;
1523
1524 template <typename>
1525 struct S2;
1526
1527 template <bool>
1528 struct enable_if;
1529 )";
1530 auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1531 struct S
1532 {
1533 template <typename T, typename enable_if<S1<T>::value>::type>
1534 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1535 };
1536 )",
1537 Code + R"(
1538 struct S
1539 {
1540 template <typename T, typename enable_if<S2<T>::value>::type>
1541 void f();
1542 };
1543 )",
1544 Lang_CXX03,
1545 functionTemplateDecl(hasName("f")));
1546 EXPECT_FALSE(testStructuralMatch(t));
1547 }
1548
TEST_F(StructuralEquivalenceDependentTemplateArgsTest,DifferentValueInDependentScopeDeclRefExpr)1549 TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1550 DifferentValueInDependentScopeDeclRefExpr) {
1551 std::string Code =
1552 R"(
1553 template <typename>
1554 struct S1;
1555
1556 template <bool>
1557 struct enable_if;
1558 )";
1559 auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
1560 struct S
1561 {
1562 template <typename T, typename enable_if<S1<T>::value1>::type>
1563 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1564 };
1565 )",
1566 Code + R"(
1567 struct S
1568 {
1569 template <typename T, typename enable_if<S1<T>::value2>::type>
1570 void f();
1571 };
1572 )",
1573 Lang_CXX03,
1574 functionTemplateDecl(hasName("f")));
1575 EXPECT_FALSE(testStructuralMatch(t));
1576 }
1577
TEST_F(StructuralEquivalenceTemplateTest,ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual)1578 TEST_F(
1579 StructuralEquivalenceTemplateTest,
1580 ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) {
1581 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1582 R"(
1583 template <class T> struct Primary {};
1584 namespace N {
1585 struct Arg;
1586 }
1587 // Explicit instantiation with qualified name.
1588 template struct Primary<N::Arg>;
1589 )",
1590 R"(
1591 template <class T> struct Primary {};
1592 namespace N {
1593 struct Arg;
1594 }
1595 using namespace N;
1596 // Explicit instantiation with UNqualified name.
1597 template struct Primary<Arg>;
1598 )",
1599 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1600 EXPECT_TRUE(testStructuralMatch(t));
1601 }
1602
TEST_F(StructuralEquivalenceTemplateTest,ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs)1603 TEST_F(
1604 StructuralEquivalenceTemplateTest,
1605 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) {
1606 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1607 R"(
1608 template <class T> struct Primary {};
1609 namespace N {
1610 struct Arg { int a; };
1611 }
1612 // Explicit instantiation with qualified name.
1613 template struct Primary<N::Arg>;
1614 )",
1615 R"(
1616 template <class T> struct Primary {};
1617 namespace N {
1618 // This struct is not equivalent with the other in the prev TU.
1619 struct Arg { double b; }; // -- Field mismatch.
1620 }
1621 using namespace N;
1622 // Explicit instantiation with UNqualified name.
1623 template struct Primary<Arg>;
1624 )",
1625 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1626 EXPECT_FALSE(testStructuralMatch(t));
1627 }
1628
TEST_F(StructuralEquivalenceTemplateTest,ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual)1629 TEST_F(
1630 StructuralEquivalenceTemplateTest,
1631 ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) {
1632 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1633 R"(
1634 template <template <class> class T> struct Primary {};
1635 namespace N {
1636 template <class T> struct Arg;
1637 }
1638 // Explicit instantiation with qualified name.
1639 template struct Primary<N::Arg>;
1640 )",
1641 R"(
1642 template <template <class> class T> struct Primary {};
1643 namespace N {
1644 template <class T> struct Arg;
1645 }
1646 using namespace N;
1647 // Explicit instantiation with UNqualified name.
1648 template struct Primary<Arg>;
1649 )",
1650 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1651 EXPECT_TRUE(testStructuralMatch(t));
1652 }
1653
TEST_F(StructuralEquivalenceTemplateTest,ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs)1654 TEST_F(
1655 StructuralEquivalenceTemplateTest,
1656 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) {
1657 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1658 R"(
1659 template <template <class> class T> struct Primary {};
1660 namespace N {
1661 template <class T> struct Arg { int a; };
1662 }
1663 // Explicit instantiation with qualified name.
1664 template struct Primary<N::Arg>;
1665 )",
1666 R"(
1667 template <template <class> class T> struct Primary {};
1668 namespace N {
1669 // This template is not equivalent with the other in the prev TU.
1670 template <class T> struct Arg { double b; }; // -- Field mismatch.
1671 }
1672 using namespace N;
1673 // Explicit instantiation with UNqualified name.
1674 template struct Primary<Arg>;
1675 )",
1676 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1677 EXPECT_FALSE(testStructuralMatch(t));
1678 }
1679
TEST_F(StructuralEquivalenceTemplateTest,ClassTemplSpecWithInequivalentShadowedTemplArg)1680 TEST_F(
1681 StructuralEquivalenceTemplateTest,
1682 ClassTemplSpecWithInequivalentShadowedTemplArg) {
1683 auto t = makeDecls<ClassTemplateSpecializationDecl>(
1684 R"(
1685 template <template <class> class T> struct Primary {};
1686 template <class T> struct Arg { int a; };
1687 // Explicit instantiation with ::Arg
1688 template struct Primary<Arg>;
1689 )",
1690 R"(
1691 template <template <class> class T> struct Primary {};
1692 template <class T> struct Arg { int a; };
1693 namespace N {
1694 // This template is not equivalent with the other in the global scope.
1695 template <class T> struct Arg { double b; }; // -- Field mismatch.
1696 // Explicit instantiation with N::Arg which shadows ::Arg
1697 template struct Primary<Arg>;
1698 }
1699 )",
1700 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
1701 EXPECT_FALSE(testStructuralMatch(t));
1702 }
1703 struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {
1704 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
1705
1706 template <typename NodeType, typename MatcherType>
1707 std::pair<NodeType *, NodeType *>
findDeclPairclang::ast_matchers::StructuralEquivalenceCacheTest1708 findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU,
1709 MatcherType M) {
1710 NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M);
1711 NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M);
1712 return {D0, D1};
1713 }
1714
1715 template <typename NodeType>
isInNonEqCacheclang::ast_matchers::StructuralEquivalenceCacheTest1716 bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) {
1717 return NonEquivalentDecls.count(D) > 0;
1718 }
1719 };
1720
TEST_F(StructuralEquivalenceCacheTest,SimpleNonEq)1721 TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {
1722 auto TU = makeTuDecls(
1723 R"(
1724 class A {};
1725 class B {};
1726 void x(A, A);
1727 )",
1728 R"(
1729 class A {};
1730 class B {};
1731 void x(A, B);
1732 )",
1733 Lang_CXX03);
1734
1735 StructuralEquivalenceContext Ctx(
1736 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
1737 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
1738
1739 auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));
1740 EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second));
1741
1742 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1743 TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1744 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1745 TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
1746 }
1747
TEST_F(StructuralEquivalenceCacheTest,SpecialNonEq)1748 TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {
1749 auto TU = makeTuDecls(
1750 R"(
1751 class A {};
1752 class B { int i; };
1753 void x(A *);
1754 void y(A *);
1755 class C {
1756 friend void x(A *);
1757 friend void y(A *);
1758 };
1759 )",
1760 R"(
1761 class A {};
1762 class B { int i; };
1763 void x(A *);
1764 void y(B *);
1765 class C {
1766 friend void x(A *);
1767 friend void y(B *);
1768 };
1769 )",
1770 Lang_CXX03);
1771
1772 StructuralEquivalenceContext Ctx(
1773 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
1774 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
1775
1776 auto C = findDeclPair<CXXRecordDecl>(
1777 TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));
1778 EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second));
1779
1780 EXPECT_FALSE(isInNonEqCache(C));
1781 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1782 TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1783 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1784 TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
1785 EXPECT_FALSE(isInNonEqCache(
1786 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
1787 EXPECT_FALSE(isInNonEqCache(
1788 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y")))));
1789 }
1790
TEST_F(StructuralEquivalenceCacheTest,Cycle)1791 TEST_F(StructuralEquivalenceCacheTest, Cycle) {
1792 auto TU = makeTuDecls(
1793 R"(
1794 class C;
1795 class A { C *c; };
1796 void x(A *);
1797 class C {
1798 friend void x(A *);
1799 };
1800 )",
1801 R"(
1802 class C;
1803 class A { C *c; };
1804 void x(A *);
1805 class C {
1806 friend void x(A *);
1807 };
1808 )",
1809 Lang_CXX03);
1810
1811 StructuralEquivalenceContext Ctx(
1812 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
1813 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
1814
1815 auto C = findDeclPair<CXXRecordDecl>(
1816 TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));
1817 EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second));
1818
1819 EXPECT_FALSE(isInNonEqCache(C));
1820 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
1821 TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
1822 EXPECT_FALSE(isInNonEqCache(
1823 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
1824 }
1825
1826 struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {};
1827
1828 /// Fallback matcher to be used only when there is no specific matcher for a
1829 /// Expr subclass. Remove this once all Expr subclasses have their own matcher.
1830 static auto &fallbackExprMatcher = expr;
1831
TEST_F(StructuralEquivalenceStmtTest,AddrLabelExpr)1832 TEST_F(StructuralEquivalenceStmtTest, AddrLabelExpr) {
1833 auto t = makeWrappedStmts("lbl: &&lbl;", "lbl: &&lbl;", Lang_CXX03,
1834 addrLabelExpr());
1835 EXPECT_TRUE(testStructuralMatch(t));
1836 }
1837
TEST_F(StructuralEquivalenceStmtTest,AddrLabelExprDifferentLabel)1838 TEST_F(StructuralEquivalenceStmtTest, AddrLabelExprDifferentLabel) {
1839 auto t = makeWrappedStmts("lbl1: lbl2: &&lbl1;", "lbl1: lbl2: &&lbl2;",
1840 Lang_CXX03, addrLabelExpr());
1841 // FIXME: Should be false. LabelDecl are incorrectly matched.
1842 EXPECT_TRUE(testStructuralMatch(t));
1843 }
1844
1845 static const std::string MemoryOrderSrc = R"(
1846 enum memory_order {
1847 memory_order_relaxed,
1848 memory_order_consume,
1849 memory_order_acquire,
1850 memory_order_release,
1851 memory_order_acq_rel,
1852 memory_order_seq_cst
1853 };
1854 )";
1855
TEST_F(StructuralEquivalenceStmtTest,AtomicExpr)1856 TEST_F(StructuralEquivalenceStmtTest, AtomicExpr) {
1857 std::string Prefix = "char a, b; " + MemoryOrderSrc;
1858 auto t = makeStmts(
1859 Prefix +
1860 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",
1861 Prefix +
1862 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",
1863 Lang_CXX03, atomicExpr());
1864 EXPECT_TRUE(testStructuralMatch(t));
1865 }
1866
TEST_F(StructuralEquivalenceStmtTest,AtomicExprDifferentOp)1867 TEST_F(StructuralEquivalenceStmtTest, AtomicExprDifferentOp) {
1868 std::string Prefix = "char a, b; " + MemoryOrderSrc;
1869 auto t = makeStmts(
1870 Prefix +
1871 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",
1872 Prefix +
1873 "void wrapped() { __atomic_store(&a, &b, memory_order_seq_cst); }",
1874 Lang_CXX03, atomicExpr());
1875 EXPECT_FALSE(testStructuralMatch(t));
1876 }
1877
TEST_F(StructuralEquivalenceStmtTest,BinaryOperator)1878 TEST_F(StructuralEquivalenceStmtTest, BinaryOperator) {
1879 auto t = makeWrappedStmts("1 + 1", "1 + 1", Lang_CXX03, binaryOperator());
1880 EXPECT_TRUE(testStructuralMatch(t));
1881 }
1882
TEST_F(StructuralEquivalenceStmtTest,BinaryOperatorDifferentOps)1883 TEST_F(StructuralEquivalenceStmtTest, BinaryOperatorDifferentOps) {
1884 auto t = makeWrappedStmts("1 + 1", "1 - 1", Lang_CXX03, binaryOperator());
1885 EXPECT_FALSE(testStructuralMatch(t));
1886 }
1887
TEST_F(StructuralEquivalenceStmtTest,CallExpr)1888 TEST_F(StructuralEquivalenceStmtTest, CallExpr) {
1889 std::string Src = "int call(); int wrapped() { call(); }";
1890 auto t = makeStmts(Src, Src, Lang_CXX03, callExpr());
1891 EXPECT_TRUE(testStructuralMatch(t));
1892 }
1893
TEST_F(StructuralEquivalenceStmtTest,CallExprDifferentCallee)1894 TEST_F(StructuralEquivalenceStmtTest, CallExprDifferentCallee) {
1895 std::string FunctionSrc = "int func1(); int func2();\n";
1896 auto t = makeStmts(FunctionSrc + "void wrapper() { func1(); }",
1897 FunctionSrc + "void wrapper() { func2(); }", Lang_CXX03,
1898 callExpr());
1899 EXPECT_FALSE(testStructuralMatch(t));
1900 }
1901
TEST_F(StructuralEquivalenceStmtTest,CharacterLiteral)1902 TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) {
1903 auto t = makeWrappedStmts("'a'", "'a'", Lang_CXX03, characterLiteral());
1904 EXPECT_TRUE(testStructuralMatch(t));
1905 }
1906
TEST_F(StructuralEquivalenceStmtTest,CharacterLiteralDifferentValues)1907 TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) {
1908 auto t = makeWrappedStmts("'a'", "'b'", Lang_CXX03, characterLiteral());
1909 EXPECT_FALSE(testStructuralMatch(t));
1910 }
1911
TEST_F(StructuralEquivalenceStmtTest,ExpressionTraitExpr)1912 TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExpr) {
1913 auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_lvalue_expr(1)",
1914 Lang_CXX03, fallbackExprMatcher());
1915 EXPECT_TRUE(testStructuralMatch(t));
1916 }
1917
TEST_F(StructuralEquivalenceStmtTest,ExpressionTraitExprDifferentKind)1918 TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExprDifferentKind) {
1919 auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_rvalue_expr(1)",
1920 Lang_CXX03, fallbackExprMatcher());
1921 EXPECT_FALSE(testStructuralMatch(t));
1922 }
1923
TEST_F(StructuralEquivalenceStmtTest,FloatingLiteral)1924 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteral) {
1925 auto t = makeWrappedStmts("1.0", "1.0", Lang_CXX03, fallbackExprMatcher());
1926 EXPECT_TRUE(testStructuralMatch(t));
1927 }
1928
TEST_F(StructuralEquivalenceStmtTest,FloatingLiteralDifferentSpelling)1929 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentSpelling) {
1930 auto t = makeWrappedStmts("0x10.1p0", "16.0625", Lang_CXX17,
1931 fallbackExprMatcher());
1932 // Same value but with different spelling is equivalent.
1933 EXPECT_TRUE(testStructuralMatch(t));
1934 }
1935
TEST_F(StructuralEquivalenceStmtTest,FloatingLiteralDifferentType)1936 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentType) {
1937 auto t = makeWrappedStmts("1.0", "1.0f", Lang_CXX03, fallbackExprMatcher());
1938 EXPECT_FALSE(testStructuralMatch(t));
1939 }
1940
TEST_F(StructuralEquivalenceStmtTest,FloatingLiteralDifferentValue)1941 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentValue) {
1942 auto t = makeWrappedStmts("1.01", "1.0", Lang_CXX03, fallbackExprMatcher());
1943 EXPECT_FALSE(testStructuralMatch(t));
1944 }
1945
TEST_F(StructuralEquivalenceStmtTest,GenericSelectionExprSame)1946 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) {
1947 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
1948 "_Generic(0u, unsigned int: 0, float: 1)", Lang_C99,
1949 genericSelectionExpr());
1950 EXPECT_TRUE(testStructuralMatch(t));
1951 }
1952
TEST_F(StructuralEquivalenceStmtTest,GenericSelectionExprSignsDiffer)1953 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) {
1954 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
1955 "_Generic(0, int: 0, float: 1)", Lang_C99,
1956 genericSelectionExpr());
1957 EXPECT_FALSE(testStructuralMatch(t));
1958 }
1959
TEST_F(StructuralEquivalenceStmtTest,GenericSelectionExprOrderDiffers)1960 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) {
1961 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",
1962 "_Generic(0u, float: 1, unsigned int: 0)", Lang_C99,
1963 genericSelectionExpr());
1964 EXPECT_FALSE(testStructuralMatch(t));
1965 }
1966
TEST_F(StructuralEquivalenceStmtTest,GenericSelectionExprDependentResultSame)1967 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) {
1968 auto t = makeStmts(
1969 R"(
1970 template <typename T>
1971 void f() {
1972 T x;
1973 (void)_Generic(x, int: 0, float: 1);
1974 }
1975 void g() { f<int>(); }
1976 )",
1977 R"(
1978 template <typename T>
1979 void f() {
1980 T x;
1981 (void)_Generic(x, int: 0, float: 1);
1982 }
1983 void g() { f<int>(); }
1984 )",
1985 Lang_CXX03, genericSelectionExpr());
1986 EXPECT_TRUE(testStructuralMatch(t));
1987 }
1988
TEST_F(StructuralEquivalenceStmtTest,GenericSelectionExprDependentResultOrderDiffers)1989 TEST_F(StructuralEquivalenceStmtTest,
1990 GenericSelectionExprDependentResultOrderDiffers) {
1991 auto t = makeStmts(
1992 R"(
1993 template <typename T>
1994 void f() {
1995 T x;
1996 (void)_Generic(x, float: 1, int: 0);
1997 }
1998 void g() { f<int>(); }
1999 )",
2000 R"(
2001 template <typename T>
2002 void f() {
2003 T x;
2004 (void)_Generic(x, int: 0, float: 1);
2005 }
2006 void g() { f<int>(); }
2007 )",
2008 Lang_CXX03, genericSelectionExpr());
2009
2010 EXPECT_FALSE(testStructuralMatch(t));
2011 }
TEST_F(StructuralEquivalenceStmtTest,IntegerLiteral)2012 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) {
2013 auto t = makeWrappedStmts("1", "1", Lang_CXX03, integerLiteral());
2014 EXPECT_TRUE(testStructuralMatch(t));
2015 }
2016
TEST_F(StructuralEquivalenceStmtTest,IntegerLiteralDifferentSpelling)2017 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentSpelling) {
2018 auto t = makeWrappedStmts("1", "0x1", Lang_CXX03, integerLiteral());
2019 // Same value but with different spelling is equivalent.
2020 EXPECT_TRUE(testStructuralMatch(t));
2021 }
2022
TEST_F(StructuralEquivalenceStmtTest,IntegerLiteralDifferentValue)2023 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) {
2024 auto t = makeWrappedStmts("1", "2", Lang_CXX03, integerLiteral());
2025 EXPECT_FALSE(testStructuralMatch(t));
2026 }
2027
TEST_F(StructuralEquivalenceStmtTest,IntegerLiteralDifferentTypes)2028 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) {
2029 auto t = makeWrappedStmts("1", "1L", Lang_CXX03, integerLiteral());
2030 EXPECT_FALSE(testStructuralMatch(t));
2031 }
2032
TEST_F(StructuralEquivalenceStmtTest,MemberExpr)2033 TEST_F(StructuralEquivalenceStmtTest, MemberExpr) {
2034 std::string ClassSrc = "struct C { int a; int b; };";
2035 auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }",
2036 ClassSrc + "int wrapper() { C c; return c.a; }",
2037 Lang_CXX03, memberExpr());
2038 EXPECT_TRUE(testStructuralMatch(t));
2039 }
2040
TEST_F(StructuralEquivalenceStmtTest,MemberExprDifferentMember)2041 TEST_F(StructuralEquivalenceStmtTest, MemberExprDifferentMember) {
2042 std::string ClassSrc = "struct C { int a; int b; };";
2043 auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }",
2044 ClassSrc + "int wrapper() { C c; return c.b; }",
2045 Lang_CXX03, memberExpr());
2046 EXPECT_FALSE(testStructuralMatch(t));
2047 }
2048
TEST_F(StructuralEquivalenceStmtTest,ObjCStringLiteral)2049 TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) {
2050 auto t =
2051 makeWrappedStmts("@\"a\"", "@\"a\"", Lang_OBJCXX, fallbackExprMatcher());
2052 EXPECT_TRUE(testStructuralMatch(t));
2053 }
2054
TEST_F(StructuralEquivalenceStmtTest,ObjCStringLiteralDifferentContent)2055 TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) {
2056 auto t =
2057 makeWrappedStmts("@\"a\"", "@\"b\"", Lang_OBJCXX, fallbackExprMatcher());
2058 EXPECT_FALSE(testStructuralMatch(t));
2059 }
2060
TEST_F(StructuralEquivalenceStmtTest,StringLiteral)2061 TEST_F(StructuralEquivalenceStmtTest, StringLiteral) {
2062 auto t = makeWrappedStmts("\"a\"", "\"a\"", Lang_CXX03, stringLiteral());
2063 EXPECT_TRUE(testStructuralMatch(t));
2064 }
2065
TEST_F(StructuralEquivalenceStmtTest,StringLiteralDifferentContent)2066 TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) {
2067 auto t = makeWrappedStmts("\"a\"", "\"b\"", Lang_CXX03, stringLiteral());
2068 EXPECT_FALSE(testStructuralMatch(t));
2069 }
2070
TEST_F(StructuralEquivalenceStmtTest,StringLiteralDifferentLength)2071 TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) {
2072 auto t = makeWrappedStmts("\"a\"", "\"aa\"", Lang_CXX03, stringLiteral());
2073 EXPECT_FALSE(testStructuralMatch(t));
2074 }
2075
TEST_F(StructuralEquivalenceStmtTest,TypeTraitExpr)2076 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExpr) {
2077 auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(int)", Lang_CXX03,
2078 fallbackExprMatcher());
2079 EXPECT_TRUE(testStructuralMatch(t));
2080 }
2081
TEST_F(StructuralEquivalenceStmtTest,TypeTraitExprDifferentType)2082 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentType) {
2083 auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(long)", Lang_CXX03,
2084 fallbackExprMatcher());
2085 EXPECT_FALSE(testStructuralMatch(t));
2086 }
2087
TEST_F(StructuralEquivalenceStmtTest,TypeTraitExprDifferentTrait)2088 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTrait) {
2089 auto t = makeWrappedStmts(
2090 "__is_pod(int)", "__is_trivially_constructible(int)", Lang_CXX03, expr());
2091 EXPECT_FALSE(testStructuralMatch(t));
2092 }
2093
TEST_F(StructuralEquivalenceStmtTest,TypeTraitExprDifferentTraits)2094 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTraits) {
2095 auto t = makeWrappedStmts("__is_constructible(int)",
2096 "__is_constructible(int, int)", Lang_CXX03, expr());
2097 EXPECT_FALSE(testStructuralMatch(t));
2098 }
2099
TEST_F(StructuralEquivalenceStmtTest,UnaryExprOrTypeTraitExpr)2100 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExpr) {
2101 auto t = makeWrappedStmts("sizeof(int)", "sizeof(int)", Lang_CXX03,
2102 unaryExprOrTypeTraitExpr());
2103 EXPECT_TRUE(testStructuralMatch(t));
2104 }
2105
TEST_F(StructuralEquivalenceStmtTest,UnaryExprOrTypeTraitExprDifferentKind)2106 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentKind) {
2107 auto t = makeWrappedStmts("sizeof(int)", "alignof(long)", Lang_CXX11,
2108 unaryExprOrTypeTraitExpr());
2109 EXPECT_FALSE(testStructuralMatch(t));
2110 }
2111
TEST_F(StructuralEquivalenceStmtTest,UnaryExprOrTypeTraitExprDifferentType)2112 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentType) {
2113 auto t = makeWrappedStmts("sizeof(int)", "sizeof(long)", Lang_CXX03,
2114 unaryExprOrTypeTraitExpr());
2115 EXPECT_FALSE(testStructuralMatch(t));
2116 }
2117
TEST_F(StructuralEquivalenceStmtTest,UnaryOperator)2118 TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) {
2119 auto t = makeWrappedStmts("+1", "+1", Lang_CXX03, unaryOperator());
2120 EXPECT_TRUE(testStructuralMatch(t));
2121 }
2122
TEST_F(StructuralEquivalenceStmtTest,UnaryOperatorDifferentOps)2123 TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) {
2124 auto t = makeWrappedStmts("+1", "-1", Lang_CXX03, unaryOperator());
2125 EXPECT_FALSE(testStructuralMatch(t));
2126 }
2127
2128 } // end namespace ast_matchers
2129 } // end namespace clang
2130