1 //===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Tests for the correct import of AST nodes from one AST context to another.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "clang/ASTMatchers/ASTMatchers.h"
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/Support/SmallVectorMemoryBuffer.h"
16
17 #include "clang/AST/DeclContextInternals.h"
18 #include "gtest/gtest.h"
19
20 #include "ASTImporterFixtures.h"
21
22 namespace clang {
23 namespace ast_matchers {
24
25 using internal::Matcher;
26 using internal::BindableMatcher;
27 using llvm::StringMap;
28
getRecordDeclOfFriend(FriendDecl * FD)29 static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
30 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
31 return cast<RecordType>(Ty)->getDecl();
32 }
33
34 struct ImportExpr : TestImportBase {};
35 struct ImportType : TestImportBase {};
36 struct ImportDecl : TestImportBase {};
37 struct ImportFixedPointExpr : ImportExpr {};
38
39 struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
40
TEST_P(CanonicalRedeclChain,ShouldBeConsequentWithMatchers)41 TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
42 Decl *FromTU = getTuDecl("void f();", Lang_CXX03);
43 auto Pattern = functionDecl(hasName("f"));
44 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
45
46 auto Redecls = getCanonicalForwardRedeclChain(D0);
47 ASSERT_EQ(Redecls.size(), 1u);
48 EXPECT_EQ(D0, Redecls[0]);
49 }
50
TEST_P(CanonicalRedeclChain,ShouldBeConsequentWithMatchers2)51 TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
52 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);
53 auto Pattern = functionDecl(hasName("f"));
54 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
55 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
56 FunctionDecl *D1 = D2->getPreviousDecl();
57
58 auto Redecls = getCanonicalForwardRedeclChain(D0);
59 ASSERT_EQ(Redecls.size(), 3u);
60 EXPECT_EQ(D0, Redecls[0]);
61 EXPECT_EQ(D1, Redecls[1]);
62 EXPECT_EQ(D2, Redecls[2]);
63 }
64
TEST_P(CanonicalRedeclChain,ShouldBeSameForAllDeclInTheChain)65 TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
66 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);
67 auto Pattern = functionDecl(hasName("f"));
68 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
69 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
70 FunctionDecl *D1 = D2->getPreviousDecl();
71
72 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
73 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
74 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
75
76 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
77 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
78 }
79
80 namespace {
81 struct RedirectingImporter : public ASTImporter {
82 using ASTImporter::ASTImporter;
83
84 protected:
ImportImplclang::ast_matchers::__anone9d694570111::RedirectingImporter85 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
86 auto *ND = dyn_cast<NamedDecl>(FromD);
87 if (!ND || ND->getName() != "shouldNotBeImported")
88 return ASTImporter::ImportImpl(FromD);
89 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
90 if (auto *ND = dyn_cast<NamedDecl>(D))
91 if (ND->getName() == "realDecl") {
92 RegisterImportedDecl(FromD, ND);
93 return ND;
94 }
95 }
96 return ASTImporter::ImportImpl(FromD);
97 }
98 };
99
100 } // namespace
101
102 struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
RedirectingImporterTestclang::ast_matchers::RedirectingImporterTest103 RedirectingImporterTest() {
104 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
105 ASTContext &FromContext, FileManager &FromFileManager,
106 bool MinimalImport,
107 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
108 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
109 FromFileManager, MinimalImport,
110 SharedState);
111 };
112 }
113 };
114
115 // Test that an ASTImporter subclass can intercept an import call.
TEST_P(RedirectingImporterTest,InterceptImport)116 TEST_P(RedirectingImporterTest, InterceptImport) {
117 Decl *From, *To;
118 std::tie(From, To) =
119 getImportedDecl("class shouldNotBeImported {};", Lang_CXX03,
120 "class realDecl {};", Lang_CXX03, "shouldNotBeImported");
121 auto *Imported = cast<CXXRecordDecl>(To);
122 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
123
124 // Make sure our importer prevented the importing of the decl.
125 auto *ToTU = Imported->getTranslationUnitDecl();
126 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
127 unsigned count =
128 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
129 EXPECT_EQ(0U, count);
130 }
131
132 // Test that when we indirectly import a declaration the custom ASTImporter
133 // is still intercepting the import.
TEST_P(RedirectingImporterTest,InterceptIndirectImport)134 TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
135 Decl *From, *To;
136 std::tie(From, To) =
137 getImportedDecl("class shouldNotBeImported {};"
138 "class F { shouldNotBeImported f; };",
139 Lang_CXX03, "class realDecl {};", Lang_CXX03, "F");
140
141 // Make sure our ASTImporter prevented the importing of the decl.
142 auto *ToTU = To->getTranslationUnitDecl();
143 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
144 unsigned count =
145 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
146 EXPECT_EQ(0U, count);
147 }
148
149 struct ImportPath : ASTImporterOptionSpecificTestBase {
150 Decl *FromTU;
151 FunctionDecl *D0, *D1, *D2;
ImportPathclang::ast_matchers::ImportPath152 ImportPath() {
153 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);
154 auto Pattern = functionDecl(hasName("f"));
155 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
156 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
157 D1 = D2->getPreviousDecl();
158 }
159 };
160
TEST_P(ImportPath,Push)161 TEST_P(ImportPath, Push) {
162 ASTImporter::ImportPathTy path;
163 path.push(D0);
164 EXPECT_FALSE(path.hasCycleAtBack());
165 }
166
TEST_P(ImportPath,SmallCycle)167 TEST_P(ImportPath, SmallCycle) {
168 ASTImporter::ImportPathTy path;
169 path.push(D0);
170 path.push(D0);
171 EXPECT_TRUE(path.hasCycleAtBack());
172 path.pop();
173 EXPECT_FALSE(path.hasCycleAtBack());
174 path.push(D0);
175 EXPECT_TRUE(path.hasCycleAtBack());
176 }
177
TEST_P(ImportPath,GetSmallCycle)178 TEST_P(ImportPath, GetSmallCycle) {
179 ASTImporter::ImportPathTy path;
180 path.push(D0);
181 path.push(D0);
182 EXPECT_TRUE(path.hasCycleAtBack());
183 std::array<Decl* ,2> Res;
184 int i = 0;
185 for (Decl *Di : path.getCycleAtBack()) {
186 Res[i++] = Di;
187 }
188 ASSERT_EQ(i, 2);
189 EXPECT_EQ(Res[0], D0);
190 EXPECT_EQ(Res[1], D0);
191 }
192
TEST_P(ImportPath,GetCycle)193 TEST_P(ImportPath, GetCycle) {
194 ASTImporter::ImportPathTy path;
195 path.push(D0);
196 path.push(D1);
197 path.push(D2);
198 path.push(D0);
199 EXPECT_TRUE(path.hasCycleAtBack());
200 std::array<Decl* ,4> Res;
201 int i = 0;
202 for (Decl *Di : path.getCycleAtBack()) {
203 Res[i++] = Di;
204 }
205 ASSERT_EQ(i, 4);
206 EXPECT_EQ(Res[0], D0);
207 EXPECT_EQ(Res[1], D2);
208 EXPECT_EQ(Res[2], D1);
209 EXPECT_EQ(Res[3], D0);
210 }
211
TEST_P(ImportPath,CycleAfterCycle)212 TEST_P(ImportPath, CycleAfterCycle) {
213 ASTImporter::ImportPathTy path;
214 path.push(D0);
215 path.push(D1);
216 path.push(D0);
217 path.push(D1);
218 path.push(D2);
219 path.push(D0);
220 EXPECT_TRUE(path.hasCycleAtBack());
221 std::array<Decl* ,4> Res;
222 int i = 0;
223 for (Decl *Di : path.getCycleAtBack()) {
224 Res[i++] = Di;
225 }
226 ASSERT_EQ(i, 4);
227 EXPECT_EQ(Res[0], D0);
228 EXPECT_EQ(Res[1], D2);
229 EXPECT_EQ(Res[2], D1);
230 EXPECT_EQ(Res[3], D0);
231
232 path.pop();
233 path.pop();
234 path.pop();
235 EXPECT_TRUE(path.hasCycleAtBack());
236 i = 0;
237 for (Decl *Di : path.getCycleAtBack()) {
238 Res[i++] = Di;
239 }
240 ASSERT_EQ(i, 3);
241 EXPECT_EQ(Res[0], D0);
242 EXPECT_EQ(Res[1], D1);
243 EXPECT_EQ(Res[2], D0);
244
245 path.pop();
246 EXPECT_FALSE(path.hasCycleAtBack());
247 }
248
TEST_P(ImportExpr,ImportStringLiteral)249 TEST_P(ImportExpr, ImportStringLiteral) {
250 MatchVerifier<Decl> Verifier;
251 testImport("void declToImport() { (void)\"foo\"; }", Lang_CXX03, "",
252 Lang_CXX03, Verifier,
253 functionDecl(hasDescendant(
254 stringLiteral(hasType(asString("const char [4]"))))));
255 testImport("void declToImport() { (void)L\"foo\"; }", Lang_CXX03, "",
256 Lang_CXX03, Verifier,
257 functionDecl(hasDescendant(
258 stringLiteral(hasType(asString("const wchar_t [4]"))))));
259 testImport("void declToImport() { (void) \"foo\" \"bar\"; }", Lang_CXX03, "",
260 Lang_CXX03, Verifier,
261 functionDecl(hasDescendant(
262 stringLiteral(hasType(asString("const char [7]"))))));
263 }
264
TEST_P(ImportExpr,ImportChooseExpr)265 TEST_P(ImportExpr, ImportChooseExpr) {
266 MatchVerifier<Decl> Verifier;
267
268 // This case tests C code that is not condition-dependent and has a true
269 // condition.
270 testImport("void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
271 Lang_C99, "", Lang_C99, Verifier,
272 functionDecl(hasDescendant(chooseExpr())));
273 }
274
TEST_P(ImportExpr,ImportGNUNullExpr)275 TEST_P(ImportExpr, ImportGNUNullExpr) {
276 MatchVerifier<Decl> Verifier;
277 testImport("void declToImport() { (void)__null; }", Lang_CXX03, "",
278 Lang_CXX03, Verifier,
279 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
280 }
281
TEST_P(ImportExpr,ImportCXXNullPtrLiteralExpr)282 TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
283 MatchVerifier<Decl> Verifier;
284 testImport(
285 "void declToImport() { (void)nullptr; }",
286 Lang_CXX11, "", Lang_CXX11, Verifier,
287 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
288 }
289
290
TEST_P(ImportExpr,ImportFloatinglLiteralExpr)291 TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
292 MatchVerifier<Decl> Verifier;
293 testImport("void declToImport() { (void)1.0; }", Lang_C99, "", Lang_C99,
294 Verifier,
295 functionDecl(hasDescendant(
296 floatLiteral(equals(1.0), hasType(asString("double"))))));
297 testImport("void declToImport() { (void)1.0e-5f; }", Lang_C99, "", Lang_C99,
298 Verifier,
299 functionDecl(hasDescendant(
300 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
301 }
302
TEST_P(ImportFixedPointExpr,ImportFixedPointerLiteralExpr)303 TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {
304 MatchVerifier<Decl> Verifier;
305 testImport("void declToImport() { (void)1.0k; }", Lang_C99, "", Lang_C99,
306 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
307 testImport("void declToImport() { (void)0.75r; }", Lang_C99, "", Lang_C99,
308 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
309 }
310
TEST_P(ImportExpr,ImportImaginaryLiteralExpr)311 TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
312 MatchVerifier<Decl> Verifier;
313 testImport(
314 "void declToImport() { (void)1.0i; }",
315 Lang_CXX14, "", Lang_CXX14, Verifier,
316 functionDecl(hasDescendant(imaginaryLiteral())));
317 }
318
TEST_P(ImportExpr,ImportCompoundLiteralExpr)319 TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
320 MatchVerifier<Decl> Verifier;
321 testImport("void declToImport() {"
322 " struct s { int x; long y; unsigned z; }; "
323 " (void)(struct s){ 42, 0L, 1U }; }",
324 Lang_CXX03, "", Lang_CXX03, Verifier,
325 functionDecl(hasDescendant(compoundLiteralExpr(
326 hasType(asString("struct s")),
327 has(initListExpr(
328 hasType(asString("struct s")),
329 has(integerLiteral(equals(42), hasType(asString("int")))),
330 has(integerLiteral(equals(0), hasType(asString("long")))),
331 has(integerLiteral(
332 equals(1), hasType(asString("unsigned int"))))))))));
333 }
334
TEST_P(ImportExpr,ImportCXXThisExpr)335 TEST_P(ImportExpr, ImportCXXThisExpr) {
336 MatchVerifier<Decl> Verifier;
337 testImport("class declToImport { void f() { (void)this; } };", Lang_CXX03, "",
338 Lang_CXX03, Verifier,
339 cxxRecordDecl(hasMethod(hasDescendant(
340 cxxThisExpr(hasType(asString("class declToImport *")))))));
341 }
342
TEST_P(ImportExpr,ImportAtomicExpr)343 TEST_P(ImportExpr, ImportAtomicExpr) {
344 MatchVerifier<Decl> Verifier;
345 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
346 Lang_C99, "", Lang_C99, Verifier,
347 functionDecl(hasDescendant(atomicExpr(
348 has(ignoringParenImpCasts(
349 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
350 hasType(asString("int *"))))),
351 has(integerLiteral(equals(1), hasType(asString("int"))))))));
352 }
353
TEST_P(ImportExpr,ImportLabelDeclAndAddrLabelExpr)354 TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
355 MatchVerifier<Decl> Verifier;
356 testImport("void declToImport() { loop: goto loop; (void)&&loop; }", Lang_C99,
357 "", Lang_C99, Verifier,
358 functionDecl(hasDescendant(labelStmt(
359 hasDeclaration(labelDecl(hasName("loop"))))),
360 hasDescendant(addrLabelExpr(
361 hasDeclaration(labelDecl(hasName("loop")))))));
362 }
363
AST_MATCHER_P(TemplateDecl,hasTemplateDecl,internal::Matcher<NamedDecl>,InnerMatcher)364 AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
365 internal::Matcher<NamedDecl>, InnerMatcher) {
366 const NamedDecl *Template = Node.getTemplatedDecl();
367 return Template && InnerMatcher.matches(*Template, Finder, Builder);
368 }
369
TEST_P(ImportExpr,ImportParenListExpr)370 TEST_P(ImportExpr, ImportParenListExpr) {
371 MatchVerifier<Decl> Verifier;
372 testImport(
373 "template<typename T> class dummy { void f() { dummy X(*this); } };"
374 "typedef dummy<int> declToImport;"
375 "template class dummy<int>;",
376 Lang_CXX03, "", Lang_CXX03, Verifier,
377 typedefDecl(hasType(templateSpecializationType(
378 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
379 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
380 hasName("f"),
381 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
382 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
383 hasOperatorName("*"),
384 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
385 }
386
TEST_P(ImportExpr,ImportSwitch)387 TEST_P(ImportExpr, ImportSwitch) {
388 MatchVerifier<Decl> Verifier;
389 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
390 Lang_C99, "", Lang_C99, Verifier,
391 functionDecl(hasDescendant(
392 switchStmt(has(compoundStmt(has(caseStmt())))))));
393 }
394
TEST_P(ImportExpr,ImportStmtExpr)395 TEST_P(ImportExpr, ImportStmtExpr) {
396 MatchVerifier<Decl> Verifier;
397 testImport(
398 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
399 Lang_C99, "", Lang_C99, Verifier,
400 traverse(ast_type_traits::TK_AsIs,
401 functionDecl(hasDescendant(varDecl(
402 hasName("C"), hasType(asString("int")),
403 hasInitializer(stmtExpr(
404 hasAnySubstatement(declStmt(hasSingleDecl(varDecl(
405 hasName("X"), hasType(asString("int")),
406 hasInitializer(integerLiteral(equals(4))))))),
407 hasDescendant(implicitCastExpr()))))))));
408 }
409
TEST_P(ImportExpr,ImportConditionalOperator)410 TEST_P(ImportExpr, ImportConditionalOperator) {
411 MatchVerifier<Decl> Verifier;
412 testImport("void declToImport() { (void)(true ? 1 : -5); }", Lang_CXX03, "",
413 Lang_CXX03, Verifier,
414 functionDecl(hasDescendant(conditionalOperator(
415 hasCondition(cxxBoolLiteral(equals(true))),
416 hasTrueExpression(integerLiteral(equals(1))),
417 hasFalseExpression(unaryOperator(
418 hasUnaryOperand(integerLiteral(equals(5)))))))));
419 }
420
TEST_P(ImportExpr,ImportBinaryConditionalOperator)421 TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
422 MatchVerifier<Decl> Verifier;
423 testImport(
424 "void declToImport() { (void)(1 ?: -5); }", Lang_CXX03, "", Lang_CXX03,
425 Verifier,
426 traverse(ast_type_traits::TK_AsIs,
427 functionDecl(hasDescendant(binaryConditionalOperator(
428 hasCondition(implicitCastExpr(
429 hasSourceExpression(opaqueValueExpr(
430 hasSourceExpression(integerLiteral(equals(1))))),
431 hasType(booleanType()))),
432 hasTrueExpression(opaqueValueExpr(
433 hasSourceExpression(integerLiteral(equals(1))))),
434 hasFalseExpression(unaryOperator(
435 hasOperatorName("-"),
436 hasUnaryOperand(integerLiteral(equals(5))))))))));
437 }
438
TEST_P(ImportExpr,ImportDesignatedInitExpr)439 TEST_P(ImportExpr, ImportDesignatedInitExpr) {
440 MatchVerifier<Decl> Verifier;
441 testImport(
442 "void declToImport() {"
443 " struct point { double x; double y; };"
444 " struct point ptarray[10] = "
445 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
446 Lang_C99, "", Lang_C99, Verifier,
447 functionDecl(hasDescendant(initListExpr(
448 has(designatedInitExpr(designatorCountIs(2),
449 hasDescendant(floatLiteral(equals(1.0))),
450 hasDescendant(integerLiteral(equals(2))))),
451 has(designatedInitExpr(designatorCountIs(2),
452 hasDescendant(floatLiteral(equals(2.0))),
453 hasDescendant(integerLiteral(equals(2))))),
454 has(designatedInitExpr(designatorCountIs(2),
455 hasDescendant(floatLiteral(equals(1.0))),
456 hasDescendant(integerLiteral(equals(0)))))))));
457 }
458
TEST_P(ImportExpr,ImportPredefinedExpr)459 TEST_P(ImportExpr, ImportPredefinedExpr) {
460 MatchVerifier<Decl> Verifier;
461 // __func__ expands as StringLiteral("declToImport")
462 testImport("void declToImport() { (void)__func__; }", Lang_CXX03, "",
463 Lang_CXX03, Verifier,
464 functionDecl(hasDescendant(predefinedExpr(
465 hasType(asString("const char [13]")),
466 has(stringLiteral(hasType(asString("const char [13]"))))))));
467 }
468
TEST_P(ImportExpr,ImportInitListExpr)469 TEST_P(ImportExpr, ImportInitListExpr) {
470 MatchVerifier<Decl> Verifier;
471 testImport(
472 "void declToImport() {"
473 " struct point { double x; double y; };"
474 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
475 " [0].x = 1.0 }; }",
476 Lang_CXX03, "", Lang_CXX03, Verifier,
477 functionDecl(hasDescendant(initListExpr(
478 has(cxxConstructExpr(requiresZeroInitialization())),
479 has(initListExpr(
480 hasType(asString("struct point")), has(floatLiteral(equals(1.0))),
481 has(implicitValueInitExpr(hasType(asString("double")))))),
482 has(initListExpr(hasType(asString("struct point")),
483 has(floatLiteral(equals(2.0))),
484 has(floatLiteral(equals(1.0)))))))));
485 }
486
487
488 const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
489
TEST_P(ImportExpr,ImportVAArgExpr)490 TEST_P(ImportExpr, ImportVAArgExpr) {
491 MatchVerifier<Decl> Verifier;
492 testImport("void declToImport(__builtin_va_list list, ...) {"
493 " (void)__builtin_va_arg(list, int); }",
494 Lang_CXX03, "", Lang_CXX03, Verifier,
495 functionDecl(hasDescendant(
496 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
497 }
498
TEST_P(ImportExpr,CXXTemporaryObjectExpr)499 TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
500 MatchVerifier<Decl> Verifier;
501 testImport(
502 "struct C {};"
503 "void declToImport() { C c = C(); }",
504 Lang_CXX03, "", Lang_CXX03, Verifier,
505 traverse(ast_type_traits::TK_AsIs,
506 functionDecl(hasDescendant(exprWithCleanups(has(cxxConstructExpr(
507 has(materializeTemporaryExpr(has(implicitCastExpr(
508 has(cxxTemporaryObjectExpr()))))))))))));
509 }
510
TEST_P(ImportType,ImportAtomicType)511 TEST_P(ImportType, ImportAtomicType) {
512 MatchVerifier<Decl> Verifier;
513 testImport(
514 "void declToImport() { typedef _Atomic(int) a_int; }",
515 Lang_CXX11, "", Lang_CXX11, Verifier,
516 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
517 }
518
TEST_P(ImportDecl,ImportFunctionTemplateDecl)519 TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
520 MatchVerifier<Decl> Verifier;
521 testImport("template <typename T> void declToImport() { };", Lang_CXX03, "",
522 Lang_CXX03, Verifier, functionTemplateDecl());
523 }
524
TEST_P(ImportExpr,ImportCXXDependentScopeMemberExpr)525 TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
526 MatchVerifier<Decl> Verifier;
527 testImport("template <typename T> struct C { T t; };"
528 "template <typename T> void declToImport() {"
529 " C<T> d;"
530 " (void)d.t;"
531 "}"
532 "void instantiate() { declToImport<int>(); }",
533 Lang_CXX03, "", Lang_CXX03, Verifier,
534 functionTemplateDecl(hasDescendant(
535 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
536 testImport("template <typename T> struct C { T t; };"
537 "template <typename T> void declToImport() {"
538 " C<T> d;"
539 " (void)(&d)->t;"
540 "}"
541 "void instantiate() { declToImport<int>(); }",
542 Lang_CXX03, "", Lang_CXX03, Verifier,
543 functionTemplateDecl(hasDescendant(
544 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
545 }
546
TEST_P(ImportType,ImportTypeAliasTemplate)547 TEST_P(ImportType, ImportTypeAliasTemplate) {
548 MatchVerifier<Decl> Verifier;
549 testImport(
550 "template <int K>"
551 "struct dummy { static const int i = K; };"
552 "template <int K> using dummy2 = dummy<K>;"
553 "int declToImport() { return dummy2<3>::i; }",
554 Lang_CXX11, "", Lang_CXX11, Verifier,
555 traverse(ast_type_traits::TK_AsIs,
556 functionDecl(hasDescendant(implicitCastExpr(has(declRefExpr()))),
557 unless(hasAncestor(
558 translationUnitDecl(has(typeAliasDecl())))))));
559 }
560
561 const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
562 varTemplateSpecializationDecl;
563
TEST_P(ImportDecl,ImportVarTemplate)564 TEST_P(ImportDecl, ImportVarTemplate) {
565 MatchVerifier<Decl> Verifier;
566 testImport(
567 "template <typename T>"
568 "T pi = T(3.1415926535897932385L);"
569 "void declToImport() { (void)pi<int>; }",
570 Lang_CXX14, "", Lang_CXX14, Verifier,
571 functionDecl(
572 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
573 unless(hasAncestor(translationUnitDecl(has(varDecl(
574 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
575 }
576
TEST_P(ImportType,ImportPackExpansion)577 TEST_P(ImportType, ImportPackExpansion) {
578 MatchVerifier<Decl> Verifier;
579 testImport("template <typename... Args>"
580 "struct dummy {"
581 " dummy(Args... args) {}"
582 " static const int i = 4;"
583 "};"
584 "int declToImport() { return dummy<int>::i; }",
585 Lang_CXX11, "", Lang_CXX11, Verifier,
586 traverse(ast_type_traits::TK_AsIs,
587 functionDecl(hasDescendant(returnStmt(
588 has(implicitCastExpr(has(declRefExpr()))))))));
589 }
590
591 const internal::VariadicDynCastAllOfMatcher<Type,
592 DependentTemplateSpecializationType>
593 dependentTemplateSpecializationType;
594
TEST_P(ImportType,ImportDependentTemplateSpecialization)595 TEST_P(ImportType, ImportDependentTemplateSpecialization) {
596 MatchVerifier<Decl> Verifier;
597 testImport("template<typename T>"
598 "struct A;"
599 "template<typename T>"
600 "struct declToImport {"
601 " typename A<T>::template B<T> a;"
602 "};",
603 Lang_CXX03, "", Lang_CXX03, Verifier,
604 classTemplateDecl(has(cxxRecordDecl(has(
605 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
606 }
607
608 const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
609 sizeOfPackExpr;
610
TEST_P(ImportExpr,ImportSizeOfPackExpr)611 TEST_P(ImportExpr, ImportSizeOfPackExpr) {
612 MatchVerifier<Decl> Verifier;
613 testImport(
614 "template <typename... Ts>"
615 "void declToImport() {"
616 " const int i = sizeof...(Ts);"
617 "};"
618 "void g() { declToImport<int>(); }",
619 Lang_CXX11, "", Lang_CXX11, Verifier,
620 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
621 testImport(
622 "template <typename... Ts>"
623 "using X = int[sizeof...(Ts)];"
624 "template <typename... Us>"
625 "struct Y {"
626 " X<Us..., int, double, int, Us...> f;"
627 "};"
628 "Y<float, int> declToImport;",
629 Lang_CXX11, "", Lang_CXX11, Verifier,
630 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
631 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
632 }
633
634 /// \brief Matches __builtin_types_compatible_p:
635 /// GNU extension to check equivalent types
636 /// Given
637 /// \code
638 /// __builtin_types_compatible_p(int, int)
639 /// \endcode
640 // will generate TypeTraitExpr <...> 'int'
641 const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
642
TEST_P(ImportExpr,ImportTypeTraitExpr)643 TEST_P(ImportExpr, ImportTypeTraitExpr) {
644 MatchVerifier<Decl> Verifier;
645 testImport(
646 "void declToImport() { "
647 " (void)__builtin_types_compatible_p(int, int);"
648 "}",
649 Lang_C99, "", Lang_C99, Verifier,
650 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
651 }
652
653 const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
654
TEST_P(ImportExpr,ImportCXXTypeidExpr)655 TEST_P(ImportExpr, ImportCXXTypeidExpr) {
656 MatchVerifier<Decl> Verifier;
657 testImport(
658 "namespace std { class type_info {}; }"
659 "void declToImport() {"
660 " int x;"
661 " auto a = typeid(int); auto b = typeid(x);"
662 "}",
663 Lang_CXX11, "", Lang_CXX11, Verifier,
664 traverse(
665 ast_type_traits::TK_AsIs,
666 functionDecl(
667 hasDescendant(varDecl(hasName("a"), hasInitializer(hasDescendant(
668 cxxTypeidExpr())))),
669 hasDescendant(varDecl(hasName("b"), hasInitializer(hasDescendant(
670 cxxTypeidExpr())))))));
671 }
672
TEST_P(ImportExpr,ImportTypeTraitExprValDep)673 TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
674 MatchVerifier<Decl> Verifier;
675 testImport(
676 "template<typename T> struct declToImport {"
677 " void m() { (void)__is_pod(T); }"
678 "};"
679 "void f() { declToImport<int>().m(); }",
680 Lang_CXX11, "", Lang_CXX11, Verifier,
681 classTemplateDecl(has(cxxRecordDecl(has(
682 functionDecl(hasDescendant(
683 typeTraitExpr(hasType(booleanType())))))))));
684 }
685
TEST_P(ImportDecl,ImportRecordDeclInFunc)686 TEST_P(ImportDecl, ImportRecordDeclInFunc) {
687 MatchVerifier<Decl> Verifier;
688 testImport("int declToImport() { "
689 " struct data_t {int a;int b;};"
690 " struct data_t d;"
691 " return 0;"
692 "}",
693 Lang_C99, "", Lang_C99, Verifier,
694 functionDecl(hasBody(compoundStmt(
695 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
696 }
697
TEST_P(ASTImporterOptionSpecificTestBase,ImportRecordTypeInFunc)698 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
699 Decl *FromTU = getTuDecl("int declToImport() { "
700 " struct data_t {int a;int b;};"
701 " struct data_t d;"
702 " return 0;"
703 "}",
704 Lang_C99, "input.c");
705 auto *FromVar =
706 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
707 ASSERT_TRUE(FromVar);
708 auto ToType =
709 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C99);
710 EXPECT_FALSE(ToType.isNull());
711 }
712
TEST_P(ASTImporterOptionSpecificTestBase,ImportRecordDeclInFuncParams)713 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
714 // This construct is not supported by ASTImporter.
715 Decl *FromTU = getTuDecl(
716 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
717 Lang_C99, "input.c");
718 auto *From = FirstDeclMatcher<FunctionDecl>().match(
719 FromTU, functionDecl(hasName("declToImport")));
720 ASSERT_TRUE(From);
721 auto *To = Import(From, Lang_C99);
722 EXPECT_EQ(To, nullptr);
723 }
724
TEST_P(ASTImporterOptionSpecificTestBase,ImportRecordDeclInFuncFromMacro)725 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
726 Decl *FromTU =
727 getTuDecl("#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
728 "int declToImport(){ return NONAME_SIZEOF(int); }",
729 Lang_C99, "input.c");
730 auto *From = FirstDeclMatcher<FunctionDecl>().match(
731 FromTU, functionDecl(hasName("declToImport")));
732 ASSERT_TRUE(From);
733 auto *To = Import(From, Lang_C99);
734 ASSERT_TRUE(To);
735 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
736 To, functionDecl(hasName("declToImport"),
737 hasDescendant(unaryExprOrTypeTraitExpr()))));
738 }
739
TEST_P(ASTImporterOptionSpecificTestBase,ImportRecordDeclInFuncParamsFromMacro)740 TEST_P(ASTImporterOptionSpecificTestBase,
741 ImportRecordDeclInFuncParamsFromMacro) {
742 // This construct is not supported by ASTImporter.
743 Decl *FromTU =
744 getTuDecl("#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
745 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
746 Lang_C99, "input.c");
747 auto *From = FirstDeclMatcher<FunctionDecl>().match(
748 FromTU, functionDecl(hasName("declToImport")));
749 ASSERT_TRUE(From);
750 auto *To = Import(From, Lang_C99);
751 EXPECT_EQ(To, nullptr);
752 }
753
754 const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
755 cxxPseudoDestructorExpr;
756
TEST_P(ImportExpr,ImportCXXPseudoDestructorExpr)757 TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
758 MatchVerifier<Decl> Verifier;
759 testImport(
760 "typedef int T;"
761 "void declToImport(int *p) {"
762 " T t;"
763 " p->T::~T();"
764 "}",
765 Lang_CXX03, "", Lang_CXX03, Verifier,
766 functionDecl(hasDescendant(callExpr(has(cxxPseudoDestructorExpr())))));
767 }
768
TEST_P(ImportDecl,ImportUsingDecl)769 TEST_P(ImportDecl, ImportUsingDecl) {
770 MatchVerifier<Decl> Verifier;
771 testImport("namespace foo { int bar; }"
772 "void declToImport() { using foo::bar; }",
773 Lang_CXX03, "", Lang_CXX03, Verifier,
774 functionDecl(hasDescendant(usingDecl())));
775 }
776
777 /// \brief Matches shadow declarations introduced into a scope by a
778 /// (resolved) using declaration.
779 ///
780 /// Given
781 /// \code
782 /// namespace n { int f; }
783 /// namespace declToImport { using n::f; }
784 /// \endcode
785 /// usingShadowDecl()
786 /// matches \code f \endcode
787 const internal::VariadicDynCastAllOfMatcher<Decl,
788 UsingShadowDecl> usingShadowDecl;
789
TEST_P(ImportDecl,ImportUsingShadowDecl)790 TEST_P(ImportDecl, ImportUsingShadowDecl) {
791 MatchVerifier<Decl> Verifier;
792 testImport("namespace foo { int bar; }"
793 "namespace declToImport { using foo::bar; }",
794 Lang_CXX03, "", Lang_CXX03, Verifier,
795 namespaceDecl(has(usingShadowDecl())));
796 }
797
TEST_P(ImportExpr,ImportUnresolvedLookupExpr)798 TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
799 MatchVerifier<Decl> Verifier;
800 testImport("template<typename T> int foo();"
801 "template <typename T> void declToImport() {"
802 " (void)::foo<T>;"
803 " (void)::template foo<T>;"
804 "}"
805 "void instantiate() { declToImport<int>(); }",
806 Lang_CXX03, "", Lang_CXX03, Verifier,
807 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
808 }
809
TEST_P(ImportExpr,ImportCXXUnresolvedConstructExpr)810 TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
811 MatchVerifier<Decl> Verifier;
812 testImport("template <typename T> struct C { T t; };"
813 "template <typename T> void declToImport() {"
814 " C<T> d;"
815 " d.t = T();"
816 "}"
817 "void instantiate() { declToImport<int>(); }",
818 Lang_CXX03, "", Lang_CXX03, Verifier,
819 functionTemplateDecl(hasDescendant(
820 binaryOperator(has(cxxUnresolvedConstructExpr())))));
821 testImport("template <typename T> struct C { T t; };"
822 "template <typename T> void declToImport() {"
823 " C<T> d;"
824 " (&d)->t = T();"
825 "}"
826 "void instantiate() { declToImport<int>(); }",
827 Lang_CXX03, "", Lang_CXX03, Verifier,
828 functionTemplateDecl(hasDescendant(
829 binaryOperator(has(cxxUnresolvedConstructExpr())))));
830 }
831
832 /// Check that function "declToImport()" (which is the templated function
833 /// for corresponding FunctionTemplateDecl) is not added into DeclContext.
834 /// Same for class template declarations.
TEST_P(ImportDecl,ImportTemplatedDeclForTemplate)835 TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
836 MatchVerifier<Decl> Verifier;
837 testImport("template <typename T> void declToImport() { T a = 1; }"
838 "void instantiate() { declToImport<int>(); }",
839 Lang_CXX03, "", Lang_CXX03, Verifier,
840 functionTemplateDecl(hasAncestor(translationUnitDecl(
841 unless(has(functionDecl(hasName("declToImport"))))))));
842 testImport("template <typename T> struct declToImport { T t; };"
843 "void instantiate() { declToImport<int>(); }",
844 Lang_CXX03, "", Lang_CXX03, Verifier,
845 classTemplateDecl(hasAncestor(translationUnitDecl(
846 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
847 }
848
TEST_P(ImportDecl,ImportClassTemplatePartialSpecialization)849 TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
850 MatchVerifier<Decl> Verifier;
851 auto Code =
852 R"s(
853 struct declToImport {
854 template <typename T0> struct X;
855 template <typename T0> struct X<T0 *> {};
856 };
857 )s";
858 testImport(Code, Lang_CXX03, "", Lang_CXX03, Verifier,
859 recordDecl(has(classTemplateDecl()),
860 has(classTemplateSpecializationDecl())));
861 }
862
TEST_P(ImportExpr,CXXOperatorCallExpr)863 TEST_P(ImportExpr, CXXOperatorCallExpr) {
864 MatchVerifier<Decl> Verifier;
865 testImport(
866 "class declToImport {"
867 " void f() { *this = declToImport(); }"
868 "};",
869 Lang_CXX03, "", Lang_CXX03, Verifier,
870 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(cxxOperatorCallExpr())))));
871 }
872
TEST_P(ImportExpr,DependentSizedArrayType)873 TEST_P(ImportExpr, DependentSizedArrayType) {
874 MatchVerifier<Decl> Verifier;
875 testImport("template<typename T, int Size> class declToImport {"
876 " T data[Size];"
877 "};",
878 Lang_CXX03, "", Lang_CXX03, Verifier,
879 classTemplateDecl(has(cxxRecordDecl(
880 has(fieldDecl(hasType(dependentSizedArrayType())))))));
881 }
882
TEST_P(ASTImporterOptionSpecificTestBase,TemplateTypeParmDeclNoDefaultArg)883 TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) {
884 Decl *FromTU = getTuDecl("template<typename T> struct X {};", Lang_CXX03);
885 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
886 FromTU, templateTypeParmDecl(hasName("T")));
887 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
888 ASSERT_FALSE(To->hasDefaultArgument());
889 }
890
TEST_P(ASTImporterOptionSpecificTestBase,TemplateTypeParmDeclDefaultArg)891 TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) {
892 Decl *FromTU =
893 getTuDecl("template<typename T = int> struct X {};", Lang_CXX03);
894 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
895 FromTU, templateTypeParmDecl(hasName("T")));
896 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
897 ASSERT_TRUE(To->hasDefaultArgument());
898 QualType ToArg = To->getDefaultArgument();
899 ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy));
900 }
901
TEST_P(ASTImporterOptionSpecificTestBase,ImportBeginLocOfDeclRefExpr)902 TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
903 Decl *FromTU =
904 getTuDecl("class A { public: static int X; }; void f() { (void)A::X; }",
905 Lang_CXX03);
906 auto From = FirstDeclMatcher<FunctionDecl>().match(
907 FromTU, functionDecl(hasName("f")));
908 ASSERT_TRUE(From);
909 ASSERT_TRUE(
910 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
911 ->getSubExpr()
912 ->getBeginLoc()
913 .isValid());
914 FunctionDecl *To = Import(From, Lang_CXX03);
915 ASSERT_TRUE(To);
916 ASSERT_TRUE(
917 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
918 ->getSubExpr()
919 ->getBeginLoc()
920 .isValid());
921 }
922
TEST_P(ASTImporterOptionSpecificTestBase,TemplateTemplateParmDeclNoDefaultArg)923 TEST_P(ASTImporterOptionSpecificTestBase,
924 TemplateTemplateParmDeclNoDefaultArg) {
925 Decl *FromTU = getTuDecl(R"(
926 template<template<typename> typename TT> struct Y {};
927 )",
928 Lang_CXX17);
929 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
930 FromTU, templateTemplateParmDecl(hasName("TT")));
931 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
932 ASSERT_FALSE(To->hasDefaultArgument());
933 }
934
TEST_P(ASTImporterOptionSpecificTestBase,TemplateTemplateParmDeclDefaultArg)935 TEST_P(ASTImporterOptionSpecificTestBase, TemplateTemplateParmDeclDefaultArg) {
936 Decl *FromTU = getTuDecl(R"(
937 template<typename T> struct X {};
938 template<template<typename> typename TT = X> struct Y {};
939 )",
940 Lang_CXX17);
941 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
942 FromTU, templateTemplateParmDecl(hasName("TT")));
943 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
944 ASSERT_TRUE(To->hasDefaultArgument());
945 const TemplateArgument &ToDefaultArg = To->getDefaultArgument().getArgument();
946 ASSERT_TRUE(To->isTemplateDecl());
947 TemplateDecl *ToTemplate = ToDefaultArg.getAsTemplate().getAsTemplateDecl();
948
949 // Find the default argument template 'X' in the AST and compare it against
950 // the default argument we got.
951 auto ToExpectedDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
952 To->getTranslationUnitDecl(), classTemplateDecl(hasName("X")));
953 ASSERT_EQ(ToTemplate, ToExpectedDecl);
954 }
955
TEST_P(ASTImporterOptionSpecificTestBase,NonTypeTemplateParmDeclNoDefaultArg)956 TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclNoDefaultArg) {
957 Decl *FromTU = getTuDecl("template<int N> struct X {};", Lang_CXX03);
958 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
959 FromTU, nonTypeTemplateParmDecl(hasName("N")));
960 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
961 ASSERT_FALSE(To->hasDefaultArgument());
962 }
963
TEST_P(ASTImporterOptionSpecificTestBase,NonTypeTemplateParmDeclDefaultArg)964 TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {
965 Decl *FromTU = getTuDecl("template<int S = 1> struct X {};", Lang_CXX03);
966 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
967 FromTU, nonTypeTemplateParmDecl(hasName("S")));
968 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
969 ASSERT_TRUE(To->hasDefaultArgument());
970 Stmt *ToArg = To->getDefaultArgument();
971 ASSERT_TRUE(isa<ConstantExpr>(ToArg));
972 ToArg = *ToArg->child_begin();
973 ASSERT_TRUE(isa<IntegerLiteral>(ToArg));
974 ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);
975 }
976
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfTemplatedDeclOfClassTemplateDecl)977 TEST_P(ASTImporterOptionSpecificTestBase,
978 ImportOfTemplatedDeclOfClassTemplateDecl) {
979 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);
980 auto From =
981 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
982 ASSERT_TRUE(From);
983 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX03));
984 ASSERT_TRUE(To);
985 Decl *ToTemplated = To->getTemplatedDecl();
986 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
987 EXPECT_TRUE(ToTemplated1);
988 EXPECT_EQ(ToTemplated1, ToTemplated);
989 }
990
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfTemplatedDeclOfFunctionTemplateDecl)991 TEST_P(ASTImporterOptionSpecificTestBase,
992 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
993 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);
994 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
995 FromTU, functionTemplateDecl());
996 ASSERT_TRUE(From);
997 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX03));
998 ASSERT_TRUE(To);
999 Decl *ToTemplated = To->getTemplatedDecl();
1000 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1001 EXPECT_TRUE(ToTemplated1);
1002 EXPECT_EQ(ToTemplated1, ToTemplated);
1003 }
1004
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfTemplatedDeclShouldImportTheClassTemplateDecl)1005 TEST_P(ASTImporterOptionSpecificTestBase,
1006 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1007 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);
1008 auto FromFT =
1009 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1010 ASSERT_TRUE(FromFT);
1011
1012 auto ToTemplated =
1013 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1014 EXPECT_TRUE(ToTemplated);
1015 auto ToTU = ToTemplated->getTranslationUnitDecl();
1016 auto ToFT =
1017 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1018 EXPECT_TRUE(ToFT);
1019 }
1020
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl)1021 TEST_P(ASTImporterOptionSpecificTestBase,
1022 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1023 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);
1024 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1025 FromTU, functionTemplateDecl());
1026 ASSERT_TRUE(FromFT);
1027
1028 auto ToTemplated =
1029 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1030 EXPECT_TRUE(ToTemplated);
1031 auto ToTU = ToTemplated->getTranslationUnitDecl();
1032 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1033 ToTU, functionTemplateDecl());
1034 EXPECT_TRUE(ToFT);
1035 }
1036
TEST_P(ASTImporterOptionSpecificTestBase,ImportCorrectTemplatedDecl)1037 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
1038 auto Code =
1039 R"(
1040 namespace x {
1041 template<class X> struct S1{};
1042 template<class X> struct S2{};
1043 template<class X> struct S3{};
1044 }
1045 )";
1046 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1047 auto FromNs =
1048 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1049 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX03));
1050 ASSERT_TRUE(ToNs);
1051 auto From =
1052 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1053 classTemplateDecl(
1054 hasName("S2")));
1055 auto To =
1056 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1057 classTemplateDecl(
1058 hasName("S2")));
1059 ASSERT_TRUE(From);
1060 ASSERT_TRUE(To);
1061 auto ToTemplated = To->getTemplatedDecl();
1062 auto ToTemplated1 =
1063 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX03));
1064 EXPECT_TRUE(ToTemplated1);
1065 ASSERT_EQ(ToTemplated1, ToTemplated);
1066 }
1067
TEST_P(ASTImporterOptionSpecificTestBase,ImportChooseExpr)1068 TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1069 // This tests the import of isConditionTrue directly to make sure the importer
1070 // gets it right.
1071 Decl *From, *To;
1072 std::tie(From, To) = getImportedDecl(
1073 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", Lang_C99,
1074 "", Lang_C99);
1075
1076 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1077 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1078
1079 const ChooseExpr *FromChooseExpr =
1080 selectFirst<ChooseExpr>("choose", FromResults);
1081 ASSERT_TRUE(FromChooseExpr);
1082
1083 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1084 ASSERT_TRUE(ToChooseExpr);
1085
1086 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1087 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1088 ToChooseExpr->isConditionDependent());
1089 }
1090
TEST_P(ASTImporterOptionSpecificTestBase,ImportFunctionWithBackReferringParameter)1091 TEST_P(ASTImporterOptionSpecificTestBase,
1092 ImportFunctionWithBackReferringParameter) {
1093 Decl *From, *To;
1094 std::tie(From, To) = getImportedDecl(
1095 R"(
1096 template <typename T> struct X {};
1097
1098 void declToImport(int y, X<int> &x) {}
1099
1100 template <> struct X<int> {
1101 void g() {
1102 X<int> x;
1103 declToImport(0, x);
1104 }
1105 };
1106 )",
1107 Lang_CXX03, "", Lang_CXX03);
1108
1109 MatchVerifier<Decl> Verifier;
1110 auto Matcher = functionDecl(hasName("declToImport"),
1111 parameterCountIs(2),
1112 hasParameter(0, hasName("y")),
1113 hasParameter(1, hasName("x")),
1114 hasParameter(1, hasType(asString("X<int> &"))));
1115 ASSERT_TRUE(Verifier.match(From, Matcher));
1116 EXPECT_TRUE(Verifier.match(To, Matcher));
1117 }
1118
TEST_P(ASTImporterOptionSpecificTestBase,TUshouldNotContainTemplatedDeclOfFunctionTemplates)1119 TEST_P(ASTImporterOptionSpecificTestBase,
1120 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1121 Decl *From, *To;
1122 std::tie(From, To) =
1123 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1124 "void instantiate() { declToImport<int>(); }",
1125 Lang_CXX03, "", Lang_CXX03);
1126
1127 auto Check = [](Decl *D) -> bool {
1128 auto TU = D->getTranslationUnitDecl();
1129 for (auto Child : TU->decls()) {
1130 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1131 if (FD->getNameAsString() == "declToImport") {
1132 GTEST_NONFATAL_FAILURE_(
1133 "TU should not contain any FunctionDecl with name declToImport");
1134 return false;
1135 }
1136 }
1137 }
1138 return true;
1139 };
1140
1141 ASSERT_TRUE(Check(From));
1142 EXPECT_TRUE(Check(To));
1143 }
1144
TEST_P(ASTImporterOptionSpecificTestBase,TUshouldNotContainTemplatedDeclOfClassTemplates)1145 TEST_P(ASTImporterOptionSpecificTestBase,
1146 TUshouldNotContainTemplatedDeclOfClassTemplates) {
1147 Decl *From, *To;
1148 std::tie(From, To) =
1149 getImportedDecl("template <typename T> struct declToImport { T t; };"
1150 "void instantiate() { declToImport<int>(); }",
1151 Lang_CXX03, "", Lang_CXX03);
1152
1153 auto Check = [](Decl *D) -> bool {
1154 auto TU = D->getTranslationUnitDecl();
1155 for (auto Child : TU->decls()) {
1156 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1157 if (RD->getNameAsString() == "declToImport") {
1158 GTEST_NONFATAL_FAILURE_(
1159 "TU should not contain any CXXRecordDecl with name declToImport");
1160 return false;
1161 }
1162 }
1163 }
1164 return true;
1165 };
1166
1167 ASSERT_TRUE(Check(From));
1168 EXPECT_TRUE(Check(To));
1169 }
1170
TEST_P(ASTImporterOptionSpecificTestBase,TUshouldNotContainTemplatedDeclOfTypeAlias)1171 TEST_P(ASTImporterOptionSpecificTestBase,
1172 TUshouldNotContainTemplatedDeclOfTypeAlias) {
1173 Decl *From, *To;
1174 std::tie(From, To) =
1175 getImportedDecl(
1176 "template <typename T> struct X {};"
1177 "template <typename T> using declToImport = X<T>;"
1178 "void instantiate() { declToImport<int> a; }",
1179 Lang_CXX11, "", Lang_CXX11);
1180
1181 auto Check = [](Decl *D) -> bool {
1182 auto TU = D->getTranslationUnitDecl();
1183 for (auto Child : TU->decls()) {
1184 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1185 if (AD->getNameAsString() == "declToImport") {
1186 GTEST_NONFATAL_FAILURE_(
1187 "TU should not contain any TypeAliasDecl with name declToImport");
1188 return false;
1189 }
1190 }
1191 }
1192 return true;
1193 };
1194
1195 ASSERT_TRUE(Check(From));
1196 EXPECT_TRUE(Check(To));
1197 }
1198
TEST_P(ASTImporterOptionSpecificTestBase,TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation)1199 TEST_P(ASTImporterOptionSpecificTestBase,
1200 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1201
1202 Decl *From, *To;
1203 std::tie(From, To) = getImportedDecl(
1204 R"(
1205 template<class T>
1206 class Base {};
1207 class declToImport : public Base<declToImport> {};
1208 )",
1209 Lang_CXX03, "", Lang_CXX03);
1210
1211 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1212 auto Pattern =
1213 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1214 ASSERT_TRUE(
1215 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1216 EXPECT_TRUE(
1217 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1218
1219 // Check that the ClassTemplateSpecializationDecl is the child of the
1220 // ClassTemplateDecl.
1221 Pattern = translationUnitDecl(has(classTemplateDecl(
1222 hasName("Base"), has(classTemplateSpecializationDecl()))));
1223 ASSERT_TRUE(
1224 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1225 EXPECT_TRUE(
1226 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1227 }
1228
AST_MATCHER_P(RecordDecl,hasFieldOrder,std::vector<StringRef>,Order)1229 AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1230 size_t Index = 0;
1231 for (Decl *D : Node.decls()) {
1232 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1233 auto *ND = cast<NamedDecl>(D);
1234 if (Index == Order.size())
1235 return false;
1236 if (ND->getName() != Order[Index])
1237 return false;
1238 ++Index;
1239 }
1240 }
1241 return Index == Order.size();
1242 }
1243
TEST_P(ASTImporterOptionSpecificTestBase,TUshouldContainClassTemplateSpecializationOfExplicitInstantiation)1244 TEST_P(ASTImporterOptionSpecificTestBase,
1245 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1246 Decl *From, *To;
1247 std::tie(From, To) = getImportedDecl(
1248 R"(
1249 namespace NS {
1250 template<class T>
1251 class X {};
1252 template class X<int>;
1253 }
1254 )",
1255 Lang_CXX03, "", Lang_CXX03, "NS");
1256
1257 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1258 // ClassTemplateDecl.
1259 auto Pattern = namespaceDecl(has(classTemplateDecl(
1260 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1261 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1262 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1263
1264 // Check that the ClassTemplateSpecializationDecl is the child of the
1265 // NamespaceDecl.
1266 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1267 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1268 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1269 }
1270
TEST_P(ASTImporterOptionSpecificTestBase,CXXRecordDeclFieldsShouldBeInCorrectOrder)1271 TEST_P(ASTImporterOptionSpecificTestBase,
1272 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1273 Decl *From, *To;
1274 std::tie(From, To) =
1275 getImportedDecl(
1276 "struct declToImport { int a; int b; };",
1277 Lang_CXX11, "", Lang_CXX11);
1278
1279 MatchVerifier<Decl> Verifier;
1280 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1281 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1282 }
1283
TEST_P(ASTImporterOptionSpecificTestBase,CXXRecordDeclFieldOrderShouldNotDependOnImportOrder)1284 TEST_P(ASTImporterOptionSpecificTestBase,
1285 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1286 Decl *From, *To;
1287 std::tie(From, To) = getImportedDecl(
1288 // The original recursive algorithm of ASTImporter first imports 'c' then
1289 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1290 R"s(
1291 struct declToImport {
1292 int a = c + b;
1293 int b = 1;
1294 int c = 2;
1295 };
1296 )s",
1297 Lang_CXX11, "", Lang_CXX11);
1298
1299 MatchVerifier<Decl> Verifier;
1300 ASSERT_TRUE(
1301 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1302 EXPECT_TRUE(
1303 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1304 }
1305
TEST_P(ASTImporterOptionSpecificTestBase,CXXRecordDeclFieldAndIndirectFieldOrder)1306 TEST_P(ASTImporterOptionSpecificTestBase,
1307 CXXRecordDeclFieldAndIndirectFieldOrder) {
1308 Decl *From, *To;
1309 std::tie(From, To) = getImportedDecl(
1310 // First field is "a", then the field for unnamed union, then "b" and "c"
1311 // from it (indirect fields), then "d".
1312 R"s(
1313 struct declToImport {
1314 int a = d;
1315 union {
1316 int b;
1317 int c;
1318 };
1319 int d;
1320 };
1321 )s",
1322 Lang_CXX11, "", Lang_CXX11);
1323
1324 MatchVerifier<Decl> Verifier;
1325 ASSERT_TRUE(Verifier.match(
1326 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1327 EXPECT_TRUE(Verifier.match(
1328 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1329 }
1330
TEST_P(ASTImporterOptionSpecificTestBase,ShouldImportImplicitCXXRecordDecl)1331 TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
1332 Decl *From, *To;
1333 std::tie(From, To) = getImportedDecl(
1334 R"(
1335 struct declToImport {
1336 };
1337 )",
1338 Lang_CXX03, "", Lang_CXX03);
1339
1340 MatchVerifier<Decl> Verifier;
1341 // Match the implicit Decl.
1342 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1343 ASSERT_TRUE(Verifier.match(From, Matcher));
1344 EXPECT_TRUE(Verifier.match(To, Matcher));
1345 }
1346
TEST_P(ASTImporterOptionSpecificTestBase,ShouldImportImplicitCXXRecordDeclOfClassTemplate)1347 TEST_P(ASTImporterOptionSpecificTestBase,
1348 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1349 Decl *From, *To;
1350 std::tie(From, To) = getImportedDecl(
1351 R"(
1352 template <typename U>
1353 struct declToImport {
1354 };
1355 )",
1356 Lang_CXX03, "", Lang_CXX03);
1357
1358 MatchVerifier<Decl> Verifier;
1359 // Match the implicit Decl.
1360 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1361 ASSERT_TRUE(Verifier.match(From, Matcher));
1362 EXPECT_TRUE(Verifier.match(To, Matcher));
1363 }
1364
TEST_P(ASTImporterOptionSpecificTestBase,ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl)1365 TEST_P(ASTImporterOptionSpecificTestBase,
1366 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1367 Decl *From, *To;
1368 std::tie(From, To) = getImportedDecl(
1369 R"(
1370 template<class T>
1371 class Base {};
1372 class declToImport : public Base<declToImport> {};
1373 )",
1374 Lang_CXX03, "", Lang_CXX03);
1375
1376 auto hasImplicitClass = has(cxxRecordDecl());
1377 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1378 hasName("Base"),
1379 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1380 ASSERT_TRUE(
1381 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1382 EXPECT_TRUE(
1383 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1384 }
1385
TEST_P(ASTImporterOptionSpecificTestBase,IDNSOrdinary)1386 TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
1387 Decl *From, *To;
1388 std::tie(From, To) =
1389 getImportedDecl("void declToImport() {}", Lang_CXX03, "", Lang_CXX03);
1390
1391 MatchVerifier<Decl> Verifier;
1392 auto Matcher = functionDecl();
1393 ASSERT_TRUE(Verifier.match(From, Matcher));
1394 EXPECT_TRUE(Verifier.match(To, Matcher));
1395 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1396 }
1397
TEST_P(ASTImporterOptionSpecificTestBase,IDNSOfNonmemberOperator)1398 TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
1399 Decl *FromTU = getTuDecl(
1400 R"(
1401 struct X {};
1402 void operator<<(int, X);
1403 )",
1404 Lang_CXX03);
1405 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1406 const Decl *To = Import(From, Lang_CXX03);
1407 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1408 }
1409
TEST_P(ASTImporterOptionSpecificTestBase,ShouldImportMembersOfClassTemplateSpecializationDecl)1410 TEST_P(ASTImporterOptionSpecificTestBase,
1411 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1412 Decl *From, *To;
1413 std::tie(From, To) = getImportedDecl(
1414 R"(
1415 template<class T>
1416 class Base { int a; };
1417 class declToImport : Base<declToImport> {};
1418 )",
1419 Lang_CXX03, "", Lang_CXX03);
1420
1421 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1422 hasName("Base"),
1423 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1424 ASSERT_TRUE(
1425 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1426 EXPECT_TRUE(
1427 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1428 }
1429
TEST_P(ASTImporterOptionSpecificTestBase,ImportDefinitionOfClassTemplateAfterFwdDecl)1430 TEST_P(ASTImporterOptionSpecificTestBase,
1431 ImportDefinitionOfClassTemplateAfterFwdDecl) {
1432 {
1433 Decl *FromTU = getTuDecl(
1434 R"(
1435 template <typename T>
1436 struct B;
1437 )",
1438 Lang_CXX03, "input0.cc");
1439 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1440 FromTU, classTemplateDecl(hasName("B")));
1441
1442 Import(FromD, Lang_CXX03);
1443 }
1444
1445 {
1446 Decl *FromTU = getTuDecl(
1447 R"(
1448 template <typename T>
1449 struct B {
1450 void f();
1451 };
1452 )",
1453 Lang_CXX03, "input1.cc");
1454 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1455 FromTU, functionDecl(hasName("f")));
1456 Import(FromD, Lang_CXX03);
1457 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1458 FromTU, classTemplateDecl(hasName("B")));
1459 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
1460 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1461 }
1462 }
1463
TEST_P(ASTImporterOptionSpecificTestBase,ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition)1464 TEST_P(ASTImporterOptionSpecificTestBase,
1465 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1466 Decl *ToTU = getToTuDecl(
1467 R"(
1468 template <typename T>
1469 struct B {
1470 void f();
1471 };
1472
1473 template <typename T>
1474 struct B;
1475 )",
1476 Lang_CXX03);
1477 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1478 [](const ClassTemplateDecl *T) {
1479 return T->isThisDeclarationADefinition();
1480 })
1481 .match(ToTU, classTemplateDecl()));
1482
1483 Decl *FromTU = getTuDecl(
1484 R"(
1485 template <typename T>
1486 struct B {
1487 void f();
1488 };
1489 )",
1490 Lang_CXX03, "input1.cc");
1491 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1492 FromTU, classTemplateDecl(hasName("B")));
1493
1494 Import(FromD, Lang_CXX03);
1495
1496 // We should have only one definition.
1497 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1498 [](const ClassTemplateDecl *T) {
1499 return T->isThisDeclarationADefinition();
1500 })
1501 .match(ToTU, classTemplateDecl()));
1502 }
1503
TEST_P(ASTImporterOptionSpecificTestBase,ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition)1504 TEST_P(ASTImporterOptionSpecificTestBase,
1505 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1506 Decl *ToTU = getToTuDecl(
1507 R"(
1508 struct B {
1509 void f();
1510 };
1511
1512 struct B;
1513 )",
1514 Lang_CXX03);
1515 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1516 ToTU, cxxRecordDecl(unless(isImplicit()))));
1517
1518 Decl *FromTU = getTuDecl(
1519 R"(
1520 struct B {
1521 void f();
1522 };
1523 )",
1524 Lang_CXX03, "input1.cc");
1525 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1526 FromTU, cxxRecordDecl(hasName("B")));
1527
1528 Import(FromD, Lang_CXX03);
1529
1530 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1531 ToTU, cxxRecordDecl(unless(isImplicit()))));
1532 }
1533
CompareSourceLocs(FullSourceLoc Loc1,FullSourceLoc Loc2)1534 static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1535 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1536 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1537 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1538 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1539 }
CompareSourceRanges(SourceRange Range1,SourceRange Range2,SourceManager & SM1,SourceManager & SM2)1540 static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1541 SourceManager &SM1, SourceManager &SM2) {
1542 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1543 FullSourceLoc{ Range2.getBegin(), SM2 });
1544 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1545 FullSourceLoc{ Range2.getEnd(), SM2 });
1546 }
TEST_P(ASTImporterOptionSpecificTestBase,ImportSourceLocs)1547 TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
1548 Decl *FromTU = getTuDecl(
1549 R"(
1550 #define MFOO(arg) arg = arg + 1
1551
1552 void foo() {
1553 int a = 5;
1554 MFOO(a);
1555 }
1556 )",
1557 Lang_CXX03);
1558 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1559 auto ToD = Import(FromD, Lang_CXX03);
1560
1561 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1562 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1563 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1564 auto FromRHS =
1565 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1566
1567 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1568 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1569 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1570 FromSM);
1571 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1572 FromSM);
1573 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1574 FromSM);
1575 }
1576
TEST_P(ASTImporterOptionSpecificTestBase,ImportNestedMacro)1577 TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
1578 Decl *FromTU = getTuDecl(
1579 R"(
1580 #define FUNC_INT void declToImport
1581 #define FUNC FUNC_INT
1582 FUNC(int a);
1583 )",
1584 Lang_CXX03);
1585 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1586 auto ToD = Import(FromD, Lang_CXX03);
1587
1588 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1589 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1590 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1591 FromSM);
1592 }
1593
TEST_P(ASTImporterOptionSpecificTestBase,ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)1594 TEST_P(
1595 ASTImporterOptionSpecificTestBase,
1596 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
1597 Decl *ToTU = getToTuDecl(
1598 R"(
1599 template <typename T>
1600 struct B;
1601
1602 template <>
1603 struct B<int> {};
1604
1605 template <>
1606 struct B<int>;
1607 )",
1608 Lang_CXX03);
1609 // We should have only one definition.
1610 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1611 [](const ClassTemplateSpecializationDecl *T) {
1612 return T->isThisDeclarationADefinition();
1613 })
1614 .match(ToTU, classTemplateSpecializationDecl()));
1615
1616 Decl *FromTU = getTuDecl(
1617 R"(
1618 template <typename T>
1619 struct B;
1620
1621 template <>
1622 struct B<int> {};
1623 )",
1624 Lang_CXX03, "input1.cc");
1625 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1626 FromTU, classTemplateSpecializationDecl(hasName("B")));
1627
1628 Import(FromD, Lang_CXX03);
1629
1630 // We should have only one definition.
1631 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1632 [](const ClassTemplateSpecializationDecl *T) {
1633 return T->isThisDeclarationADefinition();
1634 })
1635 .match(ToTU, classTemplateSpecializationDecl()));
1636 }
1637
TEST_P(ASTImporterOptionSpecificTestBase,ObjectsWithUnnamedStructType)1638 TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
1639 Decl *FromTU = getTuDecl(
1640 R"(
1641 struct { int a; int b; } object0 = { 2, 3 };
1642 struct { int x; int y; int z; } object1;
1643 )",
1644 Lang_CXX03, "input0.cc");
1645
1646 auto *Obj0 =
1647 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1648 auto *From0 = getRecordDecl(Obj0);
1649 auto *Obj1 =
1650 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1651 auto *From1 = getRecordDecl(Obj1);
1652
1653 auto *To0 = Import(From0, Lang_CXX03);
1654 auto *To1 = Import(From1, Lang_CXX03);
1655
1656 EXPECT_TRUE(To0);
1657 EXPECT_TRUE(To1);
1658 EXPECT_NE(To0, To1);
1659 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1660 }
1661
TEST_P(ASTImporterOptionSpecificTestBase,AnonymousRecords)1662 TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
1663 auto *Code =
1664 R"(
1665 struct X {
1666 struct { int a; };
1667 struct { int b; };
1668 };
1669 )";
1670 Decl *FromTU0 = getTuDecl(Code, Lang_C99, "input0.c");
1671
1672 Decl *FromTU1 = getTuDecl(Code, Lang_C99, "input1.c");
1673
1674 auto *X0 =
1675 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1676 auto *X1 =
1677 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1678 Import(X0, Lang_C99);
1679 Import(X1, Lang_C99);
1680
1681 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1682 // We expect no (ODR) warning during the import.
1683 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1684 EXPECT_EQ(1u,
1685 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1686 }
1687
TEST_P(ASTImporterOptionSpecificTestBase,AnonymousRecordsReversed)1688 TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
1689 Decl *FromTU0 = getTuDecl(
1690 R"(
1691 struct X {
1692 struct { int a; };
1693 struct { int b; };
1694 };
1695 )",
1696 Lang_C99, "input0.c");
1697
1698 Decl *FromTU1 = getTuDecl(
1699 R"(
1700 struct X { // reversed order
1701 struct { int b; };
1702 struct { int a; };
1703 };
1704 )",
1705 Lang_C99, "input1.c");
1706
1707 auto *X0 =
1708 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1709 auto *X1 =
1710 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1711 Import(X0, Lang_C99);
1712 Import(X1, Lang_C99);
1713
1714 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1715 // We expect one (ODR) warning during the import.
1716 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1717 EXPECT_EQ(1u,
1718 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1719 }
1720
TEST_P(ASTImporterOptionSpecificTestBase,ImportDoesUpdateUsedFlag)1721 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
1722 auto Pattern = varDecl(hasName("x"));
1723 VarDecl *Imported1;
1724 {
1725 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX03, "input0.cc");
1726 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1727 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1728 }
1729 VarDecl *Imported2;
1730 {
1731 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input1.cc");
1732 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1733 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1734 }
1735 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1736 EXPECT_FALSE(Imported2->isUsed(false));
1737 {
1738 Decl *FromTU = getTuDecl("extern int x; int f() { return x; }", Lang_CXX03,
1739 "input2.cc");
1740 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1741 FromTU, functionDecl(hasName("f")));
1742 Import(FromD, Lang_CXX03);
1743 }
1744 EXPECT_TRUE(Imported2->isUsed(false));
1745 }
1746
TEST_P(ASTImporterOptionSpecificTestBase,ImportDoesUpdateUsedFlag2)1747 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
1748 auto Pattern = varDecl(hasName("x"));
1749 VarDecl *ExistingD;
1750 {
1751 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX03);
1752 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1753 }
1754 EXPECT_FALSE(ExistingD->isUsed(false));
1755 {
1756 Decl *FromTU =
1757 getTuDecl("int x = 1; int f() { return x; }", Lang_CXX03, "input1.cc");
1758 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1759 FromTU, functionDecl(hasName("f")));
1760 Import(FromD, Lang_CXX03);
1761 }
1762 EXPECT_TRUE(ExistingD->isUsed(false));
1763 }
1764
TEST_P(ASTImporterOptionSpecificTestBase,ImportDoesUpdateUsedFlag3)1765 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
1766 auto Pattern = varDecl(hasName("a"));
1767 VarDecl *ExistingD;
1768 {
1769 Decl *ToTU = getToTuDecl(
1770 R"(
1771 struct A {
1772 static const int a = 1;
1773 };
1774 )",
1775 Lang_CXX03);
1776 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1777 }
1778 EXPECT_FALSE(ExistingD->isUsed(false));
1779 {
1780 Decl *FromTU = getTuDecl(
1781 R"(
1782 struct A {
1783 static const int a = 1;
1784 };
1785 const int *f() { return &A::a; } // requires storage,
1786 // thus used flag will be set
1787 )",
1788 Lang_CXX03, "input1.cc");
1789 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1790 FromTU, functionDecl(hasName("f")));
1791 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1792 ASSERT_TRUE(FromD->isUsed(false));
1793 Import(FromFunD, Lang_CXX03);
1794 }
1795 EXPECT_TRUE(ExistingD->isUsed(false));
1796 }
1797
TEST_P(ASTImporterOptionSpecificTestBase,ReimportWithUsedFlag)1798 TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
1799 auto Pattern = varDecl(hasName("x"));
1800
1801 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input0.cc");
1802 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1803
1804 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1805
1806 ASSERT_FALSE(Imported1->isUsed(false));
1807
1808 FromD->setIsUsed();
1809 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
1810
1811 EXPECT_EQ(Imported1, Imported2);
1812 EXPECT_TRUE(Imported2->isUsed(false));
1813 }
1814
1815 struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
1816
TEST_P(ImportFunctions,ImportPrototypeOfRecursiveFunction)1817 TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
1818 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);
1819 auto Pattern = functionDecl(hasName("f"));
1820 auto *From =
1821 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
1822
1823 Decl *ImportedD = Import(From, Lang_CXX03);
1824 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1825
1826 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1827 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1828 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1829 EXPECT_TRUE(ImportedD == To0);
1830 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1831 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1832 EXPECT_EQ(To1->getPreviousDecl(), To0);
1833 }
1834
TEST_P(ImportFunctions,ImportDefinitionOfRecursiveFunction)1835 TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1836 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);
1837 auto Pattern = functionDecl(hasName("f"));
1838 auto *From =
1839 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
1840
1841 Decl *ImportedD = Import(From, Lang_CXX03);
1842 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1843
1844 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1845 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1846 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1847 EXPECT_TRUE(ImportedD == To1);
1848 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1849 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1850 EXPECT_EQ(To1->getPreviousDecl(), To0);
1851 }
1852
TEST_P(ImportFunctions,OverriddenMethodsShouldBeImported)1853 TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1854 auto Code =
1855 R"(
1856 struct B { virtual void f(); };
1857 void B::f() {}
1858 struct D : B { void f(); };
1859 )";
1860 auto Pattern =
1861 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1862 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1863 CXXMethodDecl *Proto =
1864 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1865
1866 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1867 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));
1868 EXPECT_EQ(To->size_overridden_methods(), 1u);
1869 }
1870
TEST_P(ImportFunctions,VirtualFlagShouldBePreservedWhenImportingPrototype)1871 TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1872 auto Code =
1873 R"(
1874 struct B { virtual void f(); };
1875 void B::f() {}
1876 )";
1877 auto Pattern =
1878 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1879 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1880 CXXMethodDecl *Proto =
1881 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1882 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1883
1884 ASSERT_TRUE(Proto->isVirtual());
1885 ASSERT_TRUE(Def->isVirtual());
1886 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));
1887 EXPECT_TRUE(To->isVirtual());
1888 }
1889
TEST_P(ImportFunctions,ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl)1890 TEST_P(ImportFunctions,
1891 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
1892 Decl *ToTU = getToTuDecl(
1893 R"(
1894 void f() {}
1895 void f();
1896 )",
1897 Lang_CXX03);
1898 ASSERT_EQ(1u,
1899 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1900 return FD->doesThisDeclarationHaveABody();
1901 }).match(ToTU, functionDecl()));
1902
1903 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX03, "input0.cc");
1904 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1905
1906 Import(FromD, Lang_CXX03);
1907
1908 EXPECT_EQ(1u,
1909 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1910 return FD->doesThisDeclarationHaveABody();
1911 }).match(ToTU, functionDecl()));
1912 }
1913
TEST_P(ImportFunctions,ImportOverriddenMethodTwice)1914 TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
1915 auto Code =
1916 R"(
1917 struct B { virtual void f(); };
1918 struct D:B { void f(); };
1919 )";
1920 auto BFP =
1921 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1922 auto DFP =
1923 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1924
1925 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);
1926 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
1927 Import(DF, Lang_CXX03);
1928
1929 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
1930 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
1931 Import(BF, Lang_CXX03);
1932
1933 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1934
1935 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
1936 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
1937 }
1938
TEST_P(ImportFunctions,ImportOverriddenMethodTwiceDefinitionFirst)1939 TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
1940 auto CodeWithoutDef =
1941 R"(
1942 struct B { virtual void f(); };
1943 struct D:B { void f(); };
1944 )";
1945 auto CodeWithDef =
1946 R"(
1947 struct B { virtual void f(){}; };
1948 struct D:B { void f(){}; };
1949 )";
1950 auto BFP =
1951 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1952 auto DFP =
1953 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1954 auto BFDefP = cxxMethodDecl(
1955 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
1956 auto DFDefP = cxxMethodDecl(
1957 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
1958 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
1959
1960 {
1961 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX03, "input0.cc");
1962 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
1963 Import(FromD, Lang_CXX03);
1964 }
1965 {
1966 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX03, "input1.cc");
1967 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
1968 Import(FromB, Lang_CXX03);
1969 }
1970
1971 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1972
1973 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
1974 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
1975 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
1976 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
1977 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
1978 }
1979
TEST_P(ImportFunctions,ImportOverriddenMethodTwiceOutOfClassDef)1980 TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
1981 auto Code =
1982 R"(
1983 struct B { virtual void f(); };
1984 struct D:B { void f(); };
1985 void B::f(){};
1986 )";
1987
1988 auto BFP =
1989 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1990 auto BFDefP = cxxMethodDecl(
1991 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
1992 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
1993 unless(isDefinition()));
1994
1995 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);
1996 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
1997 Import(D, Lang_CXX03);
1998
1999 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2000 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2001 Import(B, Lang_CXX03);
2002
2003 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2004
2005 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2006 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2007
2008 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2009 ToTU, cxxRecordDecl(hasName("B")));
2010 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2011 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2012 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2013
2014 // The definition should be out-of-class.
2015 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2016 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2017 ToBFOutOfClass->getLexicalDeclContext());
2018 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2019 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2020
2021 // Check that the redecl chain is intact.
2022 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2023 }
2024
TEST_P(ImportFunctions,ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode)2025 TEST_P(ImportFunctions,
2026 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2027 auto CodeTU0 =
2028 R"(
2029 struct B { virtual void f(); };
2030 struct D:B { void f(); };
2031 )";
2032 auto CodeTU1 =
2033 R"(
2034 struct B { virtual void f(); };
2035 struct D:B { void f(); };
2036 void B::f(){}
2037 void D::f(){}
2038 void foo(B &b, D &d) { b.f(); d.f(); }
2039 )";
2040
2041 auto BFP =
2042 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2043 auto BFDefP = cxxMethodDecl(
2044 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2045 auto DFP =
2046 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2047 auto DFDefP = cxxMethodDecl(
2048 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2049 auto FooDef = functionDecl(hasName("foo"));
2050
2051 {
2052 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX03, "input0.cc");
2053 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2054 Import(D, Lang_CXX03);
2055 }
2056
2057 {
2058 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX03, "input1.cc");
2059 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2060 Import(Foo, Lang_CXX03);
2061 }
2062
2063 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2064
2065 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2066 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2067 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2068 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2069
2070 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2071 ToTU, cxxRecordDecl(hasName("B")));
2072 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2073 ToTU, cxxRecordDecl(hasName("D")));
2074 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2075 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2076 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2077 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2078 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2079 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2080
2081 // The definition should be out-of-class.
2082 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2083 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2084 ToBFOutOfClass->getLexicalDeclContext());
2085 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2086 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2087
2088 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2089 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2090 ToDFOutOfClass->getLexicalDeclContext());
2091 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2092 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2093
2094 // Check that the redecl chain is intact.
2095 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2096 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2097 }
2098
TEST_P(ASTImporterOptionSpecificTestBase,ImportVariableChainInC)2099 TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2100 std::string Code = "static int v; static int v = 0;";
2101 auto Pattern = varDecl(hasName("v"));
2102
2103 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C99, "input0.c");
2104
2105 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2106 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2107
2108 auto *To0 = Import(From0, Lang_C99);
2109 auto *To1 = Import(From1, Lang_C99);
2110
2111 EXPECT_TRUE(To0);
2112 ASSERT_TRUE(To1);
2113 EXPECT_NE(To0, To1);
2114 EXPECT_EQ(To1->getPreviousDecl(), To0);
2115 }
2116
TEST_P(ImportFunctions,ImportFromDifferentScopedAnonNamespace)2117 TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2118 TranslationUnitDecl *FromTu =
2119 getTuDecl("namespace NS0 { namespace { void f(); } }"
2120 "namespace NS1 { namespace { void f(); } }",
2121 Lang_CXX03, "input0.cc");
2122 auto Pattern = functionDecl(hasName("f"));
2123
2124 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2125 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2126
2127 auto *ToF0 = Import(FromF0, Lang_CXX03);
2128 auto *ToF1 = Import(FromF1, Lang_CXX03);
2129
2130 EXPECT_TRUE(ToF0);
2131 ASSERT_TRUE(ToF1);
2132 EXPECT_NE(ToF0, ToF1);
2133 EXPECT_FALSE(ToF1->getPreviousDecl());
2134 }
2135
TEST_P(ImportFunctions,ImportFunctionFromUnnamedNamespace)2136 TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2137 {
2138 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2139 Lang_CXX03, "input0.cc");
2140 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2141 FromTU, functionDecl(hasName("g0")));
2142
2143 Import(FromD, Lang_CXX03);
2144 }
2145 {
2146 Decl *FromTU =
2147 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2148 Lang_CXX03, "input1.cc");
2149 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2150 FromTU, functionDecl(hasName("g1")));
2151 Import(FromD, Lang_CXX03);
2152 }
2153
2154 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2155 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2156 2u);
2157 }
2158
TEST_P(ImportFunctions,ImportImplicitFunctionsInLambda)2159 TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2160 Decl *FromTU = getTuDecl(
2161 R"(
2162 void foo() {
2163 (void)[]() { ; };
2164 }
2165 )",
2166 Lang_CXX11);
2167 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2168 FromTU, functionDecl(hasName("foo")));
2169 auto *ToD = Import(FromD, Lang_CXX03);
2170 EXPECT_TRUE(ToD);
2171 CXXRecordDecl *LambdaRec =
2172 cast<LambdaExpr>(cast<CStyleCastExpr>(
2173 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2174 ->getSubExpr())
2175 ->getLambdaClass();
2176 EXPECT_TRUE(LambdaRec->getDestructor());
2177 }
2178
TEST_P(ImportFunctions,CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs)2179 TEST_P(ImportFunctions,
2180 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2181 Decl *FromTU = getTuDecl(
2182 R"(
2183 struct X {
2184 template <typename T>
2185 void foo(){}
2186 };
2187 void f() {
2188 X x;
2189 x.foo<int>();
2190 }
2191 )",
2192 Lang_CXX03);
2193 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2194 FromTU, functionDecl(hasName("f")));
2195 auto *ToD = Import(FromD, Lang_CXX03);
2196 EXPECT_TRUE(ToD);
2197 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2198 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2199 }
2200
TEST_P(ImportFunctions,DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs)2201 TEST_P(ImportFunctions,
2202 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2203 Decl *FromTU = getTuDecl(
2204 R"(
2205 struct X {
2206 template <typename T>
2207 void foo(){}
2208 };
2209 template <typename T>
2210 void f() {
2211 X x;
2212 x.foo<T>();
2213 }
2214 void g() {
2215 f<int>();
2216 }
2217 )",
2218 Lang_CXX03);
2219 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2220 FromTU, functionDecl(hasName("g")));
2221 auto *ToD = Import(FromD, Lang_CXX03);
2222 EXPECT_TRUE(ToD);
2223 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2224 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2225 ToTU, translationUnitDecl(hasDescendant(
2226 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2227 }
2228
2229 struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2230
TEST_P(ImportFunctionTemplates,ImportFunctionTemplateInRecordDeclTwice)2231 TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2232 auto Code =
2233 R"(
2234 class X {
2235 template <class T>
2236 void f(T t);
2237 };
2238 )";
2239 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2240 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2241 FromTU1, functionTemplateDecl(hasName("f")));
2242 auto *ToD1 = Import(FromD1, Lang_CXX03);
2243 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");
2244 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2245 FromTU2, functionTemplateDecl(hasName("f")));
2246 auto *ToD2 = Import(FromD2, Lang_CXX03);
2247 EXPECT_EQ(ToD1, ToD2);
2248 }
2249
TEST_P(ImportFunctionTemplates,ImportFunctionTemplateWithDefInRecordDeclTwice)2250 TEST_P(ImportFunctionTemplates,
2251 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2252 auto Code =
2253 R"(
2254 class X {
2255 template <class T>
2256 void f(T t);
2257 };
2258 template <class T>
2259 void X::f(T t) {};
2260 )";
2261 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2262 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2263 FromTU1, functionTemplateDecl(hasName("f")));
2264 auto *ToD1 = Import(FromD1, Lang_CXX03);
2265 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");
2266 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2267 FromTU2, functionTemplateDecl(hasName("f")));
2268 auto *ToD2 = Import(FromD2, Lang_CXX03);
2269 EXPECT_EQ(ToD1, ToD2);
2270 }
2271
TEST_P(ImportFunctionTemplates,ImportFunctionWhenThereIsAFunTemplateWithSameName)2272 TEST_P(ImportFunctionTemplates,
2273 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2274 getToTuDecl(
2275 R"(
2276 template <typename T>
2277 void foo(T) {}
2278 void foo();
2279 )",
2280 Lang_CXX03);
2281 Decl *FromTU = getTuDecl("void foo();", Lang_CXX03);
2282 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2283 FromTU, functionDecl(hasName("foo")));
2284 auto *ImportedD = Import(FromD, Lang_CXX03);
2285 EXPECT_TRUE(ImportedD);
2286 }
2287
TEST_P(ImportFunctionTemplates,ImportConstructorWhenThereIsAFunTemplateWithSameName)2288 TEST_P(ImportFunctionTemplates,
2289 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2290 auto Code =
2291 R"(
2292 struct Foo {
2293 template <typename T>
2294 Foo(T) {}
2295 Foo();
2296 };
2297 )";
2298 getToTuDecl(Code, Lang_CXX03);
2299 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
2300 auto *FromD =
2301 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
2302 auto *ImportedD = Import(FromD, Lang_CXX03);
2303 EXPECT_TRUE(ImportedD);
2304 }
2305
TEST_P(ImportFunctionTemplates,ImportOperatorWhenThereIsAFunTemplateWithSameName)2306 TEST_P(ImportFunctionTemplates,
2307 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2308 getToTuDecl(
2309 R"(
2310 template <typename T>
2311 void operator<(T,T) {}
2312 struct X{};
2313 void operator<(X, X);
2314 )",
2315 Lang_CXX03);
2316 Decl *FromTU = getTuDecl(
2317 R"(
2318 struct X{};
2319 void operator<(X, X);
2320 )",
2321 Lang_CXX03);
2322 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2323 FromTU, functionDecl(hasOverloadedOperatorName("<")));
2324 auto *ImportedD = Import(FromD, Lang_CXX03);
2325 EXPECT_TRUE(ImportedD);
2326 }
2327
2328 struct ImportFriendFunctions : ImportFunctions {};
2329
TEST_P(ImportFriendFunctions,ImportFriendFunctionRedeclChainProto)2330 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2331 auto Pattern = functionDecl(hasName("f"));
2332
2333 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2334 "void f();",
2335 Lang_CXX03, "input0.cc");
2336 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2337
2338 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2339 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2340 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2341 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2342 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2343 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2344 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2345 }
2346
TEST_P(ImportFriendFunctions,ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst)2347 TEST_P(ImportFriendFunctions,
2348 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2349 auto Pattern = functionDecl(hasName("f"));
2350
2351 Decl *FromTU = getTuDecl("void f();"
2352 "struct X { friend void f(); };",
2353 Lang_CXX03, "input0.cc");
2354 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2355
2356 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2357 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2358 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2359 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2360 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2361 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2362 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2363 }
2364
TEST_P(ImportFriendFunctions,ImportFriendFunctionRedeclChainDef)2365 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2366 auto Pattern = functionDecl(hasName("f"));
2367
2368 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2369 "void f();",
2370 Lang_CXX03, "input0.cc");
2371 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2372
2373 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2374 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2375 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2376 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2377 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2378 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2379 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2380 }
2381
TEST_P(ImportFriendFunctions,ImportFriendFunctionRedeclChainDef_OutOfClassDef)2382 TEST_P(ImportFriendFunctions,
2383 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2384 auto Pattern = functionDecl(hasName("f"));
2385
2386 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2387 "void f(){}",
2388 Lang_CXX03, "input0.cc");
2389 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2390
2391 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2392 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2393 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2394 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2395 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2396 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2397 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2398 }
2399
TEST_P(ImportFriendFunctions,ImportFriendFunctionRedeclChainDefWithClass)2400 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
2401 auto Pattern = functionDecl(hasName("f"));
2402
2403 Decl *FromTU = getTuDecl(
2404 R"(
2405 class X;
2406 void f(X *x){}
2407 class X{
2408 friend void f(X *x);
2409 };
2410 )",
2411 Lang_CXX03, "input0.cc");
2412 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2413
2414 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2415 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2416 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2417 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2418 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2419 .match(ToTU, friendDecl())
2420 ->getFriendDecl());
2421 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2422 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2423 // The parameters must refer the same type
2424 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2425 (*ImportedD->param_begin())->getOriginalType());
2426 }
2427
TEST_P(ImportFriendFunctions,ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto)2428 TEST_P(ImportFriendFunctions,
2429 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2430 auto Pattern = functionDecl(hasName("f"));
2431
2432 Decl *FromTU = getTuDecl(
2433 R"(
2434 class X;
2435 void f(X *x){}
2436 class X{
2437 friend void f(X *x);
2438 };
2439 )",
2440 Lang_CXX03, "input0.cc");
2441 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2442
2443 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2444 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2445 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2446 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2447 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2448 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2449
2450 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2451 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2452 // The parameters must refer the same type
2453 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2454 (*ImportedD->param_begin())->getOriginalType());
2455 }
2456
TEST_P(ImportFriendFunctions,ImportFriendFunctionFromMultipleTU)2457 TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2458 auto Pattern = functionDecl(hasName("f"));
2459
2460 FunctionDecl *ImportedD;
2461 {
2462 Decl *FromTU =
2463 getTuDecl("struct X { friend void f(){} };", Lang_CXX03, "input0.cc");
2464 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2465 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2466 }
2467 FunctionDecl *ImportedD1;
2468 {
2469 Decl *FromTU = getTuDecl("void f();", Lang_CXX03, "input1.cc");
2470 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2471 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2472 }
2473
2474 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2475 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2476 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2477 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2478 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2479 }
2480
TEST_P(ImportFriendFunctions,Lookup)2481 TEST_P(ImportFriendFunctions, Lookup) {
2482 auto FunctionPattern = functionDecl(hasName("f"));
2483 auto ClassPattern = cxxRecordDecl(hasName("X"));
2484
2485 TranslationUnitDecl *FromTU =
2486 getTuDecl("struct X { friend void f(); };", Lang_CXX03, "input0.cc");
2487 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2488 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2489 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2490 {
2491 auto FromName = FromD->getDeclName();
2492 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2493 auto LookupRes = Class->noload_lookup(FromName);
2494 ASSERT_EQ(LookupRes.size(), 0u);
2495 LookupRes = FromTU->noload_lookup(FromName);
2496 ASSERT_EQ(LookupRes.size(), 1u);
2497 }
2498
2499 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2500 auto ToName = ToD->getDeclName();
2501
2502 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2503 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2504 auto LookupRes = Class->noload_lookup(ToName);
2505 EXPECT_EQ(LookupRes.size(), 0u);
2506 LookupRes = ToTU->noload_lookup(ToName);
2507 EXPECT_EQ(LookupRes.size(), 1u);
2508
2509 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2510 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2511 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2512 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2513 }
2514
TEST_P(ImportFriendFunctions,LookupWithProtoAfter)2515 TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
2516 auto FunctionPattern = functionDecl(hasName("f"));
2517 auto ClassPattern = cxxRecordDecl(hasName("X"));
2518
2519 TranslationUnitDecl *FromTU =
2520 getTuDecl("struct X { friend void f(); };"
2521 // This proto decl makes f available to normal
2522 // lookup, otherwise it is hidden.
2523 // Normal C++ lookup (implemented in
2524 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2525 // returns the found `NamedDecl` only if the set IDNS is matched
2526 "void f();",
2527 Lang_CXX03, "input0.cc");
2528 auto *FromFriend =
2529 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2530 auto *FromNormal =
2531 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2532 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2533 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2534 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2535 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2536
2537 auto FromName = FromFriend->getDeclName();
2538 auto *FromClass =
2539 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2540 auto LookupRes = FromClass->noload_lookup(FromName);
2541 ASSERT_EQ(LookupRes.size(), 0u);
2542 LookupRes = FromTU->noload_lookup(FromName);
2543 ASSERT_EQ(LookupRes.size(), 1u);
2544
2545 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX03));
2546 auto ToName = ToFriend->getDeclName();
2547
2548 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2549 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2550 LookupRes = ToClass->noload_lookup(ToName);
2551 EXPECT_EQ(LookupRes.size(), 0u);
2552 LookupRes = ToTU->noload_lookup(ToName);
2553 // Test is disabled because this result is 2.
2554 EXPECT_EQ(LookupRes.size(), 1u);
2555
2556 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2557 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2558 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2559 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2560 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2561 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2562 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2563 }
2564
TEST_P(ImportFriendFunctions,LookupWithProtoBefore)2565 TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2566 auto FunctionPattern = functionDecl(hasName("f"));
2567 auto ClassPattern = cxxRecordDecl(hasName("X"));
2568
2569 TranslationUnitDecl *FromTU = getTuDecl("void f();"
2570 "struct X { friend void f(); };",
2571 Lang_CXX03, "input0.cc");
2572 auto *FromNormal =
2573 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2574 auto *FromFriend =
2575 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2576 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2577 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2578 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2579 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2580
2581 auto FromName = FromNormal->getDeclName();
2582 auto *FromClass =
2583 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2584 auto LookupRes = FromClass->noload_lookup(FromName);
2585 ASSERT_EQ(LookupRes.size(), 0u);
2586 LookupRes = FromTU->noload_lookup(FromName);
2587 ASSERT_EQ(LookupRes.size(), 1u);
2588
2589 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX03));
2590 auto ToName = ToNormal->getDeclName();
2591 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2592
2593 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2594 LookupRes = ToClass->noload_lookup(ToName);
2595 EXPECT_EQ(LookupRes.size(), 0u);
2596 LookupRes = ToTU->noload_lookup(ToName);
2597 EXPECT_EQ(LookupRes.size(), 1u);
2598
2599 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2600 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2601 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2602 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2603 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2604 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2605 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2606 }
2607
TEST_P(ImportFriendFunctions,ImportFriendChangesLookup)2608 TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2609 auto Pattern = functionDecl(hasName("f"));
2610
2611 TranslationUnitDecl *FromNormalTU =
2612 getTuDecl("void f();", Lang_CXX03, "input0.cc");
2613 auto *FromNormalF =
2614 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2615 TranslationUnitDecl *FromFriendTU =
2616 getTuDecl("class X { friend void f(); };", Lang_CXX03, "input1.cc");
2617 auto *FromFriendF =
2618 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2619 auto FromNormalName = FromNormalF->getDeclName();
2620 auto FromFriendName = FromFriendF->getDeclName();
2621
2622 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2623 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2624 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2625 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2626 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2627 ASSERT_EQ(LookupRes.size(), 1u);
2628 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2629 ASSERT_EQ(LookupRes.size(), 1u);
2630
2631 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX03));
2632 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2633 auto ToName = ToNormalF->getDeclName();
2634 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2635 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2636 LookupRes = ToTU->noload_lookup(ToName);
2637 EXPECT_EQ(LookupRes.size(), 1u);
2638 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2639
2640 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX03));
2641 LookupRes = ToTU->noload_lookup(ToName);
2642 EXPECT_EQ(LookupRes.size(), 1u);
2643 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2644
2645 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2646 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2647
2648 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2649 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2650 }
2651
TEST_P(ImportFriendFunctions,ImportFriendList)2652 TEST_P(ImportFriendFunctions, ImportFriendList) {
2653 TranslationUnitDecl *FromTU = getTuDecl("struct X { friend void f(); };"
2654 "void f();",
2655 Lang_CXX03, "input0.cc");
2656 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2657 FromTU, functionDecl(hasName("f")));
2658
2659 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2660 FromTU, cxxRecordDecl(hasName("X")));
2661 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2662 auto FromFriends = FromClass->friends();
2663 unsigned int FrN = 0;
2664 for (auto Fr : FromFriends) {
2665 ASSERT_EQ(Fr, FromFriend);
2666 ++FrN;
2667 }
2668 ASSERT_EQ(FrN, 1u);
2669
2670 Import(FromFriendF, Lang_CXX03);
2671 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2672 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2673 ToTU, cxxRecordDecl(hasName("X")));
2674 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2675 auto ToFriends = ToClass->friends();
2676 FrN = 0;
2677 for (auto Fr : ToFriends) {
2678 EXPECT_EQ(Fr, ToFriend);
2679 ++FrN;
2680 }
2681 EXPECT_EQ(FrN, 1u);
2682 }
2683
AST_MATCHER_P(TagDecl,hasTypedefForAnonDecl,Matcher<TypedefNameDecl>,InnerMatcher)2684 AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2685 InnerMatcher) {
2686 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2687 return InnerMatcher.matches(*Typedef, Finder, Builder);
2688 return false;
2689 }
2690
TEST_P(ImportDecl,ImportEnumSequential)2691 TEST_P(ImportDecl, ImportEnumSequential) {
2692 CodeFiles Samples{{"main.c",
2693 {"void foo();"
2694 "void moo();"
2695 "int main() { foo(); moo(); }",
2696 Lang_C99}},
2697
2698 {"foo.c",
2699 {"typedef enum { THING_VALUE } thing_t;"
2700 "void conflict(thing_t type);"
2701 "void foo() { (void)THING_VALUE; }"
2702 "void conflict(thing_t type) {}",
2703 Lang_C99}},
2704
2705 {"moo.c",
2706 {"typedef enum { THING_VALUE } thing_t;"
2707 "void conflict(thing_t type);"
2708 "void moo() { conflict(THING_VALUE); }",
2709 Lang_C99}}};
2710
2711 auto VerificationMatcher =
2712 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2713 hasTypedefForAnonDecl(hasName("thing_t")));
2714
2715 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2716 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2717
2718 testImportSequence(
2719 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2720 // Just check that there is only one enum decl in the result AST.
2721 "main.c", enumDecl(), VerificationMatcher);
2722
2723 // For different import order, result should be the same.
2724 testImportSequence(
2725 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2726 // Check that there is only one enum decl in the result AST.
2727 "main.c", enumDecl(), VerificationMatcher);
2728 }
2729
TEST_P(ImportDecl,ImportFieldOrder)2730 TEST_P(ImportDecl, ImportFieldOrder) {
2731 MatchVerifier<Decl> Verifier;
2732 testImport("struct declToImport {"
2733 " int b = a + 2;"
2734 " int a = 5;"
2735 "};",
2736 Lang_CXX11, "", Lang_CXX11, Verifier,
2737 recordDecl(hasFieldOrder({"b", "a"})));
2738 }
2739
2740 const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2741 dependentScopeDeclRefExpr;
2742
TEST_P(ImportExpr,DependentScopeDeclRefExpr)2743 TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
2744 MatchVerifier<Decl> Verifier;
2745 testImport("template <typename T> struct S { static T foo; };"
2746 "template <typename T> void declToImport() {"
2747 " (void) S<T>::foo;"
2748 "}"
2749 "void instantiate() { declToImport<int>(); }"
2750 "template <typename T> T S<T>::foo;",
2751 Lang_CXX11, "", Lang_CXX11, Verifier,
2752 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2753 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2754
2755 testImport("template <typename T> struct S {"
2756 "template<typename S> static void foo(){};"
2757 "};"
2758 "template <typename T> void declToImport() {"
2759 " S<T>::template foo<T>();"
2760 "}"
2761 "void instantiate() { declToImport<int>(); }",
2762 Lang_CXX11, "", Lang_CXX11, Verifier,
2763 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2764 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2765 }
2766
2767 const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2768 dependentNameType;
2769
TEST_P(ImportExpr,DependentNameType)2770 TEST_P(ImportExpr, DependentNameType) {
2771 MatchVerifier<Decl> Verifier;
2772 testImport("template <typename T> struct declToImport {"
2773 " typedef typename T::type dependent_name;"
2774 "};",
2775 Lang_CXX11, "", Lang_CXX11, Verifier,
2776 classTemplateDecl(has(
2777 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2778 }
2779
TEST_P(ImportExpr,UnresolvedMemberExpr)2780 TEST_P(ImportExpr, UnresolvedMemberExpr) {
2781 MatchVerifier<Decl> Verifier;
2782 testImport("struct S { template <typename T> void mem(); };"
2783 "template <typename U> void declToImport() {"
2784 " S s;"
2785 " s.mem<U>();"
2786 "}"
2787 "void instantiate() { declToImport<int>(); }",
2788 Lang_CXX11, "", Lang_CXX11, Verifier,
2789 functionTemplateDecl(has(functionDecl(has(
2790 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2791 }
2792
2793 class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
2794 public:
2795 static constexpr auto DefaultCode = R"(
2796 struct A { int x; };
2797 void f() {
2798 A a;
2799 A a1(a);
2800 A a2(A{});
2801 a = a1;
2802 a = A{};
2803 a.~A();
2804 })";
2805
2806 template <typename MatcherType>
testImportOf(const MatcherType & MethodMatcher,const char * Code=DefaultCode)2807 void testImportOf(
2808 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2809 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2810 }
2811
2812 template <typename MatcherType>
testNoImportOf(const MatcherType & MethodMatcher,const char * Code=DefaultCode)2813 void testNoImportOf(
2814 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2815 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2816 }
2817
2818 private:
2819 template <typename MatcherType>
test(const MatcherType & MethodMatcher,const char * Code,unsigned int ExpectedCount)2820 void test(const MatcherType &MethodMatcher,
2821 const char *Code, unsigned int ExpectedCount) {
2822 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2823
2824 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2825 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2826 ToTU, ClassMatcher);
2827
2828 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
2829
2830 {
2831 CXXMethodDecl *Method =
2832 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2833 ToClass->removeDecl(Method);
2834 SharedStatePtr->getLookupTable()->remove(Method);
2835 }
2836
2837 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
2838
2839 Decl *ImportedClass = nullptr;
2840 {
2841 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2842 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2843 FromTU, ClassMatcher);
2844 ImportedClass = Import(FromClass, Lang_CXX11);
2845 }
2846
2847 EXPECT_EQ(ToClass, ImportedClass);
2848 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2849 ExpectedCount);
2850 }
2851 };
2852
TEST_P(ImportImplicitMethods,DefaultConstructor)2853 TEST_P(ImportImplicitMethods, DefaultConstructor) {
2854 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2855 }
2856
TEST_P(ImportImplicitMethods,CopyConstructor)2857 TEST_P(ImportImplicitMethods, CopyConstructor) {
2858 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2859 }
2860
TEST_P(ImportImplicitMethods,MoveConstructor)2861 TEST_P(ImportImplicitMethods, MoveConstructor) {
2862 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2863 }
2864
TEST_P(ImportImplicitMethods,Destructor)2865 TEST_P(ImportImplicitMethods, Destructor) {
2866 testImportOf(cxxDestructorDecl());
2867 }
2868
TEST_P(ImportImplicitMethods,CopyAssignment)2869 TEST_P(ImportImplicitMethods, CopyAssignment) {
2870 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2871 }
2872
TEST_P(ImportImplicitMethods,MoveAssignment)2873 TEST_P(ImportImplicitMethods, MoveAssignment) {
2874 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2875 }
2876
TEST_P(ImportImplicitMethods,DoNotImportUserProvided)2877 TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2878 auto Code = R"(
2879 struct A { A() { int x; } };
2880 )";
2881 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2882 }
2883
TEST_P(ImportImplicitMethods,DoNotImportDefault)2884 TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2885 auto Code = R"(
2886 struct A { A() = default; };
2887 )";
2888 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2889 }
2890
TEST_P(ImportImplicitMethods,DoNotImportDeleted)2891 TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2892 auto Code = R"(
2893 struct A { A() = delete; };
2894 )";
2895 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2896 }
2897
TEST_P(ImportImplicitMethods,DoNotImportOtherMethod)2898 TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2899 auto Code = R"(
2900 struct A { void f() { } };
2901 )";
2902 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2903 }
2904
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfEquivalentRecord)2905 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
2906 Decl *ToR1;
2907 {
2908 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input0.cc");
2909 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2910 FromTU, cxxRecordDecl(hasName("A")));
2911
2912 ToR1 = Import(FromR, Lang_CXX03);
2913 }
2914
2915 Decl *ToR2;
2916 {
2917 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input1.cc");
2918 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2919 FromTU, cxxRecordDecl(hasName("A")));
2920
2921 ToR2 = Import(FromR, Lang_CXX03);
2922 }
2923
2924 EXPECT_EQ(ToR1, ToR2);
2925 }
2926
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfNonEquivalentRecord)2927 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
2928 Decl *ToR1;
2929 {
2930 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
2931 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2932 FromTU, cxxRecordDecl(hasName("A")));
2933 ToR1 = Import(FromR, Lang_CXX03);
2934 }
2935 Decl *ToR2;
2936 {
2937 Decl *FromTU =
2938 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");
2939 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2940 FromTU, cxxRecordDecl(hasName("A")));
2941 ToR2 = Import(FromR, Lang_CXX03);
2942 }
2943 EXPECT_NE(ToR1, ToR2);
2944 }
2945
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfEquivalentField)2946 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
2947 Decl *ToF1;
2948 {
2949 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
2950 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2951 FromTU, fieldDecl(hasName("x")));
2952 ToF1 = Import(FromF, Lang_CXX03);
2953 }
2954 Decl *ToF2;
2955 {
2956 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input1.cc");
2957 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2958 FromTU, fieldDecl(hasName("x")));
2959 ToF2 = Import(FromF, Lang_CXX03);
2960 }
2961 EXPECT_EQ(ToF1, ToF2);
2962 }
2963
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfNonEquivalentField)2964 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
2965 Decl *ToF1;
2966 {
2967 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
2968 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2969 FromTU, fieldDecl(hasName("x")));
2970 ToF1 = Import(FromF, Lang_CXX03);
2971 }
2972 Decl *ToF2;
2973 {
2974 Decl *FromTU =
2975 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");
2976 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2977 FromTU, fieldDecl(hasName("x")));
2978 ToF2 = Import(FromF, Lang_CXX03);
2979 }
2980 EXPECT_NE(ToF1, ToF2);
2981 }
2982
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfEquivalentMethod)2983 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
2984 Decl *ToM1;
2985 {
2986 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
2987 Lang_CXX03, "input0.cc");
2988 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2989 FromTU, functionDecl(hasName("x"), isDefinition()));
2990 ToM1 = Import(FromM, Lang_CXX03);
2991 }
2992 Decl *ToM2;
2993 {
2994 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
2995 Lang_CXX03, "input1.cc");
2996 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2997 FromTU, functionDecl(hasName("x"), isDefinition()));
2998 ToM2 = Import(FromM, Lang_CXX03);
2999 }
3000 EXPECT_EQ(ToM1, ToM2);
3001 }
3002
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfNonEquivalentMethod)3003 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
3004 Decl *ToM1;
3005 {
3006 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3007 Lang_CXX03, "input0.cc");
3008 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3009 FromTU, functionDecl(hasName("x"), isDefinition()));
3010 ToM1 = Import(FromM, Lang_CXX03);
3011 }
3012 Decl *ToM2;
3013 {
3014 Decl *FromTU =
3015 getTuDecl("struct A { void x() const; }; void A::x() const { }",
3016 Lang_CXX03, "input1.cc");
3017 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3018 FromTU, functionDecl(hasName("x"), isDefinition()));
3019 ToM2 = Import(FromM, Lang_CXX03);
3020 }
3021 EXPECT_NE(ToM1, ToM2);
3022 }
3023
TEST_P(ASTImporterOptionSpecificTestBase,ImportUnnamedStructsWithRecursingField)3024 TEST_P(ASTImporterOptionSpecificTestBase,
3025 ImportUnnamedStructsWithRecursingField) {
3026 Decl *FromTU = getTuDecl(
3027 R"(
3028 struct A {
3029 struct {
3030 struct A *next;
3031 } entry0;
3032 struct {
3033 struct A *next;
3034 } entry1;
3035 };
3036 )",
3037 Lang_C99, "input0.cc");
3038 auto *From =
3039 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3040
3041 Import(From, Lang_C99);
3042
3043 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3044 auto *Entry0 =
3045 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3046 auto *Entry1 =
3047 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3048 auto *R0 = getRecordDecl(Entry0);
3049 auto *R1 = getRecordDecl(Entry1);
3050 EXPECT_NE(R0, R1);
3051 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3052 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3053 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3054 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3055 }
3056
TEST_P(ASTImporterOptionSpecificTestBase,ImportUnnamedFieldsInCorrectOrder)3057 TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
3058 Decl *FromTU = getTuDecl(
3059 R"(
3060 void f(int X, int Y, bool Z) {
3061 (void)[X, Y, Z] { (void)Z; };
3062 }
3063 )",
3064 Lang_CXX11, "input0.cc");
3065 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3066 FromTU, functionDecl(hasName("f")));
3067 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3068 EXPECT_TRUE(ToF);
3069
3070 CXXRecordDecl *FromLambda =
3071 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3072 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3073
3074 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3075 EXPECT_TRUE(ToLambda);
3076
3077 // Check if the fields of the lambda class are imported in correct order.
3078 unsigned FromIndex = 0u;
3079 for (auto *FromField : FromLambda->fields()) {
3080 ASSERT_FALSE(FromField->getDeclName());
3081 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3082 EXPECT_TRUE(ToField);
3083 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3084 EXPECT_TRUE(ToIndex);
3085 EXPECT_EQ(*ToIndex, FromIndex);
3086 ++FromIndex;
3087 }
3088
3089 EXPECT_EQ(FromIndex, 3u);
3090 }
3091
TEST_P(ASTImporterOptionSpecificTestBase,MergeFieldDeclsOfClassTemplateSpecialization)3092 TEST_P(ASTImporterOptionSpecificTestBase,
3093 MergeFieldDeclsOfClassTemplateSpecialization) {
3094 std::string ClassTemplate =
3095 R"(
3096 template <typename T>
3097 struct X {
3098 int a{0}; // FieldDecl with InitListExpr
3099 X(char) : a(3) {} // (1)
3100 X(int) {} // (2)
3101 };
3102 )";
3103 Decl *ToTU = getToTuDecl(ClassTemplate +
3104 R"(
3105 void foo() {
3106 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3107 X<char> xc('c');
3108 }
3109 )", Lang_CXX11);
3110 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3111 ToTU, classTemplateSpecializationDecl(hasName("X")));
3112 // FieldDecl without InitlistExpr:
3113 auto *ToField = *ToSpec->field_begin();
3114 ASSERT_TRUE(ToField);
3115 ASSERT_FALSE(ToField->getInClassInitializer());
3116 Decl *FromTU = getTuDecl(ClassTemplate +
3117 R"(
3118 void bar() {
3119 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3120 X<char> xc(1);
3121 }
3122 )", Lang_CXX11);
3123 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3124 FromTU, classTemplateSpecializationDecl(hasName("X")));
3125 // FieldDecl with InitlistExpr:
3126 auto *FromField = *FromSpec->field_begin();
3127 ASSERT_TRUE(FromField);
3128 ASSERT_TRUE(FromField->getInClassInitializer());
3129
3130 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3131 ASSERT_TRUE(ImportedSpec);
3132 EXPECT_EQ(ImportedSpec, ToSpec);
3133 // After the import, the FieldDecl has to be merged, thus it should have the
3134 // InitListExpr.
3135 EXPECT_TRUE(ToField->getInClassInitializer());
3136 }
3137
TEST_P(ASTImporterOptionSpecificTestBase,MergeFunctionOfClassTemplateSpecialization)3138 TEST_P(ASTImporterOptionSpecificTestBase,
3139 MergeFunctionOfClassTemplateSpecialization) {
3140 std::string ClassTemplate =
3141 R"(
3142 template <typename T>
3143 struct X {
3144 void f() {}
3145 void g() {}
3146 };
3147 )";
3148 Decl *ToTU = getToTuDecl(ClassTemplate +
3149 R"(
3150 void foo() {
3151 X<char> x;
3152 x.f();
3153 }
3154 )", Lang_CXX11);
3155 Decl *FromTU = getTuDecl(ClassTemplate +
3156 R"(
3157 void bar() {
3158 X<char> x;
3159 x.g();
3160 }
3161 )", Lang_CXX11);
3162 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3163 FromTU, classTemplateSpecializationDecl(hasName("X")));
3164 auto FunPattern = functionDecl(hasName("g"),
3165 hasParent(classTemplateSpecializationDecl()));
3166 auto *FromFun =
3167 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3168 auto *ToFun =
3169 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3170 ASSERT_TRUE(FromFun->hasBody());
3171 ASSERT_FALSE(ToFun->hasBody());
3172 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3173 ASSERT_TRUE(ImportedSpec);
3174 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3175 ToTU, classTemplateSpecializationDecl(hasName("X")));
3176 EXPECT_EQ(ImportedSpec, ToSpec);
3177 EXPECT_TRUE(ToFun->hasBody());
3178 }
3179
TEST_P(ASTImporterOptionSpecificTestBase,MergeTemplateSpecWithForwardDecl)3180 TEST_P(ASTImporterOptionSpecificTestBase, MergeTemplateSpecWithForwardDecl) {
3181 std::string ClassTemplate =
3182 R"(
3183 template<typename T>
3184 struct X { int m; };
3185 template<>
3186 struct X<int> { int m; };
3187 )";
3188 // Append a forward decl for our template specialization.
3189 getToTuDecl(ClassTemplate + "template<> struct X<int>;", Lang_CXX11);
3190 Decl *FromTU = getTuDecl(ClassTemplate, Lang_CXX11);
3191 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3192 FromTU, classTemplateSpecializationDecl(hasName("X"), isDefinition()));
3193 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3194 // Check that our definition got merged with the existing definition.
3195 EXPECT_TRUE(FromSpec->isThisDeclarationADefinition());
3196 EXPECT_TRUE(ImportedSpec->isThisDeclarationADefinition());
3197 }
3198
TEST_P(ASTImporterOptionSpecificTestBase,ODRViolationOfClassTemplateSpecializationsShouldBeReported)3199 TEST_P(ASTImporterOptionSpecificTestBase,
3200 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3201 std::string ClassTemplate =
3202 R"(
3203 template <typename T>
3204 struct X {};
3205 )";
3206 Decl *ToTU = getToTuDecl(ClassTemplate +
3207 R"(
3208 template <>
3209 struct X<char> {
3210 int a;
3211 };
3212 void foo() {
3213 X<char> x;
3214 }
3215 )",
3216 Lang_CXX11);
3217 Decl *FromTU = getTuDecl(ClassTemplate +
3218 R"(
3219 template <>
3220 struct X<char> {
3221 int b;
3222 };
3223 void foo() {
3224 X<char> x;
3225 }
3226 )",
3227 Lang_CXX11);
3228 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3229 FromTU, classTemplateSpecializationDecl(hasName("X")));
3230 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3231
3232 // We expect one (ODR) warning during the import.
3233 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3234
3235 // The second specialization is different from the first, thus it violates
3236 // ODR, consequently we expect to keep the first specialization only, which is
3237 // already in the "To" context.
3238 EXPECT_FALSE(ImportedSpec);
3239 EXPECT_EQ(1u,
3240 DeclCounter<ClassTemplateSpecializationDecl>().match(
3241 ToTU, classTemplateSpecializationDecl(hasName("X"))));
3242 }
3243
TEST_P(ASTImporterOptionSpecificTestBase,MergeCtorOfClassTemplateSpecialization)3244 TEST_P(ASTImporterOptionSpecificTestBase,
3245 MergeCtorOfClassTemplateSpecialization) {
3246 std::string ClassTemplate =
3247 R"(
3248 template <typename T>
3249 struct X {
3250 X(char) {}
3251 X(int) {}
3252 };
3253 )";
3254 Decl *ToTU = getToTuDecl(ClassTemplate +
3255 R"(
3256 void foo() {
3257 X<char> x('c');
3258 }
3259 )", Lang_CXX11);
3260 Decl *FromTU = getTuDecl(ClassTemplate +
3261 R"(
3262 void bar() {
3263 X<char> x(1);
3264 }
3265 )", Lang_CXX11);
3266 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3267 FromTU, classTemplateSpecializationDecl(hasName("X")));
3268 // Match the void(int) ctor.
3269 auto CtorPattern =
3270 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3271 hasParent(classTemplateSpecializationDecl()));
3272 auto *FromCtor =
3273 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3274 auto *ToCtor =
3275 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3276 ASSERT_TRUE(FromCtor->hasBody());
3277 ASSERT_FALSE(ToCtor->hasBody());
3278 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3279 ASSERT_TRUE(ImportedSpec);
3280 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3281 ToTU, classTemplateSpecializationDecl(hasName("X")));
3282 EXPECT_EQ(ImportedSpec, ToSpec);
3283 EXPECT_TRUE(ToCtor->hasBody());
3284 }
3285
TEST_P(ASTImporterOptionSpecificTestBase,ClassTemplateFriendDecl)3286 TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateFriendDecl) {
3287 const auto *Code =
3288 R"(
3289 template <class T> class X { friend T; };
3290 struct Y {};
3291 template class X<Y>;
3292 )";
3293 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3294 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3295 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3296 FromTU, classTemplateSpecializationDecl());
3297 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3298 ToTU, classTemplateSpecializationDecl());
3299
3300 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3301 EXPECT_EQ(ImportedSpec, ToSpec);
3302 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3303 ToTU, classTemplateSpecializationDecl()));
3304 }
3305
TEST_P(ASTImporterOptionSpecificTestBase,ClassTemplatePartialSpecializationsShouldNotBeDuplicated)3306 TEST_P(ASTImporterOptionSpecificTestBase,
3307 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3308 auto Code =
3309 R"(
3310 // primary template
3311 template<class T1, class T2, int I>
3312 class A {};
3313
3314 // partial specialization
3315 template<class T, int I>
3316 class A<T, T*, I> {};
3317 )";
3318 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3319 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3320 auto *FromSpec =
3321 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3322 FromTU, classTemplatePartialSpecializationDecl());
3323 auto *ToSpec =
3324 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3325 ToTU, classTemplatePartialSpecializationDecl());
3326
3327 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3328 EXPECT_EQ(ImportedSpec, ToSpec);
3329 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3330 ToTU, classTemplatePartialSpecializationDecl()));
3331 }
3332
TEST_P(ASTImporterOptionSpecificTestBase,ClassTemplateSpecializationsShouldNotBeDuplicated)3333 TEST_P(ASTImporterOptionSpecificTestBase,
3334 ClassTemplateSpecializationsShouldNotBeDuplicated) {
3335 auto Code =
3336 R"(
3337 // primary template
3338 template<class T1, class T2, int I>
3339 class A {};
3340
3341 // full specialization
3342 template<>
3343 class A<int, int, 1> {};
3344 )";
3345 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3346 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3347 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3348 FromTU, classTemplateSpecializationDecl());
3349 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3350 ToTU, classTemplateSpecializationDecl());
3351
3352 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3353 EXPECT_EQ(ImportedSpec, ToSpec);
3354 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3355 ToTU, classTemplateSpecializationDecl()));
3356 }
3357
TEST_P(ASTImporterOptionSpecificTestBase,ClassTemplateFullAndPartialSpecsShouldNotBeMixed)3358 TEST_P(ASTImporterOptionSpecificTestBase,
3359 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3360 std::string PrimaryTemplate =
3361 R"(
3362 template<class T1, class T2, int I>
3363 class A {};
3364 )";
3365 auto PartialSpec =
3366 R"(
3367 template<class T, int I>
3368 class A<T, T*, I> {};
3369 )";
3370 auto FullSpec =
3371 R"(
3372 template<>
3373 class A<int, int, 1> {};
3374 )";
3375 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3376 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3377 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3378 FromTU, classTemplateSpecializationDecl());
3379
3380 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3381 EXPECT_TRUE(ImportedSpec);
3382 // Check the number of partial specializations.
3383 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3384 ToTU, classTemplatePartialSpecializationDecl()));
3385 // Check the number of full specializations.
3386 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3387 ToTU, classTemplateSpecializationDecl(
3388 unless(classTemplatePartialSpecializationDecl()))));
3389 }
3390
TEST_P(ASTImporterOptionSpecificTestBase,InitListExprValueKindShouldBeImported)3391 TEST_P(ASTImporterOptionSpecificTestBase,
3392 InitListExprValueKindShouldBeImported) {
3393 Decl *TU = getTuDecl(
3394 R"(
3395 const int &init();
3396 void foo() { const int &a{init()}; }
3397 )", Lang_CXX11, "input0.cc");
3398 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3399 ASSERT_TRUE(FromD->getAnyInitializer());
3400 auto *InitExpr = FromD->getAnyInitializer();
3401 ASSERT_TRUE(InitExpr);
3402 ASSERT_TRUE(InitExpr->isGLValue());
3403
3404 auto *ToD = Import(FromD, Lang_CXX11);
3405 EXPECT_TRUE(ToD);
3406 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3407 EXPECT_TRUE(ToInitExpr);
3408 EXPECT_TRUE(ToInitExpr->isGLValue());
3409 }
3410
3411 struct ImportVariables : ASTImporterOptionSpecificTestBase {};
3412
TEST_P(ImportVariables,ImportOfOneDeclBringsInTheWholeChain)3413 TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3414 Decl *FromTU = getTuDecl(
3415 R"(
3416 struct A {
3417 static const int a = 1 + 2;
3418 };
3419 const int A::a;
3420 )",
3421 Lang_CXX03, "input1.cc");
3422
3423 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3424 FromTU, varDecl(hasName("a"))); // Decl with init
3425 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3426 FromTU, varDecl(hasName("a"))); // Decl with definition
3427 ASSERT_NE(FromDWithInit, FromDWithDef);
3428 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3429
3430 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3431 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3432 ASSERT_TRUE(ToD0);
3433 ASSERT_TRUE(ToD1);
3434 EXPECT_NE(ToD0, ToD1);
3435 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3436 }
3437
TEST_P(ImportVariables,InitAndDefinitionAreInDifferentTUs)3438 TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3439 auto StructA =
3440 R"(
3441 struct A {
3442 static const int a = 1 + 2;
3443 };
3444 )";
3445 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);
3446 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX03,
3447 "input1.cc");
3448
3449 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3450 FromTU, varDecl(hasName("a"))); // Decl with init
3451 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3452 FromTU, varDecl(hasName("a"))); // Decl with definition
3453 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3454 ASSERT_TRUE(FromDWithInit->getInit());
3455 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3456 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3457 ASSERT_FALSE(FromDWithDef->getInit());
3458
3459 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3460 ToTU, varDecl(hasName("a"))); // Decl with init
3461 ASSERT_TRUE(ToD->getInit());
3462 ASSERT_FALSE(ToD->getDefinition());
3463
3464 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3465 EXPECT_TRUE(ImportedD->getAnyInitializer());
3466 EXPECT_TRUE(ImportedD->getDefinition());
3467 }
3468
TEST_P(ImportVariables,InitAndDefinitionAreInTheFromContext)3469 TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3470 auto StructA =
3471 R"(
3472 struct A {
3473 static const int a;
3474 };
3475 )";
3476 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);
3477 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3478 Lang_CXX03, "input1.cc");
3479
3480 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3481 FromTU, varDecl(hasName("a")));
3482 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3483 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3484 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3485 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3486 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3487 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3488 ASSERT_TRUE(FromDWithDef->getInit());
3489
3490 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3491 ToTU, varDecl(hasName("a")));
3492 ASSERT_FALSE(ToD->getInit());
3493 ASSERT_FALSE(ToD->getDefinition());
3494
3495 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3496 EXPECT_TRUE(ImportedD->getAnyInitializer());
3497 EXPECT_TRUE(ImportedD->getDefinition());
3498 }
3499
3500 struct ImportClasses : ASTImporterOptionSpecificTestBase {};
3501
TEST_P(ImportClasses,ImportDefinitionWhenProtoIsInNestedToContext)3502 TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3503 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C99);
3504 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");
3505 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3506 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3507 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3508
3509 Decl *ImportedDef = Import(FromDef, Lang_C99);
3510
3511 EXPECT_NE(ImportedDef, ToProto);
3512 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3513 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3514 EXPECT_TRUE(ImportedDef == ToDef);
3515 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3516 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3517 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3518 }
3519
TEST_P(ImportClasses,ImportDefinitionWhenProtoIsInNestedToContextCXX)3520 TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3521 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX03);
3522 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX03, "input1.cc");
3523 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3524 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3525 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3526
3527 Decl *ImportedDef = Import(FromDef, Lang_CXX03);
3528
3529 EXPECT_NE(ImportedDef, ToProto);
3530 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3531 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3532 EXPECT_TRUE(ImportedDef == ToDef);
3533 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3534 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3535 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3536 }
3537
TEST_P(ImportClasses,ImportNestedPrototypeThenDefinition)3538 TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3539 Decl *FromTU0 =
3540 getTuDecl("struct A { struct X *Xp; };", Lang_C99, "input0.cc");
3541 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");
3542 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3543 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3544 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3545
3546 Decl *ImportedProto = Import(FromProto, Lang_C99);
3547 Decl *ImportedDef = Import(FromDef, Lang_C99);
3548 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3549
3550 EXPECT_NE(ImportedDef, ImportedProto);
3551 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3552 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3553 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3554 EXPECT_TRUE(ImportedDef == ToDef);
3555 EXPECT_TRUE(ImportedProto == ToProto);
3556 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3557 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3558 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3559 }
3560
3561
3562 struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
3563
TEST_P(ImportFriendClasses,ImportOfFriendRecordDoesNotMergeDefinition)3564 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3565 Decl *FromTU = getTuDecl(
3566 R"(
3567 class A {
3568 template <int I> class F {};
3569 class X {
3570 template <int I> friend class F;
3571 };
3572 };
3573 )",
3574 Lang_CXX03, "input0.cc");
3575
3576 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3577 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3578 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3579 FromTU, cxxRecordDecl(hasName("F")));
3580
3581 ASSERT_TRUE(FromClass);
3582 ASSERT_TRUE(FromFriendClass);
3583 ASSERT_NE(FromClass, FromFriendClass);
3584 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3585 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3586 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3587 FromClass->getDescribedClassTemplate());
3588
3589 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX03));
3590 auto *ToFriendClass =
3591 cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX03));
3592
3593 EXPECT_TRUE(ToClass);
3594 EXPECT_TRUE(ToFriendClass);
3595 EXPECT_NE(ToClass, ToFriendClass);
3596 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3597 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3598 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3599 ToClass->getDescribedClassTemplate());
3600 }
3601
TEST_P(ImportFriendClasses,ImportOfRecursiveFriendClass)3602 TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3603 Decl *FromTu = getTuDecl(
3604 R"(
3605 class declToImport {
3606 friend class declToImport;
3607 };
3608 )",
3609 Lang_CXX03, "input.cc");
3610
3611 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3612 FromTu, cxxRecordDecl(hasName("declToImport")));
3613 auto *ToD = Import(FromD, Lang_CXX03);
3614 auto Pattern = cxxRecordDecl(has(friendDecl()));
3615 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3616 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3617 }
3618
TEST_P(ImportFriendClasses,UndeclaredFriendClassShouldNotBeVisible)3619 TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
3620 Decl *FromTu =
3621 getTuDecl("class X { friend class Y; };", Lang_CXX03, "from.cc");
3622 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
3623 FromTu, cxxRecordDecl(hasName("X")));
3624 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3625 RecordDecl *FromRecordOfFriend =
3626 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));
3627
3628 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
3629 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
3630 cast<DeclContext>(FromX));
3631 ASSERT_FALSE(
3632 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
3633 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
3634 FromRecordOfFriend));
3635 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
3636 ->lookup(FromRecordOfFriend->getDeclName())
3637 .empty());
3638
3639 auto *ToX = Import(FromX, Lang_CXX03);
3640 ASSERT_TRUE(ToX);
3641
3642 Decl *ToTu = ToX->getTranslationUnitDecl();
3643 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3644 RecordDecl *ToRecordOfFriend =
3645 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));
3646
3647 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
3648 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
3649 EXPECT_FALSE(
3650 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
3651 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
3652 ToRecordOfFriend));
3653 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
3654 ->lookup(ToRecordOfFriend->getDeclName())
3655 .empty());
3656 }
3657
TEST_P(ImportFriendClasses,ImportOfRecursiveFriendClassTemplate)3658 TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3659 Decl *FromTu = getTuDecl(
3660 R"(
3661 template<class A> class declToImport {
3662 template<class A1> friend class declToImport;
3663 };
3664 )",
3665 Lang_CXX03, "input.cc");
3666
3667 auto *FromD =
3668 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3669 auto *ToD = Import(FromD, Lang_CXX03);
3670
3671 auto Pattern = classTemplateDecl(
3672 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3673 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3674 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3675
3676 auto *Class =
3677 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3678 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3679 EXPECT_NE(Friend->getFriendDecl(), Class);
3680 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3681 }
3682
TEST_P(ImportFriendClasses,ProperPrevDeclForClassTemplateDecls)3683 TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3684 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3685
3686 ClassTemplateSpecializationDecl *Imported1;
3687 {
3688 Decl *FromTU = getTuDecl("template<class T> class X;"
3689 "struct Y { friend class X<int>; };",
3690 Lang_CXX03, "input0.cc");
3691 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3692 FromTU, Pattern);
3693
3694 Imported1 =
3695 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
3696 }
3697 ClassTemplateSpecializationDecl *Imported2;
3698 {
3699 Decl *FromTU = getTuDecl("template<class T> class X;"
3700 "template<> class X<int>{};"
3701 "struct Z { friend class X<int>; };",
3702 Lang_CXX03, "input1.cc");
3703 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3704 FromTU, Pattern);
3705
3706 Imported2 =
3707 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
3708 }
3709
3710 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3711 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3712 2u);
3713 ASSERT_TRUE(Imported2->getPreviousDecl());
3714 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3715 }
3716
TEST_P(ImportFriendClasses,TypeForDeclShouldBeSetInTemplated)3717 TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3718 Decl *FromTU0 = getTuDecl(
3719 R"(
3720 class X {
3721 class Y;
3722 };
3723 class X::Y {
3724 template <typename T>
3725 friend class F; // The decl context of F is the global namespace.
3726 };
3727 )",
3728 Lang_CXX03, "input0.cc");
3729 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3730 FromTU0, classTemplateDecl(hasName("F")));
3731 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
3732 Decl *FromTU1 = getTuDecl(
3733 R"(
3734 template <typename T>
3735 class F {};
3736 )",
3737 Lang_CXX03, "input1.cc");
3738 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3739 FromTU1, classTemplateDecl(hasName("F")));
3740 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
3741 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3742 Imported1->getTemplatedDecl()->getTypeForDecl());
3743 }
3744
TEST_P(ImportFriendClasses,DeclsFromFriendsShouldBeInRedeclChains)3745 TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3746 Decl *From, *To;
3747 std::tie(From, To) =
3748 getImportedDecl("class declToImport {};", Lang_CXX03,
3749 "class Y { friend class declToImport; };", Lang_CXX03);
3750 auto *Imported = cast<CXXRecordDecl>(To);
3751
3752 EXPECT_TRUE(Imported->getPreviousDecl());
3753 }
3754
TEST_P(ImportFriendClasses,ImportOfClassTemplateDefinitionShouldConnectToFwdFriend)3755 TEST_P(ImportFriendClasses,
3756 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3757 Decl *ToTU = getToTuDecl(
3758 R"(
3759 class X {
3760 class Y;
3761 };
3762 class X::Y {
3763 template <typename T>
3764 friend class F; // The decl context of F is the global namespace.
3765 };
3766 )",
3767 Lang_CXX03);
3768 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3769 ToTU, classTemplateDecl(hasName("F")));
3770 Decl *FromTU = getTuDecl(
3771 R"(
3772 template <typename T>
3773 class F {};
3774 )",
3775 Lang_CXX03, "input0.cc");
3776 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3777 FromTU, classTemplateDecl(hasName("F")));
3778 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
3779 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3780 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3781 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3782 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3783 }
3784
TEST_P(ImportFriendClasses,ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked)3785 TEST_P(ImportFriendClasses,
3786 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3787 Decl *FromTU0 = getTuDecl(
3788 R"(
3789 class X {
3790 class Y;
3791 };
3792 class X::Y {
3793 template <typename T>
3794 friend class F; // The decl context of F is the global namespace.
3795 };
3796 )",
3797 Lang_CXX03, "input0.cc");
3798 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3799 FromTU0, classTemplateDecl(hasName("F")));
3800 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
3801 Decl *FromTU1 = getTuDecl(
3802 R"(
3803 template <typename T>
3804 class F {};
3805 )",
3806 Lang_CXX03, "input1.cc");
3807 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3808 FromTU1, classTemplateDecl(hasName("F")));
3809 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
3810 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3811 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3812 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3813 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3814 }
3815
TEST_P(ImportFriendClasses,ImportOfClassDefinitionAndFwdFriendShouldBeLinked)3816 TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3817 Decl *FromTU0 = getTuDecl(
3818 R"(
3819 class X {
3820 class Y;
3821 };
3822 class X::Y {
3823 friend class F; // The decl context of F is the global namespace.
3824 };
3825 )",
3826 Lang_CXX03, "input0.cc");
3827 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3828 QualType FT = Friend->getFriendType()->getType();
3829 FT = FromTU0->getASTContext().getCanonicalType(FT);
3830 auto *Fwd = cast<TagType>(FT)->getDecl();
3831 auto *ImportedFwd = Import(Fwd, Lang_CXX03);
3832 Decl *FromTU1 = getTuDecl(
3833 R"(
3834 class F {};
3835 )",
3836 Lang_CXX03, "input1.cc");
3837 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3838 FromTU1, cxxRecordDecl(hasName("F")));
3839 auto *ImportedDef = Import(Definition, Lang_CXX03);
3840 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3841 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3842 }
3843
TEST_P(ImportFriendClasses,ImportOfRepeatedFriendType)3844 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) {
3845 const char *Code =
3846 R"(
3847 class Container {
3848 friend class X;
3849 friend class X;
3850 };
3851 )";
3852 Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
3853 Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
3854
3855 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3856 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3857 auto *FromFriend1 =
3858 FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3859 auto *FromFriend2 = LastDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3860
3861 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
3862 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
3863
3864 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
3865 EXPECT_EQ(ToFriend1, ToImportedFriend1);
3866 EXPECT_EQ(ToFriend2, ToImportedFriend2);
3867 }
3868
TEST_P(ImportFriendClasses,ImportOfRepeatedFriendDecl)3869 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
3870 const char *Code =
3871 R"(
3872 class Container {
3873 friend void f();
3874 friend void f();
3875 };
3876 )";
3877 Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
3878 Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
3879
3880 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3881 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3882 auto *FromFriend1 =
3883 FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3884 auto *FromFriend2 = LastDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3885
3886 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
3887 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
3888
3889 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
3890 EXPECT_EQ(ToFriend1, ToImportedFriend1);
3891 EXPECT_EQ(ToFriend2, ToImportedFriend2);
3892 }
3893
TEST_P(ASTImporterOptionSpecificTestBase,FriendFunInClassTemplate)3894 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
3895 auto *Code = R"(
3896 template <class T>
3897 struct X {
3898 friend void foo(){}
3899 };
3900 )";
3901 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
3902 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3903 ToTU, functionDecl(hasName("foo")));
3904
3905 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");
3906 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3907 FromTU, functionDecl(hasName("foo")));
3908 auto *ImportedFoo = Import(FromFoo, Lang_CXX03);
3909 EXPECT_EQ(ImportedFoo, ToFoo);
3910 }
3911
3912 struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
3913
TEST_P(DeclContextTest,removeDeclOfClassTemplateSpecialization)3914 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3915 Decl *TU = getTuDecl(
3916 R"(
3917 namespace NS {
3918
3919 template <typename T>
3920 struct S {};
3921 template struct S<int>;
3922
3923 inline namespace INS {
3924 template <typename T>
3925 struct S {};
3926 template struct S<int>;
3927 }
3928
3929 }
3930 )", Lang_CXX11, "input0.cc");
3931 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3932 TU, namespaceDecl());
3933 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3934 TU, classTemplateSpecializationDecl());
3935 ASSERT_TRUE(NS->containsDecl(Spec));
3936
3937 NS->removeDecl(Spec);
3938 EXPECT_FALSE(NS->containsDecl(Spec));
3939 }
3940
TEST_P(DeclContextTest,removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage)3941 TEST_P(DeclContextTest,
3942 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
3943 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX03);
3944 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3945 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3946
3947 // Investigate the list.
3948 auto *DC = A0->getDeclContext();
3949 ASSERT_TRUE(DC->containsDecl(A0));
3950 ASSERT_TRUE(DC->containsDecl(A1));
3951
3952 // Investigate the lookup table.
3953 auto *Map = DC->getLookupPtr();
3954 ASSERT_TRUE(Map);
3955 auto I = Map->find(A0->getDeclName());
3956 ASSERT_NE(I, Map->end());
3957 StoredDeclsList &L = I->second;
3958 // The lookup table contains the most recent decl of A.
3959 ASSERT_NE(L.getAsDecl(), A0);
3960 ASSERT_EQ(L.getAsDecl(), A1);
3961
3962 ASSERT_TRUE(L.getAsDecl());
3963 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
3964 // The point here is to have a Vec with only one element, which is not the
3965 // one we are going to delete from the DC later.
3966 L.setHasExternalDecls();
3967 ASSERT_TRUE(L.getAsVector());
3968 ASSERT_EQ(1u, L.getAsVector()->size());
3969
3970 // This asserts in the old implementation.
3971 DC->removeDecl(A0);
3972 EXPECT_FALSE(DC->containsDecl(A0));
3973 }
3974
3975 struct ImportFunctionTemplateSpecializations
3976 : ASTImporterOptionSpecificTestBase {};
3977
TEST_P(ImportFunctionTemplateSpecializations,TUshouldNotContainFunctionTemplateImplicitInstantiation)3978 TEST_P(ImportFunctionTemplateSpecializations,
3979 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3980
3981 Decl *FromTU = getTuDecl(
3982 R"(
3983 template<class T>
3984 int f() { return 0; }
3985 void foo() { f<int>(); }
3986 )",
3987 Lang_CXX03, "input0.cc");
3988
3989 // Check that the function template instantiation is NOT the child of the TU.
3990 auto Pattern = translationUnitDecl(
3991 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3992 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3993
3994 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3995 FromTU, functionDecl(hasName("foo")));
3996 ASSERT_TRUE(Import(Foo, Lang_CXX03));
3997
3998 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3999 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4000 }
4001
TEST_P(ImportFunctionTemplateSpecializations,TUshouldNotContainFunctionTemplateExplicitInstantiation)4002 TEST_P(ImportFunctionTemplateSpecializations,
4003 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4004
4005 Decl *FromTU = getTuDecl(
4006 R"(
4007 template<class T>
4008 int f() { return 0; }
4009 template int f<int>();
4010 )",
4011 Lang_CXX03, "input0.cc");
4012
4013 // Check that the function template instantiation is NOT the child of the TU.
4014 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4015 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4016 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4017
4018 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),
4019 Lang_CXX03));
4020
4021 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4022 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4023 }
4024
TEST_P(ImportFunctionTemplateSpecializations,TUshouldContainFunctionTemplateSpecialization)4025 TEST_P(ImportFunctionTemplateSpecializations,
4026 TUshouldContainFunctionTemplateSpecialization) {
4027
4028 Decl *FromTU = getTuDecl(
4029 R"(
4030 template<class T>
4031 int f() { return 0; }
4032 template <> int f<int>() { return 4; }
4033 )",
4034 Lang_CXX03, "input0.cc");
4035
4036 // Check that the function template specialization is the child of the TU.
4037 auto Specialization =
4038 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4039 auto Pattern = translationUnitDecl(has(Specialization));
4040 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4041
4042 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization),
4043 Lang_CXX03));
4044
4045 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4046 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4047 }
4048
TEST_P(ImportFunctionTemplateSpecializations,FunctionTemplateSpecializationRedeclChain)4049 TEST_P(ImportFunctionTemplateSpecializations,
4050 FunctionTemplateSpecializationRedeclChain) {
4051
4052 Decl *FromTU = getTuDecl(
4053 R"(
4054 template<class T>
4055 int f() { return 0; }
4056 template <> int f<int>() { return 4; }
4057 )",
4058 Lang_CXX03, "input0.cc");
4059
4060 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4061 hasParent(translationUnitDecl()));
4062 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4063 {
4064 auto *TU = FromTU;
4065 auto *SpecD = FromSpecD;
4066 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4067 TU, functionTemplateDecl());
4068 auto *FirstSpecD = *(TemplateD->spec_begin());
4069 ASSERT_EQ(SpecD, FirstSpecD);
4070 ASSERT_TRUE(SpecD->getPreviousDecl());
4071 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4072 ->doesThisDeclarationHaveABody());
4073 }
4074
4075 ASSERT_TRUE(Import(FromSpecD, Lang_CXX03));
4076
4077 {
4078 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4079 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4080 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4081 TU, functionTemplateDecl());
4082 auto *FirstSpecD = *(TemplateD->spec_begin());
4083 EXPECT_EQ(SpecD, FirstSpecD);
4084 ASSERT_TRUE(SpecD->getPreviousDecl());
4085 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4086 ->doesThisDeclarationHaveABody());
4087 }
4088 }
4089
TEST_P(ImportFunctionTemplateSpecializations,MatchNumberOfFunctionTemplateSpecializations)4090 TEST_P(ImportFunctionTemplateSpecializations,
4091 MatchNumberOfFunctionTemplateSpecializations) {
4092
4093 Decl *FromTU = getTuDecl(
4094 R"(
4095 template <typename T> constexpr int f() { return 0; }
4096 template <> constexpr int f<int>() { return 4; }
4097 void foo() {
4098 static_assert(f<char>() == 0, "");
4099 static_assert(f<int>() == 4, "");
4100 }
4101 )",
4102 Lang_CXX11, "input0.cc");
4103 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4104 FromTU, functionDecl(hasName("foo")));
4105
4106 Import(FromD, Lang_CXX11);
4107 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4108 EXPECT_EQ(
4109 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4110 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4111 }
4112
TEST_P(ASTImporterOptionSpecificTestBase,ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined)4113 TEST_P(ASTImporterOptionSpecificTestBase,
4114 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4115 {
4116 Decl *FromTU = getTuDecl(
4117 R"(
4118 template <typename T>
4119 struct B;
4120 )",
4121 Lang_CXX03, "input0.cc");
4122 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4123 FromTU, classTemplateDecl(hasName("B")));
4124
4125 Import(FromD, Lang_CXX03);
4126 }
4127
4128 {
4129 Decl *FromTU = getTuDecl(
4130 R"(
4131 template <typename T>
4132 struct B {
4133 void f();
4134 B* b;
4135 };
4136 )",
4137 Lang_CXX03, "input1.cc");
4138 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4139 FromTU, functionDecl(hasName("f")));
4140 Import(FromD, Lang_CXX03);
4141 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4142 FromTU, classTemplateDecl(hasName("B")));
4143 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
4144 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4145
4146 // We expect no (ODR) warning during the import.
4147 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4148 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4149 }
4150 }
4151
TEST_P(ASTImporterOptionSpecificTestBase,ImportingTypedefShouldImportTheCompleteType)4152 TEST_P(ASTImporterOptionSpecificTestBase,
4153 ImportingTypedefShouldImportTheCompleteType) {
4154 // We already have an incomplete underlying type in the "To" context.
4155 auto Code =
4156 R"(
4157 template <typename T>
4158 struct S {
4159 void foo();
4160 };
4161 using U = S<int>;
4162 )";
4163 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4164 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4165 typedefNameDecl(hasName("U")));
4166 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4167
4168 // The "From" context has the same typedef, but the underlying type is
4169 // complete this time.
4170 Decl *FromTU = getTuDecl(std::string(Code) +
4171 R"(
4172 void foo(U* u) {
4173 u->foo();
4174 }
4175 )", Lang_CXX11);
4176 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4177 typedefNameDecl(hasName("U")));
4178 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4179
4180 // The imported type should be complete.
4181 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4182 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4183 }
4184
TEST_P(ASTImporterOptionSpecificTestBase,ImportTemplateParameterLists)4185 TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4186 auto Code =
4187 R"(
4188 template<class T>
4189 int f() { return 0; }
4190 template <> int f<int>() { return 4; }
4191 )";
4192
4193 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
4194 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4195 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
4196 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
4197
4198 auto *ToD = Import(FromD, Lang_CXX03);
4199 // The template parameter list should exist.
4200 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
4201 }
4202
4203 struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
4204
TEST_P(ASTImporterLookupTableTest,OneDecl)4205 TEST_P(ASTImporterLookupTableTest, OneDecl) {
4206 auto *ToTU = getToTuDecl("int a;", Lang_CXX03);
4207 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4208 ASTImporterLookupTable LT(*ToTU);
4209 auto Res = LT.lookup(ToTU, D->getDeclName());
4210 ASSERT_EQ(Res.size(), 1u);
4211 EXPECT_EQ(*Res.begin(), D);
4212 }
4213
findInDeclListOfDC(DeclContext * DC,DeclarationName Name)4214 static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4215 for (Decl *D : DC->decls()) {
4216 if (auto *ND = dyn_cast<NamedDecl>(D))
4217 if (ND->getDeclName() == Name)
4218 return ND;
4219 }
4220 return nullptr;
4221 }
4222
TEST_P(ASTImporterLookupTableTest,FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup)4223 TEST_P(ASTImporterLookupTableTest,
4224 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4225 auto *Code = R"(
4226 template <class T>
4227 struct X {
4228 friend void foo(){}
4229 };
4230 )";
4231 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
4232 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4233 ToTU, classTemplateDecl(hasName("X")));
4234 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4235 ToTU, functionDecl(hasName("foo")));
4236 DeclContext *FooDC = Foo->getDeclContext();
4237 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4238 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4239 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4240 DeclarationName FooName = Foo->getDeclName();
4241
4242 // Cannot find in the LookupTable of its DC (TUDecl)
4243 SmallVector<NamedDecl *, 2> FoundDecls;
4244 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4245 EXPECT_EQ(FoundDecls.size(), 0u);
4246
4247 // Cannot find in the LookupTable of its LexicalDC (X)
4248 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4249 EXPECT_EQ(FoundDecls.size(), 0u);
4250
4251 // Can't find in the list of Decls of the DC.
4252 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4253
4254 // Can't find in the list of Decls of the LexicalDC
4255 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4256
4257 // ASTImporter specific lookup finds it.
4258 ASTImporterLookupTable LT(*ToTU);
4259 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4260 ASSERT_EQ(Res.size(), 1u);
4261 EXPECT_EQ(*Res.begin(), Foo);
4262 }
4263
TEST_P(ASTImporterLookupTableTest,FwdDeclStructShouldBeFoundByImporterSpecificLookup)4264 TEST_P(ASTImporterLookupTableTest,
4265 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4266 TranslationUnitDecl *ToTU =
4267 getToTuDecl("struct A { struct Foo *p; };", Lang_C99);
4268 auto *Foo =
4269 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4270 auto *A =
4271 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4272 DeclContext *FooDC = Foo->getDeclContext();
4273 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4274 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4275 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4276 DeclarationName FooName = Foo->getDeclName();
4277
4278 // Cannot find in the LookupTable of its DC (TUDecl).
4279 SmallVector<NamedDecl *, 2> FoundDecls;
4280 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4281 EXPECT_EQ(FoundDecls.size(), 0u);
4282
4283 // Cannot find in the LookupTable of its LexicalDC (A).
4284 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4285 EXPECT_EQ(FoundDecls.size(), 0u);
4286
4287 // Can't find in the list of Decls of the DC.
4288 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4289
4290 // Can find in the list of Decls of the LexicalDC.
4291 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4292
4293 // ASTImporter specific lookup finds it.
4294 ASTImporterLookupTable LT(*ToTU);
4295 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4296 ASSERT_EQ(Res.size(), 1u);
4297 EXPECT_EQ(*Res.begin(), Foo);
4298 }
4299
TEST_P(ASTImporterLookupTableTest,LookupFindsNamesInDifferentDC)4300 TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4301 TranslationUnitDecl *ToTU =
4302 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C99);
4303 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4304 .match(ToTU, varDecl(hasName("V")))
4305 ->getDeclName();
4306 auto *A =
4307 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4308 auto *B =
4309 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4310
4311 ASTImporterLookupTable LT(*ToTU);
4312
4313 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4314 ASSERT_EQ(Res.size(), 1u);
4315 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4316 ToTU, fieldDecl(hasName("V"),
4317 hasParent(recordDecl(hasName("A"))))));
4318 Res = LT.lookup(cast<DeclContext>(B), VName);
4319 ASSERT_EQ(Res.size(), 1u);
4320 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4321 ToTU, fieldDecl(hasName("V"),
4322 hasParent(recordDecl(hasName("B"))))));
4323 Res = LT.lookup(ToTU, VName);
4324 ASSERT_EQ(Res.size(), 1u);
4325 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4326 ToTU, varDecl(hasName("V"),
4327 hasParent(translationUnitDecl()))));
4328 }
4329
TEST_P(ASTImporterLookupTableTest,LookupFindsOverloadedNames)4330 TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4331 TranslationUnitDecl *ToTU = getToTuDecl(
4332 R"(
4333 void foo();
4334 void foo(int);
4335 void foo(int, int);
4336 )",
4337 Lang_CXX03);
4338
4339 ASTImporterLookupTable LT(*ToTU);
4340 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4341 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4342 DeclarationName Name = F0->getDeclName();
4343 auto Res = LT.lookup(ToTU, Name);
4344 EXPECT_EQ(Res.size(), 3u);
4345 EXPECT_EQ(Res.count(F0), 1u);
4346 EXPECT_EQ(Res.count(F2), 1u);
4347 }
4348
TEST_P(ASTImporterLookupTableTest,DifferentOperatorsShouldHaveDifferentResultSet)4349 TEST_P(ASTImporterLookupTableTest,
4350 DifferentOperatorsShouldHaveDifferentResultSet) {
4351 TranslationUnitDecl *ToTU = getToTuDecl(
4352 R"(
4353 struct X{};
4354 void operator+(X, X);
4355 void operator-(X, X);
4356 )",
4357 Lang_CXX03);
4358
4359 ASTImporterLookupTable LT(*ToTU);
4360 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4361 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4362 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4363 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4364 DeclarationName NamePlus = FPlus->getDeclName();
4365 auto ResPlus = LT.lookup(ToTU, NamePlus);
4366 EXPECT_EQ(ResPlus.size(), 1u);
4367 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4368 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4369 DeclarationName NameMinus = FMinus->getDeclName();
4370 auto ResMinus = LT.lookup(ToTU, NameMinus);
4371 EXPECT_EQ(ResMinus.size(), 1u);
4372 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4373 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4374 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4375 }
4376
TEST_P(ASTImporterLookupTableTest,LookupDeclNamesFromDifferentTUs)4377 TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4378 TranslationUnitDecl *ToTU = getToTuDecl(
4379 R"(
4380 struct X {};
4381 void operator+(X, X);
4382 )",
4383 Lang_CXX03);
4384 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4385 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4386
4387 Decl *FromTU = getTuDecl(
4388 R"(
4389 struct X {};
4390 void operator+(X, X);
4391 )",
4392 Lang_CXX03);
4393 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4394 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4395
4396 // FromPlus have a different TU, thus its DeclarationName is different too.
4397 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4398
4399 ASTImporterLookupTable LT(*ToTU);
4400 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4401 ASSERT_EQ(Res.size(), 1u);
4402 EXPECT_EQ(*Res.begin(), ToPlus);
4403
4404 // FromPlus have a different TU, thus its DeclarationName is different too.
4405 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4406 ASSERT_EQ(Res.size(), 0u);
4407 }
4408
TEST_P(ASTImporterLookupTableTest,LookupFindsFwdFriendClassDeclWithElaboratedType)4409 TEST_P(ASTImporterLookupTableTest,
4410 LookupFindsFwdFriendClassDeclWithElaboratedType) {
4411 TranslationUnitDecl *ToTU = getToTuDecl(
4412 R"(
4413 class Y { friend class F; };
4414 )",
4415 Lang_CXX03);
4416
4417 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4418 // So we must dig up the underlying CXXRecordDecl.
4419 ASTImporterLookupTable LT(*ToTU);
4420 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4421 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4422 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4423 ToTU, cxxRecordDecl(hasName("Y")));
4424
4425 DeclarationName Name = RD->getDeclName();
4426 auto Res = LT.lookup(ToTU, Name);
4427 EXPECT_EQ(Res.size(), 1u);
4428 EXPECT_EQ(*Res.begin(), RD);
4429
4430 Res = LT.lookup(Y, Name);
4431 EXPECT_EQ(Res.size(), 0u);
4432 }
4433
TEST_P(ASTImporterLookupTableTest,LookupFindsFwdFriendClassDeclWithUnelaboratedType)4434 TEST_P(ASTImporterLookupTableTest,
4435 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4436 TranslationUnitDecl *ToTU = getToTuDecl(
4437 R"(
4438 class F;
4439 class Y { friend F; };
4440 )",
4441 Lang_CXX11);
4442
4443 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4444 // So we must dig up the underlying CXXRecordDecl.
4445 ASTImporterLookupTable LT(*ToTU);
4446 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4447 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4448 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4449
4450 DeclarationName Name = RD->getDeclName();
4451 auto Res = LT.lookup(ToTU, Name);
4452 EXPECT_EQ(Res.size(), 1u);
4453 EXPECT_EQ(*Res.begin(), RD);
4454
4455 Res = LT.lookup(Y, Name);
4456 EXPECT_EQ(Res.size(), 0u);
4457 }
4458
TEST_P(ASTImporterLookupTableTest,LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert)4459 TEST_P(ASTImporterLookupTableTest,
4460 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4461 TranslationUnitDecl *ToTU = getToTuDecl(
4462 R"(
4463 class F;
4464 using alias_of_f = F;
4465 class Y { friend alias_of_f; };
4466 )",
4467 Lang_CXX11);
4468
4469 // ASTImporterLookupTable constructor handles using declarations correctly,
4470 // no assert is expected.
4471 ASTImporterLookupTable LT(*ToTU);
4472
4473 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4474 ToTU, typeAliasDecl(hasName("alias_of_f")));
4475 DeclarationName Name = Alias->getDeclName();
4476 auto Res = LT.lookup(ToTU, Name);
4477 EXPECT_EQ(Res.count(Alias), 1u);
4478 }
4479
TEST_P(ASTImporterLookupTableTest,LookupFindsFwdFriendClassTemplateDecl)4480 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4481 TranslationUnitDecl *ToTU = getToTuDecl(
4482 R"(
4483 class Y { template <class T> friend class F; };
4484 )",
4485 Lang_CXX03);
4486
4487 ASTImporterLookupTable LT(*ToTU);
4488 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4489 ToTU, classTemplateDecl(hasName("F")));
4490 DeclarationName Name = F->getDeclName();
4491 auto Res = LT.lookup(ToTU, Name);
4492 EXPECT_EQ(Res.size(), 2u);
4493 EXPECT_EQ(Res.count(F), 1u);
4494 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4495 }
4496
TEST_P(ASTImporterLookupTableTest,DependentFriendClass)4497 TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4498 TranslationUnitDecl *ToTU = getToTuDecl(
4499 R"(
4500 template <typename T>
4501 class F;
4502
4503 template <typename T>
4504 class Y {
4505 friend class F<T>;
4506 };
4507 )",
4508 Lang_CXX03);
4509
4510 ASTImporterLookupTable LT(*ToTU);
4511 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4512 ToTU, classTemplateDecl(hasName("F")));
4513 DeclarationName Name = F->getDeclName();
4514 auto Res = LT.lookup(ToTU, Name);
4515 EXPECT_EQ(Res.size(), 2u);
4516 EXPECT_EQ(Res.count(F), 1u);
4517 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4518 }
4519
TEST_P(ASTImporterLookupTableTest,FriendClassTemplateSpecialization)4520 TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4521 TranslationUnitDecl *ToTU = getToTuDecl(
4522 R"(
4523 template <typename T>
4524 class F;
4525
4526 class Y {
4527 friend class F<int>;
4528 };
4529 )",
4530 Lang_CXX03);
4531
4532 ASTImporterLookupTable LT(*ToTU);
4533 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4534 ToTU, classTemplateDecl(hasName("F")));
4535 DeclarationName Name = F->getDeclName();
4536 auto Res = LT.lookup(ToTU, Name);
4537 ASSERT_EQ(Res.size(), 3u);
4538 EXPECT_EQ(Res.count(F), 1u);
4539 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4540 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4541 }
4542
TEST_P(ASTImporterLookupTableTest,LookupFindsFwdFriendFunctionDecl)4543 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4544 TranslationUnitDecl *ToTU = getToTuDecl(
4545 R"(
4546 class Y { friend void F(); };
4547 )",
4548 Lang_CXX03);
4549
4550 ASTImporterLookupTable LT(*ToTU);
4551 auto *F =
4552 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4553 DeclarationName Name = F->getDeclName();
4554 auto Res = LT.lookup(ToTU, Name);
4555 EXPECT_EQ(Res.size(), 1u);
4556 EXPECT_EQ(*Res.begin(), F);
4557 }
4558
TEST_P(ASTImporterLookupTableTest,LookupFindsDeclsInClassTemplateSpecialization)4559 TEST_P(ASTImporterLookupTableTest,
4560 LookupFindsDeclsInClassTemplateSpecialization) {
4561 TranslationUnitDecl *ToTU = getToTuDecl(
4562 R"(
4563 template <typename T>
4564 struct X {
4565 int F;
4566 };
4567 void foo() {
4568 X<char> xc;
4569 }
4570 )",
4571 Lang_CXX03);
4572
4573 ASTImporterLookupTable LT(*ToTU);
4574
4575 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4576 ToTU, classTemplateDecl(hasName("X")));
4577 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4578 ToTU,
4579 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4580
4581 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4582 ToTU, classTemplateSpecializationDecl(hasName("X")));
4583 FieldDecl *FieldInSpec = *Spec->field_begin();
4584 ASSERT_TRUE(FieldInSpec);
4585
4586 DeclarationName Name = FieldInSpec->getDeclName();
4587 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4588
4589 SmallVector<NamedDecl *, 2> FoundDecls;
4590 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4591 EXPECT_EQ(FoundDecls.size(), 1u);
4592 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4593
4594 auto Res = LT.lookup(TemplateDC, Name);
4595 ASSERT_EQ(Res.size(), 1u);
4596 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4597
4598 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4599 FoundDecls);
4600 EXPECT_EQ(FoundDecls.size(), 1u);
4601 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4602
4603 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4604 ASSERT_EQ(Res.size(), 1u);
4605 EXPECT_EQ(*Res.begin(), FieldInSpec);
4606 }
4607
TEST_P(ASTImporterLookupTableTest,LookupFindsFwdFriendFunctionTemplateDecl)4608 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4609 TranslationUnitDecl *ToTU = getToTuDecl(
4610 R"(
4611 class Y { template <class T> friend void F(); };
4612 )",
4613 Lang_CXX03);
4614
4615 ASTImporterLookupTable LT(*ToTU);
4616 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4617 ToTU, functionTemplateDecl(hasName("F")));
4618 DeclarationName Name = F->getDeclName();
4619 auto Res = LT.lookup(ToTU, Name);
4620 EXPECT_EQ(Res.size(), 2u);
4621 EXPECT_EQ(Res.count(F), 1u);
4622 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4623 }
4624
TEST_P(ASTImporterLookupTableTest,MultipleBefriendingClasses)4625 TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4626 TranslationUnitDecl *ToTU = getToTuDecl(
4627 R"(
4628 struct X;
4629 struct A {
4630 friend struct X;
4631 };
4632 struct B {
4633 friend struct X;
4634 };
4635 )",
4636 Lang_CXX03);
4637
4638 ASTImporterLookupTable LT(*ToTU);
4639 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4640 ToTU, cxxRecordDecl(hasName("X")));
4641 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4642 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4643 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4644 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4645 ASSERT_EQ(RD0, RD1);
4646 ASSERT_EQ(RD1, X);
4647
4648 DeclarationName Name = X->getDeclName();
4649 auto Res = LT.lookup(ToTU, Name);
4650 EXPECT_EQ(Res.size(), 1u);
4651 EXPECT_EQ(*Res.begin(), X);
4652 }
4653
TEST_P(ASTImporterLookupTableTest,EnumConstantDecl)4654 TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4655 TranslationUnitDecl *ToTU = getToTuDecl(
4656 R"(
4657 enum E {
4658 A,
4659 B
4660 };
4661 )",
4662 Lang_C99);
4663
4664 ASTImporterLookupTable LT(*ToTU);
4665 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4666 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4667 ToTU, enumConstantDecl(hasName("A")));
4668
4669 DeclarationName Name = A->getDeclName();
4670 // Redecl context is the TU.
4671 ASSERT_EQ(E->getRedeclContext(), ToTU);
4672
4673 SmallVector<NamedDecl *, 2> FoundDecls;
4674 // Normal lookup finds in the DC.
4675 E->localUncachedLookup(Name, FoundDecls);
4676 EXPECT_EQ(FoundDecls.size(), 1u);
4677
4678 // Normal lookup finds in the Redecl context.
4679 ToTU->localUncachedLookup(Name, FoundDecls);
4680 EXPECT_EQ(FoundDecls.size(), 1u);
4681
4682 // Import specific lookup finds in the DC.
4683 auto Res = LT.lookup(E, Name);
4684 ASSERT_EQ(Res.size(), 1u);
4685 EXPECT_EQ(*Res.begin(), A);
4686
4687 // Import specific lookup finds in the Redecl context.
4688 Res = LT.lookup(ToTU, Name);
4689 ASSERT_EQ(Res.size(), 1u);
4690 EXPECT_EQ(*Res.begin(), A);
4691 }
4692
TEST_P(ASTImporterLookupTableTest,LookupSearchesInTheWholeRedeclChain)4693 TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4694 TranslationUnitDecl *ToTU = getToTuDecl(
4695 R"(
4696 namespace N {
4697 int A;
4698 }
4699 namespace N {
4700 }
4701 )",
4702 Lang_CXX03);
4703 auto *N1 =
4704 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4705 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4706 DeclarationName Name = A->getDeclName();
4707
4708 ASTImporterLookupTable LT(*ToTU);
4709 auto Res = LT.lookup(N1, Name);
4710 ASSERT_EQ(Res.size(), 1u);
4711 EXPECT_EQ(*Res.begin(), A);
4712 }
4713
TEST_P(ASTImporterOptionSpecificTestBase,RedeclChainShouldBeCorrectAmongstNamespaces)4714 TEST_P(ASTImporterOptionSpecificTestBase,
4715 RedeclChainShouldBeCorrectAmongstNamespaces) {
4716 Decl *FromTU = getTuDecl(
4717 R"(
4718 namespace NS {
4719 struct X;
4720 struct Y {
4721 static const int I = 3;
4722 };
4723 }
4724 namespace NS {
4725 struct X { // <--- To be imported
4726 void method(int i = Y::I) {}
4727 int f;
4728 };
4729 }
4730 )",
4731 Lang_CXX03);
4732 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4733 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4734 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4735 FromTU,
4736 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4737 ASSERT_NE(FromFwd, FromDef);
4738 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4739 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4740 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4741
4742 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX03));
4743 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX03));
4744 EXPECT_NE(ToFwd, ToDef);
4745 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4746 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4747 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4748 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4749 // We expect no (ODR) warning during the import.
4750 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4751 }
4752
4753 struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4754
TEST_P(ImportFriendFunctionTemplates,LookupShouldFindPreviousFriend)4755 TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4756 Decl *ToTU = getToTuDecl(
4757 R"(
4758 class X {
4759 template <typename T> friend void foo();
4760 };
4761 )",
4762 Lang_CXX03);
4763 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4764 ToTU, functionTemplateDecl(hasName("foo")));
4765
4766 Decl *FromTU = getTuDecl(
4767 R"(
4768 template <typename T> void foo();
4769 )",
4770 Lang_CXX03);
4771 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4772 FromTU, functionTemplateDecl(hasName("foo")));
4773 auto *Imported = Import(FromFoo, Lang_CXX03);
4774
4775 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
4776 }
4777
4778 struct ASTImporterWithFakeErrors : ASTImporter {
4779 using ASTImporter::ASTImporter;
returnWithErrorInTestclang::ast_matchers::ASTImporterWithFakeErrors4780 bool returnWithErrorInTest() override { return true; }
4781 };
4782
4783 struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
ErrorHandlingTestclang::ast_matchers::ErrorHandlingTest4784 ErrorHandlingTest() {
4785 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4786 ASTContext &FromContext, FileManager &FromFileManager,
4787 bool MinimalImport,
4788 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
4789 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4790 FromContext, FromFileManager,
4791 MinimalImport, SharedState);
4792 };
4793 }
4794 // In this test we purposely report an error (UnsupportedConstruct) when
4795 // importing the below stmt.
4796 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4797 };
4798
4799 // Check a case when no new AST node is created in the AST before encountering
4800 // the error.
TEST_P(ErrorHandlingTest,ErrorHappensBeforeCreatingANewNode)4801 TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4802 TranslationUnitDecl *ToTU = getToTuDecl(
4803 R"(
4804 template <typename T>
4805 class X {};
4806 template <>
4807 class X<int> { int a; };
4808 )",
4809 Lang_CXX03);
4810 TranslationUnitDecl *FromTU = getTuDecl(
4811 R"(
4812 template <typename T>
4813 class X {};
4814 template <>
4815 class X<int> { double b; };
4816 )",
4817 Lang_CXX03);
4818 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4819 FromTU, classTemplateSpecializationDecl(hasName("X")));
4820 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX03);
4821 EXPECT_FALSE(ImportedSpec);
4822
4823 // The original Decl is kept, no new decl is created.
4824 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4825 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4826 1u);
4827
4828 // But an error is set to the counterpart in the "from" context.
4829 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4830 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4831 ASSERT_TRUE(OptErr);
4832 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4833 }
4834
4835 // Check a case when a new AST node is created but not linked to the AST before
4836 // encountering the error.
TEST_P(ErrorHandlingTest,ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST)4837 TEST_P(ErrorHandlingTest,
4838 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4839 TranslationUnitDecl *FromTU = getTuDecl(
4840 std::string("void foo() { ") + ErroneousStmt + " }", Lang_CXX03);
4841 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4842 FromTU, functionDecl(hasName("foo")));
4843
4844 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX03);
4845 EXPECT_FALSE(ImportedFoo);
4846
4847 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4848 // Created, but not linked.
4849 EXPECT_EQ(
4850 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4851 0u);
4852
4853 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4854 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4855 ASSERT_TRUE(OptErr);
4856 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4857 }
4858
4859 // Check a case when a new AST node is created and linked to the AST before
4860 // encountering the error. The error is set for the counterpart of the nodes in
4861 // the "from" context.
TEST_P(ErrorHandlingTest,ErrorHappensAfterNodeIsCreatedAndLinked)4862 TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4863 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
4864 void f();
4865 void f() { )") + ErroneousStmt + R"( }
4866 )",
4867 Lang_CXX03);
4868 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4869 FromTU, functionDecl(hasName("f")));
4870 auto *FromDef =
4871 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4872 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX03);
4873 EXPECT_FALSE(ImportedProto); // Could not import.
4874 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4875 // definition. The definition is not added to its DC, but the fwd decl is
4876 // there.
4877 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4878 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4879 1u);
4880 // Match the fwd decl.
4881 auto *ToProto =
4882 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4883 EXPECT_TRUE(ToProto);
4884 // An error is set to the counterpart in the "from" context both for the fwd
4885 // decl and the definition.
4886 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
4887 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
4888 ASSERT_TRUE(OptErr);
4889 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4890 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
4891 ASSERT_TRUE(OptErr);
4892 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4893 }
4894
4895 // An error should be set for a class if we cannot import one member.
TEST_P(ErrorHandlingTest,ErrorIsPropagatedFromMemberToClass)4896 TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
4897 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
4898 class X {
4899 void f() { )") + ErroneousStmt + R"( } // This member has the error
4900 // during import.
4901 void ok(); // The error should not prevent importing this.
4902 }; // An error will be set for X too.
4903 )",
4904 Lang_CXX03);
4905 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4906 FromTU, cxxRecordDecl(hasName("X")));
4907 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
4908
4909 // An error is set for X.
4910 EXPECT_FALSE(ImportedX);
4911 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4912 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4913 ASSERT_TRUE(OptErr);
4914 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4915
4916 // An error is set for f().
4917 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
4918 FromTU, cxxMethodDecl(hasName("f")));
4919 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4920 ASSERT_TRUE(OptErr);
4921 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4922 // And any subsequent import should fail.
4923 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX03);
4924 EXPECT_FALSE(ImportedF);
4925
4926 // There is an error set for the other member too.
4927 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
4928 FromTU, cxxMethodDecl(hasName("ok")));
4929 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
4930 EXPECT_TRUE(OptErr);
4931 // Cannot import the other member.
4932 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX03);
4933 EXPECT_FALSE(ImportedOK);
4934 }
4935
4936 // Check that an error propagates to the dependent AST nodes.
4937 // In the below code it means that an error in X should propagate to A.
4938 // And even to F since the containing A is erroneous.
4939 // And to all AST nodes which we visit during the import process which finally
4940 // ends up in a failure (in the error() function).
TEST_P(ErrorHandlingTest,ErrorPropagatesThroughImportCycles)4941 TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
4942 Decl *FromTU = getTuDecl(std::string(R"(
4943 namespace NS {
4944 class A {
4945 template <int I> class F {};
4946 class X {
4947 template <int I> friend class F;
4948 void error() { )") +
4949 ErroneousStmt + R"( }
4950 };
4951 };
4952
4953 class B {};
4954 } // NS
4955 )",
4956 Lang_CXX03, "input0.cc");
4957
4958 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
4959 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4960 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
4961 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
4962 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
4963 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
4964 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
4965 FromTU, namespaceDecl(hasName("NS")));
4966
4967 // Start by importing the templated CXXRecordDecl of F.
4968 // Import fails for that.
4969 EXPECT_FALSE(Import(FromFRD, Lang_CXX03));
4970 // Import fails for A.
4971 EXPECT_FALSE(Import(FromA, Lang_CXX03));
4972 // But we should be able to import the independent B.
4973 EXPECT_TRUE(Import(FromB, Lang_CXX03));
4974 // And the namespace.
4975 EXPECT_TRUE(Import(FromNS, Lang_CXX03));
4976
4977 // An error is set to the templated CXXRecordDecl of F.
4978 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
4979 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
4980 EXPECT_TRUE(OptErr);
4981
4982 // An error is set to A.
4983 OptErr = Importer->getImportDeclErrorIfAny(FromA);
4984 EXPECT_TRUE(OptErr);
4985
4986 // There is no error set to B.
4987 OptErr = Importer->getImportDeclErrorIfAny(FromB);
4988 EXPECT_FALSE(OptErr);
4989
4990 // There is no error set to NS.
4991 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
4992 EXPECT_FALSE(OptErr);
4993
4994 // Check some of those decls whose ancestor is X, they all should have an
4995 // error set if we visited them during an import process which finally failed.
4996 // These decls are part of a cycle in an ImportPath.
4997 // There would not be any error set for these decls if we hadn't follow the
4998 // ImportPaths and the cycles.
4999 OptErr = Importer->getImportDeclErrorIfAny(
5000 FirstDeclMatcher<ClassTemplateDecl>().match(
5001 FromTU, classTemplateDecl(hasName("F"))));
5002 // An error is set to the 'F' ClassTemplateDecl.
5003 EXPECT_TRUE(OptErr);
5004 // An error is set to the FriendDecl.
5005 OptErr = Importer->getImportDeclErrorIfAny(
5006 FirstDeclMatcher<FriendDecl>().match(
5007 FromTU, friendDecl()));
5008 EXPECT_TRUE(OptErr);
5009 // An error is set to the implicit class of A.
5010 OptErr =
5011 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5012 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
5013 EXPECT_TRUE(OptErr);
5014 // An error is set to the implicit class of X.
5015 OptErr =
5016 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5017 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
5018 EXPECT_TRUE(OptErr);
5019 }
5020
TEST_P(ErrorHandlingTest,ErrorIsNotPropagatedFromMemberToNamespace)5021 TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
5022 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5023 namespace X {
5024 void f() { )") + ErroneousStmt + R"( } // This member has the error
5025 // during import.
5026 void ok(); // The error should not prevent importing this.
5027 }; // An error will be set for X too.
5028 )",
5029 Lang_CXX03);
5030 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
5031 FromTU, namespaceDecl(hasName("X")));
5032 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX03);
5033
5034 // There is no error set for X.
5035 EXPECT_TRUE(ImportedX);
5036 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5037 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5038 ASSERT_FALSE(OptErr);
5039
5040 // An error is set for f().
5041 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
5042 FromTU, functionDecl(hasName("f")));
5043 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5044 ASSERT_TRUE(OptErr);
5045 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5046 // And any subsequent import should fail.
5047 FunctionDecl *ImportedF = Import(FromF, Lang_CXX03);
5048 EXPECT_FALSE(ImportedF);
5049
5050 // There is no error set for ok().
5051 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
5052 FromTU, functionDecl(hasName("ok")));
5053 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5054 EXPECT_FALSE(OptErr);
5055 // And we should be able to import.
5056 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX03);
5057 EXPECT_TRUE(ImportedOK);
5058 }
5059
5060 // An error should be set for a class if it had a previous import with an error
5061 // from another TU.
TEST_P(ErrorHandlingTest,ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt)5062 TEST_P(ErrorHandlingTest,
5063 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
5064 // We already have a fwd decl.
5065 TranslationUnitDecl *ToTU = getToTuDecl("class X;", Lang_CXX03);
5066 // Then we import a definition.
5067 {
5068 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5069 class X {
5070 void f() { )") + ErroneousStmt + R"( }
5071 void ok();
5072 };
5073 )",
5074 Lang_CXX03);
5075 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5076 FromTU, cxxRecordDecl(hasName("X")));
5077 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
5078
5079 // An error is set for X ...
5080 EXPECT_FALSE(ImportedX);
5081 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5082 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5083 ASSERT_TRUE(OptErr);
5084 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5085 }
5086 // ... but the node had been created.
5087 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
5088 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
5089 // An error is set for "ToXDef" in the shared state.
5090 Optional<ImportError> OptErr =
5091 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
5092 ASSERT_TRUE(OptErr);
5093 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5094
5095 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5096 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
5097 // An error is NOT set for the fwd Decl of X in the shared state.
5098 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
5099 ASSERT_FALSE(OptErr);
5100
5101 // Try to import X again but from another TU.
5102 {
5103 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5104 class X {
5105 void f() { )") + ErroneousStmt + R"( }
5106 void ok();
5107 };
5108 )",
5109 Lang_CXX03, "input1.cc");
5110
5111 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5112 FromTU, cxxRecordDecl(hasName("X")));
5113 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
5114
5115 // If we did not save the errors for the "to" context then the below checks
5116 // would fail, because the lookup finds the fwd Decl of the existing
5117 // definition in the "to" context. We can reach the existing definition via
5118 // the found fwd Decl. That existing definition is structurally equivalent
5119 // (we check only the fields) with this one we want to import, so we return
5120 // with the existing definition, which is erroneous (one method is missing).
5121
5122 // The import should fail.
5123 EXPECT_FALSE(ImportedX);
5124 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5125 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5126 // And an error is set for this new X in the "from" ctx.
5127 ASSERT_TRUE(OptErr);
5128 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5129 }
5130 }
5131
TEST_P(ErrorHandlingTest,ImportOfOverriddenMethods)5132 TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
5133 auto MatchFooA =
5134 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));
5135 auto MatchFooB =
5136 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));
5137 auto MatchFooC =
5138 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));
5139
5140 // Provoke import of a method that has overridden methods with import error.
5141 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5142 struct C;
5143 struct A {
5144 virtual void foo();
5145 void f1(C *);
5146 };
5147 void A::foo() {
5148 )") + ErroneousStmt + R"(
5149 }
5150 struct B : public A {
5151 void foo() override;
5152 };
5153 struct C : public B {
5154 void foo() override;
5155 };
5156 )",
5157 Lang_CXX11);
5158 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
5159 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
5160 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
5161
5162 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
5163 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();
5164 auto CheckError = [&Importer](Decl *FromD) {
5165 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD);
5166 ASSERT_TRUE(OptErr);
5167 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5168 };
5169 CheckError(FromFooA);
5170 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
5171 CheckError(FromFooB);
5172 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
5173 CheckError(FromFooC);
5174 }
5175
TEST_P(ASTImporterOptionSpecificTestBase,LambdaInFunctionBody)5176 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5177 Decl *FromTU = getTuDecl(
5178 R"(
5179 void f() {
5180 auto L = [](){};
5181 }
5182 )",
5183 Lang_CXX11, "input0.cc");
5184 auto Pattern = lambdaExpr();
5185 CXXRecordDecl *FromL =
5186 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5187
5188 auto ToL = Import(FromL, Lang_CXX11);
5189 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5190 unsigned FromLSize =
5191 std::distance(FromL->decls().begin(), FromL->decls().end());
5192 EXPECT_NE(ToLSize, 0u);
5193 EXPECT_EQ(ToLSize, FromLSize);
5194 }
5195
TEST_P(ASTImporterOptionSpecificTestBase,LambdaInFunctionParam)5196 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5197 Decl *FromTU = getTuDecl(
5198 R"(
5199 template <typename F>
5200 void f(F L = [](){}) {}
5201 )",
5202 Lang_CXX11, "input0.cc");
5203 auto Pattern = lambdaExpr();
5204 CXXRecordDecl *FromL =
5205 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5206
5207 auto ToL = Import(FromL, Lang_CXX11);
5208 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5209 unsigned FromLSize =
5210 std::distance(FromL->decls().begin(), FromL->decls().end());
5211 EXPECT_NE(ToLSize, 0u);
5212 EXPECT_EQ(ToLSize, FromLSize);
5213 }
5214
TEST_P(ASTImporterOptionSpecificTestBase,LambdaInGlobalScope)5215 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
5216 Decl *FromTU = getTuDecl(
5217 R"(
5218 auto l1 = [](unsigned lp) { return 1; };
5219 auto l2 = [](int lp) { return 2; };
5220 int f(int p) {
5221 return l1(p) + l2(p);
5222 }
5223 )",
5224 Lang_CXX11, "input0.cc");
5225 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
5226 FromTU, functionDecl(hasName("f")));
5227 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
5228 EXPECT_TRUE(ToF);
5229 }
5230
TEST_P(ASTImporterOptionSpecificTestBase,ImportExistingFriendClassTemplateDef)5231 TEST_P(ASTImporterOptionSpecificTestBase,
5232 ImportExistingFriendClassTemplateDef) {
5233 auto Code =
5234 R"(
5235 template <class T1, class T2>
5236 struct Base {
5237 template <class U1, class U2>
5238 friend struct Class;
5239 };
5240 template <class T1, class T2>
5241 struct Class { };
5242 )";
5243
5244 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
5245 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");
5246
5247 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5248 ToTU, classTemplateDecl(hasName("Class")));
5249 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5250 ToTU, classTemplateDecl(hasName("Class")));
5251 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
5252 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
5253 // Previous friend decl is not linked to it!
5254 ASSERT_FALSE(ToClassDef->getPreviousDecl());
5255 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
5256 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
5257
5258 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5259 FromTU, classTemplateDecl(hasName("Class")));
5260 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5261 FromTU, classTemplateDecl(hasName("Class")));
5262 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
5263 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
5264 ASSERT_FALSE(FromClassDef->getPreviousDecl());
5265 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
5266 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
5267
5268 auto *ImportedDef = Import(FromClassDef, Lang_CXX03);
5269 // At import we should find the definition for 'Class' even if the
5270 // prototype (inside 'friend') for it comes first in the AST and is not
5271 // linked to the definition.
5272 EXPECT_EQ(ImportedDef, ToClassDef);
5273 }
5274
5275 struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
LLDBLookupTestclang::ast_matchers::LLDBLookupTest5276 LLDBLookupTest() {
5277 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5278 ASTContext &FromContext, FileManager &FromFileManager,
5279 bool MinimalImport,
5280 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5281 return new ASTImporter(ToContext, ToFileManager, FromContext,
5282 FromFileManager, MinimalImport,
5283 // We use the regular lookup.
5284 /*SharedState=*/nullptr);
5285 };
5286 }
5287 };
5288
TEST_P(LLDBLookupTest,ImporterShouldFindInTransparentContext)5289 TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
5290 TranslationUnitDecl *ToTU = getToTuDecl(
5291 R"(
5292 extern "C" {
5293 class X{};
5294 };
5295 )",
5296 Lang_CXX03);
5297 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
5298 ToTU, cxxRecordDecl(hasName("X")));
5299
5300 // Set up a stub external storage.
5301 ToTU->setHasExternalLexicalStorage(true);
5302 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
5303 ToTU->setMustBuildLookupTable();
5304 struct TestExternalASTSource : ExternalASTSource {};
5305 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
5306
5307 Decl *FromTU = getTuDecl(
5308 R"(
5309 class X;
5310 )",
5311 Lang_CXX03);
5312 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5313 FromTU, cxxRecordDecl(hasName("X")));
5314 auto *ImportedX = Import(FromX, Lang_CXX03);
5315 // The lookup must find the existing class definition in the LinkageSpecDecl.
5316 // Then the importer renders the existing and the new decl into one chain.
5317 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
5318 }
5319
5320 struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
5321
TEST_P(SVEBuiltins,ImportTypes)5322 TEST_P(SVEBuiltins, ImportTypes) {
5323 static const char *const TypeNames[] = {
5324 "__SVInt8_t",
5325 "__SVInt16_t",
5326 "__SVInt32_t",
5327 "__SVInt64_t",
5328 "__SVUint8_t",
5329 "__SVUint16_t",
5330 "__SVUint32_t",
5331 "__SVUint64_t",
5332 "__SVFloat16_t",
5333 "__SVBFloat16_t",
5334 "__SVFloat32_t",
5335 "__SVFloat64_t",
5336 "__SVBool_t"
5337 };
5338
5339 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX03);
5340 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cc");
5341 for (auto *TypeName : TypeNames) {
5342 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
5343 ToTU, typedefDecl(hasName(TypeName)));
5344 QualType ToType = ToTypedef->getUnderlyingType();
5345
5346 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
5347 FromTU, typedefDecl(hasName(TypeName)));
5348 QualType FromType = FromTypedef->getUnderlyingType();
5349
5350 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX03);
5351 EXPECT_EQ(ImportedType, ToType);
5352 }
5353 }
5354
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfDefaultImplicitFunctions)5355 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
5356 // Test that import of implicit functions works and the functions
5357 // are merged into one chain.
5358 auto GetDeclToImport = [this](StringRef File) {
5359 Decl *FromTU = getTuDecl(
5360 R"(
5361 struct X { };
5362 // Force generating some implicit operator definitions for X.
5363 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
5364 )",
5365 Lang_CXX11, File);
5366 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5367 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5368 // Destructor is picked as one example of implicit function.
5369 return FromD->getDestructor();
5370 };
5371
5372 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
5373 ASSERT_TRUE(ToD1);
5374
5375 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
5376 ASSERT_TRUE(ToD2);
5377
5378 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
5379 }
5380
TEST_P(ASTImporterOptionSpecificTestBase,ImportOfExplicitlyDefaultedOrDeleted)5381 TEST_P(ASTImporterOptionSpecificTestBase,
5382 ImportOfExplicitlyDefaultedOrDeleted) {
5383 Decl *FromTU = getTuDecl(
5384 R"(
5385 struct X { X() = default; X(const X&) = delete; };
5386 )",
5387 Lang_CXX11);
5388 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5389 FromTU, cxxRecordDecl(hasName("X")));
5390 auto *ImportedX = Import(FromX, Lang_CXX11);
5391 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
5392 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5393 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
5394 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5395
5396 ASSERT_TRUE(ImportedX);
5397 EXPECT_TRUE(Constr1->isDefaulted());
5398 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
5399 EXPECT_TRUE(Constr2->isDeletedAsWritten());
5400 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
5401 }
5402
5403 INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
5404 ::testing::Values(std::vector<std::string>{
5405 "-target", "aarch64-linux-gnu"}), );
5406
5407 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5408 ::testing::Values(std::vector<std::string>()), );
5409
5410 INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5411 ::testing::Values(std::vector<std::string>()), );
5412
TEST_P(ASTImporterOptionSpecificTestBase,LambdasAreDifferentiated)5413 TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
5414 Decl *FromTU = getTuDecl(
5415 R"(
5416 void f() {
5417 auto L0 = [](){};
5418 auto L1 = [](){};
5419 }
5420 )",
5421 Lang_CXX11, "input0.cc");
5422 auto Pattern = lambdaExpr();
5423 CXXRecordDecl *FromL0 =
5424 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5425 CXXRecordDecl *FromL1 =
5426 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5427 ASSERT_NE(FromL0, FromL1);
5428
5429 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5430 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5431 EXPECT_NE(ToL0, ToL1);
5432 }
5433
TEST_P(ASTImporterOptionSpecificTestBase,LambdasInFunctionParamsAreDifferentiated)5434 TEST_P(ASTImporterOptionSpecificTestBase,
5435 LambdasInFunctionParamsAreDifferentiated) {
5436 Decl *FromTU = getTuDecl(
5437 R"(
5438 template <typename F0, typename F1>
5439 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
5440 )",
5441 Lang_CXX11, "input0.cc");
5442 auto Pattern = cxxRecordDecl(isLambda());
5443 CXXRecordDecl *FromL0 =
5444 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5445 CXXRecordDecl *FromL1 =
5446 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5447 ASSERT_NE(FromL0, FromL1);
5448
5449 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5450 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5451 ASSERT_NE(ToL0, ToL1);
5452 }
5453
TEST_P(ASTImporterOptionSpecificTestBase,LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed)5454 TEST_P(ASTImporterOptionSpecificTestBase,
5455 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
5456 Decl *FromTU = getTuDecl(
5457 R"(
5458 #define LAMBDA [](){}
5459 template <typename F0, typename F1>
5460 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
5461 )",
5462 Lang_CXX11, "input0.cc");
5463 auto Pattern = cxxRecordDecl(isLambda());
5464 CXXRecordDecl *FromL0 =
5465 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5466 CXXRecordDecl *FromL1 =
5467 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5468 ASSERT_NE(FromL0, FromL1);
5469
5470 Import(FromL0, Lang_CXX11);
5471 Import(FromL1, Lang_CXX11);
5472 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5473 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5474 ASSERT_NE(ToL0, ToL1);
5475 }
5476
TEST_P(ASTImporterOptionSpecificTestBase,ImportAssignedLambda)5477 TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
5478 Decl *FromTU = getTuDecl(
5479 R"(
5480 void f() {
5481 auto x = []{} = {}; auto x2 = x;
5482 }
5483 )",
5484 Lang_CXX20, "input0.cc");
5485 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5486 FromTU, functionDecl(hasName("f")));
5487 // We have only one lambda class.
5488 ASSERT_EQ(
5489 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5490 1u);
5491
5492 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
5493 EXPECT_TRUE(ToF);
5494 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5495 // We have only one lambda class after the import.
5496 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5497 1u);
5498 }
5499
TEST_P(ASTImporterOptionSpecificTestBase,ImportDefaultConstructibleLambdas)5500 TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
5501 Decl *FromTU = getTuDecl(
5502 R"(
5503 void f() {
5504 auto x = []{} = {};
5505 auto xb = []{} = {};
5506 }
5507 )",
5508 Lang_CXX20, "input0.cc");
5509 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5510 FromTU, functionDecl(hasName("f")));
5511 // We have two lambda classes.
5512 ASSERT_EQ(
5513 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5514 2u);
5515
5516 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
5517 EXPECT_TRUE(ToF);
5518 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5519 // We have two lambda classes after the import.
5520 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5521 2u);
5522 }
5523
TEST_P(ASTImporterOptionSpecificTestBase,ImplicitlyDeclareSelf)5524 TEST_P(ASTImporterOptionSpecificTestBase, ImplicitlyDeclareSelf) {
5525 Decl *FromTU = getTuDecl(R"(
5526 __attribute__((objc_root_class))
5527 @interface Root
5528 @end
5529 @interface C : Root
5530 -(void)method;
5531 @end
5532 @implementation C
5533 -(void)method {}
5534 @end
5535 )",
5536 Lang_OBJCXX, "input.mm");
5537 auto *FromMethod = LastDeclMatcher<ObjCMethodDecl>().match(
5538 FromTU, namedDecl(hasName("method")));
5539 ASSERT_TRUE(FromMethod);
5540 auto ToMethod = Import(FromMethod, Lang_OBJCXX);
5541 ASSERT_TRUE(ToMethod);
5542
5543 // Both methods should have their implicit parameters.
5544 EXPECT_TRUE(FromMethod->getSelfDecl() != nullptr);
5545 EXPECT_TRUE(ToMethod->getSelfDecl() != nullptr);
5546 }
5547
5548 struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {};
5549
TEST_P(ImportAutoFunctions,ReturnWithTypedefDeclaredInside)5550 TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
5551 Decl *FromTU = getTuDecl(
5552 R"(
5553 auto X = [](long l) {
5554 using int_type = long;
5555 auto dur = 13;
5556 return static_cast<int_type>(dur);
5557 };
5558 )",
5559 Lang_CXX14, "input0.cc");
5560 CXXMethodDecl *From =
5561 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, cxxMethodDecl());
5562
5563 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
5564 // Normally the return type would be the built-in 'long' type. However, there
5565 // are cases when Clang does not use the canonical type and the TypeAlias is
5566 // used. I could not create such an AST from regular source code, it requires
5567 // some special state in the preprocessor. I've found such an AST when Clang
5568 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
5569 // that with creduce, because after preprocessing, the AST no longer
5570 // contained the TypeAlias as a return type of the lambda.
5571 ASTContext &Ctx = From->getASTContext();
5572 TypeAliasDecl *FromTA =
5573 FirstDeclMatcher<TypeAliasDecl>().match(FromTU, typeAliasDecl());
5574 QualType TT = Ctx.getTypedefType(FromTA);
5575 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());
5576 QualType NewFunType =
5577 Ctx.getFunctionType(TT, FPT->getParamTypes(), FPT->getExtProtoInfo());
5578 From->setType(NewFunType);
5579
5580 CXXMethodDecl *To = Import(From, Lang_CXX14);
5581 EXPECT_TRUE(To);
5582 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
5583 }
5584
TEST_P(ImportAutoFunctions,ReturnWithStructDeclaredInside)5585 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
5586 Decl *FromTU = getTuDecl(
5587 R"(
5588 auto foo() {
5589 struct X {};
5590 return X();
5591 }
5592 )",
5593 Lang_CXX14, "input0.cc");
5594 FunctionDecl *From =
5595 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5596
5597 FunctionDecl *To = Import(From, Lang_CXX14);
5598 EXPECT_TRUE(To);
5599 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5600 }
5601
TEST_P(ImportAutoFunctions,ReturnWithStructDeclaredInside2)5602 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
5603 Decl *FromTU = getTuDecl(
5604 R"(
5605 auto foo() {
5606 struct X {};
5607 return X();
5608 }
5609 )",
5610 Lang_CXX14, "input0.cc");
5611 FunctionDecl *From =
5612 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5613
5614 // This time import the type directly.
5615 QualType ToT = ImportType(From->getType(), From, Lang_CXX14);
5616 const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);
5617 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
5618 }
5619
TEST_P(ImportAutoFunctions,ReturnWithTypedefToStructDeclaredInside)5620 TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
5621 Decl *FromTU = getTuDecl(
5622 R"(
5623 auto foo() {
5624 struct X {};
5625 using Y = X;
5626 return Y();
5627 }
5628 )",
5629 Lang_CXX14, "input0.cc");
5630 FunctionDecl *From =
5631 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5632
5633 FunctionDecl *To = Import(From, Lang_CXX14);
5634 EXPECT_TRUE(To);
5635 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5636 }
5637
TEST_P(ImportAutoFunctions,ReturnWithStructDeclaredNestedInside)5638 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
5639 Decl *FromTU = getTuDecl(
5640 R"(
5641 auto foo() {
5642 struct X { struct Y{}; };
5643 return X::Y();
5644 }
5645 )",
5646 Lang_CXX14, "input0.cc");
5647 FunctionDecl *From =
5648 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5649
5650 FunctionDecl *To = Import(From, Lang_CXX14);
5651 EXPECT_TRUE(To);
5652 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5653 }
5654
TEST_P(ImportAutoFunctions,ReturnWithInternalLambdaType)5655 TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
5656 Decl *FromTU = getTuDecl(
5657 R"(
5658 auto f() {
5659 auto l = []() {
5660 struct X {};
5661 return X();
5662 };
5663 return l();
5664 }
5665 )",
5666 Lang_CXX17, "input0.cc");
5667 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5668 FromTU, functionDecl(hasName("f")));
5669
5670 FunctionDecl *To = Import(From, Lang_CXX17);
5671 EXPECT_TRUE(To);
5672 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5673 }
5674
TEST_P(ImportAutoFunctions,ReturnWithTypeInIf)5675 TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
5676 Decl *FromTU = getTuDecl(
5677 R"(
5678 auto f() {
5679 if (struct X {} x; true)
5680 return X();
5681 else
5682 return X();
5683 }
5684 )",
5685 Lang_CXX17, "input0.cc");
5686 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5687 FromTU, functionDecl(hasName("f")));
5688
5689 FunctionDecl *To = Import(From, Lang_CXX17);
5690 EXPECT_TRUE(To);
5691 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5692 }
5693
TEST_P(ImportAutoFunctions,ReturnWithTypeInFor)5694 TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
5695 Decl *FromTU = getTuDecl(
5696 R"(
5697 auto f() {
5698 for (struct X {} x;;)
5699 return X();
5700 }
5701 )",
5702 Lang_CXX17, "input0.cc");
5703 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5704 FromTU, functionDecl(hasName("f")));
5705
5706 FunctionDecl *To = Import(From, Lang_CXX17);
5707 EXPECT_TRUE(To);
5708 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5709 }
5710
TEST_P(ImportAutoFunctions,ReturnWithTypeInSwitch)5711 TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
5712 Decl *FromTU = getTuDecl(
5713 R"(
5714 auto f() {
5715 switch (struct X {} x; 10) {
5716 case 10:
5717 return X();
5718 }
5719 }
5720 )",
5721 Lang_CXX17, "input0.cc");
5722 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5723 FromTU, functionDecl(hasName("f")));
5724
5725 FunctionDecl *To = Import(From, Lang_CXX17);
5726 EXPECT_TRUE(To);
5727 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5728 }
5729
5730 struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
5731
TEST_P(ImportSourceLocations,PreserveFileIDTreeStructure)5732 TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
5733 // Tests that the FileID tree structure (with the links being the include
5734 // chains) is preserved while importing other files (which need to be
5735 // added to this structure with fake include locations.
5736
5737 SourceLocation Location1;
5738 {
5739 auto Pattern = varDecl(hasName("X"));
5740 Decl *FromTU = getTuDecl("int X;", Lang_C99, "input0.c");
5741 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5742
5743 Location1 = Import(FromD, Lang_C99)->getLocation();
5744 }
5745 SourceLocation Location2;
5746 {
5747 auto Pattern = varDecl(hasName("Y"));
5748 Decl *FromTU = getTuDecl("int Y;", Lang_C99, "input1.c");
5749 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5750
5751 Location2 = Import(FromD, Lang_C99)->getLocation();
5752 }
5753
5754 SourceManager &ToSM = ToAST->getSourceManager();
5755 FileID FileID1 = ToSM.getFileID(Location1);
5756 FileID FileID2 = ToSM.getFileID(Location2);
5757
5758 // Check that the imported files look like as if they were included from the
5759 // start of the main file.
5760 SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
5761 EXPECT_NE(FileID1, ToSM.getMainFileID());
5762 EXPECT_NE(FileID2, ToSM.getMainFileID());
5763 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
5764 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
5765
5766 // Let the SourceManager check the order of the locations. The order should
5767 // be the order in which the declarations are imported.
5768 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
5769 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
5770 }
5771
TEST_P(ImportSourceLocations,NormalFileBuffer)5772 TEST_P(ImportSourceLocations, NormalFileBuffer) {
5773 // Test importing normal file buffers.
5774
5775 std::string Path = "input0.c";
5776 std::string Source = "int X;";
5777 TranslationUnitDecl *FromTU = getTuDecl(Source, Lang_C99, Path);
5778
5779 SourceLocation ImportedLoc;
5780 {
5781 // Import the VarDecl to trigger the importing of the FileID.
5782 auto Pattern = varDecl(hasName("X"));
5783 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5784 ImportedLoc = Import(FromD, Lang_C99)->getLocation();
5785 }
5786
5787 // Make sure the imported buffer has the original contents.
5788 SourceManager &ToSM = ToAST->getSourceManager();
5789 FileID ImportedID = ToSM.getFileID(ImportedLoc);
5790 EXPECT_EQ(Source,
5791 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
5792 }
5793
TEST_P(ImportSourceLocations,OverwrittenFileBuffer)5794 TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {
5795 // Test importing overwritten file buffers.
5796
5797 std::string Path = "input0.c";
5798 TranslationUnitDecl *FromTU = getTuDecl("int X;", Lang_C99, Path);
5799
5800 // Overwrite the file buffer for our input file with new content.
5801 const std::string Contents = "overwritten contents";
5802 SourceLocation ImportedLoc;
5803 {
5804 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();
5805 clang::FileManager &FM = FromSM.getFileManager();
5806 const clang::FileEntry &FE =
5807 *FM.getVirtualFile(Path, static_cast<off_t>(Contents.size()), 0);
5808
5809 llvm::SmallVector<char, 64> Buffer;
5810 Buffer.append(Contents.begin(), Contents.end());
5811 auto FileContents =
5812 std::make_unique<llvm::SmallVectorMemoryBuffer>(std::move(Buffer), Path);
5813 FromSM.overrideFileContents(&FE, std::move(FileContents));
5814
5815 // Import the VarDecl to trigger the importing of the FileID.
5816 auto Pattern = varDecl(hasName("X"));
5817 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5818 ImportedLoc = Import(FromD, Lang_C99)->getLocation();
5819 }
5820
5821 // Make sure the imported buffer has the overwritten contents.
5822 SourceManager &ToSM = ToAST->getSourceManager();
5823 FileID ImportedID = ToSM.getFileID(ImportedLoc);
5824 EXPECT_EQ(Contents,
5825 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
5826 }
5827
TEST_P(ASTImporterOptionSpecificTestBase,ImportExprOfAlignmentAttr)5828 TEST_P(ASTImporterOptionSpecificTestBase, ImportExprOfAlignmentAttr) {
5829 // Test if import of these packed and aligned attributes does not trigger an
5830 // error situation where source location from 'From' context is referenced in
5831 // 'To' context through evaluation of the alignof attribute.
5832 // This happens if the 'alignof(A)' expression is not imported correctly.
5833 Decl *FromTU = getTuDecl(
5834 R"(
5835 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };
5836 struct alignas(alignof(A)) S {};
5837 )",
5838 Lang_CXX11, "input.cc");
5839 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5840 FromTU, cxxRecordDecl(hasName("S"), unless(isImplicit())));
5841 ASSERT_TRUE(FromD);
5842
5843 auto *ToD = Import(FromD, Lang_CXX11);
5844 ASSERT_TRUE(ToD);
5845
5846 auto *FromAttr = FromD->getAttr<AlignedAttr>();
5847 auto *ToAttr = ToD->getAttr<AlignedAttr>();
5848 EXPECT_EQ(FromAttr->isInherited(), ToAttr->isInherited());
5849 EXPECT_EQ(FromAttr->isPackExpansion(), ToAttr->isPackExpansion());
5850 EXPECT_EQ(FromAttr->isImplicit(), ToAttr->isImplicit());
5851 EXPECT_EQ(FromAttr->getSyntax(), ToAttr->getSyntax());
5852 EXPECT_EQ(FromAttr->getSemanticSpelling(), ToAttr->getSemanticSpelling());
5853 EXPECT_TRUE(ToAttr->getAlignmentExpr());
5854
5855 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(
5856 ToD->getTranslationUnitDecl(),
5857 cxxRecordDecl(hasName("A"), unless(isImplicit())));
5858 // Ensure that 'struct A' was imported (through reference from attribute of
5859 // 'S').
5860 EXPECT_TRUE(ToA);
5861 }
5862
TEST_P(ASTImporterOptionSpecificTestBase,ImportFormatAttr)5863 TEST_P(ASTImporterOptionSpecificTestBase, ImportFormatAttr) {
5864 Decl *FromTU = getTuDecl(
5865 R"(
5866 int foo(const char * fmt, ...)
5867 __attribute__ ((__format__ (__scanf__, 1, 2)));
5868 )",
5869 Lang_CXX03, "input.cc");
5870 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
5871 FromTU, functionDecl(hasName("foo")));
5872 ASSERT_TRUE(FromD);
5873
5874 auto *ToD = Import(FromD, Lang_CXX03);
5875 ASSERT_TRUE(ToD);
5876 ToD->dump(); // Should not crash!
5877
5878 auto *FromAttr = FromD->getAttr<FormatAttr>();
5879 auto *ToAttr = ToD->getAttr<FormatAttr>();
5880 EXPECT_EQ(FromAttr->isInherited(), ToAttr->isInherited());
5881 EXPECT_EQ(FromAttr->isPackExpansion(), ToAttr->isPackExpansion());
5882 EXPECT_EQ(FromAttr->isImplicit(), ToAttr->isImplicit());
5883 EXPECT_EQ(FromAttr->getSyntax(), ToAttr->getSyntax());
5884 EXPECT_EQ(FromAttr->getAttributeSpellingListIndex(),
5885 ToAttr->getAttributeSpellingListIndex());
5886 EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());
5887 }
5888 template <typename T>
ExtendWithOptions(const T & Values,const std::vector<std::string> & Args)5889 auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {
5890 auto Copy = Values;
5891 for (std::vector<std::string> &ArgV : Copy) {
5892 for (const std::string &Arg : Args) {
5893 ArgV.push_back(Arg);
5894 }
5895 }
5896 return ::testing::ValuesIn(Copy);
5897 }
5898
5899 struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
ImportWithExternalSourceclang::ast_matchers::ImportWithExternalSource5900 ImportWithExternalSource() {
5901 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5902 ASTContext &FromContext, FileManager &FromFileManager,
5903 bool MinimalImport,
5904 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5905 return new ASTImporter(ToContext, ToFileManager, FromContext,
5906 FromFileManager, MinimalImport,
5907 // We use the regular lookup.
5908 /*SharedState=*/nullptr);
5909 };
5910 }
5911 };
5912
5913 /// An ExternalASTSource that keeps track of the tags is completed.
5914 struct SourceWithCompletedTagList : clang::ExternalASTSource {
5915 std::vector<clang::TagDecl *> &CompletedTags;
SourceWithCompletedTagListclang::ast_matchers::SourceWithCompletedTagList5916 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)
5917 : CompletedTags(CompletedTags) {}
CompleteTypeclang::ast_matchers::SourceWithCompletedTagList5918 void CompleteType(TagDecl *Tag) override {
5919 auto *Record = cast<CXXRecordDecl>(Tag);
5920 Record->startDefinition();
5921 Record->completeDefinition();
5922 CompletedTags.push_back(Tag);
5923 }
5924 using clang::ExternalASTSource::CompleteType;
5925 };
5926
TEST_P(ImportWithExternalSource,CompleteRecordBeforeImporting)5927 TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
5928 // Create an empty TU.
5929 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cpp");
5930
5931 // Create and add the test ExternalASTSource.
5932 std::vector<clang::TagDecl *> CompletedTags;
5933 IntrusiveRefCntPtr<ExternalASTSource> source =
5934 new SourceWithCompletedTagList(CompletedTags);
5935 clang::ASTContext &Context = FromTU->getASTContext();
5936 Context.setExternalSource(std::move(source));
5937
5938 // Create a dummy class by hand with external lexical storage.
5939 IdentifierInfo &Ident = Context.Idents.get("test_class");
5940 auto *Record = CXXRecordDecl::Create(
5941 Context, TTK_Class, FromTU, SourceLocation(), SourceLocation(), &Ident);
5942 Record->setHasExternalLexicalStorage();
5943 FromTU->addDecl(Record);
5944
5945 // Do a minimal import of the created class.
5946 EXPECT_EQ(0U, CompletedTags.size());
5947 Import(Record, Lang_CXX03);
5948 EXPECT_EQ(0U, CompletedTags.size());
5949
5950 // Import the definition of the created class.
5951 llvm::Error Err = findFromTU(Record)->Importer->ImportDefinition(Record);
5952 EXPECT_FALSE((bool)Err);
5953 consumeError(std::move(Err));
5954
5955 // Make sure the class was completed once.
5956 EXPECT_EQ(1U, CompletedTags.size());
5957 EXPECT_EQ(Record, CompletedTags.front());
5958 }
5959
TEST_P(ImportFunctions,CTADImplicit)5960 TEST_P(ImportFunctions, CTADImplicit) {
5961 Decl *FromTU = getTuDecl(
5962 R"(
5963 template <typename T> struct A {
5964 A(T);
5965 };
5966 A a{(int)0};
5967 )",
5968 Lang_CXX17, "input.cc");
5969 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
5970 FromTU,
5971 cxxDeductionGuideDecl(hasParameter(0, hasType(asString("A<T>")))));
5972 auto *ToD = Import(FromD, Lang_CXX17);
5973 ASSERT_TRUE(ToD);
5974 EXPECT_TRUE(ToD->isCopyDeductionCandidate());
5975 // Check that the deduced class template is also imported.
5976 EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
5977 FromD->getDeducedTemplate()));
5978 }
5979
TEST_P(ImportFunctions,CTADUserDefinedExplicit)5980 TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
5981 Decl *FromTU = getTuDecl(
5982 R"(
5983 template <typename T> struct A {
5984 A(T);
5985 };
5986 template <typename T> explicit A(T) -> A<float>;
5987 A a{(int)0}; // calls A<float>::A(float)
5988 )",
5989 Lang_CXX17, "input.cc");
5990 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
5991 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
5992 // Not-implicit: i.e. not compiler-generated, user defined.
5993 ASSERT_FALSE(FromD->isImplicit());
5994 ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.
5995 auto *ToD = Import(FromD, Lang_CXX17);
5996 ASSERT_TRUE(ToD);
5997 EXPECT_FALSE(FromD->isImplicit());
5998 EXPECT_TRUE(ToD->isExplicit());
5999 }
6000
6001 // FIXME Move these tests out of ASTImporterTest. For that we need to factor
6002 // out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
6003 // into a new test Fixture. Then we should lift up this Fixture to its own
6004 // implementation file and only then could we reuse the Fixture in other AST
6005 // unitttests.
6006 struct CTAD : ASTImporterOptionSpecificTestBase {};
6007
TEST_P(CTAD,DeductionGuideShouldReferToANonLocalTypedef)6008 TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
6009 Decl *TU = getTuDecl(
6010 R"(
6011 typedef int U;
6012 template <typename T> struct A {
6013 A(U, T);
6014 };
6015 A a{(int)0, (int)0};
6016 )",
6017 Lang_CXX17, "input.cc");
6018 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6019 TU, cxxDeductionGuideDecl());
6020 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
6021 TU, typedefNameDecl(hasName("U")));
6022 ParmVarDecl *Param = Guide->getParamDecl(0);
6023 // The type of the first param (which is a typedef) should match the typedef
6024 // in the global scope.
6025 EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
6026 }
6027
TEST_P(CTAD,DeductionGuideShouldReferToANonLocalTypedefInParamPtr)6028 TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
6029 Decl *TU = getTuDecl(
6030 R"(
6031 typedef int U;
6032 template <typename T> struct A {
6033 A(U*, T);
6034 };
6035 A a{(int*)0, (int)0};
6036 )",
6037 Lang_CXX17, "input.cc");
6038 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6039 TU, cxxDeductionGuideDecl());
6040 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
6041 TU, typedefNameDecl(hasName("U")));
6042 ParmVarDecl *Param = Guide->getParamDecl(0);
6043 EXPECT_EQ(Param->getType()
6044 ->getAs<PointerType>()
6045 ->getPointeeType()
6046 ->getAs<TypedefType>()
6047 ->getDecl(),
6048 Typedef);
6049 }
6050
TEST_P(CTAD,DeductionGuideShouldCopyALocalTypedef)6051 TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
6052 Decl *TU = getTuDecl(
6053 R"(
6054 template <typename T> struct A {
6055 typedef T U;
6056 A(U, T);
6057 };
6058 A a{(int)0, (int)0};
6059 )",
6060 Lang_CXX17, "input.cc");
6061 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
6062 TU, cxxDeductionGuideDecl());
6063 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
6064 TU, typedefNameDecl(hasName("U")));
6065 ParmVarDecl *Param = Guide->getParamDecl(0);
6066 EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
6067 }
6068
6069 INSTANTIATE_TEST_CASE_P(ParameterizedTests, CTAD,
6070 DefaultTestValuesForRunOptions, );
6071
6072 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
6073 DefaultTestValuesForRunOptions, );
6074
6075 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
6076 ::testing::Values(std::vector<std::string>()), );
6077
6078 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
6079 DefaultTestValuesForRunOptions, );
6080
6081 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFixedPointExpr,
6082 ExtendWithOptions(DefaultTestArrayForRunOptions,
6083 std::vector<std::string>{
6084 "-ffixed-point"}), );
6085
6086 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
6087 DefaultTestValuesForRunOptions, );
6088
6089 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
6090 DefaultTestValuesForRunOptions, );
6091
6092 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
6093 DefaultTestValuesForRunOptions, );
6094
6095 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
6096 DefaultTestValuesForRunOptions, );
6097
6098 INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
6099 DefaultTestValuesForRunOptions, );
6100
6101 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
6102 DefaultTestValuesForRunOptions, );
6103
6104 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportAutoFunctions,
6105 DefaultTestValuesForRunOptions, );
6106
6107 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
6108 DefaultTestValuesForRunOptions, );
6109
6110 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
6111 DefaultTestValuesForRunOptions, );
6112
6113 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
6114 DefaultTestValuesForRunOptions, );
6115
6116 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
6117 DefaultTestValuesForRunOptions, );
6118
6119 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
6120 DefaultTestValuesForRunOptions, );
6121
6122 INSTANTIATE_TEST_CASE_P(ParameterizedTests,
6123 ImportFunctionTemplateSpecializations,
6124 DefaultTestValuesForRunOptions, );
6125
6126 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
6127 DefaultTestValuesForRunOptions, );
6128
6129 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
6130 DefaultTestValuesForRunOptions, );
6131
6132 INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
6133 DefaultTestValuesForRunOptions, );
6134
6135 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportSourceLocations,
6136 DefaultTestValuesForRunOptions, );
6137
6138 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportWithExternalSource,
6139 DefaultTestValuesForRunOptions, );
6140
6141 } // end namespace ast_matchers
6142 } // end namespace clang
6143