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 | |
15 | namespace clang { |
16 | namespace ast_matchers { |
17 | |
18 | using std::get; |
19 | |
20 | struct 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 | |
181 | TEST_F(StructuralEquivalenceTest, Int) { |
182 | auto Decls = makeNamedDecls(SrcCode0: "int foo;" , SrcCode1: "int foo;" , Lang: Lang_CXX03); |
183 | EXPECT_TRUE(testStructuralMatch(Decls)); |
184 | } |
185 | |
186 | TEST_F(StructuralEquivalenceTest, IntVsSignedInt) { |
187 | auto Decls = makeNamedDecls(SrcCode0: "int foo;" , SrcCode1: "signed int foo;" , Lang: Lang_CXX03); |
188 | EXPECT_TRUE(testStructuralMatch(Decls)); |
189 | } |
190 | |
191 | TEST_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. |
198 | TEST_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 | |
203 | TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) { |
204 | auto Decls = makeNamedDecls(SrcCode0: "struct foo;" , SrcCode1: "struct foo;" , Lang: Lang_CXX03); |
205 | EXPECT_TRUE(testStructuralMatch(Decls)); |
206 | } |
207 | |
208 | TEST_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 | |
214 | TEST_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 | |
220 | TEST_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 | |
230 | TEST_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 | |
240 | TEST_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. |
258 | TEST_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 | |
284 | TEST_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 | |
300 | struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { |
301 | }; |
302 | |
303 | TEST_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 | |
309 | TEST_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 | |
317 | TEST_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 | |
325 | TEST_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 | |
332 | TEST_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 | |
338 | TEST_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 | |
344 | TEST_F(StructuralEquivalenceFunctionTest, Throw) { |
345 | auto t = makeNamedDecls(SrcCode0: "void foo();" , SrcCode1: "void foo() throw();" , Lang: Lang_CXX03); |
346 | EXPECT_FALSE(testStructuralMatch(t)); |
347 | } |
348 | |
349 | TEST_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 | |
355 | TEST_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 | |
361 | TEST_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 | |
367 | TEST_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 | |
373 | TEST_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 | |
379 | TEST_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 | |
385 | TEST_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 | |
391 | TEST_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 | |
397 | TEST_F(StructuralEquivalenceFunctionTest, ReturnType) { |
398 | auto t = makeNamedDecls(SrcCode0: "char foo();" , SrcCode1: "int foo();" , Lang: Lang_CXX03); |
399 | EXPECT_FALSE(testStructuralMatch(t)); |
400 | } |
401 | |
402 | TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) { |
403 | auto t = makeNamedDecls(SrcCode0: "char foo();" , SrcCode1: "const char foo();" , Lang: Lang_CXX03); |
404 | EXPECT_FALSE(testStructuralMatch(t)); |
405 | } |
406 | |
407 | TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) { |
408 | auto t = makeNamedDecls(SrcCode0: "char &foo();" , |
409 | SrcCode1: "char &&foo();" , Lang: Lang_CXX11); |
410 | EXPECT_FALSE(testStructuralMatch(t)); |
411 | } |
412 | |
413 | TEST_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 | |
418 | TEST_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 | |
423 | TEST_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 | |
428 | TEST_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 | |
434 | TEST_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 | |
439 | TEST_F(StructuralEquivalenceFunctionTest, NameInParen) { |
440 | auto t = makeNamedDecls(SrcCode0: "void ((foo))();" , SrcCode1: "void foo();" , Lang: Lang_CXX03); |
441 | EXPECT_TRUE(testStructuralMatch(t)); |
442 | } |
443 | |
444 | TEST_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 | |
452 | TEST_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 | |
460 | TEST_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 | |
466 | TEST_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 | |
477 | TEST_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 | |
487 | struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest { |
488 | }; |
489 | |
490 | TEST_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 | |
497 | TEST_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 | |
503 | TEST_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 | |
511 | TEST_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 | |
517 | TEST_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 | |
523 | TEST_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 | |
529 | TEST_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 | |
535 | TEST_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 | |
542 | TEST_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 | |
548 | TEST_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 | |
555 | TEST_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 | |
562 | TEST_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 | |
570 | TEST_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 | |
578 | TEST_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 | |
586 | TEST_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 | |
595 | TEST_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 | |
603 | TEST_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 | |
611 | struct 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 | |
619 | TEST_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 | |
626 | TEST_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 | |
632 | TEST_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 | |
639 | TEST_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 | |
645 | TEST_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 | |
652 | TEST_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 | |
660 | TEST_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 | |
673 | TEST_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 | |
700 | TEST_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 | |
729 | TEST_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 | |
771 | TEST_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 | |
807 | TEST_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 | |
814 | TEST_F(StructuralEquivalenceRecordTest, |
815 | FwdDeclRecordShouldBeEqualWithFwdDeclRecord) { |
816 | auto t = makeNamedDecls(SrcCode0: "class foo;" , SrcCode1: "class foo;" , Lang: Lang_CXX11); |
817 | EXPECT_TRUE(testStructuralMatch(t)); |
818 | } |
819 | |
820 | TEST_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 | |
827 | TEST_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 | |
834 | TEST_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 | |
840 | TEST_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 | |
847 | TEST_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 | |
854 | TEST_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 | |
861 | struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {}; |
862 | |
863 | TEST_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 | |
877 | TEST_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 | |
889 | TEST_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 | |
901 | TEST_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 | |
913 | TEST_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 | |
920 | TEST_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 | |
930 | TEST_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 | |
940 | struct StructuralEquivalenceRecordContextTest : StructuralEquivalenceTest {}; |
941 | |
942 | TEST_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 | |
948 | TEST_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 | |
954 | TEST_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 | |
960 | TEST_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 | |
966 | TEST_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 | |
972 | TEST_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 | |
979 | TEST_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 | |
987 | TEST_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 | |
994 | TEST_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 | |
1001 | TEST_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 | |
1008 | TEST_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 | |
1014 | TEST_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 | |
1020 | TEST_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 | |
1027 | TEST_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 | |
1050 | TEST_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 | |
1064 | TEST_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 | |
1071 | TEST_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 | |
1078 | TEST_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 | |
1085 | struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {}; |
1086 | |
1087 | TEST_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 | |
1092 | TEST_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 | |
1099 | TEST_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 | |
1106 | TEST_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 | |
1112 | struct StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {}; |
1113 | |
1114 | TEST_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 | |
1120 | TEST_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 | |
1127 | TEST_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 | |
1134 | TEST_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 | |
1141 | TEST_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 | |
1147 | TEST_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 | |
1154 | struct StructuralEquivalenceObjCCategoryTest : StructuralEquivalenceTest {}; |
1155 | |
1156 | TEST_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 | |
1163 | TEST_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 | |
1170 | TEST_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 | |
1177 | TEST_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 | |
1189 | TEST_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 | |
1196 | TEST_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 | |
1204 | TEST_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 | |
1212 | TEST_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 | |
1222 | TEST_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 | |
1230 | TEST_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 | |
1238 | TEST_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 | |
1246 | TEST_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 | |
1254 | TEST_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 | |
1262 | TEST_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 | |
1270 | TEST_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 | |
1278 | TEST_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 | |
1286 | TEST_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 | |
1300 | TEST_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 | |
1308 | TEST_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 | |
1316 | TEST_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 | |
1324 | TEST_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 | |
1332 | TEST_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 | |
1339 | TEST_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 | |
1347 | struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {}; |
1348 | |
1349 | TEST_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 | |
1355 | TEST_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 | |
1361 | TEST_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 | |
1367 | TEST_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 | |
1373 | TEST_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 | |
1379 | TEST_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 | |
1385 | TEST_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 | |
1393 | TEST_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 | |
1400 | TEST_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 | |
1411 | TEST_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 | |
1422 | TEST_F(StructuralEquivalenceTemplateTest, |
1423 | TemplateVsSubstTemplateTemplateParmInArgEq) { |
1424 | auto t = makeDecls<ClassTemplateSpecializationDecl>( |
1425 | SrcCode0: R"( |
1426 | template <typename P1> class Arg { }; |
1427 | template <template <typename PP1> class P1> class Primary { }; |
1428 | |
1429 | void f() { |
1430 | // Make specialization with simple template. |
1431 | Primary <Arg> A; |
1432 | } |
1433 | )" , |
1434 | SrcCode1: R"( |
1435 | template <typename P1> class Arg { }; |
1436 | template <template <typename PP1> class P1> class Primary { }; |
1437 | |
1438 | template <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. |
1446 | template class Templ <Arg>; |
1447 | )" , |
1448 | Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary" ))); |
1449 | EXPECT_TRUE(testStructuralMatch(t)); |
1450 | } |
1451 | |
1452 | TEST_F(StructuralEquivalenceTemplateTest, |
1453 | TemplateVsSubstTemplateTemplateParmInArgNotEq) { |
1454 | auto t = makeDecls<ClassTemplateSpecializationDecl>( |
1455 | SrcCode0: R"( |
1456 | template <typename P1> class Arg { }; |
1457 | template <template <typename PP1> class P1> class Primary { }; |
1458 | |
1459 | void 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. |
1466 | template <typename P1> class Arg { int X; }; |
1467 | template <template <typename PP1> class P1> class Primary { }; |
1468 | |
1469 | template <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. |
1477 | template class Templ <Arg>; |
1478 | )" , |
1479 | Lang: Lang_CXX03, AMatcher: classTemplateSpecializationDecl(hasName(Name: "Primary" ))); |
1480 | EXPECT_FALSE(testStructuralMatch(t)); |
1481 | } |
1482 | |
1483 | struct StructuralEquivalenceDependentTemplateArgsTest |
1484 | : StructuralEquivalenceTemplateTest {}; |
1485 | |
1486 | TEST_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 | |
1507 | TEST_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 | |
1539 | TEST_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 | |
1560 | TEST_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 | |
1592 | TEST_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 | |
1621 | TEST_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 | |
1646 | TEST_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 | |
1672 | TEST_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 | |
1697 | TEST_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 | |
1723 | TEST_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 | |
1740 | TEST_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 | |
1757 | TEST_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 | } |
1780 | struct 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 | |
1798 | TEST_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 | |
1825 | TEST_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 | |
1844 | TEST_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 | |
1862 | TEST_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 | |
1880 | TEST_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 | |
1898 | TEST_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 | |
1941 | TEST_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 | |
1976 | struct 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. |
1980 | static auto &fallbackExprMatcher = expr; |
1981 | |
1982 | TEST_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 | |
1988 | TEST_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 | |
1995 | static const std::string MemoryOrderSrc = R"( |
1996 | enum 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 | |
2006 | TEST_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 | |
2017 | TEST_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 | |
2028 | TEST_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 | |
2033 | TEST_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 | |
2038 | TEST_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 | |
2044 | TEST_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 | |
2052 | TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) { |
2053 | auto t = makeWrappedStmts(SrcCode0: "'a'" , SrcCode1: "'a'" , Lang: Lang_CXX03, AMatcher: characterLiteral()); |
2054 | EXPECT_TRUE(testStructuralMatch(t)); |
2055 | } |
2056 | |
2057 | TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) { |
2058 | auto t = makeWrappedStmts(SrcCode0: "'a'" , SrcCode1: "'b'" , Lang: Lang_CXX03, AMatcher: characterLiteral()); |
2059 | EXPECT_FALSE(testStructuralMatch(t)); |
2060 | } |
2061 | |
2062 | TEST_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 | |
2068 | TEST_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 | |
2074 | TEST_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 | |
2079 | TEST_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 | |
2086 | TEST_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 | |
2091 | TEST_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 | |
2096 | TEST_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 | |
2103 | TEST_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 | |
2110 | TEST_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 | |
2117 | TEST_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 | |
2139 | TEST_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 | } |
2162 | TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) { |
2163 | auto t = makeWrappedStmts(SrcCode0: "1" , SrcCode1: "1" , Lang: Lang_CXX03, AMatcher: integerLiteral()); |
2164 | EXPECT_TRUE(testStructuralMatch(t)); |
2165 | } |
2166 | |
2167 | TEST_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 | |
2173 | TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) { |
2174 | auto t = makeWrappedStmts(SrcCode0: "1" , SrcCode1: "2" , Lang: Lang_CXX03, AMatcher: integerLiteral()); |
2175 | EXPECT_FALSE(testStructuralMatch(t)); |
2176 | } |
2177 | |
2178 | TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) { |
2179 | auto t = makeWrappedStmts(SrcCode0: "1" , SrcCode1: "1L" , Lang: Lang_CXX03, AMatcher: integerLiteral()); |
2180 | EXPECT_FALSE(testStructuralMatch(t)); |
2181 | } |
2182 | |
2183 | TEST_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 | |
2191 | TEST_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 | |
2199 | TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) { |
2200 | auto t = |
2201 | makeWrappedStmts(SrcCode0: "@\"a\"" , SrcCode1: "@\"a\"" , Lang: Lang_OBJCXX, AMatcher: fallbackExprMatcher()); |
2202 | EXPECT_TRUE(testStructuralMatch(t)); |
2203 | } |
2204 | |
2205 | TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) { |
2206 | auto t = |
2207 | makeWrappedStmts(SrcCode0: "@\"a\"" , SrcCode1: "@\"b\"" , Lang: Lang_OBJCXX, AMatcher: fallbackExprMatcher()); |
2208 | EXPECT_FALSE(testStructuralMatch(t)); |
2209 | } |
2210 | |
2211 | TEST_F(StructuralEquivalenceStmtTest, StringLiteral) { |
2212 | auto t = makeWrappedStmts(SrcCode0: "\"a\"" , SrcCode1: "\"a\"" , Lang: Lang_CXX03, AMatcher: stringLiteral()); |
2213 | EXPECT_TRUE(testStructuralMatch(t)); |
2214 | } |
2215 | |
2216 | TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) { |
2217 | auto t = makeWrappedStmts(SrcCode0: "\"a\"" , SrcCode1: "\"b\"" , Lang: Lang_CXX03, AMatcher: stringLiteral()); |
2218 | EXPECT_FALSE(testStructuralMatch(t)); |
2219 | } |
2220 | |
2221 | TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) { |
2222 | auto t = makeWrappedStmts(SrcCode0: "\"a\"" , SrcCode1: "\"aa\"" , Lang: Lang_CXX03, AMatcher: stringLiteral()); |
2223 | EXPECT_FALSE(testStructuralMatch(t)); |
2224 | } |
2225 | |
2226 | TEST_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 | |
2232 | TEST_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 | |
2238 | TEST_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 | |
2244 | TEST_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 | |
2250 | TEST_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 | |
2256 | TEST_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 | |
2262 | TEST_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 | |
2268 | TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) { |
2269 | auto t = makeWrappedStmts(SrcCode0: "+1" , SrcCode1: "+1" , Lang: Lang_CXX03, AMatcher: unaryOperator()); |
2270 | EXPECT_TRUE(testStructuralMatch(t)); |
2271 | } |
2272 | |
2273 | TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) { |
2274 | auto t = makeWrappedStmts(SrcCode0: "+1" , SrcCode1: "-1" , Lang: Lang_CXX03, AMatcher: unaryOperator()); |
2275 | EXPECT_FALSE(testStructuralMatch(t)); |
2276 | } |
2277 | |
2278 | TEST_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 | |
2402 | TEST_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 | |
2429 | TEST_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 | |
2448 | TEST_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 | |
2470 | TEST_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 | |
2502 | TEST_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 | |
2533 | TEST_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 | |
2571 | TEST_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 | |
2589 | TEST_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 | |