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