[RISCV] Add missing SiFive P400 scheduling model test for divisions. NFC
[llvm-project.git] / clang / unittests / AST / ASTImporterTest.cpp
blobd197d30df3adf555e0b0b91c5f1355b116778d8b
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.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/RecordLayout.h"
14 #include "clang/ASTMatchers/ASTMatchers.h"
15 #include "clang/Testing/CommandLineArgs.h"
16 #include "llvm/Support/SmallVectorMemoryBuffer.h"
18 #include "clang/AST/DeclContextInternals.h"
19 #include "gtest/gtest.h"
21 #include "ASTImporterFixtures.h"
22 #include <optional>
24 namespace clang {
25 namespace ast_matchers {
27 using internal::Matcher;
29 static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
30 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
31 return cast<RecordType>(Ty)->getDecl();
34 struct ImportExpr : TestImportBase {};
35 struct ImportType : TestImportBase {};
36 struct ImportDecl : TestImportBase {};
37 struct ImportFixedPointExpr : ImportExpr {};
39 struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
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);
46 auto Redecls = getCanonicalForwardRedeclChain(D0);
47 ASSERT_EQ(Redecls.size(), 1u);
48 EXPECT_EQ(D0, Redecls[0]);
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();
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]);
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();
72 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
73 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
74 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
76 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
77 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
80 namespace {
81 struct RedirectingImporter : public ASTImporter {
82 using ASTImporter::ASTImporter;
84 protected:
85 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;
96 return ASTImporter::ImportImpl(FromD);
100 } // namespace
102 struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
103 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);
115 // Test that an ASTImporter subclass can intercept an import call.
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");
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);
132 // Test that when we indirectly import a declaration the custom ASTImporter
133 // is still intercepting the import.
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");
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);
149 struct ImportPath : ASTImporterOptionSpecificTestBase {
150 Decl *FromTU;
151 FunctionDecl *D0, *D1, *D2;
152 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();
161 TEST_P(ImportPath, Push) {
162 ASTImporter::ImportPathTy path;
163 path.push(D0);
164 EXPECT_FALSE(path.hasCycleAtBack());
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());
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;
188 ASSERT_EQ(i, 2);
189 EXPECT_EQ(Res[0], D0);
190 EXPECT_EQ(Res[1], D0);
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;
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);
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;
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);
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;
240 ASSERT_EQ(i, 3);
241 EXPECT_EQ(Res[0], D0);
242 EXPECT_EQ(Res[1], D1);
243 EXPECT_EQ(Res[2], D0);
245 path.pop();
246 EXPECT_FALSE(path.hasCycleAtBack());
249 const internal::VariadicDynCastAllOfMatcher<Stmt, SourceLocExpr> sourceLocExpr;
251 AST_MATCHER_P(SourceLocExpr, hasBuiltinStr, StringRef, Str) {
252 return Node.getBuiltinStr() == Str;
255 TEST_P(ImportExpr, ImportSourceLocExpr) {
256 MatchVerifier<Decl> Verifier;
257 testImport("void declToImport() { (void)__builtin_FILE(); }", Lang_CXX03, "",
258 Lang_CXX03, Verifier,
259 functionDecl(hasDescendant(
260 sourceLocExpr(hasBuiltinStr("__builtin_FILE")))));
261 testImport("void declToImport() { (void)__builtin_FILE_NAME(); }", Lang_CXX03,
262 "", Lang_CXX03, Verifier,
263 functionDecl(hasDescendant(
264 sourceLocExpr(hasBuiltinStr("__builtin_FILE_NAME")))));
265 testImport("void declToImport() { (void)__builtin_COLUMN(); }", Lang_CXX03,
266 "", Lang_CXX03, Verifier,
267 functionDecl(hasDescendant(
268 sourceLocExpr(hasBuiltinStr("__builtin_COLUMN")))));
271 TEST_P(ImportExpr, ImportStringLiteral) {
272 MatchVerifier<Decl> Verifier;
273 testImport("void declToImport() { (void)\"foo\"; }", Lang_CXX03, "",
274 Lang_CXX03, Verifier,
275 functionDecl(hasDescendant(
276 stringLiteral(hasType(asString("const char[4]"))))));
277 testImport("void declToImport() { (void)L\"foo\"; }", Lang_CXX03, "",
278 Lang_CXX03, Verifier,
279 functionDecl(hasDescendant(
280 stringLiteral(hasType(asString("const wchar_t[4]"))))));
281 testImport("void declToImport() { (void) \"foo\" \"bar\"; }", Lang_CXX03, "",
282 Lang_CXX03, Verifier,
283 functionDecl(hasDescendant(
284 stringLiteral(hasType(asString("const char[7]"))))));
287 TEST_P(ImportExpr, ImportChooseExpr) {
288 MatchVerifier<Decl> Verifier;
290 // This case tests C code that is not condition-dependent and has a true
291 // condition.
292 testImport("void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
293 Lang_C99, "", Lang_C99, Verifier,
294 functionDecl(hasDescendant(chooseExpr())));
297 const internal::VariadicDynCastAllOfMatcher<Stmt, ShuffleVectorExpr>
298 shuffleVectorExpr;
300 TEST_P(ImportExpr, ImportShuffleVectorExpr) {
301 MatchVerifier<Decl> Verifier;
302 constexpr auto Code = R"code(
303 typedef double vector4double __attribute__((__vector_size__(32)));
304 vector4double declToImport(vector4double a, vector4double b) {
305 return __builtin_shufflevector(a, b, 0, 1, 2, 3);
307 )code";
308 const auto Pattern = functionDecl(hasDescendant(shuffleVectorExpr(
309 allOf(has(declRefExpr(to(parmVarDecl(hasName("a"))))),
310 has(declRefExpr(to(parmVarDecl(hasName("b"))))),
311 has(integerLiteral(equals(0))), has(integerLiteral(equals(1))),
312 has(integerLiteral(equals(2))), has(integerLiteral(equals(3)))))));
313 testImport(Code, Lang_C99, "", Lang_C99, Verifier, Pattern);
316 TEST_P(ImportExpr, ImportGNUNullExpr) {
317 MatchVerifier<Decl> Verifier;
318 testImport("void declToImport() { (void)__null; }", Lang_CXX03, "",
319 Lang_CXX03, Verifier,
320 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
323 TEST_P(ImportExpr, ImportGenericSelectionExpr) {
324 MatchVerifier<Decl> Verifier;
326 testImport(
327 "void declToImport() { int x; (void)_Generic(x, int: 0, float: 1); }",
328 Lang_C99, "", Lang_C99, Verifier,
329 functionDecl(hasDescendant(genericSelectionExpr())));
332 TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
333 MatchVerifier<Decl> Verifier;
334 testImport(
335 "void declToImport() { (void)nullptr; }",
336 Lang_CXX11, "", Lang_CXX11, Verifier,
337 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
341 TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
342 MatchVerifier<Decl> Verifier;
343 testImport("void declToImport() { (void)1.0; }", Lang_C99, "", Lang_C99,
344 Verifier,
345 functionDecl(hasDescendant(
346 floatLiteral(equals(1.0), hasType(asString("double"))))));
347 testImport("void declToImport() { (void)1.0e-5f; }", Lang_C99, "", Lang_C99,
348 Verifier,
349 functionDecl(hasDescendant(
350 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
353 TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {
354 MatchVerifier<Decl> Verifier;
355 testImport("void declToImport() { (void)1.0k; }", Lang_C99, "", Lang_C99,
356 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
357 testImport("void declToImport() { (void)0.75r; }", Lang_C99, "", Lang_C99,
358 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
361 TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
362 MatchVerifier<Decl> Verifier;
363 testImport(
364 "void declToImport() { (void)1.0i; }",
365 Lang_CXX14, "", Lang_CXX14, Verifier,
366 functionDecl(hasDescendant(imaginaryLiteral())));
369 TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
370 MatchVerifier<Decl> Verifier;
371 testImport("void declToImport() {"
372 " struct s { int x; long y; unsigned z; }; "
373 " (void)(struct s){ 42, 0L, 1U }; }",
374 Lang_CXX03, "", Lang_CXX03, Verifier,
375 functionDecl(hasDescendant(compoundLiteralExpr(
376 hasType(asString("struct s")),
377 has(initListExpr(
378 hasType(asString("struct s")),
379 has(integerLiteral(equals(42), hasType(asString("int")))),
380 has(integerLiteral(equals(0), hasType(asString("long")))),
381 has(integerLiteral(
382 equals(1), hasType(asString("unsigned int"))))))))));
385 TEST_P(ImportExpr, ImportCXXThisExpr) {
386 MatchVerifier<Decl> Verifier;
387 testImport("class declToImport { void f() { (void)this; } };", Lang_CXX03, "",
388 Lang_CXX03, Verifier,
389 cxxRecordDecl(hasMethod(hasDescendant(
390 cxxThisExpr(hasType(asString("class declToImport *")))))));
393 TEST_P(ImportExpr, ImportAtomicExpr) {
394 MatchVerifier<Decl> Verifier;
395 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
396 Lang_C99, "", Lang_C99, Verifier,
397 functionDecl(hasDescendant(atomicExpr(
398 has(ignoringParenImpCasts(
399 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
400 hasType(asString("int *"))))),
401 has(integerLiteral(equals(1), hasType(asString("int"))))))));
404 TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
405 MatchVerifier<Decl> Verifier;
406 testImport("void declToImport() { loop: goto loop; (void)&&loop; }", Lang_C99,
407 "", Lang_C99, Verifier,
408 functionDecl(hasDescendant(labelStmt(
409 hasDeclaration(labelDecl(hasName("loop"))))),
410 hasDescendant(addrLabelExpr(
411 hasDeclaration(labelDecl(hasName("loop")))))));
414 AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
415 internal::Matcher<NamedDecl>, InnerMatcher) {
416 const NamedDecl *Template = Node.getTemplatedDecl();
417 return Template && InnerMatcher.matches(*Template, Finder, Builder);
420 TEST_P(ImportExpr, ImportParenListExpr) {
421 MatchVerifier<Decl> Verifier;
422 testImport(
423 "template<typename T> class dummy { void f() { dummy X(*this); } };"
424 "typedef dummy<int> declToImport;"
425 "template class dummy<int>;",
426 Lang_CXX03, "", Lang_CXX03, Verifier,
427 typedefDecl(hasType(elaboratedType(namesType(templateSpecializationType(
428 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
429 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(
430 allOf(hasName("f"),
431 hasBody(compoundStmt(has(declStmt(hasSingleDecl(varDecl(
432 hasInitializer(parenListExpr(has(unaryOperator(
433 hasOperatorName("*"),
434 hasUnaryOperand(
435 cxxThisExpr())))))))))))))))))))))))));
438 TEST_P(ImportExpr, ImportSwitch) {
439 MatchVerifier<Decl> Verifier;
440 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
441 Lang_C99, "", Lang_C99, Verifier,
442 functionDecl(hasDescendant(
443 switchStmt(has(compoundStmt(has(caseStmt())))))));
446 TEST_P(ImportExpr, ImportStmtExpr) {
447 MatchVerifier<Decl> Verifier;
448 testImport(
449 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
450 Lang_C99, "", Lang_C99, Verifier,
451 traverse(TK_AsIs,
452 functionDecl(hasDescendant(varDecl(
453 hasName("C"), hasType(asString("int")),
454 hasInitializer(stmtExpr(
455 hasAnySubstatement(declStmt(hasSingleDecl(varDecl(
456 hasName("X"), hasType(asString("int")),
457 hasInitializer(integerLiteral(equals(4))))))),
458 hasDescendant(implicitCastExpr()))))))));
461 TEST_P(ImportExpr, ImportConditionalOperator) {
462 MatchVerifier<Decl> Verifier;
463 testImport("void declToImport() { (void)(true ? 1 : -5); }", Lang_CXX03, "",
464 Lang_CXX03, Verifier,
465 functionDecl(hasDescendant(conditionalOperator(
466 hasCondition(cxxBoolLiteral(equals(true))),
467 hasTrueExpression(integerLiteral(equals(1))),
468 hasFalseExpression(unaryOperator(
469 hasUnaryOperand(integerLiteral(equals(5)))))))));
472 TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
473 MatchVerifier<Decl> Verifier;
474 testImport(
475 "void declToImport() { (void)(1 ?: -5); }", Lang_CXX03, "", Lang_CXX03,
476 Verifier,
477 traverse(TK_AsIs,
478 functionDecl(hasDescendant(binaryConditionalOperator(
479 hasCondition(implicitCastExpr(
480 hasSourceExpression(opaqueValueExpr(
481 hasSourceExpression(integerLiteral(equals(1))))),
482 hasType(booleanType()))),
483 hasTrueExpression(opaqueValueExpr(
484 hasSourceExpression(integerLiteral(equals(1))))),
485 hasFalseExpression(unaryOperator(
486 hasOperatorName("-"),
487 hasUnaryOperand(integerLiteral(equals(5))))))))));
490 TEST_P(ImportExpr, ImportDesignatedInitExpr) {
491 MatchVerifier<Decl> Verifier;
492 testImport(
493 "void declToImport() {"
494 " struct point { double x; double y; };"
495 " struct point ptarray[10] = "
496 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
497 Lang_C99, "", Lang_C99, Verifier,
498 functionDecl(hasDescendant(initListExpr(
499 has(designatedInitExpr(designatorCountIs(2),
500 hasDescendant(floatLiteral(equals(1.0))),
501 hasDescendant(integerLiteral(equals(2))))),
502 has(designatedInitExpr(designatorCountIs(2),
503 hasDescendant(floatLiteral(equals(2.0))),
504 hasDescendant(integerLiteral(equals(2))))),
505 has(designatedInitExpr(designatorCountIs(2),
506 hasDescendant(floatLiteral(equals(1.0))),
507 hasDescendant(integerLiteral(equals(0)))))))));
510 TEST_P(ImportExpr, ImportPredefinedExpr) {
511 MatchVerifier<Decl> Verifier;
512 // __func__ expands as StringLiteral("declToImport")
513 testImport("void declToImport() { (void)__func__; }", Lang_CXX03, "",
514 Lang_CXX03, Verifier,
515 functionDecl(hasDescendant(predefinedExpr(
516 hasType(asString("const char[13]")),
517 has(stringLiteral(hasType(asString("const char[13]"))))))));
520 TEST_P(ImportExpr, ImportInitListExpr) {
521 MatchVerifier<Decl> Verifier;
522 testImport("void declToImport() {"
523 " struct point { double x; double y; };"
524 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
525 " [0].x = 1.0 }; }",
526 Lang_CXX03, "", Lang_CXX03, Verifier,
527 functionDecl(hasDescendant(initListExpr(
528 has(cxxConstructExpr(requiresZeroInitialization())),
529 has(initListExpr(
530 hasType(asString("point")), has(floatLiteral(equals(1.0))),
531 has(implicitValueInitExpr(hasType(asString("double")))))),
532 has(initListExpr(hasType(asString("point")),
533 has(floatLiteral(equals(2.0))),
534 has(floatLiteral(equals(1.0)))))))));
537 const internal::VariadicDynCastAllOfMatcher<Expr, CXXDefaultInitExpr>
538 cxxDefaultInitExpr;
540 TEST_P(ImportExpr, ImportCXXDefaultInitExpr) {
541 MatchVerifier<Decl> Verifier;
542 testImport("class declToImport { int DefInit = 5; }; declToImport X;",
543 Lang_CXX11, "", Lang_CXX11, Verifier,
544 cxxRecordDecl(hasDescendant(cxxConstructorDecl(
545 hasAnyConstructorInitializer(cxxCtorInitializer(
546 withInitializer(cxxDefaultInitExpr())))))));
547 testImport(
548 "struct X { int A = 5; }; X declToImport{};", Lang_CXX17, "", Lang_CXX17,
549 Verifier,
550 varDecl(hasInitializer(initListExpr(hasInit(0, cxxDefaultInitExpr())))));
553 const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
555 TEST_P(ImportExpr, ImportVAArgExpr) {
556 MatchVerifier<Decl> Verifier;
557 testImport("void declToImport(__builtin_va_list list, ...) {"
558 " (void)__builtin_va_arg(list, int); }",
559 Lang_CXX03, "", Lang_CXX03, Verifier,
560 functionDecl(hasDescendant(
561 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
564 const internal::VariadicDynCastAllOfMatcher<Stmt, BuiltinBitCastExpr>
565 builtinBitCastExpr;
567 TEST_P(ImportExpr, ImportBuiltinBitCastExpr) {
568 MatchVerifier<Decl> Verifier;
569 testImport("void declToImport(int X) {"
570 " (void)__builtin_bit_cast(float, X); }",
571 Lang_CXX20, "", Lang_CXX20, Verifier,
572 functionDecl(hasDescendant(
573 cStyleCastExpr(hasSourceExpression(builtinBitCastExpr())))));
576 TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
577 MatchVerifier<Decl> Verifier;
578 testImport(
579 "struct C {};"
580 "void declToImport() { C c = C(); }",
581 Lang_CXX03, "", Lang_CXX03, Verifier,
582 traverse(TK_AsIs,
583 functionDecl(hasDescendant(exprWithCleanups(has(cxxConstructExpr(
584 has(materializeTemporaryExpr(has(implicitCastExpr(
585 has(cxxTemporaryObjectExpr()))))))))))));
588 TEST_P(ImportType, ImportAtomicType) {
589 MatchVerifier<Decl> Verifier;
590 testImport(
591 "void declToImport() { typedef _Atomic(int) a_int; }",
592 Lang_CXX11, "", Lang_CXX11, Verifier,
593 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
596 TEST_P(ImportType, ImportBitIntType) {
597 const AstTypeMatcher<BitIntType> bitIntType;
598 MatchVerifier<Decl> Verifier;
599 testImport("_BitInt(10) declToImport;", Lang_CXX11, "", Lang_CXX11, Verifier,
600 varDecl(hasType(bitIntType())));
603 TEST_P(ImportType, ImportDependentBitIntType) {
604 const AstTypeMatcher<DependentBitIntType> dependentBitIntType;
605 MatchVerifier<Decl> Verifier;
606 testImport("template<int Width> using declToImport = _BitInt(Width);",
607 Lang_CXX11, "", Lang_CXX11, Verifier,
608 typeAliasTemplateDecl(
609 has(typeAliasDecl(hasType(dependentBitIntType())))));
612 TEST_P(ImportType, ImportDependentAddressSpaceType) {
613 const AstTypeMatcher<DependentAddressSpaceType> dependentAddressSpaceType;
614 MatchVerifier<Decl> Verifier;
615 testImport(
617 template<typename T, int AddrSpace>
618 using declToImport = T __attribute__((address_space(AddrSpace)));
620 Lang_CXX11, "", Lang_CXX11, Verifier,
621 typeAliasTemplateDecl(
622 has(typeAliasDecl(hasType(dependentAddressSpaceType())))));
625 TEST_P(ImportType, ImportVectorType) {
626 const AstTypeMatcher<VectorType> vectorType;
627 MatchVerifier<Decl> Verifier;
628 testImport("typedef int __attribute__((vector_size(12))) declToImport;",
629 Lang_CXX11, "", Lang_CXX11, Verifier,
630 typedefDecl(hasType(vectorType())));
633 TEST_P(ImportType, ImportDependentVectorType) {
634 const AstTypeMatcher<DependentVectorType> dependentVectorType;
635 MatchVerifier<Decl> Verifier;
636 testImport(
638 template<typename T, int Size>
639 using declToImport = T __attribute__((vector_size(Size)));
641 Lang_CXX11, "", Lang_CXX11, Verifier,
642 typeAliasTemplateDecl(
643 has(typeAliasDecl(hasType(dependentVectorType())))));
646 struct ImportOpenCLPipe : ImportType {
647 std::vector<std::string> getExtraArgs() const override {
648 return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};
652 TEST_P(ImportOpenCLPipe, ImportPipeType) {
653 const AstTypeMatcher<PipeType> pipeType;
654 MatchVerifier<Decl> Verifier;
655 testImport("typedef pipe int declToImport;", Lang_OpenCL, "", Lang_OpenCL,
656 Verifier, typedefDecl(hasType(pipeType())));
659 struct ImportMatrixType : ImportType {
660 std::vector<std::string> getExtraArgs() const override {
661 return {"-fenable-matrix"};
665 TEST_P(ImportMatrixType, ImportConstantMatrixType) {
666 const AstTypeMatcher<ConstantMatrixType> constantMatrixType;
667 MatchVerifier<Decl> Verifier;
668 testImport("typedef int __attribute__((matrix_type(5, 5))) declToImport;",
669 Lang_CXX11, "", Lang_CXX11, Verifier,
670 typedefDecl(hasType(constantMatrixType())));
673 TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {
674 const AstTypeMatcher<DependentSizedMatrixType> dependentSizedMatrixType;
675 MatchVerifier<Decl> Verifier;
676 testImport(
678 template<typename T, int Rows, int Cols>
679 using declToImport = T __attribute__((matrix_type(Rows, Cols)));
681 Lang_CXX11, "", Lang_CXX11, Verifier,
682 typeAliasTemplateDecl(
683 has(typeAliasDecl(hasType(dependentSizedMatrixType())))));
686 TEST_P(ImportType, ImportUsingType) {
687 MatchVerifier<Decl> Verifier;
688 testImport("struct C {};"
689 "void declToImport() { using ::C; new C{}; }",
690 Lang_CXX11, "", Lang_CXX11, Verifier,
691 functionDecl(hasDescendant(cxxNewExpr(hasType(pointerType(
692 pointee(elaboratedType(namesType(usingType())))))))));
695 TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
696 MatchVerifier<Decl> Verifier;
697 testImport("template <typename T> void declToImport() { };", Lang_CXX03, "",
698 Lang_CXX03, Verifier, functionTemplateDecl());
701 TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
702 MatchVerifier<Decl> Verifier;
703 testImport("template <typename T> struct C { T t; };"
704 "template <typename T> void declToImport() {"
705 " C<T> d;"
706 " (void)d.t;"
708 "void instantiate() { declToImport<int>(); }",
709 Lang_CXX03, "", Lang_CXX03, Verifier,
710 functionTemplateDecl(hasDescendant(
711 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
712 testImport("template <typename T> struct C { T t; };"
713 "template <typename T> void declToImport() {"
714 " C<T> d;"
715 " (void)(&d)->t;"
717 "void instantiate() { declToImport<int>(); }",
718 Lang_CXX03, "", Lang_CXX03, Verifier,
719 functionTemplateDecl(hasDescendant(
720 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
723 TEST_P(ImportType, ImportTypeAliasTemplate) {
724 MatchVerifier<Decl> Verifier;
725 testImport(
726 "template <int K>"
727 "struct dummy { static const int i = K; };"
728 "template <int K> using dummy2 = dummy<K>;"
729 "int declToImport() { return dummy2<3>::i; }",
730 Lang_CXX11, "", Lang_CXX11, Verifier,
731 traverse(TK_AsIs,
732 functionDecl(hasDescendant(implicitCastExpr(has(declRefExpr()))),
733 unless(hasAncestor(
734 translationUnitDecl(has(typeAliasDecl())))))));
737 const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
738 varTemplateSpecializationDecl;
740 TEST_P(ImportDecl, ImportVarTemplate) {
741 MatchVerifier<Decl> Verifier;
742 testImport(
743 "template <typename T>"
744 "T pi = T(3.1415926535897932385L);"
745 "void declToImport() { (void)pi<int>; }",
746 Lang_CXX14, "", Lang_CXX14, Verifier,
747 functionDecl(
748 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
749 unless(hasAncestor(translationUnitDecl(has(varDecl(
750 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
753 TEST_P(ImportType, ImportPackExpansion) {
754 MatchVerifier<Decl> Verifier;
755 testImport("template <typename... Args>"
756 "struct dummy {"
757 " dummy(Args... args) {}"
758 " static const int i = 4;"
759 "};"
760 "int declToImport() { return dummy<int>::i; }",
761 Lang_CXX11, "", Lang_CXX11, Verifier,
762 traverse(TK_AsIs, functionDecl(hasDescendant(returnStmt(has(
763 implicitCastExpr(has(declRefExpr()))))))));
766 TEST_P(ImportType, ImportDependentTemplateSpecialization) {
767 MatchVerifier<Decl> Verifier;
768 testImport("template<typename T>"
769 "struct A;"
770 "template<typename T>"
771 "struct declToImport {"
772 " typename A<T>::template B<T> a;"
773 "};",
774 Lang_CXX03, "", Lang_CXX03, Verifier,
775 classTemplateDecl(has(cxxRecordDecl(has(
776 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
779 TEST_P(ImportType, ImportDeducedTemplateSpecialization) {
780 MatchVerifier<Decl> Verifier;
781 testImport("template <typename T>"
782 "class C { public: C(T); };"
783 "C declToImport(123);",
784 Lang_CXX17, "", Lang_CXX17, Verifier,
785 varDecl(hasType(elaboratedType(
786 namesType(deducedTemplateSpecializationType())))));
789 const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
790 sizeOfPackExpr;
792 TEST_P(ImportExpr, ImportSizeOfPackExpr) {
793 MatchVerifier<Decl> Verifier;
794 testImport(
795 "template <typename... Ts>"
796 "void declToImport() {"
797 " const int i = sizeof...(Ts);"
798 "};"
799 "void g() { declToImport<int>(); }",
800 Lang_CXX11, "", Lang_CXX11, Verifier,
801 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
802 testImport(
803 "template <typename... Ts>"
804 "using X = int[sizeof...(Ts)];"
805 "template <typename... Us>"
806 "struct Y {"
807 " X<Us..., int, double, int, Us...> f;"
808 "};"
809 "Y<float, int> declToImport;",
810 Lang_CXX11, "", Lang_CXX11, Verifier,
811 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
812 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
815 TEST_P(ImportExpr, ImportCXXFoldExpr) {
816 auto Match1 = cxxFoldExpr(hasOperatorName("+"), isLeftFold(),
817 unless(hasFoldInit(expr())));
818 auto Match2 =
819 cxxFoldExpr(hasOperatorName("-"), isLeftFold(), hasFoldInit(expr()));
820 auto Match3 = cxxFoldExpr(hasOperatorName("*"), isRightFold(),
821 unless(hasFoldInit(expr())));
822 auto Match4 =
823 cxxFoldExpr(hasOperatorName("/"), isRightFold(), hasFoldInit(expr()));
825 MatchVerifier<Decl> Verifier;
826 testImport("template <typename... Ts>"
827 "void declToImport(Ts... args) {"
828 " const int i1 = (... + args);"
829 " const int i2 = (1 - ... - args);"
830 " const int i3 = (args * ...);"
831 " const int i4 = (args / ... / 1);"
832 "};"
833 "void g() { declToImport(1, 2, 3, 4, 5); }",
834 Lang_CXX17, "", Lang_CXX17, Verifier,
835 functionTemplateDecl(hasDescendant(Match1), hasDescendant(Match2),
836 hasDescendant(Match3),
837 hasDescendant(Match4)));
840 /// \brief Matches __builtin_types_compatible_p:
841 /// GNU extension to check equivalent types
842 /// Given
843 /// \code
844 /// __builtin_types_compatible_p(int, int)
845 /// \endcode
846 // will generate TypeTraitExpr <...> 'int'
847 const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
849 TEST_P(ImportExpr, ImportTypeTraitExpr) {
850 MatchVerifier<Decl> Verifier;
851 testImport(
852 "void declToImport() { "
853 " (void)__builtin_types_compatible_p(int, int);"
854 "}",
855 Lang_C99, "", Lang_C99, Verifier,
856 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
859 const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
861 TEST_P(ImportExpr, ImportCXXTypeidExpr) {
862 MatchVerifier<Decl> Verifier;
863 testImport(
864 "namespace std { class type_info {}; }"
865 "void declToImport() {"
866 " int x;"
867 " auto a = typeid(int); auto b = typeid(x);"
868 "}",
869 Lang_CXX11, "", Lang_CXX11, Verifier,
870 traverse(
871 TK_AsIs,
872 functionDecl(
873 hasDescendant(varDecl(hasName("a"), hasInitializer(hasDescendant(
874 cxxTypeidExpr())))),
875 hasDescendant(varDecl(hasName("b"), hasInitializer(hasDescendant(
876 cxxTypeidExpr())))))));
879 TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
880 MatchVerifier<Decl> Verifier;
881 testImport(
882 "template<typename T> struct declToImport {"
883 " void m() { (void)__is_pod(T); }"
884 "};"
885 "void f() { declToImport<int>().m(); }",
886 Lang_CXX11, "", Lang_CXX11, Verifier,
887 classTemplateDecl(has(cxxRecordDecl(has(
888 functionDecl(hasDescendant(
889 typeTraitExpr(hasType(booleanType())))))))));
892 TEST_P(ImportDecl, ImportRecordDeclInFunc) {
893 MatchVerifier<Decl> Verifier;
894 testImport("int declToImport() { "
895 " struct data_t {int a;int b;};"
896 " struct data_t d;"
897 " return 0;"
898 "}",
899 Lang_C99, "", Lang_C99, Verifier,
900 functionDecl(hasBody(compoundStmt(
901 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
904 TEST_P(ImportDecl, ImportedVarDeclPreservesThreadLocalStorage) {
905 MatchVerifier<Decl> Verifier;
906 testImport("thread_local int declToImport;", Lang_CXX11, "", Lang_CXX11,
907 Verifier, varDecl(hasThreadStorageDuration()));
910 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
911 Decl *FromTU = getTuDecl("int declToImport() { "
912 " struct data_t {int a;int b;};"
913 " struct data_t d;"
914 " return 0;"
915 "}",
916 Lang_C99, "input.c");
917 auto *FromVar =
918 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
919 ASSERT_TRUE(FromVar);
920 auto ToType =
921 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C99);
922 EXPECT_FALSE(ToType.isNull());
925 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
926 // This construct is not supported by ASTImporter.
927 Decl *FromTU = getTuDecl(
928 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
929 Lang_C99, "input.c");
930 auto *From = FirstDeclMatcher<FunctionDecl>().match(
931 FromTU, functionDecl(hasName("declToImport")));
932 ASSERT_TRUE(From);
933 auto *To = Import(From, Lang_C99);
934 EXPECT_EQ(To, nullptr);
937 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
938 Decl *FromTU =
939 getTuDecl("#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
940 "int declToImport(){ return NONAME_SIZEOF(int); }",
941 Lang_C99, "input.c");
942 auto *From = FirstDeclMatcher<FunctionDecl>().match(
943 FromTU, functionDecl(hasName("declToImport")));
944 ASSERT_TRUE(From);
945 auto *To = Import(From, Lang_C99);
946 ASSERT_TRUE(To);
947 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
948 To, functionDecl(hasName("declToImport"),
949 hasDescendant(unaryExprOrTypeTraitExpr()))));
952 TEST_P(ASTImporterOptionSpecificTestBase,
953 ImportRecordDeclInFuncParamsFromMacro) {
954 // This construct is not supported by ASTImporter.
955 Decl *FromTU =
956 getTuDecl("#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
957 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
958 Lang_C99, "input.c");
959 auto *From = FirstDeclMatcher<FunctionDecl>().match(
960 FromTU, functionDecl(hasName("declToImport")));
961 ASSERT_TRUE(From);
962 auto *To = Import(From, Lang_C99);
963 EXPECT_EQ(To, nullptr);
966 const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
967 cxxPseudoDestructorExpr;
969 TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
970 MatchVerifier<Decl> Verifier;
971 testImport(
972 "typedef int T;"
973 "void declToImport(int *p) {"
974 " T t;"
975 " p->T::~T();"
976 "}",
977 Lang_CXX03, "", Lang_CXX03, Verifier,
978 functionDecl(hasDescendant(callExpr(has(cxxPseudoDestructorExpr())))));
981 TEST_P(ImportDecl, ImportUsingDecl) {
982 MatchVerifier<Decl> Verifier;
983 testImport("namespace foo { int bar; }"
984 "void declToImport() { using foo::bar; }",
985 Lang_CXX03, "", Lang_CXX03, Verifier,
986 functionDecl(hasDescendant(usingDecl(hasName("bar")))));
989 TEST_P(ImportDecl, ImportUsingTemplate) {
990 MatchVerifier<Decl> Verifier;
991 testImport("namespace ns { template <typename T> struct S {}; }"
992 "template <template <typename> class T> class X {};"
993 "void declToImport() {"
994 "using ns::S; X<S> xi; }",
995 Lang_CXX11, "", Lang_CXX11, Verifier,
996 functionDecl(hasDescendant(varDecl(hasTypeLoc(elaboratedTypeLoc(
997 hasNamedTypeLoc(templateSpecializationTypeLoc(
998 hasAnyTemplateArgumentLoc(templateArgumentLoc())))))))));
1001 TEST_P(ImportDecl, ImportUsingEnumDecl) {
1002 MatchVerifier<Decl> Verifier;
1003 testImport("namespace foo { enum bar { baz, toto, quux }; }"
1004 "void declToImport() { using enum foo::bar; }",
1005 Lang_CXX20, "", Lang_CXX20, Verifier,
1006 functionDecl(hasDescendant(usingEnumDecl(hasName("bar")))));
1009 const internal::VariadicDynCastAllOfMatcher<Decl, UsingPackDecl> usingPackDecl;
1011 TEST_P(ImportDecl, ImportUsingPackDecl) {
1012 MatchVerifier<Decl> Verifier;
1013 testImport(
1014 "struct A { int operator()() { return 1; } };"
1015 "struct B { int operator()() { return 2; } };"
1016 "template<typename ...T> struct C : T... { using T::operator()...; };"
1017 "C<A, B> declToImport;",
1018 Lang_CXX20, "", Lang_CXX20, Verifier,
1019 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
1020 hasDeclaration(classTemplateSpecializationDecl(
1021 hasDescendant(usingPackDecl())))))))));
1024 /// \brief Matches shadow declarations introduced into a scope by a
1025 /// (resolved) using declaration.
1027 /// Given
1028 /// \code
1029 /// namespace n { int f; }
1030 /// namespace declToImport { using n::f; }
1031 /// \endcode
1032 /// usingShadowDecl()
1033 /// matches \code f \endcode
1034 const internal::VariadicDynCastAllOfMatcher<Decl,
1035 UsingShadowDecl> usingShadowDecl;
1037 TEST_P(ImportDecl, ImportUsingShadowDecl) {
1038 MatchVerifier<Decl> Verifier;
1039 // from using-decl
1040 testImport("namespace foo { int bar; }"
1041 "namespace declToImport { using foo::bar; }",
1042 Lang_CXX03, "", Lang_CXX03, Verifier,
1043 namespaceDecl(has(usingShadowDecl(hasName("bar")))));
1044 // from using-enum-decl
1045 testImport("namespace foo { enum bar {baz, toto, quux }; }"
1046 "namespace declToImport { using enum foo::bar; }",
1047 Lang_CXX20, "", Lang_CXX20, Verifier,
1048 namespaceDecl(has(usingShadowDecl(hasName("baz")))));
1051 TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
1052 MatchVerifier<Decl> Verifier;
1053 testImport("template<typename T> int foo();"
1054 "template <typename T> void declToImport() {"
1055 " (void)::foo<T>;"
1056 " (void)::template foo<T>;"
1058 "void instantiate() { declToImport<int>(); }",
1059 Lang_CXX03, "", Lang_CXX03, Verifier,
1060 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
1063 TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
1064 MatchVerifier<Decl> Verifier;
1065 testImport("template <typename T> struct C { T t; };"
1066 "template <typename T> void declToImport() {"
1067 " C<T> d;"
1068 " d.t = T();"
1070 "void instantiate() { declToImport<int>(); }",
1071 Lang_CXX03, "", Lang_CXX03, Verifier,
1072 functionTemplateDecl(hasDescendant(
1073 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1074 testImport("template <typename T> struct C { T t; };"
1075 "template <typename T> void declToImport() {"
1076 " C<T> d;"
1077 " (&d)->t = T();"
1079 "void instantiate() { declToImport<int>(); }",
1080 Lang_CXX03, "", Lang_CXX03, Verifier,
1081 functionTemplateDecl(hasDescendant(
1082 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1085 /// Check that function "declToImport()" (which is the templated function
1086 /// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1087 /// Same for class template declarations.
1088 TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
1089 MatchVerifier<Decl> Verifier;
1090 testImport("template <typename T> void declToImport() { T a = 1; }"
1091 "void instantiate() { declToImport<int>(); }",
1092 Lang_CXX03, "", Lang_CXX03, Verifier,
1093 functionTemplateDecl(hasAncestor(translationUnitDecl(
1094 unless(has(functionDecl(hasName("declToImport"))))))));
1095 testImport("template <typename T> struct declToImport { T t; };"
1096 "void instantiate() { declToImport<int>(); }",
1097 Lang_CXX03, "", Lang_CXX03, Verifier,
1098 classTemplateDecl(hasAncestor(translationUnitDecl(
1099 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
1102 TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
1103 MatchVerifier<Decl> Verifier;
1104 auto Code =
1105 R"s(
1106 struct declToImport {
1107 template <typename T0> struct X;
1108 template <typename T0> struct X<T0 *> {};
1110 )s";
1111 testImport(Code, Lang_CXX03, "", Lang_CXX03, Verifier,
1112 recordDecl(has(classTemplateDecl()),
1113 has(classTemplateSpecializationDecl())));
1116 TEST_P(ImportExpr, CXXOperatorCallExpr) {
1117 MatchVerifier<Decl> Verifier;
1118 testImport(
1119 "class declToImport {"
1120 " void f() { *this = declToImport(); }"
1121 "};",
1122 Lang_CXX03, "", Lang_CXX03, Verifier,
1123 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(cxxOperatorCallExpr())))));
1126 TEST_P(ImportExpr, DependentSizedArrayType) {
1127 MatchVerifier<Decl> Verifier;
1128 testImport("template<typename T, int Size> class declToImport {"
1129 " T data[Size];"
1130 "};",
1131 Lang_CXX03, "", Lang_CXX03, Verifier,
1132 classTemplateDecl(has(cxxRecordDecl(
1133 has(fieldDecl(hasType(dependentSizedArrayType())))))));
1136 TEST_P(ImportExpr, DependentSizedExtVectorType) {
1137 MatchVerifier<Decl> Verifier;
1138 testImport("template<typename T, int Size>"
1139 "class declToImport {"
1140 " typedef T __attribute__((ext_vector_type(Size))) type;"
1141 "};",
1142 Lang_CXX03, "", Lang_CXX03, Verifier,
1143 classTemplateDecl(has(cxxRecordDecl(
1144 has(typedefDecl(hasType(dependentSizedExtVectorType())))))));
1147 TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingPackDecl) {
1148 Decl *FromTU = getTuDecl(
1149 "struct A { int operator()() { return 1; } };"
1150 "struct B { int operator()() { return 2; } };"
1151 "template<typename ...T> struct C : T... { using T::operator()...; };"
1152 "C<A, B> Var;",
1153 Lang_CXX20);
1155 auto From = FirstDeclMatcher<UsingPackDecl>().match(FromTU, usingPackDecl());
1156 ASSERT_TRUE(From);
1157 auto To = cast<UsingPackDecl>(Import(From, Lang_CXX20));
1158 ASSERT_TRUE(To);
1160 ArrayRef<NamedDecl *> FromExpansions = From->expansions();
1161 ArrayRef<NamedDecl *> ToExpansions = To->expansions();
1162 ASSERT_EQ(FromExpansions.size(), ToExpansions.size());
1163 for (unsigned int I = 0; I < FromExpansions.size(); ++I) {
1164 auto ImportedExpansion = Import(FromExpansions[I], Lang_CXX20);
1165 EXPECT_EQ(ImportedExpansion, ToExpansions[I]);
1168 auto ImportedDC = cast<Decl>(Import(From->getDeclContext(), Lang_CXX20));
1169 EXPECT_EQ(ImportedDC, cast<Decl>(To->getDeclContext()));
1172 TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) {
1173 Decl *FromTU = getTuDecl("template<typename T> struct X {};", Lang_CXX03);
1174 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
1175 FromTU, templateTypeParmDecl(hasName("T")));
1176 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
1177 ASSERT_FALSE(To->hasDefaultArgument());
1180 TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) {
1181 Decl *FromTU =
1182 getTuDecl("template<typename T = int> struct X {};", Lang_CXX03);
1183 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
1184 FromTU, templateTypeParmDecl(hasName("T")));
1185 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
1186 ASSERT_TRUE(To->hasDefaultArgument());
1187 QualType ToArg = To->getDefaultArgument().getArgument().getAsType();
1188 ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy));
1191 TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1192 Decl *FromTU =
1193 getTuDecl("class A { public: static int X; }; void f() { (void)A::X; }",
1194 Lang_CXX03);
1195 auto From = FirstDeclMatcher<FunctionDecl>().match(
1196 FromTU, functionDecl(hasName("f")));
1197 ASSERT_TRUE(From);
1198 ASSERT_TRUE(
1199 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1200 ->getSubExpr()
1201 ->getBeginLoc()
1202 .isValid());
1203 FunctionDecl *To = Import(From, Lang_CXX03);
1204 ASSERT_TRUE(To);
1205 ASSERT_TRUE(
1206 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1207 ->getSubExpr()
1208 ->getBeginLoc()
1209 .isValid());
1212 TEST_P(ASTImporterOptionSpecificTestBase,
1213 TemplateTemplateParmDeclNoDefaultArg) {
1214 Decl *FromTU = getTuDecl(R"(
1215 template<template<typename> typename TT> struct Y {};
1217 Lang_CXX17);
1218 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
1219 FromTU, templateTemplateParmDecl(hasName("TT")));
1220 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
1221 ASSERT_FALSE(To->hasDefaultArgument());
1224 TEST_P(ASTImporterOptionSpecificTestBase, TemplateTemplateParmDeclDefaultArg) {
1225 Decl *FromTU = getTuDecl(R"(
1226 template<typename T> struct X {};
1227 template<template<typename> typename TT = X> struct Y {};
1229 Lang_CXX17);
1230 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
1231 FromTU, templateTemplateParmDecl(hasName("TT")));
1232 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
1233 ASSERT_TRUE(To->hasDefaultArgument());
1234 const TemplateArgument &ToDefaultArg = To->getDefaultArgument().getArgument();
1235 ASSERT_TRUE(To->isTemplateDecl());
1236 TemplateDecl *ToTemplate = ToDefaultArg.getAsTemplate().getAsTemplateDecl();
1238 // Find the default argument template 'X' in the AST and compare it against
1239 // the default argument we got.
1240 auto ToExpectedDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
1241 To->getTranslationUnitDecl(), classTemplateDecl(hasName("X")));
1242 ASSERT_EQ(ToTemplate, ToExpectedDecl);
1245 TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclNoDefaultArg) {
1246 Decl *FromTU = getTuDecl("template<int N> struct X {};", Lang_CXX03);
1247 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1248 FromTU, nonTypeTemplateParmDecl(hasName("N")));
1249 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
1250 ASSERT_FALSE(To->hasDefaultArgument());
1253 TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {
1254 Decl *FromTU = getTuDecl("template<int S = 1> struct X {};", Lang_CXX03);
1255 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1256 FromTU, nonTypeTemplateParmDecl(hasName("S")));
1257 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
1258 ASSERT_TRUE(To->hasDefaultArgument());
1259 Stmt *ToArg = To->getDefaultArgument().getArgument().getAsExpr();
1260 ASSERT_TRUE(isa<IntegerLiteral>(ToArg));
1261 ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);
1264 TEST_P(ASTImporterOptionSpecificTestBase, TemplateArgumentsDefaulted) {
1265 Decl *FromTU = getTuDecl(R"(
1266 template<typename T> struct X {};
1267 template<typename TP = double,
1268 int NTTP = 50,
1269 template<typename> typename TT = X> struct S {};
1270 S<> s;
1272 Lang_CXX17);
1273 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1274 FromTU, classTemplateSpecializationDecl(hasName("S")));
1275 ASSERT_TRUE(FromSpec);
1276 auto *ToSpec = Import(FromSpec, Lang_CXX03);
1277 ASSERT_TRUE(ToSpec);
1278 auto const &TList = ToSpec->getTemplateArgs();
1279 for (auto const &Arg : TList.asArray()) {
1280 ASSERT_TRUE(Arg.getIsDefaulted());
1284 TEST_P(ASTImporterOptionSpecificTestBase,
1285 ImportOfTemplatedDeclOfClassTemplateDecl) {
1286 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);
1287 auto From =
1288 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1289 ASSERT_TRUE(From);
1290 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX03));
1291 ASSERT_TRUE(To);
1292 Decl *ToTemplated = To->getTemplatedDecl();
1293 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1294 EXPECT_TRUE(ToTemplated1);
1295 EXPECT_EQ(ToTemplated1, ToTemplated);
1298 TEST_P(ASTImporterOptionSpecificTestBase,
1299 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1300 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);
1301 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1302 FromTU, functionTemplateDecl());
1303 ASSERT_TRUE(From);
1304 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX03));
1305 ASSERT_TRUE(To);
1306 Decl *ToTemplated = To->getTemplatedDecl();
1307 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1308 EXPECT_TRUE(ToTemplated1);
1309 EXPECT_EQ(ToTemplated1, ToTemplated);
1312 TEST_P(ASTImporterOptionSpecificTestBase,
1313 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1314 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);
1315 auto FromFT =
1316 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1317 ASSERT_TRUE(FromFT);
1319 auto ToTemplated =
1320 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1321 EXPECT_TRUE(ToTemplated);
1322 auto ToTU = ToTemplated->getTranslationUnitDecl();
1323 auto ToFT =
1324 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1325 EXPECT_TRUE(ToFT);
1328 TEST_P(ASTImporterOptionSpecificTestBase,
1329 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1330 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);
1331 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1332 FromTU, functionTemplateDecl());
1333 ASSERT_TRUE(FromFT);
1335 auto ToTemplated =
1336 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1337 EXPECT_TRUE(ToTemplated);
1338 auto ToTU = ToTemplated->getTranslationUnitDecl();
1339 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1340 ToTU, functionTemplateDecl());
1341 EXPECT_TRUE(ToFT);
1344 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
1345 auto Code =
1347 namespace x {
1348 template<class X> struct S1{};
1349 template<class X> struct S2{};
1350 template<class X> struct S3{};
1353 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
1354 auto FromNs =
1355 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1356 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX03));
1357 ASSERT_TRUE(ToNs);
1358 auto From =
1359 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1360 classTemplateDecl(
1361 hasName("S2")));
1362 auto To =
1363 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1364 classTemplateDecl(
1365 hasName("S2")));
1366 ASSERT_TRUE(From);
1367 ASSERT_TRUE(To);
1368 auto ToTemplated = To->getTemplatedDecl();
1369 auto ToTemplated1 =
1370 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX03));
1371 EXPECT_TRUE(ToTemplated1);
1372 ASSERT_EQ(ToTemplated1, ToTemplated);
1375 TEST_P(ASTImporterOptionSpecificTestBase,
1376 ImportTemplateSpecializationStaticMember) {
1377 auto FromCode =
1379 template <typename H> class Test{
1380 public:
1381 static const unsigned int length;
1384 template<> const unsigned int Test<int>::length;
1385 template<> const unsigned int Test<int>::length = 0;
1387 auto ToCode =
1389 template <typename H> class Test {
1390 public:
1391 static const unsigned int length;
1394 template <> const unsigned int Test<int>::length;
1396 void foo() { int i = 1 / Test<int>::length; }
1398 Decl *FromTU = getTuDecl(FromCode, Lang_CXX14);
1399 auto FromDecl = FirstDeclMatcher<VarDecl>().match(
1400 FromTU, varDecl(hasName("length"), isDefinition()));
1401 Decl *ToTu = getToTuDecl(ToCode, Lang_CXX14);
1402 auto ToX = Import(FromDecl, Lang_CXX03);
1403 auto ToDecl = FirstDeclMatcher<VarDecl>().match(
1404 ToTu, varDecl(hasName("length"), isDefinition()));
1405 EXPECT_TRUE(ToX);
1406 EXPECT_EQ(ToX, ToDecl);
1409 TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1410 // This tests the import of isConditionTrue directly to make sure the importer
1411 // gets it right.
1412 Decl *From, *To;
1413 std::tie(From, To) = getImportedDecl(
1414 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", Lang_C99,
1415 "", Lang_C99);
1417 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1418 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1420 const ChooseExpr *FromChooseExpr =
1421 selectFirst<ChooseExpr>("choose", FromResults);
1422 ASSERT_TRUE(FromChooseExpr);
1424 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1425 ASSERT_TRUE(ToChooseExpr);
1427 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1428 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1429 ToChooseExpr->isConditionDependent());
1432 TEST_P(ASTImporterOptionSpecificTestBase, ImportConvertVectorExpr) {
1433 Decl *From, *To;
1434 std::tie(From, To) = getImportedDecl(
1435 "typedef double v4double __attribute__((__vector_size__(32)));"
1436 "typedef float v4float __attribute__((__vector_size__(16)));"
1437 "v4float vf;"
1438 "void declToImport() { (void)__builtin_convertvector(vf, v4double); }",
1439 Lang_CXX03, "", Lang_CXX03);
1441 auto ToResults =
1442 match(convertVectorExpr().bind("convert"), To->getASTContext());
1443 auto FromResults =
1444 match(convertVectorExpr().bind("convert"), From->getASTContext());
1446 const ConvertVectorExpr *FromConvertVectorExpr =
1447 selectFirst<ConvertVectorExpr>("convert", FromResults);
1448 ASSERT_TRUE(FromConvertVectorExpr);
1450 const ConvertVectorExpr *ToConvertVectorExpr =
1451 selectFirst<ConvertVectorExpr>("convert", ToResults);
1452 ASSERT_TRUE(ToConvertVectorExpr);
1455 TEST_P(ASTImporterOptionSpecificTestBase, ImportGenericSelectionExpr) {
1456 Decl *From, *To;
1457 std::tie(From, To) = getImportedDecl(
1459 int declToImport() {
1460 int x;
1461 return _Generic(x, int: 0, default: 1);
1464 Lang_C99, "", Lang_C99);
1466 auto ToResults =
1467 match(genericSelectionExpr().bind("expr"), To->getASTContext());
1468 auto FromResults =
1469 match(genericSelectionExpr().bind("expr"), From->getASTContext());
1471 const GenericSelectionExpr *FromGenericSelectionExpr =
1472 selectFirst<GenericSelectionExpr>("expr", FromResults);
1473 ASSERT_TRUE(FromGenericSelectionExpr);
1475 const GenericSelectionExpr *ToGenericSelectionExpr =
1476 selectFirst<GenericSelectionExpr>("expr", ToResults);
1477 ASSERT_TRUE(ToGenericSelectionExpr);
1479 EXPECT_EQ(FromGenericSelectionExpr->isResultDependent(),
1480 ToGenericSelectionExpr->isResultDependent());
1481 EXPECT_EQ(FromGenericSelectionExpr->getResultIndex(),
1482 ToGenericSelectionExpr->getResultIndex());
1485 TEST_P(ASTImporterOptionSpecificTestBase,
1486 ImportFunctionWithBackReferringParameter) {
1487 Decl *From, *To;
1488 std::tie(From, To) = getImportedDecl(
1490 template <typename T> struct X {};
1492 void declToImport(int y, X<int> &x) {}
1494 template <> struct X<int> {
1495 void g() {
1496 X<int> x;
1497 declToImport(0, x);
1501 Lang_CXX03, "", Lang_CXX03);
1503 MatchVerifier<Decl> Verifier;
1504 auto Matcher = functionDecl(hasName("declToImport"),
1505 parameterCountIs(2),
1506 hasParameter(0, hasName("y")),
1507 hasParameter(1, hasName("x")),
1508 hasParameter(1, hasType(asString("X<int> &"))));
1509 ASSERT_TRUE(Verifier.match(From, Matcher));
1510 EXPECT_TRUE(Verifier.match(To, Matcher));
1513 TEST_P(ASTImporterOptionSpecificTestBase,
1514 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1515 Decl *From, *To;
1516 std::tie(From, To) =
1517 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1518 "void instantiate() { declToImport<int>(); }",
1519 Lang_CXX03, "", Lang_CXX03);
1521 auto Check = [](Decl *D) -> bool {
1522 auto TU = D->getTranslationUnitDecl();
1523 for (auto Child : TU->decls()) {
1524 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1525 if (FD->getNameAsString() == "declToImport") {
1526 GTEST_NONFATAL_FAILURE_(
1527 "TU should not contain any FunctionDecl with name declToImport");
1528 return false;
1532 return true;
1535 ASSERT_TRUE(Check(From));
1536 EXPECT_TRUE(Check(To));
1539 TEST_P(ASTImporterOptionSpecificTestBase,
1540 TUshouldNotContainTemplatedDeclOfClassTemplates) {
1541 Decl *From, *To;
1542 std::tie(From, To) =
1543 getImportedDecl("template <typename T> struct declToImport { T t; };"
1544 "void instantiate() { declToImport<int>(); }",
1545 Lang_CXX03, "", Lang_CXX03);
1547 auto Check = [](Decl *D) -> bool {
1548 auto TU = D->getTranslationUnitDecl();
1549 for (auto Child : TU->decls()) {
1550 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1551 if (RD->getNameAsString() == "declToImport") {
1552 GTEST_NONFATAL_FAILURE_(
1553 "TU should not contain any CXXRecordDecl with name declToImport");
1554 return false;
1558 return true;
1561 ASSERT_TRUE(Check(From));
1562 EXPECT_TRUE(Check(To));
1565 TEST_P(ASTImporterOptionSpecificTestBase,
1566 TUshouldNotContainTemplatedDeclOfTypeAlias) {
1567 Decl *From, *To;
1568 std::tie(From, To) =
1569 getImportedDecl(
1570 "template <typename T> struct X {};"
1571 "template <typename T> using declToImport = X<T>;"
1572 "void instantiate() { declToImport<int> a; }",
1573 Lang_CXX11, "", Lang_CXX11);
1575 auto Check = [](Decl *D) -> bool {
1576 auto TU = D->getTranslationUnitDecl();
1577 for (auto Child : TU->decls()) {
1578 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1579 if (AD->getNameAsString() == "declToImport") {
1580 GTEST_NONFATAL_FAILURE_(
1581 "TU should not contain any TypeAliasDecl with name declToImport");
1582 return false;
1586 return true;
1589 ASSERT_TRUE(Check(From));
1590 EXPECT_TRUE(Check(To));
1593 TEST_P(ASTImporterOptionSpecificTestBase,
1594 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1596 Decl *From, *To;
1597 std::tie(From, To) = getImportedDecl(
1599 template<class T>
1600 class Base {};
1601 class declToImport : public Base<declToImport> {};
1603 Lang_CXX03, "", Lang_CXX03);
1605 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1606 auto Pattern =
1607 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1608 ASSERT_TRUE(
1609 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1610 EXPECT_TRUE(
1611 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1613 // Check that the ClassTemplateSpecializationDecl is the child of the
1614 // ClassTemplateDecl.
1615 Pattern = translationUnitDecl(has(classTemplateDecl(
1616 hasName("Base"), has(classTemplateSpecializationDecl()))));
1617 ASSERT_TRUE(
1618 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1619 EXPECT_TRUE(
1620 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1623 AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1624 size_t Index = 0;
1625 for (Decl *D : Node.decls()) {
1626 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1627 auto *ND = cast<NamedDecl>(D);
1628 if (Index == Order.size())
1629 return false;
1630 if (ND->getName() != Order[Index])
1631 return false;
1632 ++Index;
1635 return Index == Order.size();
1638 TEST_P(ASTImporterOptionSpecificTestBase,
1639 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1640 Decl *From, *To;
1641 std::tie(From, To) = getImportedDecl(
1643 namespace NS {
1644 template<class T>
1645 class X {};
1646 template class X<int>;
1649 Lang_CXX03, "", Lang_CXX03, "NS");
1651 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1652 // ClassTemplateDecl.
1653 auto Pattern = namespaceDecl(has(classTemplateDecl(
1654 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1655 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1656 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1658 // Check that the ClassTemplateSpecializationDecl is the child of the
1659 // NamespaceDecl.
1660 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1661 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1662 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1665 TEST_P(ASTImporterOptionSpecificTestBase,
1666 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1667 Decl *From, *To;
1668 std::tie(From, To) =
1669 getImportedDecl(
1670 "struct declToImport { int a; int b; };",
1671 Lang_CXX11, "", Lang_CXX11);
1673 MatchVerifier<Decl> Verifier;
1674 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1675 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1678 TEST_P(ASTImporterOptionSpecificTestBase,
1679 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1680 Decl *From, *To;
1681 std::tie(From, To) = getImportedDecl(
1682 // The original recursive algorithm of ASTImporter first imports 'c' then
1683 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1684 R"s(
1685 struct declToImport {
1686 int a = c + b;
1687 int b = 1;
1688 int c = 2;
1690 )s",
1691 Lang_CXX11, "", Lang_CXX11);
1693 MatchVerifier<Decl> Verifier;
1694 ASSERT_TRUE(
1695 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1696 EXPECT_TRUE(
1697 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1700 TEST_P(ASTImporterOptionSpecificTestBase,
1701 CXXRecordDeclFieldAndIndirectFieldOrder) {
1702 Decl *From, *To;
1703 std::tie(From, To) = getImportedDecl(
1704 // First field is "a", then the field for unnamed union, then "b" and "c"
1705 // from it (indirect fields), then "d".
1706 R"s(
1707 struct declToImport {
1708 int a = d;
1709 union {
1710 int b;
1711 int c;
1713 int d;
1715 )s",
1716 Lang_CXX11, "", Lang_CXX11);
1718 MatchVerifier<Decl> Verifier;
1719 ASSERT_TRUE(Verifier.match(
1720 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1721 EXPECT_TRUE(Verifier.match(
1722 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1725 TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
1726 Decl *From, *To;
1727 std::tie(From, To) = getImportedDecl(
1729 struct declToImport {
1732 Lang_CXX03, "", Lang_CXX03);
1734 MatchVerifier<Decl> Verifier;
1735 // Match the implicit Decl.
1736 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1737 ASSERT_TRUE(Verifier.match(From, Matcher));
1738 EXPECT_TRUE(Verifier.match(To, Matcher));
1741 TEST_P(ASTImporterOptionSpecificTestBase,
1742 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1743 Decl *From, *To;
1744 std::tie(From, To) = getImportedDecl(
1746 template <typename U>
1747 struct declToImport {
1750 Lang_CXX03, "", Lang_CXX03);
1752 MatchVerifier<Decl> Verifier;
1753 // Match the implicit Decl.
1754 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1755 ASSERT_TRUE(Verifier.match(From, Matcher));
1756 EXPECT_TRUE(Verifier.match(To, Matcher));
1759 TEST_P(ASTImporterOptionSpecificTestBase,
1760 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1761 Decl *From, *To;
1762 std::tie(From, To) = getImportedDecl(
1764 template<class T>
1765 class Base {};
1766 class declToImport : public Base<declToImport> {};
1768 Lang_CXX03, "", Lang_CXX03);
1770 auto hasImplicitClass = has(cxxRecordDecl());
1771 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1772 hasName("Base"),
1773 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1774 ASSERT_TRUE(
1775 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1776 EXPECT_TRUE(
1777 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1780 TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
1781 Decl *From, *To;
1782 std::tie(From, To) =
1783 getImportedDecl("void declToImport() {}", Lang_CXX03, "", Lang_CXX03);
1785 MatchVerifier<Decl> Verifier;
1786 auto Matcher = functionDecl();
1787 ASSERT_TRUE(Verifier.match(From, Matcher));
1788 EXPECT_TRUE(Verifier.match(To, Matcher));
1789 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1792 TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
1793 Decl *FromTU = getTuDecl(
1795 struct X {};
1796 void operator<<(int, X);
1798 Lang_CXX03);
1799 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1800 const Decl *To = Import(From, Lang_CXX03);
1801 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1804 TEST_P(ASTImporterOptionSpecificTestBase,
1805 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1806 Decl *From, *To;
1807 std::tie(From, To) = getImportedDecl(
1809 template<class T>
1810 class Base { int a; };
1811 class declToImport : Base<declToImport> {};
1813 Lang_CXX03, "", Lang_CXX03);
1815 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1816 hasName("Base"),
1817 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1818 ASSERT_TRUE(
1819 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1820 EXPECT_TRUE(
1821 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1824 TEST_P(ASTImporterOptionSpecificTestBase,
1825 ImportDefinitionOfClassTemplateAfterFwdDecl) {
1827 Decl *FromTU = getTuDecl(
1829 template <typename T>
1830 struct B;
1832 Lang_CXX03, "input0.cc");
1833 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1834 FromTU, classTemplateDecl(hasName("B")));
1836 Import(FromD, Lang_CXX03);
1840 Decl *FromTU = getTuDecl(
1842 template <typename T>
1843 struct B {
1844 void f();
1847 Lang_CXX03, "input1.cc");
1848 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1849 FromTU, functionDecl(hasName("f")));
1850 Import(FromD, Lang_CXX03);
1851 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1852 FromTU, classTemplateDecl(hasName("B")));
1853 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
1854 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1858 TEST_P(ASTImporterOptionSpecificTestBase,
1859 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1860 Decl *ToTU = getToTuDecl(
1862 template <typename T>
1863 struct B {
1864 void f();
1867 template <typename T>
1868 struct B;
1870 Lang_CXX03);
1871 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1872 [](const ClassTemplateDecl *T) {
1873 return T->isThisDeclarationADefinition();
1875 .match(ToTU, classTemplateDecl()));
1877 Decl *FromTU = getTuDecl(
1879 template <typename T>
1880 struct B {
1881 void f();
1884 Lang_CXX03, "input1.cc");
1885 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1886 FromTU, classTemplateDecl(hasName("B")));
1888 Import(FromD, Lang_CXX03);
1890 // We should have only one definition.
1891 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1892 [](const ClassTemplateDecl *T) {
1893 return T->isThisDeclarationADefinition();
1895 .match(ToTU, classTemplateDecl()));
1898 TEST_P(ASTImporterOptionSpecificTestBase,
1899 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1900 Decl *ToTU = getToTuDecl(
1902 struct B {
1903 void f();
1906 struct B;
1908 Lang_CXX03);
1909 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1910 ToTU, cxxRecordDecl(unless(isImplicit()))));
1912 Decl *FromTU = getTuDecl(
1914 struct B {
1915 void f();
1918 Lang_CXX03, "input1.cc");
1919 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1920 FromTU, cxxRecordDecl(hasName("B")));
1922 Import(FromD, Lang_CXX03);
1924 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1925 ToTU, cxxRecordDecl(unless(isImplicit()))));
1928 static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1929 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1930 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1931 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1932 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1934 static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1935 SourceManager &SM1, SourceManager &SM2) {
1936 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1937 FullSourceLoc{ Range2.getBegin(), SM2 });
1938 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1939 FullSourceLoc{ Range2.getEnd(), SM2 });
1941 TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
1942 Decl *FromTU = getTuDecl(
1944 #define MFOO(arg) arg = arg + 1
1946 void foo() {
1947 int a = 5;
1948 MFOO(a);
1951 Lang_CXX03);
1952 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1953 auto ToD = Import(FromD, Lang_CXX03);
1955 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1956 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1957 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1958 auto FromRHS =
1959 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1961 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1962 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1963 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1964 FromSM);
1965 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1966 FromSM);
1967 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1968 FromSM);
1971 TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
1972 Decl *FromTU = getTuDecl(
1974 #define FUNC_INT void declToImport
1975 #define FUNC FUNC_INT
1976 FUNC(int a);
1978 Lang_CXX03);
1979 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1980 auto ToD = Import(FromD, Lang_CXX03);
1982 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1983 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1984 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1985 FromSM);
1988 TEST_P(
1989 ASTImporterOptionSpecificTestBase,
1990 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
1991 Decl *ToTU = getToTuDecl(
1993 template <typename T>
1994 struct B;
1996 template <>
1997 struct B<int> {};
1999 template <>
2000 struct B<int>;
2002 Lang_CXX03);
2003 // We should have only one definition.
2004 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
2005 [](const ClassTemplateSpecializationDecl *T) {
2006 return T->isThisDeclarationADefinition();
2008 .match(ToTU, classTemplateSpecializationDecl()));
2010 Decl *FromTU = getTuDecl(
2012 template <typename T>
2013 struct B;
2015 template <>
2016 struct B<int> {};
2018 Lang_CXX03, "input1.cc");
2019 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2020 FromTU, classTemplateSpecializationDecl(hasName("B")));
2022 Import(FromD, Lang_CXX03);
2024 // We should have only one definition.
2025 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
2026 [](const ClassTemplateSpecializationDecl *T) {
2027 return T->isThisDeclarationADefinition();
2029 .match(ToTU, classTemplateSpecializationDecl()));
2032 TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
2033 Decl *FromTU = getTuDecl(
2035 struct { int a; int b; } object0 = { 2, 3 };
2036 struct { int x; int y; int z; } object1;
2038 Lang_CXX03, "input0.cc");
2040 auto *Obj0 =
2041 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
2042 auto *From0 = getRecordDecl(Obj0);
2043 auto *Obj1 =
2044 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
2045 auto *From1 = getRecordDecl(Obj1);
2047 auto *To0 = Import(From0, Lang_CXX03);
2048 auto *To1 = Import(From1, Lang_CXX03);
2050 EXPECT_TRUE(To0);
2051 EXPECT_TRUE(To1);
2052 EXPECT_NE(To0, To1);
2053 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
2056 TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
2057 auto *Code =
2059 struct X {
2060 struct { int a; };
2061 struct { int b; };
2064 Decl *FromTU0 = getTuDecl(Code, Lang_C99, "input0.c");
2066 Decl *FromTU1 = getTuDecl(Code, Lang_C99, "input1.c");
2068 auto *X0 =
2069 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
2070 auto *X1 =
2071 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
2072 Import(X0, Lang_C99);
2073 Import(X1, Lang_C99);
2075 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2076 // We expect no (ODR) warning during the import.
2077 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2078 EXPECT_EQ(1u,
2079 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2082 TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
2083 Decl *FromTU0 = getTuDecl(
2085 struct X {
2086 struct { int a; };
2087 struct { int b; };
2090 Lang_C99, "input0.c");
2092 Decl *FromTU1 = getTuDecl(
2094 struct X { // reversed order
2095 struct { int b; };
2096 struct { int a; };
2099 Lang_C99, "input1.c");
2101 auto *X0 =
2102 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
2103 auto *X1 =
2104 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
2105 Import(X0, Lang_C99);
2106 Import(X1, Lang_C99);
2108 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2109 // We expect one (ODR) warning during the import.
2110 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2111 EXPECT_EQ(1u,
2112 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2115 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
2116 auto Pattern = varDecl(hasName("x"));
2117 VarDecl *Imported1;
2119 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX03, "input0.cc");
2120 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2121 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2123 VarDecl *Imported2;
2125 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input1.cc");
2126 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2127 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2129 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
2130 EXPECT_FALSE(Imported2->isUsed(false));
2132 Decl *FromTU = getTuDecl("extern int x; int f() { return x; }", Lang_CXX03,
2133 "input2.cc");
2134 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2135 FromTU, functionDecl(hasName("f")));
2136 Import(FromD, Lang_CXX03);
2138 EXPECT_TRUE(Imported2->isUsed(false));
2141 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
2142 auto Pattern = varDecl(hasName("x"));
2143 VarDecl *ExistingD;
2145 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX03);
2146 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2148 EXPECT_FALSE(ExistingD->isUsed(false));
2150 Decl *FromTU =
2151 getTuDecl("int x = 1; int f() { return x; }", Lang_CXX03, "input1.cc");
2152 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2153 FromTU, functionDecl(hasName("f")));
2154 Import(FromD, Lang_CXX03);
2156 EXPECT_TRUE(ExistingD->isUsed(false));
2159 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
2160 auto Pattern = varDecl(hasName("a"));
2161 VarDecl *ExistingD;
2163 Decl *ToTU = getToTuDecl(
2165 struct A {
2166 static const int a = 1;
2169 Lang_CXX03);
2170 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2172 EXPECT_FALSE(ExistingD->isUsed(false));
2174 Decl *FromTU = getTuDecl(
2176 struct A {
2177 static const int a = 1;
2179 const int *f() { return &A::a; } // requires storage,
2180 // thus used flag will be set
2182 Lang_CXX03, "input1.cc");
2183 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2184 FromTU, functionDecl(hasName("f")));
2185 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2186 ASSERT_TRUE(FromD->isUsed(false));
2187 Import(FromFunD, Lang_CXX03);
2189 EXPECT_TRUE(ExistingD->isUsed(false));
2192 TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
2193 auto Pattern = varDecl(hasName("x"));
2195 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input0.cc");
2196 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2198 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2200 ASSERT_FALSE(Imported1->isUsed(false));
2202 FromD->setIsUsed();
2203 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2205 EXPECT_EQ(Imported1, Imported2);
2206 EXPECT_TRUE(Imported2->isUsed(false));
2209 struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
2211 TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
2212 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);
2213 auto Pattern = functionDecl(hasName("f"));
2214 auto *From =
2215 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
2217 Decl *ImportedD = Import(From, Lang_CXX03);
2218 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2220 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2221 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2222 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2223 EXPECT_TRUE(ImportedD == To0);
2224 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2225 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2226 EXPECT_EQ(To1->getPreviousDecl(), To0);
2229 TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2230 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);
2231 auto Pattern = functionDecl(hasName("f"));
2232 auto *From =
2233 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
2235 Decl *ImportedD = Import(From, Lang_CXX03);
2236 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2238 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2239 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2240 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2241 EXPECT_TRUE(ImportedD == To1);
2242 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2243 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2244 EXPECT_EQ(To1->getPreviousDecl(), To0);
2247 TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2248 auto Code =
2250 struct B { virtual void f(); };
2251 void B::f() {}
2252 struct D : B { void f(); };
2254 auto Pattern =
2255 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2256 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
2257 CXXMethodDecl *Proto =
2258 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2260 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2261 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));
2262 EXPECT_EQ(To->size_overridden_methods(), 1u);
2265 TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2266 auto Code =
2268 struct B { virtual void f(); };
2269 void B::f() {}
2271 auto Pattern =
2272 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2273 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
2274 CXXMethodDecl *Proto =
2275 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2276 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2278 ASSERT_TRUE(Proto->isVirtual());
2279 ASSERT_TRUE(Def->isVirtual());
2280 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));
2281 EXPECT_TRUE(To->isVirtual());
2284 TEST_P(ImportFunctions,
2285 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2286 Decl *ToTU = getToTuDecl(
2288 void f() {}
2289 void f();
2291 Lang_CXX03);
2292 ASSERT_EQ(1u,
2293 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2294 return FD->doesThisDeclarationHaveABody();
2295 }).match(ToTU, functionDecl()));
2297 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX03, "input0.cc");
2298 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2300 Import(FromD, Lang_CXX03);
2302 EXPECT_EQ(1u,
2303 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2304 return FD->doesThisDeclarationHaveABody();
2305 }).match(ToTU, functionDecl()));
2308 TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2309 auto Code =
2311 struct B { virtual void f(); };
2312 struct D:B { void f(); };
2314 auto BFP =
2315 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2316 auto DFP =
2317 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2319 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);
2320 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2321 Import(DF, Lang_CXX03);
2323 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2324 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2325 Import(BF, Lang_CXX03);
2327 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2329 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2330 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2333 TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2334 auto CodeWithoutDef =
2336 struct B { virtual void f(); };
2337 struct D:B { void f(); };
2339 auto CodeWithDef =
2341 struct B { virtual void f(){}; };
2342 struct D:B { void f(){}; };
2344 auto BFP =
2345 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2346 auto DFP =
2347 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2348 auto BFDefP = cxxMethodDecl(
2349 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2350 auto DFDefP = cxxMethodDecl(
2351 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2352 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2355 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX03, "input0.cc");
2356 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2357 Import(FromD, Lang_CXX03);
2360 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX03, "input1.cc");
2361 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2362 Import(FromB, Lang_CXX03);
2365 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2367 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2368 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2369 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2370 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2371 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2374 TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2375 auto Code =
2377 struct B { virtual void f(); };
2378 struct D:B { void f(); };
2379 void B::f(){};
2382 auto BFP =
2383 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2384 auto BFDefP = cxxMethodDecl(
2385 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2386 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2387 unless(isDefinition()));
2389 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);
2390 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2391 Import(D, Lang_CXX03);
2393 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2394 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2395 Import(B, Lang_CXX03);
2397 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2399 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2400 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2402 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2403 ToTU, cxxRecordDecl(hasName("B")));
2404 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2405 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2406 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2408 // The definition should be out-of-class.
2409 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2410 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2411 ToBFOutOfClass->getLexicalDeclContext());
2412 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2413 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2415 // Check that the redecl chain is intact.
2416 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2419 TEST_P(ImportFunctions,
2420 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2421 auto CodeTU0 =
2423 struct B { virtual void f(); };
2424 struct D:B { void f(); };
2426 auto CodeTU1 =
2428 struct B { virtual void f(); };
2429 struct D:B { void f(); };
2430 void B::f(){}
2431 void D::f(){}
2432 void foo(B &b, D &d) { b.f(); d.f(); }
2435 auto BFP =
2436 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2437 auto BFDefP = cxxMethodDecl(
2438 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2439 auto DFP =
2440 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2441 auto DFDefP = cxxMethodDecl(
2442 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2443 auto FooDef = functionDecl(hasName("foo"));
2446 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX03, "input0.cc");
2447 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2448 Import(D, Lang_CXX03);
2452 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX03, "input1.cc");
2453 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2454 Import(Foo, Lang_CXX03);
2457 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2459 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2460 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2461 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2462 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2464 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2465 ToTU, cxxRecordDecl(hasName("B")));
2466 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2467 ToTU, cxxRecordDecl(hasName("D")));
2468 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2469 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2470 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2471 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2472 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2473 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2475 // The definition should be out-of-class.
2476 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2477 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2478 ToBFOutOfClass->getLexicalDeclContext());
2479 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2480 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2482 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2483 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2484 ToDFOutOfClass->getLexicalDeclContext());
2485 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2486 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2488 // Check that the redecl chain is intact.
2489 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2490 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2493 TEST_P(ASTImporterOptionSpecificTestBase,
2494 ImportVirtualOverriddenMethodOnALoop) {
2495 // B::f() calls => f1() ==> C ==> C::f()
2496 // \
2497 // \---- A::f()
2499 // C::f()'s ImportOverriddenMethods() asserts B::isVirtual(), so B::f()'s
2500 // ImportOverriddenMethods() should be completed before B::f()'s body
2501 const char *Code =
2503 void f1();
2504 class A {
2505 virtual void f(){}
2507 class B: public A {
2508 void f() override {
2509 f1();
2512 class C: public B {
2513 void f() override {}
2515 void f1() { C c; }
2517 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
2519 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
2520 FromTU, cxxMethodDecl(hasName("B::f")));
2522 auto *ToBF = Import(FromF, Lang_CXX11);
2523 EXPECT_TRUE(ToBF->isVirtual());
2525 auto *ToCF = FirstDeclMatcher<CXXMethodDecl>().match(
2526 ToBF->getTranslationUnitDecl(), cxxMethodDecl(hasName("C::f")));
2527 EXPECT_TRUE(ToCF->isVirtual());
2530 TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2531 std::string Code = "static int v; static int v = 0;";
2532 auto Pattern = varDecl(hasName("v"));
2534 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C99, "input0.c");
2536 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2537 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2539 auto *To0 = Import(From0, Lang_C99);
2540 auto *To1 = Import(From1, Lang_C99);
2542 EXPECT_TRUE(To0);
2543 ASSERT_TRUE(To1);
2544 EXPECT_NE(To0, To1);
2545 EXPECT_EQ(To1->getPreviousDecl(), To0);
2548 TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2549 TranslationUnitDecl *FromTu =
2550 getTuDecl("namespace NS0 { namespace { void f(); } }"
2551 "namespace NS1 { namespace { void f(); } }",
2552 Lang_CXX03, "input0.cc");
2553 auto Pattern = functionDecl(hasName("f"));
2555 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2556 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2558 auto *ToF0 = Import(FromF0, Lang_CXX03);
2559 auto *ToF1 = Import(FromF1, Lang_CXX03);
2561 EXPECT_TRUE(ToF0);
2562 ASSERT_TRUE(ToF1);
2563 EXPECT_NE(ToF0, ToF1);
2564 EXPECT_FALSE(ToF1->getPreviousDecl());
2567 TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2569 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2570 Lang_CXX03, "input0.cc");
2571 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2572 FromTU, functionDecl(hasName("g0")));
2574 Import(FromD, Lang_CXX03);
2577 Decl *FromTU =
2578 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2579 Lang_CXX03, "input1.cc");
2580 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2581 FromTU, functionDecl(hasName("g1")));
2582 Import(FromD, Lang_CXX03);
2585 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2586 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2587 2u);
2590 TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2591 Decl *FromTU = getTuDecl(
2593 void foo() {
2594 (void)[]() { ; };
2597 Lang_CXX11);
2598 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2599 FromTU, functionDecl(hasName("foo")));
2600 auto *ToD = Import(FromD, Lang_CXX03);
2601 EXPECT_TRUE(ToD);
2602 CXXRecordDecl *LambdaRec =
2603 cast<LambdaExpr>(cast<CStyleCastExpr>(
2604 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2605 ->getSubExpr())
2606 ->getLambdaClass();
2607 EXPECT_TRUE(LambdaRec->getDestructor());
2610 TEST_P(ImportFunctions,
2611 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2612 Decl *FromTU = getTuDecl(
2614 struct X {
2615 template <typename T>
2616 void foo(){}
2618 void f() {
2619 X x;
2620 x.foo<int>();
2623 Lang_CXX03);
2624 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2625 FromTU, functionDecl(hasName("f")));
2626 auto *ToD = Import(FromD, Lang_CXX03);
2627 EXPECT_TRUE(ToD);
2628 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2629 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2632 TEST_P(ImportFunctions,
2633 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2634 Decl *FromTU = getTuDecl(
2636 struct X {
2637 template <typename T>
2638 void foo(){}
2640 template <typename T>
2641 void f() {
2642 X x;
2643 x.foo<T>();
2645 void g() {
2646 f<int>();
2649 Lang_CXX03);
2650 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2651 FromTU, functionDecl(hasName("g")));
2652 auto *ToD = Import(FromD, Lang_CXX03);
2653 EXPECT_TRUE(ToD);
2654 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2655 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2656 ToTU, translationUnitDecl(hasDescendant(
2657 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2660 struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2662 TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2663 auto Code =
2665 class X {
2666 template <class T>
2667 void f(T t);
2670 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2671 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2672 FromTU1, functionTemplateDecl(hasName("f")));
2673 auto *ToD1 = Import(FromD1, Lang_CXX03);
2674 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");
2675 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2676 FromTU2, functionTemplateDecl(hasName("f")));
2677 auto *ToD2 = Import(FromD2, Lang_CXX03);
2678 EXPECT_EQ(ToD1, ToD2);
2681 TEST_P(ImportFunctionTemplates,
2682 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2683 auto Code =
2685 class X {
2686 template <class T>
2687 void f(T t);
2689 template <class T>
2690 void X::f(T t) {};
2692 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");
2693 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2694 FromTU1, functionTemplateDecl(hasName("f")));
2695 auto *ToD1 = Import(FromD1, Lang_CXX03);
2696 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");
2697 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2698 FromTU2, functionTemplateDecl(hasName("f")));
2699 auto *ToD2 = Import(FromD2, Lang_CXX03);
2700 EXPECT_EQ(ToD1, ToD2);
2703 TEST_P(ImportFunctionTemplates,
2704 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2705 getToTuDecl(
2707 template <typename T>
2708 void foo(T) {}
2709 void foo();
2711 Lang_CXX03);
2712 Decl *FromTU = getTuDecl("void foo();", Lang_CXX03);
2713 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2714 FromTU, functionDecl(hasName("foo")));
2715 auto *ImportedD = Import(FromD, Lang_CXX03);
2716 EXPECT_TRUE(ImportedD);
2719 TEST_P(ImportFunctionTemplates,
2720 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2721 auto Code =
2723 struct Foo {
2724 template <typename T>
2725 Foo(T) {}
2726 Foo();
2729 getToTuDecl(Code, Lang_CXX03);
2730 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
2731 auto *FromD =
2732 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
2733 auto *ImportedD = Import(FromD, Lang_CXX03);
2734 EXPECT_TRUE(ImportedD);
2737 TEST_P(ImportFunctionTemplates,
2738 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2739 getToTuDecl(
2741 template <typename T>
2742 void operator<(T,T) {}
2743 struct X{};
2744 void operator<(X, X);
2746 Lang_CXX03);
2747 Decl *FromTU = getTuDecl(
2749 struct X{};
2750 void operator<(X, X);
2752 Lang_CXX03);
2753 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2754 FromTU, functionDecl(hasOverloadedOperatorName("<")));
2755 auto *ImportedD = Import(FromD, Lang_CXX03);
2756 EXPECT_TRUE(ImportedD);
2759 struct ImportFriendFunctions : ImportFunctions {};
2761 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2762 auto Pattern = functionDecl(hasName("f"));
2764 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2765 "void f();",
2766 Lang_CXX03, "input0.cc");
2767 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2769 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2770 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2771 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2772 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2773 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2774 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2775 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2778 TEST_P(ImportFriendFunctions,
2779 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2780 auto Pattern = functionDecl(hasName("f"));
2782 Decl *FromTU = getTuDecl("void f();"
2783 "struct X { friend void f(); };",
2784 Lang_CXX03, "input0.cc");
2785 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2787 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2788 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2789 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2790 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2791 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2792 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2793 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2796 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2797 auto Pattern = functionDecl(hasName("f"));
2799 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2800 "void f();",
2801 Lang_CXX03, "input0.cc");
2802 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2804 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2805 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2806 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2807 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2808 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2809 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2810 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2813 TEST_P(ImportFriendFunctions,
2814 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2815 auto Pattern = functionDecl(hasName("f"));
2817 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2818 "void f(){}",
2819 Lang_CXX03, "input0.cc");
2820 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2822 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2823 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2824 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2825 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2826 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2827 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2828 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2831 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
2832 auto Pattern = functionDecl(hasName("f"));
2834 Decl *FromTU = getTuDecl(
2836 class X;
2837 void f(X *x){}
2838 class X{
2839 friend void f(X *x);
2842 Lang_CXX03, "input0.cc");
2843 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2845 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2846 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2847 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2848 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2849 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2850 .match(ToTU, friendDecl())
2851 ->getFriendDecl());
2852 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2853 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2854 // The parameters must refer the same type
2855 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2856 (*ImportedD->param_begin())->getOriginalType());
2859 TEST_P(ImportFriendFunctions,
2860 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2861 auto Pattern = functionDecl(hasName("f"));
2863 Decl *FromTU = getTuDecl(
2865 class X;
2866 void f(X *x){}
2867 class X{
2868 friend void f(X *x);
2871 Lang_CXX03, "input0.cc");
2872 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2874 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2875 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2876 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2877 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2878 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2879 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2881 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2882 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2883 // The parameters must refer the same type
2884 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2885 (*ImportedD->param_begin())->getOriginalType());
2888 TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2889 auto Pattern = functionDecl(hasName("f"));
2891 FunctionDecl *ImportedD;
2893 Decl *FromTU =
2894 getTuDecl("struct X { friend void f(){} };", Lang_CXX03, "input0.cc");
2895 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2896 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2898 FunctionDecl *ImportedD1;
2900 Decl *FromTU = getTuDecl("void f();", Lang_CXX03, "input1.cc");
2901 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2902 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2905 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2906 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2907 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2908 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2909 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2912 TEST_P(ImportFriendFunctions, Lookup) {
2913 auto FunctionPattern = functionDecl(hasName("f"));
2914 auto ClassPattern = cxxRecordDecl(hasName("X"));
2916 TranslationUnitDecl *FromTU =
2917 getTuDecl("struct X { friend void f(); };", Lang_CXX03, "input0.cc");
2918 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2919 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2920 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2922 auto FromName = FromD->getDeclName();
2923 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2924 auto LookupRes = Class->noload_lookup(FromName);
2925 ASSERT_TRUE(LookupRes.empty());
2926 LookupRes = FromTU->noload_lookup(FromName);
2927 ASSERT_TRUE(LookupRes.isSingleResult());
2930 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2931 auto ToName = ToD->getDeclName();
2933 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2934 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2935 auto LookupRes = Class->noload_lookup(ToName);
2936 EXPECT_TRUE(LookupRes.empty());
2937 LookupRes = ToTU->noload_lookup(ToName);
2938 EXPECT_TRUE(LookupRes.isSingleResult());
2940 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2941 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2942 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2943 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2946 TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
2947 auto FunctionPattern = functionDecl(hasName("f"));
2948 auto ClassPattern = cxxRecordDecl(hasName("X"));
2950 TranslationUnitDecl *FromTU =
2951 getTuDecl("struct X { friend void f(); };"
2952 // This proto decl makes f available to normal
2953 // lookup, otherwise it is hidden.
2954 // Normal C++ lookup (implemented in
2955 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2956 // returns the found `NamedDecl` only if the set IDNS is matched
2957 "void f();",
2958 Lang_CXX03, "input0.cc");
2959 auto *FromFriend =
2960 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2961 auto *FromNormal =
2962 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2963 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2964 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2965 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2966 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2968 auto FromName = FromFriend->getDeclName();
2969 auto *FromClass =
2970 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2971 auto LookupRes = FromClass->noload_lookup(FromName);
2972 ASSERT_TRUE(LookupRes.empty());
2973 LookupRes = FromTU->noload_lookup(FromName);
2974 ASSERT_TRUE(LookupRes.isSingleResult());
2976 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX03));
2977 auto ToName = ToFriend->getDeclName();
2979 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2980 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2981 LookupRes = ToClass->noload_lookup(ToName);
2982 EXPECT_TRUE(LookupRes.empty());
2983 LookupRes = ToTU->noload_lookup(ToName);
2984 // Test is disabled because this result is 2.
2985 EXPECT_TRUE(LookupRes.isSingleResult());
2987 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2988 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2989 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2990 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2991 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2992 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2993 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2996 TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2997 auto FunctionPattern = functionDecl(hasName("f"));
2998 auto ClassPattern = cxxRecordDecl(hasName("X"));
3000 TranslationUnitDecl *FromTU = getTuDecl("void f();"
3001 "struct X { friend void f(); };",
3002 Lang_CXX03, "input0.cc");
3003 auto *FromNormal =
3004 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
3005 auto *FromFriend =
3006 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
3007 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3008 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3009 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3010 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3012 auto FromName = FromNormal->getDeclName();
3013 auto *FromClass =
3014 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
3015 auto LookupRes = FromClass->noload_lookup(FromName);
3016 ASSERT_TRUE(LookupRes.empty());
3017 LookupRes = FromTU->noload_lookup(FromName);
3018 ASSERT_TRUE(LookupRes.isSingleResult());
3020 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX03));
3021 auto ToName = ToNormal->getDeclName();
3022 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3024 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
3025 LookupRes = ToClass->noload_lookup(ToName);
3026 EXPECT_TRUE(LookupRes.empty());
3027 LookupRes = ToTU->noload_lookup(ToName);
3028 EXPECT_TRUE(LookupRes.isSingleResult());
3030 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
3031 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3032 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3033 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3034 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3035 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3036 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3039 TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
3040 auto Pattern = functionDecl(hasName("f"));
3042 TranslationUnitDecl *FromNormalTU =
3043 getTuDecl("void f();", Lang_CXX03, "input0.cc");
3044 auto *FromNormalF =
3045 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
3046 TranslationUnitDecl *FromFriendTU =
3047 getTuDecl("class X { friend void f(); };", Lang_CXX03, "input1.cc");
3048 auto *FromFriendF =
3049 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
3050 auto FromNormalName = FromNormalF->getDeclName();
3051 auto FromFriendName = FromFriendF->getDeclName();
3053 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3054 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3055 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3056 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3057 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
3058 ASSERT_TRUE(LookupRes.isSingleResult());
3059 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
3060 ASSERT_TRUE(LookupRes.isSingleResult());
3062 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX03));
3063 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3064 auto ToName = ToNormalF->getDeclName();
3065 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3066 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3067 LookupRes = ToTU->noload_lookup(ToName);
3068 EXPECT_TRUE(LookupRes.isSingleResult());
3069 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
3071 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX03));
3072 LookupRes = ToTU->noload_lookup(ToName);
3073 EXPECT_TRUE(LookupRes.isSingleResult());
3074 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3076 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3077 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3079 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3080 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3083 TEST_P(ImportFriendFunctions, ImportFriendList) {
3084 TranslationUnitDecl *FromTU = getTuDecl("struct X { friend void f(); };"
3085 "void f();",
3086 Lang_CXX03, "input0.cc");
3087 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
3088 FromTU, functionDecl(hasName("f")));
3090 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3091 FromTU, cxxRecordDecl(hasName("X")));
3092 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
3093 auto FromFriends = FromClass->friends();
3094 unsigned int FrN = 0;
3095 for (auto Fr : FromFriends) {
3096 ASSERT_EQ(Fr, FromFriend);
3097 ++FrN;
3099 ASSERT_EQ(FrN, 1u);
3101 Import(FromFriendF, Lang_CXX03);
3102 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3103 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3104 ToTU, cxxRecordDecl(hasName("X")));
3105 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
3106 auto ToFriends = ToClass->friends();
3107 FrN = 0;
3108 for (auto Fr : ToFriends) {
3109 EXPECT_EQ(Fr, ToFriend);
3110 ++FrN;
3112 EXPECT_EQ(FrN, 1u);
3115 AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
3116 InnerMatcher) {
3117 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
3118 return InnerMatcher.matches(*Typedef, Finder, Builder);
3119 return false;
3122 TEST_P(ImportDecl, ImportEnumSequential) {
3123 CodeFiles Samples{{"main.c",
3124 {"void foo();"
3125 "void moo();"
3126 "int main() { foo(); moo(); }",
3127 Lang_C99}},
3129 {"foo.c",
3130 {"typedef enum { THING_VALUE } thing_t;"
3131 "void conflict(thing_t type);"
3132 "void foo() { (void)THING_VALUE; }"
3133 "void conflict(thing_t type) {}",
3134 Lang_C99}},
3136 {"moo.c",
3137 {"typedef enum { THING_VALUE } thing_t;"
3138 "void conflict(thing_t type);"
3139 "void moo() { conflict(THING_VALUE); }",
3140 Lang_C99}}};
3142 auto VerificationMatcher =
3143 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
3144 hasTypedefForAnonDecl(hasName("thing_t")));
3146 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
3147 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
3149 testImportSequence(
3150 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
3151 // Just check that there is only one enum decl in the result AST.
3152 "main.c", enumDecl(), VerificationMatcher);
3154 // For different import order, result should be the same.
3155 testImportSequence(
3156 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
3157 // Check that there is only one enum decl in the result AST.
3158 "main.c", enumDecl(), VerificationMatcher);
3161 TEST_P(ImportDecl, ImportFieldOrder) {
3162 MatchVerifier<Decl> Verifier;
3163 testImport("struct declToImport {"
3164 " int b = a + 2;"
3165 " int a = 5;"
3166 "};",
3167 Lang_CXX11, "", Lang_CXX11, Verifier,
3168 recordDecl(hasFieldOrder({"b", "a"})));
3171 TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
3172 MatchVerifier<Decl> Verifier;
3173 testImport("template <typename T> struct S { static T foo; };"
3174 "template <typename T> void declToImport() {"
3175 " (void) S<T>::foo;"
3177 "void instantiate() { declToImport<int>(); }"
3178 "template <typename T> T S<T>::foo;",
3179 Lang_CXX11, "", Lang_CXX11, Verifier,
3180 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3181 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3183 testImport("template <typename T> struct S {"
3184 "template<typename S> static void foo(){};"
3185 "};"
3186 "template <typename T> void declToImport() {"
3187 " S<T>::template foo<T>();"
3189 "void instantiate() { declToImport<int>(); }",
3190 Lang_CXX11, "", Lang_CXX11, Verifier,
3191 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3192 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3195 TEST_P(ImportExpr, DependentNameType) {
3196 MatchVerifier<Decl> Verifier;
3197 testImport("template <typename T> struct declToImport {"
3198 " typedef typename T::type dependent_name;"
3199 "};",
3200 Lang_CXX11, "", Lang_CXX11, Verifier,
3201 classTemplateDecl(has(
3202 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3205 TEST_P(ImportExpr, UnresolvedMemberExpr) {
3206 MatchVerifier<Decl> Verifier;
3207 testImport("struct S { template <typename T> void mem(); };"
3208 "template <typename U> void declToImport() {"
3209 " S s;"
3210 " s.mem<U>();"
3212 "void instantiate() { declToImport<int>(); }",
3213 Lang_CXX11, "", Lang_CXX11, Verifier,
3214 functionTemplateDecl(has(functionDecl(has(
3215 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3218 class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
3219 public:
3220 static constexpr auto DefaultCode = R"(
3221 struct A { int x; };
3222 void f() {
3223 A a;
3224 A a1(a);
3225 A a2(A{});
3226 a = a1;
3227 a = A{};
3228 a.~A();
3229 })";
3231 template <typename MatcherType>
3232 void testImportOf(
3233 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3234 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3237 template <typename MatcherType>
3238 void testNoImportOf(
3239 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3240 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3243 private:
3244 template <typename MatcherType>
3245 void test(const MatcherType &MethodMatcher,
3246 const char *Code, unsigned int ExpectedCount) {
3247 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3249 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3250 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3251 ToTU, ClassMatcher);
3253 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
3256 CXXMethodDecl *Method =
3257 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3258 ToClass->removeDecl(Method);
3259 SharedStatePtr->getLookupTable()->remove(Method);
3262 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
3264 Decl *ImportedClass = nullptr;
3266 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3267 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3268 FromTU, ClassMatcher);
3269 ImportedClass = Import(FromClass, Lang_CXX11);
3272 EXPECT_EQ(ToClass, ImportedClass);
3273 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3274 ExpectedCount);
3278 TEST_P(ImportImplicitMethods, DefaultConstructor) {
3279 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3282 TEST_P(ImportImplicitMethods, CopyConstructor) {
3283 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3286 TEST_P(ImportImplicitMethods, MoveConstructor) {
3287 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3290 TEST_P(ImportImplicitMethods, Destructor) {
3291 testImportOf(cxxDestructorDecl());
3294 TEST_P(ImportImplicitMethods, CopyAssignment) {
3295 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3298 TEST_P(ImportImplicitMethods, MoveAssignment) {
3299 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3302 TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3303 auto Code = R"(
3304 struct A { A() { int x; } };
3306 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3309 TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3310 auto Code = R"(
3311 struct A { A() = default; };
3313 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3316 TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3317 auto Code = R"(
3318 struct A { A() = delete; };
3320 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3323 TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3324 auto Code = R"(
3325 struct A { void f() { } };
3327 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3330 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
3331 Decl *ToR1;
3333 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input0.cc");
3334 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3335 FromTU, cxxRecordDecl(hasName("A")));
3337 ToR1 = Import(FromR, Lang_CXX03);
3340 Decl *ToR2;
3342 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input1.cc");
3343 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3344 FromTU, cxxRecordDecl(hasName("A")));
3346 ToR2 = Import(FromR, Lang_CXX03);
3349 EXPECT_EQ(ToR1, ToR2);
3352 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
3353 Decl *ToR1;
3355 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
3356 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3357 FromTU, cxxRecordDecl(hasName("A")));
3358 ToR1 = Import(FromR, Lang_CXX03);
3360 Decl *ToR2;
3362 Decl *FromTU =
3363 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");
3364 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3365 FromTU, cxxRecordDecl(hasName("A")));
3366 ToR2 = Import(FromR, Lang_CXX03);
3368 EXPECT_NE(ToR1, ToR2);
3371 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
3372 Decl *ToF1;
3374 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
3375 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3376 FromTU, fieldDecl(hasName("x")));
3377 ToF1 = Import(FromF, Lang_CXX03);
3379 Decl *ToF2;
3381 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input1.cc");
3382 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3383 FromTU, fieldDecl(hasName("x")));
3384 ToF2 = Import(FromF, Lang_CXX03);
3386 EXPECT_EQ(ToF1, ToF2);
3389 TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) {
3390 Decl *FromTU = getTuDecl("struct A { unsigned x : 3; };", Lang_CXX03);
3391 auto *FromF =
3392 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("x")));
3394 ASSERT_TRUE(FromF->isBitField());
3395 ASSERT_EQ(3u, FromF->getBitWidthValue(FromTU->getASTContext()));
3396 auto *ToField = Import(FromF, Lang_CXX03);
3397 auto *ToTU = ToField->getTranslationUnitDecl();
3399 EXPECT_TRUE(ToField->isBitField());
3400 EXPECT_EQ(3u, ToField->getBitWidthValue(ToTU->getASTContext()));
3402 const auto *FromBT = FromF->getBitWidth()->getType()->getAs<BuiltinType>();
3403 const auto *ToBT = ToField->getBitWidth()->getType()->getAs<BuiltinType>();
3404 ASSERT_TRUE(FromBT);
3405 ASSERT_EQ(BuiltinType::Int, FromBT->getKind());
3406 EXPECT_TRUE(ToBT);
3407 EXPECT_EQ(BuiltinType::Int, ToBT->getKind());
3410 struct ImportBlock : ASTImporterOptionSpecificTestBase {};
3411 TEST_P(ImportBlock, ImportBlocksAreUnsupported) {
3412 const auto *Code = R"(
3413 void test_block__capture_null() {
3414 int *p = 0;
3415 ^(){
3416 *p = 1;
3417 }();
3418 })";
3419 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
3420 auto *FromBlock = FirstDeclMatcher<BlockDecl>().match(FromTU, blockDecl());
3421 ASSERT_TRUE(FromBlock);
3423 auto ToBlockOrError = importOrError(FromBlock, Lang_CXX03);
3425 const auto ExpectUnsupportedConstructError = [](const ASTImportError &Error) {
3426 EXPECT_EQ(ASTImportError::UnsupportedConstruct, Error.Error);
3428 llvm::handleAllErrors(ToBlockOrError.takeError(),
3429 ExpectUnsupportedConstructError);
3432 TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl) {
3433 const auto *Code = R"(
3434 template <typename T> struct Wrapper {
3435 Wrapper(T Value = {}) {}
3437 template class Wrapper<int>;
3439 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3440 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(
3441 FromTU, parmVarDecl(hasType(asString("int"))));
3442 ASSERT_TRUE(FromVar);
3443 ASSERT_TRUE(FromVar->hasUninstantiatedDefaultArg());
3444 ASSERT_TRUE(FromVar->getUninstantiatedDefaultArg());
3446 const auto *ToVar = Import(FromVar, Lang_CXX11);
3447 EXPECT_TRUE(ToVar);
3448 EXPECT_TRUE(ToVar->hasUninstantiatedDefaultArg());
3449 EXPECT_TRUE(ToVar->getUninstantiatedDefaultArg());
3450 EXPECT_NE(FromVar->getUninstantiatedDefaultArg(),
3451 ToVar->getUninstantiatedDefaultArg());
3454 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
3455 Decl *ToF1;
3457 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");
3458 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3459 FromTU, fieldDecl(hasName("x")));
3460 ToF1 = Import(FromF, Lang_CXX03);
3462 Decl *ToF2;
3464 Decl *FromTU =
3465 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");
3466 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3467 FromTU, fieldDecl(hasName("x")));
3468 ToF2 = Import(FromF, Lang_CXX03);
3470 EXPECT_NE(ToF1, ToF2);
3473 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
3474 Decl *ToM1;
3476 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3477 Lang_CXX03, "input0.cc");
3478 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3479 FromTU, functionDecl(hasName("x"), isDefinition()));
3480 ToM1 = Import(FromM, Lang_CXX03);
3482 Decl *ToM2;
3484 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3485 Lang_CXX03, "input1.cc");
3486 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3487 FromTU, functionDecl(hasName("x"), isDefinition()));
3488 ToM2 = Import(FromM, Lang_CXX03);
3490 EXPECT_EQ(ToM1, ToM2);
3493 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
3494 Decl *ToM1;
3496 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",
3497 Lang_CXX03, "input0.cc");
3498 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3499 FromTU, functionDecl(hasName("x"), isDefinition()));
3500 ToM1 = Import(FromM, Lang_CXX03);
3502 Decl *ToM2;
3504 Decl *FromTU =
3505 getTuDecl("struct A { void x() const; }; void A::x() const { }",
3506 Lang_CXX03, "input1.cc");
3507 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3508 FromTU, functionDecl(hasName("x"), isDefinition()));
3509 ToM2 = Import(FromM, Lang_CXX03);
3511 EXPECT_NE(ToM1, ToM2);
3514 TEST_P(ASTImporterOptionSpecificTestBase,
3515 ImportUnnamedStructsWithRecursingField) {
3516 Decl *FromTU = getTuDecl(
3518 struct A {
3519 struct {
3520 struct A *next;
3521 } entry0;
3522 struct {
3523 struct A *next;
3524 } entry1;
3527 Lang_C99, "input0.cc");
3528 auto *From =
3529 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3531 Import(From, Lang_C99);
3533 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3534 auto *Entry0 =
3535 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3536 auto *Entry1 =
3537 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3538 auto *R0 = getRecordDecl(Entry0);
3539 auto *R1 = getRecordDecl(Entry1);
3540 EXPECT_NE(R0, R1);
3541 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3542 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3543 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3544 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3547 TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
3548 Decl *FromTU = getTuDecl(
3550 void f(int X, int Y, bool Z) {
3551 (void)[X, Y, Z] { (void)Z; };
3554 Lang_CXX11, "input0.cc");
3555 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3556 FromTU, functionDecl(hasName("f")));
3557 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3558 EXPECT_TRUE(ToF);
3560 CXXRecordDecl *FromLambda =
3561 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3562 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3564 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3565 EXPECT_TRUE(ToLambda);
3567 // Check if the fields of the lambda class are imported in correct order.
3568 unsigned FromIndex = 0u;
3569 for (auto *FromField : FromLambda->fields()) {
3570 ASSERT_FALSE(FromField->getDeclName());
3571 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3572 EXPECT_TRUE(ToField);
3573 std::optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3574 EXPECT_TRUE(ToIndex);
3575 EXPECT_EQ(*ToIndex, FromIndex);
3576 ++FromIndex;
3579 EXPECT_EQ(FromIndex, 3u);
3582 TEST_P(ASTImporterOptionSpecificTestBase,
3583 MergeFieldDeclsOfClassTemplateSpecialization) {
3584 std::string ClassTemplate =
3586 template <typename T>
3587 struct X {
3588 int a{0}; // FieldDecl with InitListExpr
3589 X(char) : a(3) {} // (1)
3590 X(int) {} // (2)
3593 Decl *ToTU = getToTuDecl(ClassTemplate +
3595 void foo() {
3596 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3597 X<char> xc('c');
3599 )", Lang_CXX11);
3600 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3601 ToTU, classTemplateSpecializationDecl(hasName("X")));
3602 // FieldDecl without InitlistExpr:
3603 auto *ToField = *ToSpec->field_begin();
3604 ASSERT_TRUE(ToField);
3605 ASSERT_FALSE(ToField->getInClassInitializer());
3606 Decl *FromTU = getTuDecl(ClassTemplate +
3608 void bar() {
3609 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3610 X<char> xc(1);
3612 )", Lang_CXX11);
3613 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3614 FromTU, classTemplateSpecializationDecl(hasName("X")));
3615 // FieldDecl with InitlistExpr:
3616 auto *FromField = *FromSpec->field_begin();
3617 ASSERT_TRUE(FromField);
3618 ASSERT_TRUE(FromField->getInClassInitializer());
3620 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3621 ASSERT_TRUE(ImportedSpec);
3622 EXPECT_EQ(ImportedSpec, ToSpec);
3623 // After the import, the FieldDecl has to be merged, thus it should have the
3624 // InitListExpr.
3625 EXPECT_TRUE(ToField->getInClassInitializer());
3628 TEST_P(ASTImporterOptionSpecificTestBase,
3629 MergeFunctionOfClassTemplateSpecialization) {
3630 std::string ClassTemplate =
3632 template <typename T>
3633 struct X {
3634 void f() {}
3635 void g() {}
3638 Decl *ToTU = getToTuDecl(ClassTemplate +
3640 void foo() {
3641 X<char> x;
3642 x.f();
3644 )", Lang_CXX11);
3645 Decl *FromTU = getTuDecl(ClassTemplate +
3647 void bar() {
3648 X<char> x;
3649 x.g();
3651 )", Lang_CXX11);
3652 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3653 FromTU, classTemplateSpecializationDecl(hasName("X")));
3654 auto FunPattern = functionDecl(hasName("g"),
3655 hasParent(classTemplateSpecializationDecl()));
3656 auto *FromFun =
3657 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3658 auto *ToFun =
3659 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3660 ASSERT_TRUE(FromFun->hasBody());
3661 ASSERT_FALSE(ToFun->hasBody());
3662 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3663 ASSERT_TRUE(ImportedSpec);
3664 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3665 ToTU, classTemplateSpecializationDecl(hasName("X")));
3666 EXPECT_EQ(ImportedSpec, ToSpec);
3667 EXPECT_TRUE(ToFun->hasBody());
3670 TEST_P(ASTImporterOptionSpecificTestBase, MergeTemplateSpecWithForwardDecl) {
3671 std::string ClassTemplate =
3673 template<typename T>
3674 struct X { int m; };
3675 template<>
3676 struct X<int> { int m; };
3678 // Append a forward decl for our template specialization.
3679 getToTuDecl(ClassTemplate + "template<> struct X<int>;", Lang_CXX11);
3680 Decl *FromTU = getTuDecl(ClassTemplate, Lang_CXX11);
3681 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3682 FromTU, classTemplateSpecializationDecl(hasName("X"), isDefinition()));
3683 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3684 // Check that our definition got merged with the existing definition.
3685 EXPECT_TRUE(FromSpec->isThisDeclarationADefinition());
3686 EXPECT_TRUE(ImportedSpec->isThisDeclarationADefinition());
3689 TEST_P(ASTImporterOptionSpecificTestBase,
3690 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3691 std::string ClassTemplate =
3693 template <typename T>
3694 struct X {};
3696 Decl *ToTU = getToTuDecl(ClassTemplate +
3698 template <>
3699 struct X<char> {
3700 int a;
3702 void foo() {
3703 X<char> x;
3706 Lang_CXX11);
3707 Decl *FromTU = getTuDecl(ClassTemplate +
3709 template <>
3710 struct X<char> {
3711 int b;
3713 void foo() {
3714 X<char> x;
3717 Lang_CXX11);
3718 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3719 FromTU, classTemplateSpecializationDecl(hasName("X")));
3720 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3722 // We expect one (ODR) warning during the import.
3723 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3725 // The second specialization is different from the first, thus it violates
3726 // ODR, consequently we expect to keep the first specialization only, which is
3727 // already in the "To" context.
3728 EXPECT_FALSE(ImportedSpec);
3729 EXPECT_EQ(1u,
3730 DeclCounter<ClassTemplateSpecializationDecl>().match(
3731 ToTU, classTemplateSpecializationDecl(hasName("X"))));
3734 TEST_P(ASTImporterOptionSpecificTestBase,
3735 MergeCtorOfClassTemplateSpecialization) {
3736 std::string ClassTemplate =
3738 template <typename T>
3739 struct X {
3740 X(char) {}
3741 X(int) {}
3744 Decl *ToTU = getToTuDecl(ClassTemplate +
3746 void foo() {
3747 X<char> x('c');
3749 )", Lang_CXX11);
3750 Decl *FromTU = getTuDecl(ClassTemplate +
3752 void bar() {
3753 X<char> x(1);
3755 )", Lang_CXX11);
3756 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3757 FromTU, classTemplateSpecializationDecl(hasName("X")));
3758 // Match the void(int) ctor.
3759 auto CtorPattern =
3760 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3761 hasParent(classTemplateSpecializationDecl()));
3762 auto *FromCtor =
3763 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3764 auto *ToCtor =
3765 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3766 ASSERT_TRUE(FromCtor->hasBody());
3767 ASSERT_FALSE(ToCtor->hasBody());
3768 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3769 ASSERT_TRUE(ImportedSpec);
3770 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3771 ToTU, classTemplateSpecializationDecl(hasName("X")));
3772 EXPECT_EQ(ImportedSpec, ToSpec);
3773 EXPECT_TRUE(ToCtor->hasBody());
3776 TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateFriendDecl) {
3777 const auto *Code =
3779 template <class T> class X { friend T; };
3780 struct Y {};
3781 template class X<Y>;
3783 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3784 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3785 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3786 FromTU, classTemplateSpecializationDecl());
3787 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3788 ToTU, classTemplateSpecializationDecl());
3790 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3791 EXPECT_EQ(ImportedSpec, ToSpec);
3792 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3793 ToTU, classTemplateSpecializationDecl()));
3796 TEST_P(ASTImporterOptionSpecificTestBase,
3797 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3798 auto Code =
3800 // primary template
3801 template<class T1, class T2, int I>
3802 class A {};
3804 // partial specialization
3805 template<class T, int I>
3806 class A<T, T*, I> {};
3808 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3809 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3810 auto *FromSpec =
3811 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3812 FromTU, classTemplatePartialSpecializationDecl());
3813 auto *ToSpec =
3814 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3815 ToTU, classTemplatePartialSpecializationDecl());
3817 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3818 EXPECT_EQ(ImportedSpec, ToSpec);
3819 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3820 ToTU, classTemplatePartialSpecializationDecl()));
3823 TEST_P(ASTImporterOptionSpecificTestBase,
3824 ClassTemplateSpecializationsShouldNotBeDuplicated) {
3825 auto Code =
3827 // primary template
3828 template<class T1, class T2, int I>
3829 class A {};
3831 // full specialization
3832 template<>
3833 class A<int, int, 1> {};
3835 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3836 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3837 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3838 FromTU, classTemplateSpecializationDecl());
3839 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3840 ToTU, classTemplateSpecializationDecl());
3842 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3843 EXPECT_EQ(ImportedSpec, ToSpec);
3844 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3845 ToTU, classTemplateSpecializationDecl()));
3848 TEST_P(ASTImporterOptionSpecificTestBase,
3849 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3850 std::string PrimaryTemplate =
3852 template<class T1, class T2, int I>
3853 class A {};
3855 auto PartialSpec =
3857 template<class T, int I>
3858 class A<T, T*, I> {};
3860 auto FullSpec =
3862 template<>
3863 class A<int, int, 1> {};
3865 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3866 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3867 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3868 FromTU, classTemplateSpecializationDecl());
3870 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3871 EXPECT_TRUE(ImportedSpec);
3872 // Check the number of partial specializations.
3873 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3874 ToTU, classTemplatePartialSpecializationDecl()));
3875 // Check the number of full specializations.
3876 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3877 ToTU, classTemplateSpecializationDecl(
3878 unless(classTemplatePartialSpecializationDecl()))));
3881 TEST_P(ASTImporterOptionSpecificTestBase,
3882 InitListExprValueKindShouldBeImported) {
3883 Decl *TU = getTuDecl(
3885 const int &init();
3886 void foo() { const int &a{init()}; }
3887 )", Lang_CXX11, "input0.cc");
3888 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3889 ASSERT_TRUE(FromD->getAnyInitializer());
3890 auto *InitExpr = FromD->getAnyInitializer();
3891 ASSERT_TRUE(InitExpr);
3892 ASSERT_TRUE(InitExpr->isGLValue());
3894 auto *ToD = Import(FromD, Lang_CXX11);
3895 EXPECT_TRUE(ToD);
3896 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3897 EXPECT_TRUE(ToInitExpr);
3898 EXPECT_TRUE(ToInitExpr->isGLValue());
3901 struct ImportVariables : ASTImporterOptionSpecificTestBase {};
3903 TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3904 Decl *FromTU = getTuDecl(
3906 struct A {
3907 static const int a = 1 + 2;
3909 const int A::a;
3911 Lang_CXX03, "input1.cc");
3913 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3914 FromTU, varDecl(hasName("a"))); // Decl with init
3915 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3916 FromTU, varDecl(hasName("a"))); // Decl with definition
3917 ASSERT_NE(FromDWithInit, FromDWithDef);
3918 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3920 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3921 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3922 ASSERT_TRUE(ToD0);
3923 ASSERT_TRUE(ToD1);
3924 EXPECT_NE(ToD0, ToD1);
3925 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3928 TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3929 auto StructA =
3931 struct A {
3932 static const int a = 1 + 2;
3935 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);
3936 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX03,
3937 "input1.cc");
3939 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3940 FromTU, varDecl(hasName("a"))); // Decl with init
3941 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3942 FromTU, varDecl(hasName("a"))); // Decl with definition
3943 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3944 ASSERT_TRUE(FromDWithInit->getInit());
3945 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3946 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3947 ASSERT_FALSE(FromDWithDef->getInit());
3949 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3950 ToTU, varDecl(hasName("a"))); // Decl with init
3951 ASSERT_TRUE(ToD->getInit());
3952 ASSERT_FALSE(ToD->getDefinition());
3954 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3955 EXPECT_TRUE(ImportedD->getAnyInitializer());
3956 EXPECT_TRUE(ImportedD->getDefinition());
3959 TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3960 auto StructA =
3962 struct A {
3963 static const int a;
3966 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);
3967 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3968 Lang_CXX03, "input1.cc");
3970 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3971 FromTU, varDecl(hasName("a")));
3972 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3973 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3974 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3975 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3976 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3977 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3978 ASSERT_TRUE(FromDWithDef->getInit());
3980 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3981 ToTU, varDecl(hasName("a")));
3982 ASSERT_FALSE(ToD->getInit());
3983 ASSERT_FALSE(ToD->getDefinition());
3985 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3986 EXPECT_TRUE(ImportedD->getAnyInitializer());
3987 EXPECT_TRUE(ImportedD->getDefinition());
3990 TEST_P(ImportVariables, ImportBindingDecl) {
3991 Decl *From, *To;
3992 std::tie(From, To) = getImportedDecl(
3994 void declToImport() {
3995 int a[2] = {1,2};
3996 auto [x1,y1] = a;
3997 auto& [x2,y2] = a;
3999 struct S {
4000 mutable int x1 : 2;
4001 volatile double y1;
4003 S b;
4004 const auto [x3, y3] = b;
4007 Lang_CXX17, "", Lang_CXX17);
4009 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();
4010 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
4011 FromTU, functionDecl(hasName("declToImport")));
4012 auto *ToF = Import(FromF, Lang_CXX17);
4013 EXPECT_TRUE(ToF);
4015 auto VerifyImport = [&](llvm::StringRef BindName) {
4016 auto *FromB = FirstDeclMatcher<BindingDecl>().match(
4017 FromF, bindingDecl(hasName(BindName)));
4018 ASSERT_TRUE(FromB);
4019 auto *ToB = Import(FromB, Lang_CXX17);
4020 EXPECT_TRUE(ToB);
4021 EXPECT_EQ(FromB->getBinding() != nullptr, ToB->getBinding() != nullptr);
4022 EXPECT_EQ(FromB->getDecomposedDecl() != nullptr,
4023 ToB->getDecomposedDecl() != nullptr);
4024 EXPECT_EQ(FromB->getHoldingVar() != nullptr,
4025 ToB->getHoldingVar() != nullptr);
4028 VerifyImport("x1");
4029 VerifyImport("y1");
4030 VerifyImport("x2");
4031 VerifyImport("y2");
4032 VerifyImport("x3");
4033 VerifyImport("y3");
4036 TEST_P(ImportVariables, ImportDecompositionDeclArray) {
4037 Decl *From, *To;
4038 std::tie(From, To) = getImportedDecl(
4040 void declToImport() {
4041 int a[2] = {1,2};
4042 auto [x1,y1] = a;
4045 Lang_CXX17, "", Lang_CXX17);
4047 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();
4048 auto *FromDecomp =
4049 FirstDeclMatcher<DecompositionDecl>().match(FromTU, decompositionDecl());
4050 auto *ToDecomp = Import(FromDecomp, Lang_CXX17);
4051 EXPECT_TRUE(ToDecomp);
4053 ArrayRef<BindingDecl *> FromB = FromDecomp->bindings();
4054 ArrayRef<BindingDecl *> ToB = ToDecomp->bindings();
4055 EXPECT_EQ(FromB.size(), ToB.size());
4056 for (unsigned int I = 0; I < FromB.size(); ++I) {
4057 auto *ToBI = Import(FromB[I], Lang_CXX17);
4058 EXPECT_EQ(ToBI, ToB[I]);
4062 struct ImportClasses : ASTImporterOptionSpecificTestBase {};
4064 TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
4065 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C99);
4066 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");
4067 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
4068 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
4069 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
4071 Decl *ImportedDef = Import(FromDef, Lang_C99);
4073 EXPECT_NE(ImportedDef, ToProto);
4074 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4075 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
4076 EXPECT_TRUE(ImportedDef == ToDef);
4077 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4078 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4079 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4082 TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
4083 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX03);
4084 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX03, "input1.cc");
4085 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
4086 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
4087 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
4089 Decl *ImportedDef = Import(FromDef, Lang_CXX03);
4091 EXPECT_NE(ImportedDef, ToProto);
4092 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4093 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
4094 EXPECT_TRUE(ImportedDef == ToDef);
4095 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4096 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4097 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4100 TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
4101 Decl *FromTU0 =
4102 getTuDecl("struct A { struct X *Xp; };", Lang_C99, "input0.cc");
4103 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");
4104 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
4105 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
4106 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
4108 Decl *ImportedProto = Import(FromProto, Lang_C99);
4109 Decl *ImportedDef = Import(FromDef, Lang_C99);
4110 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4112 EXPECT_NE(ImportedDef, ImportedProto);
4113 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4114 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
4115 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
4116 EXPECT_TRUE(ImportedDef == ToDef);
4117 EXPECT_TRUE(ImportedProto == ToProto);
4118 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4119 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4120 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4123 struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {
4124 void testRecursiveFriendClassTemplate(Decl *FromTu) {
4125 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4126 FromTu, classTemplateDecl());
4128 auto Pattern = classTemplateDecl(
4129 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4130 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4132 auto *FromFriend =
4133 FirstDeclMatcher<FriendDecl>().match(FromD, friendDecl());
4134 auto *FromRecordOfFriend =
4135 cast<ClassTemplateDecl>(FromFriend->getFriendDecl())
4136 ->getTemplatedDecl();
4137 EXPECT_NE(FromRecordOfFriend, FromD->getTemplatedDecl());
4138 EXPECT_TRUE(FromRecordOfFriend->getPreviousDecl() == nullptr);
4140 auto *FromDC = FromRecordOfFriend->getDeclContext();
4141 auto *FromLexicalDC = FromRecordOfFriend->getLexicalDeclContext();
4142 ASSERT_EQ(FromDC, cast<DeclContext>(FromTu));
4143 ASSERT_EQ(FromLexicalDC, cast<DeclContext>(FromD->getTemplatedDecl()));
4145 ASSERT_FALSE(FromDC->containsDecl(FromRecordOfFriend));
4146 ASSERT_FALSE(FromLexicalDC->containsDecl(FromRecordOfFriend));
4147 ASSERT_FALSE(cast<RecordDecl>(FromRecordOfFriend)
4148 ->getLookupParent()
4149 ->lookup(FromRecordOfFriend->getDeclName())
4150 .empty());
4152 auto *ToD = Import(FromD, Lang_CXX03);
4153 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4155 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4156 auto *ToRecordOfFriend =
4157 cast<ClassTemplateDecl>(ToFriend->getFriendDecl())->getTemplatedDecl();
4159 EXPECT_NE(ToRecordOfFriend, ToD->getTemplatedDecl());
4160 EXPECT_TRUE(ToRecordOfFriend->getPreviousDecl() == nullptr);
4162 auto *ToDC = ToRecordOfFriend->getDeclContext();
4163 auto *ToLexicalDC = ToRecordOfFriend->getLexicalDeclContext();
4164 ASSERT_EQ(ToDC, cast<DeclContext>(ToD->getTranslationUnitDecl()));
4165 ASSERT_EQ(ToLexicalDC, cast<DeclContext>(ToD->getTemplatedDecl()));
4167 ASSERT_FALSE(ToDC->containsDecl(ToRecordOfFriend));
4168 ASSERT_FALSE(ToLexicalDC->containsDecl(ToRecordOfFriend));
4169 ASSERT_FALSE(cast<RecordDecl>(ToRecordOfFriend)
4170 ->getLookupParent()
4171 ->lookup(ToRecordOfFriend->getDeclName())
4172 .empty());
4175 void testRepeatedFriendImport(const char *Code) {
4176 Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
4177 Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
4179 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
4180 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
4181 auto *FromFriend1 =
4182 FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
4183 auto *FromFriend2 =
4184 LastDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
4186 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
4187 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
4189 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
4190 EXPECT_EQ(ToFriend1, ToImportedFriend1);
4191 EXPECT_EQ(ToFriend2, ToImportedFriend2);
4195 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4196 Decl *FromTU = getTuDecl(
4198 class A {
4199 template <int I> class F {};
4200 class X {
4201 template <int I> friend class F;
4205 Lang_CXX03, "input0.cc");
4207 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4208 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4209 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4210 FromTU, cxxRecordDecl(hasName("F")));
4212 ASSERT_TRUE(FromClass);
4213 ASSERT_TRUE(FromFriendClass);
4214 ASSERT_NE(FromClass, FromFriendClass);
4215 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4216 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4217 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4218 FromClass->getDescribedClassTemplate());
4220 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX03));
4221 auto *ToFriendClass =
4222 cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX03));
4224 EXPECT_TRUE(ToClass);
4225 EXPECT_TRUE(ToFriendClass);
4226 EXPECT_NE(ToClass, ToFriendClass);
4227 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4228 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4229 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4230 ToClass->getDescribedClassTemplate());
4233 TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4234 Decl *FromTu = getTuDecl(
4236 class declToImport {
4237 friend class declToImport;
4240 Lang_CXX03, "input.cc");
4242 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4243 FromTu, cxxRecordDecl(hasName("declToImport")));
4244 auto *ToD = Import(FromD, Lang_CXX03);
4245 auto Pattern = cxxRecordDecl(has(friendDecl()));
4246 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4247 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4250 TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
4251 Decl *FromTu =
4252 getTuDecl("class X { friend class Y; };", Lang_CXX03, "from.cc");
4253 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4254 FromTu, cxxRecordDecl(hasName("X")));
4255 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
4256 RecordDecl *FromRecordOfFriend =
4257 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));
4259 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
4260 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
4261 cast<DeclContext>(FromX));
4262 ASSERT_FALSE(
4263 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
4264 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
4265 FromRecordOfFriend));
4266 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
4267 ->lookup(FromRecordOfFriend->getDeclName())
4268 .empty());
4270 auto *ToX = Import(FromX, Lang_CXX03);
4271 ASSERT_TRUE(ToX);
4273 Decl *ToTu = ToX->getTranslationUnitDecl();
4274 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
4275 RecordDecl *ToRecordOfFriend =
4276 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));
4278 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
4279 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
4280 EXPECT_FALSE(
4281 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
4282 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
4283 ToRecordOfFriend));
4284 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
4285 ->lookup(ToRecordOfFriend->getDeclName())
4286 .empty());
4289 TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4290 Decl *FromTu = getTuDecl(
4292 template<class A> class declToImport {
4293 template<class A1> friend class declToImport;
4296 Lang_CXX03, "input.cc");
4298 testRecursiveFriendClassTemplate(FromTu);
4301 TEST_P(ImportFriendClasses,
4302 ImportOfRecursiveFriendClassTemplateWithNonTypeParm) {
4303 Decl *FromTu = getTuDecl(
4305 template<class A1, A1 A> class declToImport {
4306 template<class B1, B1> friend class declToImport;
4309 Lang_CXX03, "input.cc");
4310 testRecursiveFriendClassTemplate(FromTu);
4313 TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4314 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4316 ClassTemplateSpecializationDecl *Imported1;
4318 Decl *FromTU = getTuDecl("template<class T> class X;"
4319 "struct Y { friend class X<int>; };",
4320 Lang_CXX03, "input0.cc");
4321 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4322 FromTU, Pattern);
4324 Imported1 =
4325 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
4327 ClassTemplateSpecializationDecl *Imported2;
4329 Decl *FromTU = getTuDecl("template<class T> class X;"
4330 "template<> class X<int>{};"
4331 "struct Z { friend class X<int>; };",
4332 Lang_CXX03, "input1.cc");
4333 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4334 FromTU, Pattern);
4336 Imported2 =
4337 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
4340 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4341 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4342 2u);
4343 ASSERT_TRUE(Imported2->getPreviousDecl());
4344 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4347 TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4348 Decl *FromTU0 = getTuDecl(
4350 class X {
4351 class Y;
4353 class X::Y {
4354 template <typename T>
4355 friend class F; // The decl context of F is the global namespace.
4358 Lang_CXX03, "input0.cc");
4359 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4360 FromTU0, classTemplateDecl(hasName("F")));
4361 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
4362 Decl *FromTU1 = getTuDecl(
4364 template <typename T>
4365 class F {};
4367 Lang_CXX03, "input1.cc");
4368 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4369 FromTU1, classTemplateDecl(hasName("F")));
4370 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
4371 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4372 Imported1->getTemplatedDecl()->getTypeForDecl());
4375 TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4376 Decl *From, *To;
4377 std::tie(From, To) =
4378 getImportedDecl("class declToImport {};", Lang_CXX03,
4379 "class Y { friend class declToImport; };", Lang_CXX03);
4380 auto *Imported = cast<CXXRecordDecl>(To);
4382 EXPECT_TRUE(Imported->getPreviousDecl());
4385 TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) {
4386 Decl *ToTU = getToTuDecl(
4388 template <class T, T U>
4389 class A;
4391 template <class T, T U>
4392 class A {
4393 public:
4394 template <class P, P Q>
4395 friend class A;
4397 A(T x) :x(x) {}
4399 private:
4400 T x;
4403 Lang_CXX11);
4405 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4406 ToTU,
4407 classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A")))));
4408 Decl *FromTU = getTuDecl(
4410 template <class T, T U>
4411 class A;
4413 template <class T, T U>
4414 class A {
4415 public:
4416 template <class P, P Q>
4417 friend class A;
4419 A(T x) : x(x) {}
4421 private:
4422 T x;
4425 A<int,3> a1(0);
4427 Lang_CXX11, "input1.cc");
4428 auto *FromA = FirstDeclMatcher<ClassTemplateDecl>().match(
4429 FromTU,
4430 classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A")))));
4431 auto *ToA = Import(FromA, Lang_CXX11);
4432 EXPECT_TRUE(ToA);
4433 EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(),
4434 ToA->getTemplatedDecl()->getTypeForDecl());
4437 TEST_P(ImportFriendClasses,
4438 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4439 Decl *ToTU = getToTuDecl(
4441 class X {
4442 class Y;
4444 class X::Y {
4445 template <typename T>
4446 friend class F; // The decl context of F is the global namespace.
4449 Lang_CXX03);
4450 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4451 ToTU, classTemplateDecl(hasName("F")));
4452 Decl *FromTU = getTuDecl(
4454 template <typename T>
4455 class F {};
4457 Lang_CXX03, "input0.cc");
4458 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4459 FromTU, classTemplateDecl(hasName("F")));
4460 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
4461 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4462 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4463 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4464 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4467 TEST_P(ImportFriendClasses,
4468 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4469 Decl *FromTU0 = getTuDecl(
4471 class X {
4472 class Y;
4474 class X::Y {
4475 template <typename T>
4476 friend class F; // The decl context of F is the global namespace.
4479 Lang_CXX03, "input0.cc");
4480 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4481 FromTU0, classTemplateDecl(hasName("F")));
4482 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
4483 Decl *FromTU1 = getTuDecl(
4485 template <typename T>
4486 class F {};
4488 Lang_CXX03, "input1.cc");
4489 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4490 FromTU1, classTemplateDecl(hasName("F")));
4491 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
4492 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4493 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4494 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4495 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4498 TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4499 Decl *FromTU0 = getTuDecl(
4501 class X {
4502 class Y;
4504 class X::Y {
4505 friend class F; // The decl context of F is the global namespace.
4508 Lang_CXX03, "input0.cc");
4509 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4510 QualType FT = Friend->getFriendType()->getType();
4511 FT = FromTU0->getASTContext().getCanonicalType(FT);
4512 auto *Fwd = cast<TagType>(FT)->getDecl();
4513 auto *ImportedFwd = Import(Fwd, Lang_CXX03);
4514 Decl *FromTU1 = getTuDecl(
4516 class F {};
4518 Lang_CXX03, "input1.cc");
4519 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4520 FromTU1, cxxRecordDecl(hasName("F")));
4521 auto *ImportedDef = Import(Definition, Lang_CXX03);
4522 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4523 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4526 TEST_P(ImportFriendClasses,
4527 ImportFriendTemplatesInDependentContext_DefToFriend) {
4528 Decl *ToTU = getToTuDecl(
4530 template<class T1>
4531 struct X {
4532 template<class T2>
4533 friend struct Y;
4536 Lang_CXX03);
4537 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4538 ToTU, classTemplateDecl(hasName("Y")));
4539 Decl *FromTU = getTuDecl(
4541 template<class T1>
4542 struct Y {};
4544 Lang_CXX03, "input0.cc");
4545 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4546 FromTU, classTemplateDecl(hasName("Y")));
4547 auto *ImportedYDef = Import(FromYDef, Lang_CXX03);
4548 EXPECT_TRUE(ImportedYDef);
4549 EXPECT_FALSE(ImportedYDef->getPreviousDecl());
4550 EXPECT_NE(ImportedYDef, ToYFriend);
4553 TEST_P(ImportFriendClasses,
4554 ImportFriendTemplatesInDependentContext_DefToFriend_NE) {
4555 getToTuDecl(
4557 template<class T1>
4558 struct X {
4559 template<class T2>
4560 friend struct Y;
4563 Lang_CXX03);
4564 Decl *FromTU = getTuDecl(
4566 template<class T1, class T2>
4567 struct Y {};
4569 Lang_CXX03, "input0.cc");
4570 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4571 FromTU, classTemplateDecl(hasName("Y")));
4572 auto *ImportedYDef = Import(FromYDef, Lang_CXX03);
4573 EXPECT_FALSE(ImportedYDef);
4576 TEST_P(ImportFriendClasses,
4577 ImportFriendTemplatesInDependentContext_FriendToFriend) {
4578 Decl *ToTU = getToTuDecl(
4580 template<class T1>
4581 struct X {
4582 template<class T2>
4583 friend struct Y;
4586 Lang_CXX03);
4587 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4588 ToTU, classTemplateDecl(hasName("Y")));
4589 Decl *FromTU = getTuDecl(
4591 template<class T1>
4592 struct X {
4593 template<class T2>
4594 friend struct Y;
4597 Lang_CXX03, "input0.cc");
4598 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4599 FromTU, classTemplateDecl(hasName("Y")));
4600 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4601 EXPECT_TRUE(ImportedYFriend);
4602 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());
4603 EXPECT_NE(ImportedYFriend, ToYFriend);
4606 TEST_P(ImportFriendClasses,
4607 ImportFriendTemplatesInDependentContext_FriendToFriend_NE) {
4608 getToTuDecl(
4610 template<class T1>
4611 struct X {
4612 template<class T2>
4613 friend struct Y;
4616 Lang_CXX03);
4617 Decl *FromTU = getTuDecl(
4619 template<class T1>
4620 struct X {
4621 template<class T2, class T3>
4622 friend struct Y;
4625 Lang_CXX03, "input0.cc");
4626 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4627 FromTU, classTemplateDecl(hasName("Y")));
4628 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4629 EXPECT_FALSE(ImportedYFriend);
4632 TEST_P(ImportFriendClasses,
4633 ImportFriendTemplatesInDependentContext_FriendToDef) {
4634 Decl *ToTU = getToTuDecl(
4636 template<class T1>
4637 struct Y {};
4639 Lang_CXX03);
4640 auto *ToYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4641 ToTU, classTemplateDecl(hasName("Y")));
4642 Decl *FromTU = getTuDecl(
4644 template<class T1>
4645 struct X {
4646 template<class T2>
4647 friend struct Y;
4650 Lang_CXX03, "input0.cc");
4651 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4652 FromTU, classTemplateDecl(hasName("Y")));
4653 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4654 EXPECT_TRUE(ImportedYFriend);
4655 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());
4656 EXPECT_NE(ImportedYFriend, ToYDef);
4659 TEST_P(ImportFriendClasses,
4660 ImportFriendTemplatesInDependentContext_FriendToDef_NE) {
4661 getToTuDecl(
4663 template<class T1>
4664 struct Y {};
4666 Lang_CXX03);
4667 Decl *FromTU = getTuDecl(
4669 template<class T1>
4670 struct X {
4671 template<class T2, class T3>
4672 friend struct Y;
4675 Lang_CXX03, "input0.cc");
4676 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4677 FromTU, classTemplateDecl(hasName("Y")));
4678 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4679 EXPECT_FALSE(ImportedYFriend);
4682 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) {
4683 const char *Code =
4685 class Container {
4686 friend class X;
4687 friend class X;
4690 testRepeatedFriendImport(Code);
4693 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
4694 const char *Code =
4696 class Container {
4697 friend void f();
4698 friend void f();
4701 testRepeatedFriendImport(Code);
4704 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
4705 const char *Code =
4707 template <class T>
4708 class Container {
4709 template <class U> friend void m();
4710 template <class U> friend void m();
4713 testRepeatedFriendImport(Code);
4716 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
4717 const char *Code =
4719 template <class T>
4720 class Container {
4721 template <class U> friend class X;
4722 template <class U> friend class X;
4725 testRepeatedFriendImport(Code);
4728 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
4729 auto *Code = R"(
4730 template <class T>
4731 struct X {
4732 friend void foo(){}
4735 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
4736 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4737 ToTU, functionDecl(hasName("foo")));
4739 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");
4740 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4741 FromTU, functionDecl(hasName("foo")));
4742 auto *ImportedFoo = Import(FromFoo, Lang_CXX03);
4743 EXPECT_EQ(ImportedFoo, ToFoo);
4746 struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
4748 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4749 Decl *TU = getTuDecl(
4751 namespace NS {
4753 template <typename T>
4754 struct S {};
4755 template struct S<int>;
4757 inline namespace INS {
4758 template <typename T>
4759 struct S {};
4760 template struct S<int>;
4764 )", Lang_CXX11, "input0.cc");
4765 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4766 TU, namespaceDecl());
4767 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4768 TU, classTemplateSpecializationDecl());
4769 ASSERT_TRUE(NS->containsDecl(Spec));
4771 NS->removeDecl(Spec);
4772 EXPECT_FALSE(NS->containsDecl(Spec));
4775 TEST_P(DeclContextTest,
4776 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4777 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX03);
4778 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4779 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4781 // Investigate the list.
4782 auto *DC = A0->getDeclContext();
4783 ASSERT_TRUE(DC->containsDecl(A0));
4784 ASSERT_TRUE(DC->containsDecl(A1));
4786 // Investigate the lookup table.
4787 auto *Map = DC->getLookupPtr();
4788 ASSERT_TRUE(Map);
4789 auto I = Map->find(A0->getDeclName());
4790 ASSERT_NE(I, Map->end());
4791 StoredDeclsList &L = I->second;
4792 // The lookup table contains the most recent decl of A.
4793 ASSERT_NE(L.getAsDecl(), A0);
4794 ASSERT_EQ(L.getAsDecl(), A1);
4796 ASSERT_TRUE(L.getAsDecl());
4797 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4798 // We do not have a list with one element.
4799 L.setHasExternalDecls();
4800 ASSERT_FALSE(L.getAsList());
4801 auto Results = L.getLookupResult();
4802 ASSERT_EQ(1u, std::distance(Results.begin(), Results.end()));
4804 // This asserts in the old implementation.
4805 DC->removeDecl(A0);
4806 EXPECT_FALSE(DC->containsDecl(A0));
4808 // Make sure we do not leave a StoredDeclsList with no entries.
4809 DC->removeDecl(A1);
4810 ASSERT_EQ(Map->find(A1->getDeclName()), Map->end());
4813 struct ImportFunctionTemplateSpecializations
4814 : ASTImporterOptionSpecificTestBase {};
4816 TEST_P(ImportFunctionTemplateSpecializations,
4817 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4819 Decl *FromTU = getTuDecl(
4821 template<class T>
4822 int f() { return 0; }
4823 void foo() { f<int>(); }
4825 Lang_CXX03, "input0.cc");
4827 // Check that the function template instantiation is NOT the child of the TU.
4828 auto Pattern = translationUnitDecl(
4829 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4830 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4832 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4833 FromTU, functionDecl(hasName("foo")));
4834 ASSERT_TRUE(Import(Foo, Lang_CXX03));
4836 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4837 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4840 TEST_P(ImportFunctionTemplateSpecializations,
4841 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4843 Decl *FromTU = getTuDecl(
4845 template<class T>
4846 int f() { return 0; }
4847 template int f<int>();
4849 Lang_CXX03, "input0.cc");
4851 // Check that the function template instantiation is NOT the child of the TU.
4852 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4853 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4854 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4856 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),
4857 Lang_CXX03));
4859 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4860 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4863 TEST_P(ImportFunctionTemplateSpecializations,
4864 TUshouldContainFunctionTemplateSpecialization) {
4866 Decl *FromTU = getTuDecl(
4868 template<class T>
4869 int f() { return 0; }
4870 template <> int f<int>() { return 4; }
4872 Lang_CXX03, "input0.cc");
4874 // Check that the function template specialization is the child of the TU.
4875 auto Specialization =
4876 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4877 auto Pattern = translationUnitDecl(has(Specialization));
4878 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4880 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization),
4881 Lang_CXX03));
4883 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4884 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4887 TEST_P(ImportFunctionTemplateSpecializations,
4888 FunctionTemplateSpecializationRedeclChain) {
4890 Decl *FromTU = getTuDecl(
4892 template<class T>
4893 int f() { return 0; }
4894 template <> int f<int>() { return 4; }
4896 Lang_CXX03, "input0.cc");
4898 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4899 hasParent(translationUnitDecl()));
4900 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4902 auto *TU = FromTU;
4903 auto *SpecD = FromSpecD;
4904 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4905 TU, functionTemplateDecl());
4906 auto *FirstSpecD = *(TemplateD->spec_begin());
4907 ASSERT_EQ(SpecD, FirstSpecD);
4908 ASSERT_TRUE(SpecD->getPreviousDecl());
4909 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4910 ->doesThisDeclarationHaveABody());
4913 ASSERT_TRUE(Import(FromSpecD, Lang_CXX03));
4916 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4917 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4918 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4919 TU, functionTemplateDecl());
4920 auto *FirstSpecD = *(TemplateD->spec_begin());
4921 EXPECT_EQ(SpecD, FirstSpecD);
4922 ASSERT_TRUE(SpecD->getPreviousDecl());
4923 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4924 ->doesThisDeclarationHaveABody());
4928 TEST_P(ImportFunctionTemplateSpecializations,
4929 MatchNumberOfFunctionTemplateSpecializations) {
4931 Decl *FromTU = getTuDecl(
4933 template <typename T> constexpr int f() { return 0; }
4934 template <> constexpr int f<int>() { return 4; }
4935 void foo() {
4936 static_assert(f<char>() == 0, "");
4937 static_assert(f<int>() == 4, "");
4940 Lang_CXX11, "input0.cc");
4941 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4942 FromTU, functionDecl(hasName("foo")));
4944 Import(FromD, Lang_CXX11);
4945 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4946 EXPECT_EQ(
4947 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4948 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4951 TEST_P(ASTImporterOptionSpecificTestBase,
4952 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4954 Decl *FromTU = getTuDecl(
4956 template <typename T>
4957 struct B;
4959 Lang_CXX03, "input0.cc");
4960 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4961 FromTU, classTemplateDecl(hasName("B")));
4963 Import(FromD, Lang_CXX03);
4967 Decl *FromTU = getTuDecl(
4969 template <typename T>
4970 struct B {
4971 void f();
4972 B* b;
4975 Lang_CXX03, "input1.cc");
4976 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4977 FromTU, functionDecl(hasName("f")));
4978 Import(FromD, Lang_CXX03);
4979 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4980 FromTU, classTemplateDecl(hasName("B")));
4981 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
4982 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4984 // We expect no (ODR) warning during the import.
4985 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4986 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4990 TEST_P(ASTImporterOptionSpecificTestBase,
4991 ImportingTypedefShouldImportTheCompleteType) {
4992 // We already have an incomplete underlying type in the "To" context.
4993 auto Code =
4995 template <typename T>
4996 struct S {
4997 void foo();
4999 using U = S<int>;
5001 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
5002 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
5003 typedefNameDecl(hasName("U")));
5004 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
5006 // The "From" context has the same typedef, but the underlying type is
5007 // complete this time.
5008 Decl *FromTU = getTuDecl(std::string(Code) +
5010 void foo(U* u) {
5011 u->foo();
5013 )", Lang_CXX11);
5014 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
5015 typedefNameDecl(hasName("U")));
5016 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
5018 // The imported type should be complete.
5019 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
5020 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
5023 TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
5024 auto Code =
5026 template<class T>
5027 int f() { return 0; }
5028 template <> int f<int>() { return 4; }
5031 Decl *FromTU = getTuDecl(Code, Lang_CXX03);
5032 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
5033 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
5034 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
5036 auto *ToD = Import(FromD, Lang_CXX03);
5037 // The template parameter list should exist.
5038 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
5041 const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
5042 varTemplateDecl;
5044 const internal::VariadicDynCastAllOfMatcher<
5045 Decl, VarTemplatePartialSpecializationDecl>
5046 varTemplatePartialSpecializationDecl;
5048 TEST_P(ASTImporterOptionSpecificTestBase,
5049 FunctionTemplateParameterDeclContext) {
5050 constexpr auto Code =
5052 template<class T>
5053 void f() {};
5056 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
5058 auto *FromD = FirstDeclMatcher<FunctionTemplateDecl>().match(
5059 FromTU, functionTemplateDecl(hasName("f")));
5061 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),
5062 FromD->getTemplatedDecl());
5064 auto *ToD = Import(FromD, Lang_CXX11);
5065 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),
5066 ToD->getTemplatedDecl());
5067 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5068 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));
5071 TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateParameterDeclContext) {
5072 constexpr auto Code =
5074 template<class T1, class T2>
5075 struct S {};
5076 template<class T2>
5077 struct S<int, T2> {};
5080 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
5082 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
5083 FromTU, classTemplateDecl(hasName("S")));
5084 auto *FromDPart =
5085 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
5086 FromTU, classTemplatePartialSpecializationDecl(hasName("S")));
5088 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),
5089 FromD->getTemplatedDecl());
5090 ASSERT_EQ(FromDPart->getTemplateParameters()->getParam(0)->getDeclContext(),
5091 FromDPart);
5093 auto *ToD = Import(FromD, Lang_CXX11);
5094 auto *ToDPart = Import(FromDPart, Lang_CXX11);
5096 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),
5097 ToD->getTemplatedDecl());
5098 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5099 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));
5101 EXPECT_EQ(ToDPart->getTemplateParameters()->getParam(0)->getDeclContext(),
5102 ToDPart);
5103 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5104 ToDPart, ToDPart->getTemplateParameters()->getParam(0)));
5107 TEST_P(ASTImporterOptionSpecificTestBase,
5108 CXXDeductionGuideTemplateParameterDeclContext) {
5109 Decl *FromTU = getTuDecl(
5111 template <typename T> struct A {
5112 A(T);
5114 A a{(int)0};
5116 Lang_CXX17, "input.cc");
5117 // clang-format off
5119 |-ClassTemplateDecl 0x1fe5000 <input.cc:2:7, line:4:7> line:2:36 A
5120 | |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T
5121 | |-CXXRecordDecl 0x1fe4f70 <col:29, line:4:7> line:2:36 struct A definition
5123 |-FunctionTemplateDecl 0x1fe5860 <line:2:7, line:3:12> col:9 implicit <deduction guide for A>
5124 | |-TemplateTypeParmDecl 0x1fe4eb0 <line:2:17, col:26> col:26 referenced typename depth 0 index 0 T
5125 | |-CXXDeductionGuideDecl 0x1fe57a8 <line:3:9, col:12> col:9 implicit <deduction guide for A> 'auto (T) -> A<T>'
5126 | | `-ParmVarDecl 0x1fe56b0 <col:11> col:12 'T'
5127 | `-CXXDeductionGuideDecl 0x20515d8 <col:9, col:12> col:9 implicit used <deduction guide for A> 'auto (int) -> A<int>'
5128 | |-TemplateArgument type 'int'
5129 | | `-BuiltinType 0x20587e0 'int'
5130 | `-ParmVarDecl 0x2051388 <col:11> col:12 'int'
5131 `-FunctionTemplateDecl 0x1fe5a78 <line:2:7, col:36> col:36 implicit <deduction guide for A>
5132 |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T
5133 `-CXXDeductionGuideDecl 0x1fe59c0 <col:36> col:36 implicit <deduction guide for A> 'auto (A<T>) -> A<T>'
5134 `-ParmVarDecl 0x1fe5958 <col:36> col:36 'A<T>'
5136 // clang-format on
5137 auto *FromD1 = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
5138 FromTU, cxxDeductionGuideDecl());
5139 auto *FromD2 = LastDeclMatcher<CXXDeductionGuideDecl>().match(
5140 FromTU, cxxDeductionGuideDecl());
5142 NamedDecl *P1 =
5143 FromD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5145 NamedDecl *P2 =
5146 FromD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5148 DeclContext *DC = P1->getDeclContext();
5150 ASSERT_EQ(P1, P2);
5151 ASSERT_TRUE(DC == FromD1 || DC == FromD2);
5153 auto *ToD1 = Import(FromD1, Lang_CXX17);
5154 auto *ToD2 = Import(FromD2, Lang_CXX17);
5155 ASSERT_TRUE(ToD1 && ToD2);
5157 P1 = ToD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5159 P2 = ToD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5161 DC = P1->getDeclContext();
5163 EXPECT_EQ(P1, P2);
5164 EXPECT_TRUE(DC == ToD1 || DC == ToD2);
5166 ASTImporterLookupTable *Tbl = SharedStatePtr->getLookupTable();
5167 if (Tbl->contains(ToD1, P1)) {
5168 EXPECT_FALSE(Tbl->contains(ToD2, P1));
5169 } else {
5170 EXPECT_TRUE(Tbl->contains(ToD2, P1));
5174 TEST_P(ASTImporterOptionSpecificTestBase, RecordVarTemplateDecl) {
5175 Decl *ToTU = getToTuDecl(
5177 template <class T>
5178 class A {
5179 public:
5180 template <class U>
5181 static constexpr bool X = true;
5184 Lang_CXX14);
5186 auto *ToTUX = FirstDeclMatcher<VarTemplateDecl>().match(
5187 ToTU, varTemplateDecl(hasName("X")));
5188 Decl *FromTU = getTuDecl(
5190 template <class T>
5191 class A {
5192 public:
5193 template <class U>
5194 static constexpr bool X = true;
5197 Lang_CXX14, "input1.cc");
5198 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5199 FromTU, varTemplateDecl(hasName("X")));
5200 auto *ToX = Import(FromX, Lang_CXX11);
5201 EXPECT_TRUE(ToX);
5202 EXPECT_EQ(ToTUX, ToX);
5205 TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {
5206 getToTuDecl(
5208 template <class U>
5209 constexpr int X = 1;
5211 Lang_CXX14);
5213 Decl *FromTU = getTuDecl(
5215 template <class U>
5216 constexpr int X = 2;
5218 Lang_CXX14, "input1.cc");
5219 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5220 FromTU, varTemplateDecl(hasName("X")));
5221 auto *ToX = Import(FromX, Lang_CXX11);
5222 // FIXME: This import should fail.
5223 EXPECT_TRUE(ToX);
5226 TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {
5227 Decl *ToTU = getToTuDecl(
5229 struct A {
5230 template <class U>
5231 static int X;
5234 Lang_CXX14);
5235 auto *ToX = FirstDeclMatcher<VarTemplateDecl>().match(
5236 ToTU, varTemplateDecl(hasName("X")));
5237 ASSERT_FALSE(ToX->isThisDeclarationADefinition());
5239 Decl *FromTU = getTuDecl(
5241 struct A {
5242 template <class U>
5243 static int X;
5245 template <class U>
5246 int A::X = 2;
5248 Lang_CXX14, "input1.cc");
5249 auto *FromXDef = LastDeclMatcher<VarTemplateDecl>().match(
5250 FromTU, varTemplateDecl(hasName("X")));
5251 ASSERT_TRUE(FromXDef->isThisDeclarationADefinition());
5252 auto *ToXDef = Import(FromXDef, Lang_CXX14);
5253 EXPECT_TRUE(ToXDef);
5254 EXPECT_TRUE(ToXDef->isThisDeclarationADefinition());
5255 EXPECT_EQ(ToXDef->getPreviousDecl(), ToX);
5258 TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateSpecializationDeclValue) {
5259 Decl *ToTU = getToTuDecl(
5261 template <class U>
5262 constexpr int X = U::Value;
5263 struct A { static constexpr int Value = 1; };
5264 constexpr int Y = X<A>;
5266 Lang_CXX14);
5268 auto *ToTUX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5269 ToTU, varTemplateSpecializationDecl(hasName("X")));
5270 Decl *FromTU = getTuDecl(
5272 template <class U>
5273 constexpr int X = U::Value;
5274 struct A { static constexpr int Value = 1; };
5275 constexpr int Y = X<A>;
5277 Lang_CXX14, "input1.cc");
5278 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5279 FromTU, varTemplateSpecializationDecl(hasName("X")));
5280 auto *ToX = Import(FromX, Lang_CXX14);
5281 EXPECT_TRUE(ToX);
5282 EXPECT_EQ(ToTUX, ToX);
5285 TEST_P(ASTImporterOptionSpecificTestBase,
5286 VarTemplateSpecializationDeclValueConflict) {
5287 getToTuDecl(
5289 template <class U>
5290 constexpr int X = U::Value;
5291 struct A { static constexpr int Value = 1; };
5292 constexpr int Y = X<A>;
5294 Lang_CXX14);
5296 Decl *FromTU = getTuDecl(
5298 template <class U>
5299 constexpr int X = U::Value;
5300 struct A { static constexpr int Value = 2; };
5301 constexpr int Y = X<A>;
5303 Lang_CXX14, "input1.cc");
5304 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5305 FromTU, varTemplateSpecializationDecl(hasName("X")));
5306 auto *ToX = Import(FromX, Lang_CXX14);
5307 EXPECT_FALSE(ToX);
5310 TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclInlineWithCXX17) {
5311 Decl *FromTU = getTuDecl(
5313 struct S {
5314 template <unsigned> static constexpr bool X = true;
5317 Lang_CXX17, "input1.cc");
5318 Decl *FromTU2 = getTuDecl(
5320 struct S {
5321 template <unsigned> static constexpr bool X = true;
5322 template <typename T> void get() { X<sizeof(T)>; }
5324 template <typename U> U qvariant_cast(const S &v) { return v.get; }
5326 Lang_CXX17, "input2.cc");
5327 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5328 FromTU, varTemplateDecl(hasName("X")));
5329 auto *ToX = Import(FromX, Lang_CXX17);
5330 ASSERT_TRUE(ToX);
5331 auto *FromX2 = FirstDeclMatcher<VarTemplateDecl>().match(
5332 FromTU2, varTemplateDecl(hasName("X")));
5333 auto *ToX2 = Import(FromX2, Lang_CXX17);
5334 EXPECT_TRUE(ToX2);
5335 EXPECT_EQ(ToX, ToX2);
5338 TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {
5339 constexpr auto Code =
5341 template<class T1, class T2>
5342 int X1;
5343 template<class T2>
5344 int X1<int, T2>;
5346 namespace Ns {
5347 template<class T1, class T2>
5348 int X2;
5349 template<class T2>
5350 int X2<int, T2>;
5354 Decl *FromTU = getTuDecl(Code, Lang_CXX14);
5356 auto *FromD1 = FirstDeclMatcher<VarTemplateDecl>().match(
5357 FromTU, varTemplateDecl(hasName("X1")));
5358 auto *FromD1Part =
5359 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(
5360 FromTU, varTemplatePartialSpecializationDecl(hasName("X1")));
5361 auto *FromD2 = FirstDeclMatcher<VarTemplateDecl>().match(
5362 FromTU, varTemplateDecl(hasName("X2")));
5363 auto *FromD2Part =
5364 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(
5365 FromTU, varTemplatePartialSpecializationDecl(hasName("X2")));
5367 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5368 FromD1->getDeclContext());
5369 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5370 FromD2->getDeclContext());
5372 ASSERT_EQ(FromD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5373 FromD1Part->getDeclContext());
5374 // FIXME: VarTemplatePartialSpecializationDecl does not update ("adopt")
5375 // template parameter decl context
5376 // ASSERT_EQ(FromD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5377 // FromD2Part->getDeclContext());
5379 auto *ToD1 = Import(FromD1, Lang_CXX14);
5380 auto *ToD2 = Import(FromD2, Lang_CXX14);
5382 auto *ToD1Part = Import(FromD1Part, Lang_CXX14);
5383 auto *ToD2Part = Import(FromD2Part, Lang_CXX14);
5385 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5386 ToD1->getDeclContext());
5387 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5388 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));
5389 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5390 ToD2->getDeclContext());
5391 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5392 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
5394 EXPECT_EQ(ToD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5395 ToD1Part->getDeclContext());
5396 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5397 ToD1Part->getDeclContext(),
5398 ToD1Part->getTemplateParameters()->getParam(0)));
5399 // EXPECT_EQ(ToD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5400 // ToD2Part->getDeclContext());
5401 // EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5402 // ToD2Part->getDeclContext(),
5403 // ToD2Part->getTemplateParameters()->getParam(0)));
5404 (void)ToD2Part;
5407 TEST_P(ASTImporterOptionSpecificTestBase,
5408 TypeAliasTemplateParameterDeclContext) {
5409 constexpr auto Code =
5411 template<class T1, class T2>
5412 struct S {};
5413 template<class T> using S1 = S<T, int>;
5414 namespace Ns {
5415 template<class T> using S2 = S<T, int>;
5419 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
5421 auto *FromD1 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
5422 FromTU, typeAliasTemplateDecl(hasName("S1")));
5423 auto *FromD2 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
5424 FromTU, typeAliasTemplateDecl(hasName("S2")));
5426 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5427 FromD1->getDeclContext());
5428 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5429 FromD2->getDeclContext());
5431 auto *ToD1 = Import(FromD1, Lang_CXX11);
5432 auto *ToD2 = Import(FromD2, Lang_CXX11);
5434 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5435 ToD1->getDeclContext());
5436 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5437 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));
5438 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5439 ToD2->getDeclContext());
5440 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5441 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
5444 TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmType) {
5445 constexpr auto Code = R"(
5446 template <class A1, class... A2> struct A {
5447 using B = A1(A2...);
5449 template struct A<void, char, float, int, short>;
5451 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input.cpp");
5452 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5453 FromTU, classTemplateSpecializationDecl());
5455 auto testType = [&](ASTContext &Ctx, const char *Name,
5456 std::optional<unsigned> PackIndex) {
5457 const auto *Subst = selectFirst<SubstTemplateTypeParmType>(
5458 "sttp", match(substTemplateTypeParmType(
5459 hasReplacementType(hasCanonicalType(asString(Name))))
5460 .bind("sttp"),
5461 Ctx));
5462 const char *ExpectedTemplateParamName = PackIndex ? "A2" : "A1";
5463 ASSERT_TRUE(Subst);
5464 ASSERT_EQ(Subst->getReplacedParameter()->getIdentifier()->getName(),
5465 ExpectedTemplateParamName);
5466 ASSERT_EQ(Subst->getPackIndex(), PackIndex);
5468 auto tests = [&](ASTContext &Ctx) {
5469 testType(Ctx, "void", std::nullopt);
5470 testType(Ctx, "char", 3);
5471 testType(Ctx, "float", 2);
5472 testType(Ctx, "int", 1);
5473 testType(Ctx, "short", 0);
5476 tests(FromTU->getASTContext());
5478 ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);
5479 tests(ToClass->getASTContext());
5482 const AstTypeMatcher<SubstTemplateTypeParmPackType>
5483 substTemplateTypeParmPackType;
5485 TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmPackType) {
5486 constexpr auto Code = R"(
5487 template<typename ...T> struct D {
5488 template<typename... U> using B = int(int (*...p)(T, U));
5489 template<typename U1, typename U2> D(B<U1, U2>*);
5491 int f(int(int, int), int(int, int));
5493 using asd = D<float, double, float>::B<int, long, int>;
5495 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input.cpp");
5496 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5497 FromTU, classTemplateSpecializationDecl());
5500 ASTContext &FromCtx = FromTU->getASTContext();
5501 const auto *FromSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
5502 "pack", match(substTemplateTypeParmPackType().bind("pack"), FromCtx));
5504 ASSERT_TRUE(FromSubstPack);
5505 ASSERT_EQ(FromSubstPack->getIdentifier()->getName(), "T");
5506 ArrayRef<TemplateArgument> FromArgPack =
5507 FromSubstPack->getArgumentPack().pack_elements();
5508 ASSERT_EQ(FromArgPack.size(), 3u);
5509 ASSERT_EQ(FromArgPack[0].getAsType(), FromCtx.FloatTy);
5510 ASSERT_EQ(FromArgPack[1].getAsType(), FromCtx.DoubleTy);
5511 ASSERT_EQ(FromArgPack[2].getAsType(), FromCtx.FloatTy);
5514 // Let's do the import.
5515 ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);
5516 ASTContext &ToCtx = ToClass->getASTContext();
5518 const auto *ToSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
5519 "pack", match(substTemplateTypeParmPackType().bind("pack"), ToCtx));
5521 // Check if it meets the requirements.
5522 ASSERT_TRUE(ToSubstPack);
5523 ASSERT_EQ(ToSubstPack->getIdentifier()->getName(), "T");
5524 ArrayRef<TemplateArgument> ToArgPack =
5525 ToSubstPack->getArgumentPack().pack_elements();
5526 ASSERT_EQ(ToArgPack.size(), 3u);
5527 ASSERT_EQ(ToArgPack[0].getAsType(), ToCtx.FloatTy);
5528 ASSERT_EQ(ToArgPack[1].getAsType(), ToCtx.DoubleTy);
5529 ASSERT_EQ(ToArgPack[2].getAsType(), ToCtx.FloatTy);
5533 struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
5535 TEST_P(ASTImporterLookupTableTest, OneDecl) {
5536 auto *ToTU = getToTuDecl("int a;", Lang_CXX03);
5537 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
5538 ASTImporterLookupTable LT(*ToTU);
5539 auto Res = LT.lookup(ToTU, D->getDeclName());
5540 ASSERT_EQ(Res.size(), 1u);
5541 EXPECT_EQ(*Res.begin(), D);
5544 static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
5545 for (Decl *D : DC->decls()) {
5546 if (auto *ND = dyn_cast<NamedDecl>(D))
5547 if (ND->getDeclName() == Name)
5548 return ND;
5550 return nullptr;
5553 TEST_P(ASTImporterLookupTableTest,
5554 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
5555 auto *Code = R"(
5556 template <class T>
5557 struct X {
5558 friend void foo(){}
5561 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
5562 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5563 ToTU, classTemplateDecl(hasName("X")));
5564 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5565 ToTU, functionDecl(hasName("foo")));
5566 DeclContext *FooDC = Foo->getDeclContext();
5567 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5568 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5569 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5570 DeclarationName FooName = Foo->getDeclName();
5572 // Cannot find in the LookupTable of its DC (TUDecl)
5573 SmallVector<NamedDecl *, 2> FoundDecls;
5574 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5575 EXPECT_EQ(FoundDecls.size(), 0u);
5577 // Cannot find in the LookupTable of its LexicalDC (X)
5578 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5579 EXPECT_EQ(FoundDecls.size(), 0u);
5581 // Can't find in the list of Decls of the DC.
5582 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5584 // Can't find in the list of Decls of the LexicalDC
5585 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5587 // ASTImporter specific lookup finds it.
5588 ASTImporterLookupTable LT(*ToTU);
5589 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5590 ASSERT_EQ(Res.size(), 1u);
5591 EXPECT_EQ(*Res.begin(), Foo);
5594 TEST_P(ASTImporterLookupTableTest,
5595 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5596 TranslationUnitDecl *ToTU =
5597 getToTuDecl("struct A { struct Foo *p; };", Lang_C99);
5598 auto *Foo =
5599 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
5600 auto *A =
5601 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5602 DeclContext *FooDC = Foo->getDeclContext();
5603 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5604 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5605 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5606 DeclarationName FooName = Foo->getDeclName();
5608 // Cannot find in the LookupTable of its DC (TUDecl).
5609 SmallVector<NamedDecl *, 2> FoundDecls;
5610 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5611 EXPECT_EQ(FoundDecls.size(), 0u);
5613 // Finds via linear search of its LexicalDC (A).
5614 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
5615 EXPECT_EQ(FoundDecls.size(), 1u);
5617 // Can't find in the list of Decls of the DC.
5618 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5620 // Can find in the list of Decls of the LexicalDC.
5621 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5623 // ASTImporter specific lookup finds it.
5624 ASTImporterLookupTable LT(*ToTU);
5625 auto Res = LT.lookup(FooDC, Foo->getDeclName());
5626 ASSERT_EQ(Res.size(), 1u);
5627 EXPECT_EQ(*Res.begin(), Foo);
5630 TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5631 TranslationUnitDecl *ToTU =
5632 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C99);
5633 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5634 .match(ToTU, varDecl(hasName("V")))
5635 ->getDeclName();
5636 auto *A =
5637 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5638 auto *B =
5639 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
5641 ASTImporterLookupTable LT(*ToTU);
5643 auto Res = LT.lookup(cast<DeclContext>(A), VName);
5644 ASSERT_EQ(Res.size(), 1u);
5645 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5646 ToTU, fieldDecl(hasName("V"),
5647 hasParent(recordDecl(hasName("A"))))));
5648 Res = LT.lookup(cast<DeclContext>(B), VName);
5649 ASSERT_EQ(Res.size(), 1u);
5650 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5651 ToTU, fieldDecl(hasName("V"),
5652 hasParent(recordDecl(hasName("B"))))));
5653 Res = LT.lookup(ToTU, VName);
5654 ASSERT_EQ(Res.size(), 1u);
5655 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5656 ToTU, varDecl(hasName("V"),
5657 hasParent(translationUnitDecl()))));
5660 TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5661 TranslationUnitDecl *ToTU = getToTuDecl(
5663 void foo();
5664 void foo(int);
5665 void foo(int, int);
5667 Lang_CXX03);
5669 ASTImporterLookupTable LT(*ToTU);
5670 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5671 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5672 DeclarationName Name = F0->getDeclName();
5673 auto Res = LT.lookup(ToTU, Name);
5674 EXPECT_EQ(Res.size(), 3u);
5675 EXPECT_EQ(Res.count(F0), 1u);
5676 EXPECT_EQ(Res.count(F2), 1u);
5679 TEST_P(ASTImporterLookupTableTest,
5680 DifferentOperatorsShouldHaveDifferentResultSet) {
5681 TranslationUnitDecl *ToTU = getToTuDecl(
5683 struct X{};
5684 void operator+(X, X);
5685 void operator-(X, X);
5687 Lang_CXX03);
5689 ASTImporterLookupTable LT(*ToTU);
5690 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5691 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5692 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5693 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5694 DeclarationName NamePlus = FPlus->getDeclName();
5695 auto ResPlus = LT.lookup(ToTU, NamePlus);
5696 EXPECT_EQ(ResPlus.size(), 1u);
5697 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5698 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5699 DeclarationName NameMinus = FMinus->getDeclName();
5700 auto ResMinus = LT.lookup(ToTU, NameMinus);
5701 EXPECT_EQ(ResMinus.size(), 1u);
5702 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5703 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5704 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5707 TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5708 TranslationUnitDecl *ToTU = getToTuDecl(
5710 struct X {};
5711 void operator+(X, X);
5713 Lang_CXX03);
5714 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5715 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5717 Decl *FromTU = getTuDecl(
5719 struct X {};
5720 void operator+(X, X);
5722 Lang_CXX03);
5723 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5724 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5726 // FromPlus have a different TU, thus its DeclarationName is different too.
5727 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5729 ASTImporterLookupTable LT(*ToTU);
5730 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5731 ASSERT_EQ(Res.size(), 1u);
5732 EXPECT_EQ(*Res.begin(), ToPlus);
5734 // FromPlus have a different TU, thus its DeclarationName is different too.
5735 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5736 ASSERT_EQ(Res.size(), 0u);
5739 TEST_P(ASTImporterLookupTableTest,
5740 LookupFindsFwdFriendClassDeclWithElaboratedType) {
5741 TranslationUnitDecl *ToTU = getToTuDecl(
5743 class Y { friend class F; };
5745 Lang_CXX03);
5747 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5748 // So we must dig up the underlying CXXRecordDecl.
5749 ASTImporterLookupTable LT(*ToTU);
5750 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5751 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5752 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5753 ToTU, cxxRecordDecl(hasName("Y")));
5755 DeclarationName Name = RD->getDeclName();
5756 auto Res = LT.lookup(ToTU, Name);
5757 EXPECT_EQ(Res.size(), 1u);
5758 EXPECT_EQ(*Res.begin(), RD);
5760 Res = LT.lookup(Y, Name);
5761 EXPECT_EQ(Res.size(), 0u);
5764 TEST_P(ASTImporterLookupTableTest,
5765 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
5766 TranslationUnitDecl *ToTU = getToTuDecl(
5768 class F;
5769 class Y { friend F; };
5771 Lang_CXX11);
5773 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5774 // So we must dig up the underlying CXXRecordDecl.
5775 ASTImporterLookupTable LT(*ToTU);
5776 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5777 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5778 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
5780 DeclarationName Name = RD->getDeclName();
5781 auto Res = LT.lookup(ToTU, Name);
5782 EXPECT_EQ(Res.size(), 1u);
5783 EXPECT_EQ(*Res.begin(), RD);
5785 Res = LT.lookup(Y, Name);
5786 EXPECT_EQ(Res.size(), 0u);
5789 TEST_P(ASTImporterLookupTableTest,
5790 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
5791 TranslationUnitDecl *ToTU = getToTuDecl(
5793 class F;
5794 using alias_of_f = F;
5795 class Y { friend alias_of_f; };
5797 Lang_CXX11);
5799 // ASTImporterLookupTable constructor handles using declarations correctly,
5800 // no assert is expected.
5801 ASTImporterLookupTable LT(*ToTU);
5803 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
5804 ToTU, typeAliasDecl(hasName("alias_of_f")));
5805 DeclarationName Name = Alias->getDeclName();
5806 auto Res = LT.lookup(ToTU, Name);
5807 EXPECT_EQ(Res.count(Alias), 1u);
5810 TEST_P(ASTImporterLookupTableTest,
5811 LookupFindsFriendClassDeclWithUsingTypeDoesNotAssert) {
5812 TranslationUnitDecl *ToTU = getToTuDecl(
5814 namespace a {
5815 namespace b { class InnerClass; }
5816 using b::InnerClass;
5818 class B {
5819 friend a::InnerClass;
5822 Lang_CXX11);
5824 // ASTImporterLookupTable constructor handles friend with using-type without
5825 // asserts.
5826 ASTImporterLookupTable LT(*ToTU);
5828 auto *Using = FirstDeclMatcher<UsingDecl>().match(
5829 ToTU, usingDecl(hasName("InnerClass")));
5830 DeclarationName Name = Using->getDeclName();
5831 auto Res = LT.lookup(ToTU, Name);
5832 EXPECT_EQ(Res.size(), 0u);
5833 auto *NsA = FirstDeclMatcher<NamespaceDecl>().match(
5834 ToTU, namespaceDecl(hasName("a")));
5835 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
5836 ToTU, cxxRecordDecl(hasName("B")));
5837 auto Res1 = LT.lookup(NsA, Name);
5838 EXPECT_EQ(Res1.count(Using), 1u);
5839 auto Res2 = LT.lookup(RecordB, Name);
5840 EXPECT_EQ(Res2.size(), 0u);
5843 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5844 TranslationUnitDecl *ToTU = getToTuDecl(
5846 class Y { template <class T> friend class F; };
5848 Lang_CXX03);
5850 ASTImporterLookupTable LT(*ToTU);
5851 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5852 ToTU, classTemplateDecl(hasName("F")));
5853 DeclarationName Name = F->getDeclName();
5854 auto Res = LT.lookup(ToTU, Name);
5855 EXPECT_EQ(Res.size(), 2u);
5856 EXPECT_EQ(Res.count(F), 1u);
5857 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5860 TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5861 TranslationUnitDecl *ToTU = getToTuDecl(
5863 template <typename T>
5864 class F;
5866 template <typename T>
5867 class Y {
5868 friend class F<T>;
5871 Lang_CXX03);
5873 ASTImporterLookupTable LT(*ToTU);
5874 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5875 ToTU, classTemplateDecl(hasName("F")));
5876 DeclarationName Name = F->getDeclName();
5877 auto Res = LT.lookup(ToTU, Name);
5878 EXPECT_EQ(Res.size(), 2u);
5879 EXPECT_EQ(Res.count(F), 1u);
5880 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5883 TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5884 TranslationUnitDecl *ToTU = getToTuDecl(
5886 template <typename T>
5887 class F;
5889 class Y {
5890 friend class F<int>;
5893 Lang_CXX03);
5895 ASTImporterLookupTable LT(*ToTU);
5896 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5897 ToTU, classTemplateDecl(hasName("F")));
5898 DeclarationName Name = F->getDeclName();
5899 auto Res = LT.lookup(ToTU, Name);
5900 ASSERT_EQ(Res.size(), 3u);
5901 EXPECT_EQ(Res.count(F), 1u);
5902 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5903 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5906 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5907 TranslationUnitDecl *ToTU = getToTuDecl(
5909 class Y { friend void F(); };
5911 Lang_CXX03);
5913 ASTImporterLookupTable LT(*ToTU);
5914 auto *F =
5915 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5916 DeclarationName Name = F->getDeclName();
5917 auto Res = LT.lookup(ToTU, Name);
5918 EXPECT_EQ(Res.size(), 1u);
5919 EXPECT_EQ(*Res.begin(), F);
5922 TEST_P(ASTImporterLookupTableTest,
5923 LookupFindsDeclsInClassTemplateSpecialization) {
5924 TranslationUnitDecl *ToTU = getToTuDecl(
5926 template <typename T>
5927 struct X {
5928 int F;
5930 void foo() {
5931 X<char> xc;
5934 Lang_CXX03);
5936 ASTImporterLookupTable LT(*ToTU);
5938 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5939 ToTU, classTemplateDecl(hasName("X")));
5940 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5941 ToTU,
5942 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5944 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5945 ToTU, classTemplateSpecializationDecl(hasName("X")));
5946 FieldDecl *FieldInSpec = *Spec->field_begin();
5947 ASSERT_TRUE(FieldInSpec);
5949 DeclarationName Name = FieldInSpec->getDeclName();
5950 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5952 SmallVector<NamedDecl *, 2> FoundDecls;
5953 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5954 EXPECT_EQ(FoundDecls.size(), 1u);
5955 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5957 auto Res = LT.lookup(TemplateDC, Name);
5958 ASSERT_EQ(Res.size(), 1u);
5959 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5961 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5962 FoundDecls);
5963 EXPECT_EQ(FoundDecls.size(), 1u);
5964 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5966 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5967 ASSERT_EQ(Res.size(), 1u);
5968 EXPECT_EQ(*Res.begin(), FieldInSpec);
5971 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5972 TranslationUnitDecl *ToTU = getToTuDecl(
5974 class Y { template <class T> friend void F(); };
5976 Lang_CXX03);
5978 ASTImporterLookupTable LT(*ToTU);
5979 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5980 ToTU, functionTemplateDecl(hasName("F")));
5981 DeclarationName Name = F->getDeclName();
5982 auto Res = LT.lookup(ToTU, Name);
5983 EXPECT_EQ(Res.size(), 2u);
5984 EXPECT_EQ(Res.count(F), 1u);
5985 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5988 TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5989 TranslationUnitDecl *ToTU = getToTuDecl(
5991 struct X;
5992 struct A {
5993 friend struct X;
5995 struct B {
5996 friend struct X;
5999 Lang_CXX03);
6001 ASTImporterLookupTable LT(*ToTU);
6002 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
6003 ToTU, cxxRecordDecl(hasName("X")));
6004 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
6005 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
6006 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
6007 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
6008 ASSERT_EQ(RD0, RD1);
6009 ASSERT_EQ(RD1, X);
6011 DeclarationName Name = X->getDeclName();
6012 auto Res = LT.lookup(ToTU, Name);
6013 EXPECT_EQ(Res.size(), 1u);
6014 EXPECT_EQ(*Res.begin(), X);
6017 TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
6018 TranslationUnitDecl *ToTU = getToTuDecl(
6020 enum E {
6025 Lang_C99);
6027 ASTImporterLookupTable LT(*ToTU);
6028 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
6029 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
6030 ToTU, enumConstantDecl(hasName("A")));
6032 DeclarationName Name = A->getDeclName();
6033 // Redecl context is the TU.
6034 ASSERT_EQ(E->getRedeclContext(), ToTU);
6036 SmallVector<NamedDecl *, 2> FoundDecls;
6037 // Normal lookup finds in the DC.
6038 E->localUncachedLookup(Name, FoundDecls);
6039 EXPECT_EQ(FoundDecls.size(), 1u);
6041 // Normal lookup finds in the Redecl context.
6042 ToTU->localUncachedLookup(Name, FoundDecls);
6043 EXPECT_EQ(FoundDecls.size(), 1u);
6045 // Import specific lookup finds in the DC.
6046 auto Res = LT.lookup(E, Name);
6047 ASSERT_EQ(Res.size(), 1u);
6048 EXPECT_EQ(*Res.begin(), A);
6050 // Import specific lookup finds in the Redecl context.
6051 Res = LT.lookup(ToTU, Name);
6052 ASSERT_EQ(Res.size(), 1u);
6053 EXPECT_EQ(*Res.begin(), A);
6056 TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
6057 TranslationUnitDecl *ToTU = getToTuDecl(
6059 namespace N {
6060 int A;
6062 namespace N {
6065 Lang_CXX03);
6066 auto *N1 =
6067 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
6068 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
6069 DeclarationName Name = A->getDeclName();
6071 ASTImporterLookupTable LT(*ToTU);
6072 auto Res = LT.lookup(N1, Name);
6073 ASSERT_EQ(Res.size(), 1u);
6074 EXPECT_EQ(*Res.begin(), A);
6077 TEST_P(ASTImporterOptionSpecificTestBase,
6078 RedeclChainShouldBeCorrectAmongstNamespaces) {
6079 Decl *FromTU = getTuDecl(
6081 namespace NS {
6082 struct X;
6083 struct Y {
6084 static const int I = 3;
6087 namespace NS {
6088 struct X { // <--- To be imported
6089 void method(int i = Y::I) {}
6090 int f;
6094 Lang_CXX03);
6095 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
6096 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
6097 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
6098 FromTU,
6099 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
6100 ASSERT_NE(FromFwd, FromDef);
6101 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
6102 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
6103 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
6105 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX03));
6106 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX03));
6107 EXPECT_NE(ToFwd, ToDef);
6108 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
6109 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
6110 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
6111 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6112 // We expect no (ODR) warning during the import.
6113 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
6116 struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
6118 TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
6119 Decl *ToTU = getToTuDecl(
6121 class X {
6122 template <typename T> friend void foo();
6125 Lang_CXX03);
6126 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
6127 ToTU, functionTemplateDecl(hasName("foo")));
6129 Decl *FromTU = getTuDecl(
6131 template <typename T> void foo();
6133 Lang_CXX03);
6134 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
6135 FromTU, functionTemplateDecl(hasName("foo")));
6136 auto *Imported = Import(FromFoo, Lang_CXX03);
6138 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
6141 TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) {
6142 Decl *From, *To;
6143 std::tie(From, To) = getImportedDecl(
6145 template <typename T> struct X {
6146 template <typename U> friend void f();
6149 Lang_CXX03, "", Lang_CXX03, "X");
6151 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(From, friendDecl());
6152 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(To, friendDecl());
6154 EXPECT_TRUE(FromFriend ==
6155 LastDeclMatcher<FriendDecl>().match(From, friendDecl()));
6156 EXPECT_TRUE(ToFriend ==
6157 LastDeclMatcher<FriendDecl>().match(To, friendDecl()));
6159 auto *FromDecl = FromFriend->getFriendDecl();
6160 auto *FromDC = FromFriend->getDeclContext();
6161 auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
6163 EXPECT_TRUE(FromDC->containsDecl(FromFriend));
6164 EXPECT_FALSE(FromDC->containsDecl(FromDecl));
6165 EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
6166 EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
6168 auto *ToDecl = ToFriend->getFriendDecl();
6169 auto *ToDC = ToFriend->getDeclContext();
6170 auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
6172 EXPECT_TRUE(ToDC->containsDecl(ToFriend));
6173 EXPECT_FALSE(ToDC->containsDecl(ToDecl));
6174 EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
6175 EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
6178 struct ASTImporterWithFakeErrors : ASTImporter {
6179 using ASTImporter::ASTImporter;
6180 bool returnWithErrorInTest() override { return true; }
6183 struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
6184 ErrorHandlingTest() {
6185 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6186 ASTContext &FromContext, FileManager &FromFileManager,
6187 bool MinimalImport,
6188 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6189 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
6190 FromContext, FromFileManager,
6191 MinimalImport, SharedState);
6194 // In this test we purposely report an error (UnsupportedConstruct) when
6195 // importing the below stmt.
6196 static constexpr auto* ErroneousStmt = R"( asm(""); )";
6199 // Check a case when no new AST node is created in the AST before encountering
6200 // the error.
6201 TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
6202 TranslationUnitDecl *ToTU = getToTuDecl(
6204 template <typename T>
6205 class X {};
6206 template <>
6207 class X<int> { int a; };
6209 Lang_CXX03);
6210 TranslationUnitDecl *FromTU = getTuDecl(
6212 template <typename T>
6213 class X {};
6214 template <>
6215 class X<int> { double b; };
6217 Lang_CXX03);
6218 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
6219 FromTU, classTemplateSpecializationDecl(hasName("X")));
6220 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX03);
6221 EXPECT_FALSE(ImportedSpec);
6223 // The original Decl is kept, no new decl is created.
6224 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
6225 ToTU, classTemplateSpecializationDecl(hasName("X"))),
6226 1u);
6228 // But an error is set to the counterpart in the "from" context.
6229 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
6230 std::optional<ASTImportError> OptErr =
6231 Importer->getImportDeclErrorIfAny(FromSpec);
6232 ASSERT_TRUE(OptErr);
6233 EXPECT_EQ(OptErr->Error, ASTImportError::NameConflict);
6236 // Check a case when a new AST node is created but not linked to the AST before
6237 // encountering the error.
6238 TEST_P(ErrorHandlingTest,
6239 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
6240 TranslationUnitDecl *FromTU = getTuDecl(
6241 std::string("void foo() { ") + ErroneousStmt + " }", Lang_CXX03);
6242 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
6243 FromTU, functionDecl(hasName("foo")));
6245 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX03);
6246 EXPECT_FALSE(ImportedFoo);
6248 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6249 // Created, but not linked.
6250 EXPECT_EQ(
6251 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
6252 0u);
6254 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
6255 std::optional<ASTImportError> OptErr =
6256 Importer->getImportDeclErrorIfAny(FromFoo);
6257 ASSERT_TRUE(OptErr);
6258 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6261 // Check a case when a new AST node is created and linked to the AST before
6262 // encountering the error. The error is set for the counterpart of the nodes in
6263 // the "from" context.
6264 TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
6265 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
6266 void f();
6267 void f() { )") + ErroneousStmt + R"( }
6269 Lang_CXX03);
6270 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
6271 FromTU, functionDecl(hasName("f")));
6272 auto *FromDef =
6273 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
6274 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX03);
6275 EXPECT_FALSE(ImportedProto); // Could not import.
6276 // However, we created two nodes in the AST. 1) the fwd decl 2) the
6277 // definition. The definition is not added to its DC, but the fwd decl is
6278 // there.
6279 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6280 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
6281 1u);
6282 // Match the fwd decl.
6283 auto *ToProto =
6284 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
6285 EXPECT_TRUE(ToProto);
6286 // An error is set to the counterpart in the "from" context both for the fwd
6287 // decl and the definition.
6288 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
6289 std::optional<ASTImportError> OptErr =
6290 Importer->getImportDeclErrorIfAny(FromProto);
6291 ASSERT_TRUE(OptErr);
6292 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6293 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
6294 ASSERT_TRUE(OptErr);
6295 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6298 // An error should be set for a class if we cannot import one member.
6299 TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
6300 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
6301 class X {
6302 void f() { )") + ErroneousStmt + R"( } // This member has the error
6303 // during import.
6304 void ok(); // The error should not prevent importing this.
6305 }; // An error will be set for X too.
6307 Lang_CXX03);
6308 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6309 FromTU, cxxRecordDecl(hasName("X")));
6310 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
6312 // An error is set for X.
6313 EXPECT_FALSE(ImportedX);
6314 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
6315 std::optional<ASTImportError> OptErr =
6316 Importer->getImportDeclErrorIfAny(FromX);
6317 ASSERT_TRUE(OptErr);
6318 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6320 // An error is set for f().
6321 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
6322 FromTU, cxxMethodDecl(hasName("f")));
6323 OptErr = Importer->getImportDeclErrorIfAny(FromF);
6324 ASSERT_TRUE(OptErr);
6325 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6326 // And any subsequent import should fail.
6327 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX03);
6328 EXPECT_FALSE(ImportedF);
6330 // There is an error set for the other member too.
6331 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
6332 FromTU, cxxMethodDecl(hasName("ok")));
6333 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
6334 EXPECT_TRUE(OptErr);
6335 // Cannot import the other member.
6336 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX03);
6337 EXPECT_FALSE(ImportedOK);
6340 // Check that an error propagates to the dependent AST nodes.
6341 // In the below code it means that an error in X should propagate to A.
6342 // And even to F since the containing A is erroneous.
6343 // And to all AST nodes which we visit during the import process which finally
6344 // ends up in a failure (in the error() function).
6345 TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
6346 Decl *FromTU = getTuDecl(std::string(R"(
6347 namespace NS {
6348 class A {
6349 template <int I> class F {};
6350 class X {
6351 template <int I> friend class F;
6352 void error() { )") +
6353 ErroneousStmt + R"( }
6357 class B {};
6358 } // NS
6360 Lang_CXX03, "input0.cc");
6362 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
6363 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
6364 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
6365 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
6366 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
6367 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
6368 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
6369 FromTU, namespaceDecl(hasName("NS")));
6371 // Start by importing the templated CXXRecordDecl of F.
6372 // Import fails for that.
6373 EXPECT_FALSE(Import(FromFRD, Lang_CXX03));
6374 // Import fails for A.
6375 EXPECT_FALSE(Import(FromA, Lang_CXX03));
6376 // But we should be able to import the independent B.
6377 EXPECT_TRUE(Import(FromB, Lang_CXX03));
6378 // And the namespace.
6379 EXPECT_TRUE(Import(FromNS, Lang_CXX03));
6381 // An error is set to the templated CXXRecordDecl of F.
6382 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
6383 std::optional<ASTImportError> OptErr =
6384 Importer->getImportDeclErrorIfAny(FromFRD);
6385 EXPECT_TRUE(OptErr);
6387 // An error is set to A.
6388 OptErr = Importer->getImportDeclErrorIfAny(FromA);
6389 EXPECT_TRUE(OptErr);
6391 // There is no error set to B.
6392 OptErr = Importer->getImportDeclErrorIfAny(FromB);
6393 EXPECT_FALSE(OptErr);
6395 // There is no error set to NS.
6396 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
6397 EXPECT_FALSE(OptErr);
6399 // Check some of those decls whose ancestor is X, they all should have an
6400 // error set if we visited them during an import process which finally failed.
6401 // These decls are part of a cycle in an ImportPath.
6402 // There would not be any error set for these decls if we hadn't follow the
6403 // ImportPaths and the cycles.
6404 OptErr = Importer->getImportDeclErrorIfAny(
6405 FirstDeclMatcher<ClassTemplateDecl>().match(
6406 FromTU, classTemplateDecl(hasName("F"))));
6407 // An error is set to the 'F' ClassTemplateDecl.
6408 EXPECT_TRUE(OptErr);
6409 // An error is set to the FriendDecl.
6410 OptErr = Importer->getImportDeclErrorIfAny(
6411 FirstDeclMatcher<FriendDecl>().match(
6412 FromTU, friendDecl()));
6413 EXPECT_TRUE(OptErr);
6414 // An error is set to the implicit class of A.
6415 OptErr =
6416 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
6417 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
6418 EXPECT_TRUE(OptErr);
6419 // An error is set to the implicit class of X.
6420 OptErr =
6421 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
6422 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
6423 EXPECT_TRUE(OptErr);
6426 TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
6427 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
6428 namespace X {
6429 void f() { )") + ErroneousStmt + R"( } // This member has the error
6430 // during import.
6431 void ok(); // The error should not prevent importing this.
6432 }; // An error will be set for X too.
6434 Lang_CXX03);
6435 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
6436 FromTU, namespaceDecl(hasName("X")));
6437 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX03);
6439 // There is no error set for X.
6440 EXPECT_TRUE(ImportedX);
6441 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
6442 std::optional<ASTImportError> OptErr =
6443 Importer->getImportDeclErrorIfAny(FromX);
6444 ASSERT_FALSE(OptErr);
6446 // An error is set for f().
6447 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
6448 FromTU, functionDecl(hasName("f")));
6449 OptErr = Importer->getImportDeclErrorIfAny(FromF);
6450 ASSERT_TRUE(OptErr);
6451 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6452 // And any subsequent import should fail.
6453 FunctionDecl *ImportedF = Import(FromF, Lang_CXX03);
6454 EXPECT_FALSE(ImportedF);
6456 // There is no error set for ok().
6457 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
6458 FromTU, functionDecl(hasName("ok")));
6459 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
6460 EXPECT_FALSE(OptErr);
6461 // And we should be able to import.
6462 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX03);
6463 EXPECT_TRUE(ImportedOK);
6466 TEST_P(ErrorHandlingTest, ODRViolationWithinTypedefDecls) {
6467 // Importing `z` should fail - instead of crashing - due to an ODR violation.
6468 // The `bar::e` typedef sets it's DeclContext after the import is done.
6469 // However, if the importation fails, it will be left as a nullptr.
6470 // During the cleanup of the failed import, we should check whether the
6471 // DeclContext is null or not - instead of dereferencing that unconditionally.
6472 constexpr auto ToTUCode = R"(
6473 namespace X {
6474 struct bar {
6475 int odr_violation;
6477 })";
6478 constexpr auto FromTUCode = R"(
6479 namespace X {
6480 enum b {};
6481 struct bar {
6482 typedef b e;
6483 static e d;
6486 int z = X::bar::d;
6488 Decl *ToTU = getToTuDecl(ToTUCode, Lang_CXX11);
6489 static_cast<void>(ToTU);
6490 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);
6491 auto *FromZ =
6492 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("z")));
6493 ASSERT_TRUE(FromZ);
6494 ASSERT_TRUE(FromZ->hasInit());
6496 auto *ImportedZ = Import(FromZ, Lang_CXX11);
6497 EXPECT_FALSE(ImportedZ);
6500 // An error should be set for a class if it had a previous import with an error
6501 // from another TU.
6502 TEST_P(ErrorHandlingTest,
6503 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
6504 // We already have a fwd decl.
6505 TranslationUnitDecl *ToTU = getToTuDecl("class X;", Lang_CXX03);
6506 // Then we import a definition.
6508 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
6509 class X {
6510 void f() { )") + ErroneousStmt + R"( }
6511 void ok();
6514 Lang_CXX03);
6515 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6516 FromTU, cxxRecordDecl(hasName("X")));
6517 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
6519 // An error is set for X ...
6520 EXPECT_FALSE(ImportedX);
6521 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
6522 std::optional<ASTImportError> OptErr =
6523 Importer->getImportDeclErrorIfAny(FromX);
6524 ASSERT_TRUE(OptErr);
6525 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6527 // ... but the node had been created.
6528 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
6529 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
6530 // An error is set for "ToXDef" in the shared state.
6531 std::optional<ASTImportError> OptErr =
6532 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
6533 ASSERT_TRUE(OptErr);
6534 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6536 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
6537 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
6538 // An error is NOT set for the fwd Decl of X in the shared state.
6539 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
6540 ASSERT_FALSE(OptErr);
6542 // Try to import X again but from another TU.
6544 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
6545 class X {
6546 void f() { )") + ErroneousStmt + R"( }
6547 void ok();
6550 Lang_CXX03, "input1.cc");
6552 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6553 FromTU, cxxRecordDecl(hasName("X")));
6554 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
6556 // If we did not save the errors for the "to" context then the below checks
6557 // would fail, because the lookup finds the fwd Decl of the existing
6558 // definition in the "to" context. We can reach the existing definition via
6559 // the found fwd Decl. That existing definition is structurally equivalent
6560 // (we check only the fields) with this one we want to import, so we return
6561 // with the existing definition, which is erroneous (one method is missing).
6563 // The import should fail.
6564 EXPECT_FALSE(ImportedX);
6565 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
6566 std::optional<ASTImportError> OptErr =
6567 Importer->getImportDeclErrorIfAny(FromX);
6568 // And an error is set for this new X in the "from" ctx.
6569 ASSERT_TRUE(OptErr);
6570 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6574 TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
6575 auto MatchFooA =
6576 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));
6577 auto MatchFooB =
6578 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));
6579 auto MatchFooC =
6580 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));
6582 // Provoke import of a method that has overridden methods with import error.
6583 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
6584 struct C;
6585 struct A {
6586 virtual void foo();
6587 void f1(C *);
6589 void A::foo() {
6590 )") + ErroneousStmt + R"(
6592 struct B : public A {
6593 void foo() override;
6595 struct C : public B {
6596 void foo() override;
6599 Lang_CXX11);
6600 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
6601 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
6602 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
6604 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
6605 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();
6606 auto CheckError = [&Importer](Decl *FromD) {
6607 std::optional<ASTImportError> OptErr =
6608 Importer->getImportDeclErrorIfAny(FromD);
6609 ASSERT_TRUE(OptErr);
6610 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6612 CheckError(FromFooA);
6613 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
6614 CheckError(FromFooB);
6615 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
6616 CheckError(FromFooC);
6619 TEST_P(ErrorHandlingTest, ODRViolationWithinParmVarDecls) {
6620 // Importing of 'f' and parameter 'P' should cause an ODR error.
6621 // The error happens after the ParmVarDecl for 'P' was already created.
6622 // This is a special case because the ParmVarDecl has a temporary DeclContext.
6623 // Expected is no crash at error handling of ASTImporter.
6624 constexpr auto ToTUCode = R"(
6625 struct X {
6626 char A;
6629 constexpr auto FromTUCode = R"(
6630 struct X {
6631 enum Y { Z };
6633 void f(int P = X::Z);
6635 Decl *ToTU = getToTuDecl(ToTUCode, Lang_CXX11);
6636 static_cast<void>(ToTU);
6637 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);
6638 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
6639 FromTU, functionDecl(hasName("f")));
6640 ASSERT_TRUE(FromF);
6642 auto *ImportedF = Import(FromF, Lang_CXX11);
6643 EXPECT_FALSE(ImportedF);
6646 TEST_P(ErrorHandlingTest, DoNotInheritErrorFromNonDependentChild) {
6647 // Declarations should not inherit an import error from a child object
6648 // if the declaration has no direct dependence to such a child.
6649 // For example a namespace should not get import error if one of the
6650 // declarations inside it fails to import.
6651 // There was a special case in error handling (when "import path circles" are
6652 // encountered) when this property was not held. This case is provoked by the
6653 // following code.
6654 constexpr auto ToTUCode = R"(
6655 namespace ns {
6656 struct Err {
6657 char A;
6661 constexpr auto FromTUCode = R"(
6662 namespace ns {
6663 struct A {
6664 using U = struct Err;
6667 namespace ns {
6668 struct Err {}; // ODR violation
6669 void f(A) {}
6673 Decl *ToTU = getToTuDecl(ToTUCode, Lang_CXX11);
6674 static_cast<void>(ToTU);
6675 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);
6676 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
6677 FromTU, cxxRecordDecl(hasName("A"), hasDefinition()));
6678 ASSERT_TRUE(FromA);
6679 auto *ImportedA = Import(FromA, Lang_CXX11);
6680 // 'A' can not be imported: ODR error at 'Err'
6681 EXPECT_FALSE(ImportedA);
6682 // When import of 'A' failed there was a "saved import path circle" that
6683 // contained namespace 'ns' (A - U - Err - ns - f - A). This should not mean
6684 // that every object in this path fails to import.
6686 Decl *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
6687 FromTU, namespaceDecl(hasName("ns")));
6688 EXPECT_TRUE(FromNS);
6689 auto *ImportedNS = Import(FromNS, Lang_CXX11);
6690 EXPECT_TRUE(ImportedNS);
6693 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
6694 Decl *FromTU = getTuDecl(
6696 void f() {
6697 auto L = [](){};
6700 Lang_CXX11, "input0.cc");
6701 auto Pattern = lambdaExpr();
6702 CXXRecordDecl *FromL =
6703 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
6705 auto ToL = Import(FromL, Lang_CXX11);
6706 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
6707 unsigned FromLSize =
6708 std::distance(FromL->decls().begin(), FromL->decls().end());
6709 EXPECT_NE(ToLSize, 0u);
6710 EXPECT_EQ(ToLSize, FromLSize);
6711 EXPECT_FALSE(FromL->isDependentLambda());
6714 TEST_P(ASTImporterOptionSpecificTestBase,
6715 ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) {
6716 Decl *From, *To;
6717 std::tie(From, To) = getImportedDecl(
6719 void foo() {
6720 (void) []() {
6721 struct X {};
6722 return X();
6726 Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only
6727 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(To, lambdaExpr());
6728 EXPECT_TRUE(ToLambda);
6731 TEST_P(ASTImporterOptionSpecificTestBase,
6732 ReturnTypeDeclaredInsideOfCXX11LambdaWithTrailingReturn) {
6733 Decl *From, *To;
6734 std::tie(From, To) = getImportedDecl(
6736 void foo() {
6737 (void) [] {
6738 struct X {};
6739 return X();
6743 Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only
6744 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(To, lambdaExpr());
6745 EXPECT_TRUE(ToLambda);
6748 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
6749 Decl *FromTU = getTuDecl(
6751 template <typename F>
6752 void f(F L = [](){}) {}
6754 Lang_CXX11, "input0.cc");
6755 auto Pattern = lambdaExpr();
6756 CXXRecordDecl *FromL =
6757 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
6759 auto ToL = Import(FromL, Lang_CXX11);
6760 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
6761 unsigned FromLSize =
6762 std::distance(FromL->decls().begin(), FromL->decls().end());
6763 EXPECT_NE(ToLSize, 0u);
6764 EXPECT_EQ(ToLSize, FromLSize);
6765 EXPECT_TRUE(FromL->isDependentLambda());
6768 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
6769 Decl *FromTU = getTuDecl(
6771 auto l1 = [](unsigned lp) { return 1; };
6772 auto l2 = [](int lp) { return 2; };
6773 int f(int p) {
6774 return l1(p) + l2(p);
6777 Lang_CXX11, "input0.cc");
6778 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
6779 FromTU, functionDecl(hasName("f")));
6780 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
6781 EXPECT_TRUE(ToF);
6784 TEST_P(ASTImporterOptionSpecificTestBase,
6785 ImportExistingFriendClassTemplateDef) {
6786 auto Code =
6788 template <class T1, class T2>
6789 struct Base {
6790 template <class U1, class U2>
6791 friend struct Class;
6793 template <class T1, class T2>
6794 struct Class { };
6797 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);
6798 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");
6800 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
6801 ToTU, classTemplateDecl(hasName("Class")));
6802 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
6803 ToTU, classTemplateDecl(hasName("Class")));
6804 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
6805 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
6806 // Previous friend decl is not linked to it!
6807 ASSERT_FALSE(ToClassDef->getPreviousDecl());
6808 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
6809 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
6811 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
6812 FromTU, classTemplateDecl(hasName("Class")));
6813 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
6814 FromTU, classTemplateDecl(hasName("Class")));
6815 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
6816 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
6817 ASSERT_FALSE(FromClassDef->getPreviousDecl());
6818 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
6819 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
6821 auto *ImportedDef = Import(FromClassDef, Lang_CXX03);
6822 // At import we should find the definition for 'Class' even if the
6823 // prototype (inside 'friend') for it comes first in the AST and is not
6824 // linked to the definition.
6825 EXPECT_EQ(ImportedDef, ToClassDef);
6828 struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
6829 LLDBLookupTest() {
6830 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6831 ASTContext &FromContext, FileManager &FromFileManager,
6832 bool MinimalImport,
6833 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6834 return new ASTImporter(ToContext, ToFileManager, FromContext,
6835 FromFileManager, MinimalImport,
6836 // We use the regular lookup.
6837 /*SharedState=*/nullptr);
6842 TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
6843 TranslationUnitDecl *ToTU = getToTuDecl(
6845 extern "C" {
6846 class X{};
6849 Lang_CXX03);
6850 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
6851 ToTU, cxxRecordDecl(hasName("X")));
6853 // Set up a stub external storage.
6854 ToTU->setHasExternalLexicalStorage(true);
6855 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
6856 ToTU->setMustBuildLookupTable();
6857 struct TestExternalASTSource : ExternalASTSource {};
6858 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
6860 Decl *FromTU = getTuDecl(
6862 class X;
6864 Lang_CXX03);
6865 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6866 FromTU, cxxRecordDecl(hasName("X")));
6867 auto *ImportedX = Import(FromX, Lang_CXX03);
6868 // The lookup must find the existing class definition in the LinkageSpecDecl.
6869 // Then the importer renders the existing and the new decl into one chain.
6870 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
6873 struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
6875 TEST_P(SVEBuiltins, ImportTypes) {
6876 static const char *const TypeNames[] = {
6877 "__SVInt8_t", "__SVInt16_t", "__SVInt32_t", "__SVInt64_t",
6878 "__SVUint8_t", "__SVUint16_t", "__SVUint32_t", "__SVUint64_t",
6879 "__SVFloat16_t", "__SVBfloat16_t", "__SVFloat32_t", "__SVFloat64_t",
6880 "__SVBool_t"};
6882 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX03);
6883 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cc");
6884 for (auto *TypeName : TypeNames) {
6885 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
6886 ToTU, typedefDecl(hasName(TypeName)));
6887 QualType ToType = ToTypedef->getUnderlyingType();
6889 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
6890 FromTU, typedefDecl(hasName(TypeName)));
6891 QualType FromType = FromTypedef->getUnderlyingType();
6893 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX03);
6894 EXPECT_EQ(ImportedType, ToType);
6898 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
6899 // Test that import of implicit functions works and the functions
6900 // are merged into one chain.
6901 auto GetDeclToImport = [this](StringRef File) {
6902 Decl *FromTU = getTuDecl(
6904 struct X { };
6905 // Force generating some implicit operator definitions for X.
6906 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
6908 Lang_CXX11, File);
6909 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
6910 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
6911 // Destructor is picked as one example of implicit function.
6912 return FromD->getDestructor();
6915 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
6916 ASSERT_TRUE(ToD1);
6918 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
6919 ASSERT_TRUE(ToD2);
6921 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
6924 TEST_P(ASTImporterOptionSpecificTestBase,
6925 ImportOfExplicitlyDefaultedOrDeleted) {
6926 Decl *FromTU = getTuDecl(
6928 struct X { X() = default; X(const X&) = delete; };
6930 Lang_CXX11);
6931 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6932 FromTU, cxxRecordDecl(hasName("X")));
6933 auto *ImportedX = Import(FromX, Lang_CXX11);
6934 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
6935 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
6936 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
6937 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
6939 ASSERT_TRUE(ImportedX);
6940 EXPECT_TRUE(Constr1->isDefaulted());
6941 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
6942 EXPECT_TRUE(Constr2->isDeletedAsWritten());
6943 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
6946 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, SVEBuiltins,
6947 ::testing::Values(std::vector<std::string>{
6948 "-target", "aarch64-linux-gnu"}));
6950 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, DeclContextTest,
6951 ::testing::Values(std::vector<std::string>()));
6953 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CanonicalRedeclChain,
6954 ::testing::Values(std::vector<std::string>()));
6956 TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
6957 Decl *FromTU = getTuDecl(
6959 void f() {
6960 auto L0 = [](){};
6961 auto L1 = [](){};
6964 Lang_CXX11, "input0.cc");
6965 auto Pattern = lambdaExpr();
6966 CXXRecordDecl *FromL0 =
6967 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
6968 CXXRecordDecl *FromL1 =
6969 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
6970 ASSERT_NE(FromL0, FromL1);
6972 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
6973 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
6974 EXPECT_NE(ToL0, ToL1);
6977 TEST_P(ASTImporterOptionSpecificTestBase,
6978 LambdasInFunctionParamsAreDifferentiated) {
6979 Decl *FromTU = getTuDecl(
6981 template <typename F0, typename F1>
6982 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
6984 Lang_CXX11, "input0.cc");
6985 auto Pattern = cxxRecordDecl(isLambda());
6986 CXXRecordDecl *FromL0 =
6987 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
6988 CXXRecordDecl *FromL1 =
6989 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
6990 ASSERT_NE(FromL0, FromL1);
6992 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
6993 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
6994 ASSERT_NE(ToL0, ToL1);
6997 TEST_P(ASTImporterOptionSpecificTestBase,
6998 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
6999 Decl *FromTU = getTuDecl(
7001 #define LAMBDA [](){}
7002 template <typename F0, typename F1>
7003 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
7005 Lang_CXX11, "input0.cc");
7006 auto Pattern = cxxRecordDecl(isLambda());
7007 CXXRecordDecl *FromL0 =
7008 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
7009 CXXRecordDecl *FromL1 =
7010 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
7011 ASSERT_NE(FromL0, FromL1);
7013 Import(FromL0, Lang_CXX11);
7014 Import(FromL1, Lang_CXX11);
7015 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
7016 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
7017 ASSERT_NE(ToL0, ToL1);
7020 TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
7021 Decl *FromTU = getTuDecl(
7023 void f() {
7024 auto x = []{} = {}; auto x2 = x;
7027 Lang_CXX20, "input0.cc");
7028 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
7029 FromTU, functionDecl(hasName("f")));
7030 // We have only one lambda class.
7031 ASSERT_EQ(
7032 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
7033 1u);
7035 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
7036 EXPECT_TRUE(ToF);
7037 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
7038 // We have only one lambda class after the import.
7039 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
7040 1u);
7043 TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
7044 Decl *FromTU = getTuDecl(
7046 void f() {
7047 auto x = []{} = {};
7048 auto xb = []{} = {};
7051 Lang_CXX20, "input0.cc");
7052 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
7053 FromTU, functionDecl(hasName("f")));
7054 // We have two lambda classes.
7055 ASSERT_EQ(
7056 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
7057 2u);
7059 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
7060 EXPECT_TRUE(ToF);
7061 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
7062 // We have two lambda classes after the import.
7063 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
7064 2u);
7067 TEST_P(ASTImporterOptionSpecificTestBase,
7068 ImportFunctionDeclWithTypeSourceInfoWithSourceDecl) {
7069 // This code results in a lambda with implicit constructor.
7070 // The constructor's TypeSourceInfo points out the function prototype.
7071 // This prototype has an EST_Unevaluated in its exception information and a
7072 // SourceDecl that is the function declaration itself.
7073 // The test verifies that AST import of such AST does not crash.
7074 // (Here the function's TypeSourceInfo references the function itself.)
7075 Decl *FromTU = getTuDecl(
7077 template<typename T> void f(T) { auto X = [](){}; }
7078 void g() { f(10); }
7080 Lang_CXX11, "input0.cc");
7082 // Use LastDeclMatcher to find the LambdaExpr in the template specialization.
7083 CXXRecordDecl *FromL = LastDeclMatcher<LambdaExpr>()
7084 .match(FromTU, lambdaExpr())
7085 ->getLambdaClass();
7087 CXXConstructorDecl *FromCtor = *FromL->ctor_begin();
7088 ASSERT_TRUE(FromCtor->isCopyConstructor());
7089 ASSERT_TRUE(FromCtor->getTypeSourceInfo());
7090 const auto *FromFPT = FromCtor->getType()->getAs<FunctionProtoType>();
7091 ASSERT_TRUE(FromFPT);
7092 EXPECT_EQ(FromCtor->getTypeSourceInfo()->getType().getTypePtr(), FromFPT);
7093 FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
7094 // If type is EST_Unevaluated, SourceDecl should be set to the parent Decl.
7095 EXPECT_EQ(FromEPI.ExceptionSpec.Type, EST_Unevaluated);
7096 EXPECT_EQ(FromEPI.ExceptionSpec.SourceDecl, FromCtor);
7098 auto ToL = Import(FromL, Lang_CXX11);
7100 // Check if the import was correct.
7101 CXXConstructorDecl *ToCtor = *ToL->ctor_begin();
7102 EXPECT_TRUE(ToCtor->getTypeSourceInfo());
7103 const auto *ToFPT = ToCtor->getType()->getAs<FunctionProtoType>();
7104 ASSERT_TRUE(ToFPT);
7105 EXPECT_EQ(ToCtor->getTypeSourceInfo()->getType().getTypePtr(), ToFPT);
7106 FunctionProtoType::ExtProtoInfo ToEPI = ToFPT->getExtProtoInfo();
7107 EXPECT_EQ(ToEPI.ExceptionSpec.Type, EST_Unevaluated);
7108 EXPECT_EQ(ToEPI.ExceptionSpec.SourceDecl, ToCtor);
7111 struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {
7112 void testImport(llvm::StringRef Code, clang::TestLanguage Lang = Lang_CXX14,
7113 bool FindLast = false) {
7114 Decl *FromTU = getTuDecl(Code, Lang, "input0.cc");
7115 FunctionDecl *From = FindLast ? LastDeclMatcher<FunctionDecl>().match(
7116 FromTU, functionDecl(hasName("foo")))
7117 : FirstDeclMatcher<FunctionDecl>().match(
7118 FromTU, functionDecl(hasName("foo")));
7120 FunctionDecl *To = Import(From, Lang);
7121 EXPECT_TRUE(To);
7122 // We check here only that the type is auto type.
7123 // These tests are to verify that no crash happens.
7124 // The crash possibility is the presence of a reference to a declaration
7125 // in the function's body from the return type, if the function has auto
7126 // return type.
7127 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
7131 TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate1) {
7132 testImport(
7134 template<class C>
7135 C f1() { return C(); }
7136 auto foo() {
7137 struct B {};
7138 return f1<B>();
7140 )");
7143 TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate2) {
7144 testImport(
7146 template<class T>
7147 int f1(T t) { return 1; }
7148 auto foo() {
7149 struct B {};
7150 return f1(B());
7152 )");
7155 TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate3) {
7156 testImport(
7158 template<class A> struct S1 {};
7159 template<class A> struct S2 {};
7160 template<class C>
7161 S1<C> f1() { return S1<C>(); }
7162 auto foo() {
7163 struct B {};
7164 return f1<S2<B *>>();
7166 )");
7169 TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate4) {
7170 testImport(
7172 template<class... A> struct S1 {};
7173 template<class... A> struct S2 {};
7174 template<class... C>
7175 S1<C...> f1() { return S1<C...>(); }
7176 auto foo() {
7177 struct B {};
7178 return f1<S2<int, B *>, bool>();
7180 )");
7183 TEST_P(ImportAutoFunctions, ReturnWithVarTemplate1) {
7184 testImport(
7186 template<class T> T X;
7187 auto foo() {
7188 struct A {};
7189 return X<A>;
7191 )");
7194 TEST_P(ImportAutoFunctions, ReturnWithVarTemplate2) {
7195 testImport(
7197 template<class A> struct S1 {};
7198 template<class T> S1<T> X;
7199 auto foo() {
7200 struct A {};
7201 return X<S1<A>>;
7203 )");
7206 TEST_P(ImportAutoFunctions, ReturnWithVarTemplate3) {
7207 testImport(
7209 template<class... A> struct S1 {};
7210 template<class... T> S1<T...> X;
7211 auto foo() {
7212 struct A {};
7213 return X<bool, S1<A, int>>;
7215 )");
7218 TEST_P(ImportAutoFunctions, ReturnWithAutoUnresolvedArg) {
7219 testImport(
7221 template<int A>
7222 auto foo() {
7223 return 22;
7225 )");
7228 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTemplateTemplateArg) {
7229 // FIXME: Is it possible to have the template arg inside the function?
7230 testImport(
7232 template<int> struct Tmpl {};
7233 template<template<int> class> struct TmplTmpl {};
7234 auto foo() {
7235 return TmplTmpl<Tmpl>();
7237 )");
7240 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDeclarationTemplateArg) {
7241 // FIXME: Is it possible to have the template arg inside the function?
7242 testImport(
7244 template<const int *> struct Tmpl {};
7245 int A[10];
7246 auto foo() {
7247 return Tmpl<A>();
7249 )");
7252 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithNullPtrTemplateArg) {
7253 testImport(
7255 template<int *> struct Tmpl {};
7256 auto foo() {
7257 constexpr int* A = nullptr;
7258 return Tmpl<A>();
7260 )");
7263 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegralTemplateArg) {
7264 testImport(
7266 template<int> struct Tmpl {};
7267 auto foo() {
7268 using Int = int;
7269 constexpr Int A = 7;
7270 return Tmpl<A>();
7272 )");
7275 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDecltypeTypeDeclaredInside) {
7276 testImport(
7278 template<class> struct Tmpl {};
7279 auto foo() {
7280 struct X {};
7281 X x;
7282 return Tmpl<decltype(x)>();
7284 )");
7287 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithUsingTypeDeclaredInside) {
7288 testImport(
7290 template<class> struct Tmpl {};
7291 namespace A { struct X {}; }
7292 auto foo() {
7293 using A::X;
7294 return Tmpl<X>();
7296 )");
7299 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArrayTypeDeclaredInside) {
7300 testImport(
7302 template<class> struct Tmpl {};
7303 auto foo() {
7304 struct X {};
7305 return Tmpl<X[10]>();
7307 )");
7310 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArraySizeExprDeclaredInside) {
7311 testImport(
7313 template<class> struct Tmpl {};
7314 auto foo() {
7315 constexpr int S = 10;
7316 return Tmpl<int[S]>();
7318 )");
7321 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPackArgDeclaredInside) {
7322 testImport(
7324 template<class ...> struct Tmpl {};
7325 auto foo() {
7326 using X = bool;
7327 return Tmpl<int, X>();
7329 )");
7332 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegerArgDeclaredInside) {
7333 testImport(
7335 template<int> struct Tmpl {};
7336 auto foo() {
7337 constexpr int X = 1;
7338 return Tmpl<X>();
7340 )");
7343 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPtrToStructDeclaredInside) {
7344 testImport(
7346 template<class> struct Tmpl {};
7347 auto foo() {
7348 struct X {};
7349 return Tmpl<X *>();
7351 )");
7354 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithRefToStructDeclaredInside) {
7355 testImport(
7357 template<class> struct Tmpl {};
7358 struct X {};
7359 auto foo() {
7360 using Y = X;
7361 return Tmpl<Y &>();
7363 )");
7366 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) {
7367 testImport(
7369 template<class> struct Tmpl {};
7370 auto foo() {
7371 struct X {};
7372 return Tmpl<X>();
7374 )");
7377 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) {
7378 testImport(
7380 template<class> struct Tmpl {};
7381 auto foo() {
7382 struct X {};
7383 return Tmpl<Tmpl<X>>();
7385 )");
7388 TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) {
7389 testImport(
7391 template<class> struct Tmpl {};
7392 auto foo() {
7393 struct X {};
7394 using x_type = X;
7395 return Tmpl<x_type>();
7397 )");
7400 TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
7401 Decl *FromTU = getTuDecl(
7403 auto X = [](long l) {
7404 using int_type = long;
7405 auto dur = 13;
7406 return static_cast<int_type>(dur);
7409 Lang_CXX14, "input0.cc");
7410 CXXMethodDecl *From =
7411 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, cxxMethodDecl());
7413 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
7414 // Normally the return type would be the built-in 'long' type. However, there
7415 // are cases when Clang does not use the canonical type and the TypeAlias is
7416 // used. I could not create such an AST from regular source code, it requires
7417 // some special state in the preprocessor. I've found such an AST when Clang
7418 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
7419 // that with creduce, because after preprocessing, the AST no longer
7420 // contained the TypeAlias as a return type of the lambda.
7421 ASTContext &Ctx = From->getASTContext();
7422 TypeAliasDecl *FromTA =
7423 FirstDeclMatcher<TypeAliasDecl>().match(FromTU, typeAliasDecl());
7424 QualType TT = Ctx.getTypedefType(FromTA);
7425 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());
7426 QualType NewFunType =
7427 Ctx.getFunctionType(TT, FPT->getParamTypes(), FPT->getExtProtoInfo());
7428 From->setType(NewFunType);
7430 CXXMethodDecl *To = Import(From, Lang_CXX14);
7431 EXPECT_TRUE(To);
7432 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
7435 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
7436 testImport(
7438 auto foo() {
7439 struct X {};
7440 return X();
7442 )");
7445 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
7446 Decl *FromTU = getTuDecl(
7448 auto foo() {
7449 struct X {};
7450 return X();
7453 Lang_CXX14, "input0.cc");
7454 FunctionDecl *From =
7455 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
7457 // This time import the type directly.
7458 QualType ToT = ImportType(From->getType(), From, Lang_CXX14);
7459 const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);
7460 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
7463 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside3) {
7464 Decl *FromTU = getTuDecl(
7466 struct S {
7467 constexpr auto foo();
7469 constexpr auto S::foo() {
7470 struct X {};
7471 return X();
7474 Lang_CXX14, "input0.cc");
7475 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
7476 FromTU, functionDecl(hasName("foo"), unless(hasBody(stmt()))));
7477 ASSERT_FALSE(From->isThisDeclarationADefinition());
7479 FunctionDecl *To = Import(From, Lang_CXX17);
7480 EXPECT_TRUE(To);
7481 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
7482 EXPECT_FALSE(To->isThisDeclarationADefinition());
7485 TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
7486 testImport(
7488 auto foo() {
7489 struct X {};
7490 using Y = X;
7491 return Y();
7493 )");
7496 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
7497 testImport(
7499 auto foo() {
7500 struct X { struct Y{}; };
7501 return X::Y();
7503 )");
7506 TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
7507 testImport(
7509 auto foo() {
7510 auto l = []() {
7511 struct X {};
7512 return X();
7514 return l();
7517 Lang_CXX17);
7520 TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
7521 testImport(
7523 auto foo() {
7524 if (struct X {} x; true)
7525 return X();
7526 else
7527 return X();
7530 Lang_CXX17);
7533 TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
7534 testImport(
7536 auto foo() {
7537 for (struct X {} x;;)
7538 return X();
7541 Lang_CXX17);
7544 TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
7545 testImport(
7547 auto foo() {
7548 switch (struct X {} x; 10) {
7549 case 10:
7550 return X();
7554 Lang_CXX17);
7557 TEST_P(ImportAutoFunctions, ReturnWithAutoTemplateType) {
7558 testImport(
7560 template<class T>
7561 struct S {};
7562 template<class T>
7563 auto foo() {
7564 return S<T>{};
7566 auto a = foo<int>();
7568 Lang_CXX14, /*FindLast=*/true);
7571 TEST_P(ImportAutoFunctions, ReturnWithSubstNonTypeTemplateParmExpr) {
7572 const char *Code =
7574 template<int>
7575 struct array {};
7577 template <int N>
7578 auto foo() { return array<N>(); }
7580 void bar() { foo<0>(); }
7582 Decl *FromTU = getTuDecl(Code, Lang_CXX17);
7584 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(
7585 FromTU, functionDecl(hasName("bar")));
7587 auto *ToBar = Import(FromBar, Lang_CXX17);
7588 EXPECT_TRUE(ToBar);
7591 TEST_P(ImportAutoFunctions, ReturnWithUnaryTransformType) {
7592 const char *Code =
7594 enum E { E1 };
7596 template<typename T>
7597 auto foo(T v) { return static_cast<__underlying_type(T)>(v); }
7599 bool bar() { return foo(E1); }
7601 Decl *FromTU = getTuDecl(Code, Lang_CXX17);
7603 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(
7604 FromTU, functionDecl(hasName("bar")));
7606 auto *ToBar = Import(FromBar, Lang_CXX17);
7607 EXPECT_TRUE(ToBar);
7610 struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
7612 TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
7613 // Tests that the FileID tree structure (with the links being the include
7614 // chains) is preserved while importing other files (which need to be
7615 // added to this structure with fake include locations.
7617 SourceLocation Location1;
7619 auto Pattern = varDecl(hasName("X"));
7620 Decl *FromTU = getTuDecl("int X;", Lang_C99, "input0.c");
7621 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
7623 Location1 = Import(FromD, Lang_C99)->getLocation();
7625 SourceLocation Location2;
7627 auto Pattern = varDecl(hasName("Y"));
7628 Decl *FromTU = getTuDecl("int Y;", Lang_C99, "input1.c");
7629 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
7631 Location2 = Import(FromD, Lang_C99)->getLocation();
7634 SourceManager &ToSM = ToAST->getSourceManager();
7635 FileID FileID1 = ToSM.getFileID(Location1);
7636 FileID FileID2 = ToSM.getFileID(Location2);
7638 // Check that the imported files look like as if they were included from the
7639 // start of the main file.
7640 SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
7641 EXPECT_NE(FileID1, ToSM.getMainFileID());
7642 EXPECT_NE(FileID2, ToSM.getMainFileID());
7643 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
7644 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
7646 // Let the SourceManager check the order of the locations. The order should
7647 // be the order in which the declarations are imported.
7648 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
7649 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
7652 TEST_P(ImportSourceLocations, NormalFileBuffer) {
7653 // Test importing normal file buffers.
7655 std::string Path = "input0.c";
7656 std::string Source = "int X;";
7657 TranslationUnitDecl *FromTU = getTuDecl(Source, Lang_C99, Path);
7659 SourceLocation ImportedLoc;
7661 // Import the VarDecl to trigger the importing of the FileID.
7662 auto Pattern = varDecl(hasName("X"));
7663 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
7664 ImportedLoc = Import(FromD, Lang_C99)->getLocation();
7667 // Make sure the imported buffer has the original contents.
7668 SourceManager &ToSM = ToAST->getSourceManager();
7669 FileID ImportedID = ToSM.getFileID(ImportedLoc);
7670 EXPECT_EQ(Source,
7671 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
7674 TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {
7675 // Test importing overwritten file buffers.
7677 std::string Path = "input0.c";
7678 TranslationUnitDecl *FromTU = getTuDecl("int X;", Lang_C99, Path);
7680 // Overwrite the file buffer for our input file with new content.
7681 const std::string Contents = "overwritten contents";
7682 SourceLocation ImportedLoc;
7684 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();
7685 clang::FileManager &FM = FromSM.getFileManager();
7686 clang::FileEntryRef FE =
7687 FM.getVirtualFileRef(Path, static_cast<off_t>(Contents.size()), 0);
7689 llvm::SmallVector<char, 64> Buffer;
7690 Buffer.append(Contents.begin(), Contents.end());
7691 auto FileContents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
7692 std::move(Buffer), Path, /*RequiresNullTerminator=*/false);
7693 FromSM.overrideFileContents(FE, std::move(FileContents));
7695 // Import the VarDecl to trigger the importing of the FileID.
7696 auto Pattern = varDecl(hasName("X"));
7697 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
7698 ImportedLoc = Import(FromD, Lang_C99)->getLocation();
7701 // Make sure the imported buffer has the overwritten contents.
7702 SourceManager &ToSM = ToAST->getSourceManager();
7703 FileID ImportedID = ToSM.getFileID(ImportedLoc);
7704 EXPECT_EQ(Contents,
7705 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
7708 struct ImportAttributes : public ASTImporterOptionSpecificTestBase {
7709 void checkAttrImportCommon(const Attr *From, const Attr *To,
7710 const Decl *ToD) {
7712 // Verify that dump does not crash because invalid data.
7713 ToD->dump(llvm::nulls());
7715 EXPECT_EQ(From->getParsedKind(), To->getParsedKind());
7716 EXPECT_EQ(From->getSyntax(), To->getSyntax());
7717 if (From->getAttrName()) {
7718 EXPECT_TRUE(To->getAttrName());
7719 EXPECT_STREQ(From->getAttrName()->getNameStart(),
7720 To->getAttrName()->getNameStart());
7721 } else {
7722 EXPECT_FALSE(To->getAttrName());
7724 if (From->getScopeName()) {
7725 EXPECT_TRUE(To->getScopeName());
7726 EXPECT_STREQ(From->getScopeName()->getNameStart(),
7727 To->getScopeName()->getNameStart());
7728 } else {
7729 EXPECT_FALSE(To->getScopeName());
7731 EXPECT_EQ(From->getSpellingListIndex(), To->getSpellingListIndex());
7732 EXPECT_STREQ(From->getSpelling(), To->getSpelling());
7733 EXPECT_EQ(From->isInherited(), To->isInherited());
7734 EXPECT_EQ(From->isImplicit(), To->isImplicit());
7735 EXPECT_EQ(From->isPackExpansion(), To->isPackExpansion());
7736 EXPECT_EQ(From->isLateParsed(), To->isLateParsed());
7739 template <class DT, class AT>
7740 void importAttr(const char *Code, AT *&FromAttr, AT *&ToAttr,
7741 TestLanguage Lang = Lang_CXX11) {
7742 static_assert(std::is_base_of<Attr, AT>::value, "AT should be an Attr");
7743 static_assert(std::is_base_of<Decl, DT>::value, "DT should be a Decl");
7745 Decl *FromTU = getTuDecl(Code, Lang, "input.cc");
7746 DT *FromD =
7747 FirstDeclMatcher<DT>().match(FromTU, namedDecl(hasName("test")));
7748 ASSERT_TRUE(FromD);
7750 DT *ToD = Import(FromD, Lang_CXX11);
7751 ASSERT_TRUE(ToD);
7753 FromAttr = FromD->template getAttr<AT>();
7754 ToAttr = ToD->template getAttr<AT>();
7755 ASSERT_TRUE(FromAttr);
7756 EXPECT_TRUE(ToAttr);
7758 checkAttrImportCommon(FromAttr, ToAttr, ToD);
7761 template <class T> void checkImported(const T *From, const T *To) {
7762 EXPECT_TRUE(To);
7763 EXPECT_NE(From, To);
7766 template <class T>
7767 void checkImportVariadicArg(const llvm::iterator_range<T **> &From,
7768 const llvm::iterator_range<T **> &To) {
7769 for (auto FromI = From.begin(), ToI = To.begin(); FromI != From.end();
7770 ++FromI, ++ToI) {
7771 ASSERT_NE(ToI, To.end());
7772 checkImported(*FromI, *ToI);
7777 template <>
7778 void ImportAttributes::checkImported<Decl>(const Decl *From, const Decl *To) {
7779 EXPECT_TRUE(To);
7780 EXPECT_NE(From, To);
7781 EXPECT_EQ(To->getTranslationUnitDecl(),
7782 ToAST->getASTContext().getTranslationUnitDecl());
7785 TEST_P(ImportAttributes, ImportAligned) {
7786 AlignedAttr *FromAttr, *ToAttr;
7787 importAttr<RecordDecl>(
7789 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };
7790 struct alignas(alignof(A)) test {};
7792 FromAttr, ToAttr);
7793 checkImported(FromAttr->getAlignmentExpr(), ToAttr->getAlignmentExpr());
7795 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(
7796 ToAST->getASTContext().getTranslationUnitDecl(),
7797 cxxRecordDecl(hasName("A"), unless(isImplicit())));
7798 // Ensure that 'struct A' was imported (through reference from attribute of
7799 // struct 'test').
7800 EXPECT_TRUE(ToA);
7803 TEST_P(ImportAttributes, ImportAlignValue) {
7804 AlignValueAttr *FromAttr, *ToAttr;
7805 importAttr<VarDecl>(
7807 void *test __attribute__((align_value(64)));
7809 FromAttr, ToAttr);
7810 checkImported(FromAttr->getAlignment(), ToAttr->getAlignment());
7813 TEST_P(ImportAttributes, ImportFormat) {
7814 FormatAttr *FromAttr, *ToAttr;
7815 importAttr<FunctionDecl>(
7817 int test(const char * fmt, ...)
7818 __attribute__ ((__format__ (__scanf__, 1, 2)));
7820 FromAttr, ToAttr);
7822 EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());
7823 EXPECT_EQ(FromAttr->getFirstArg(), ToAttr->getFirstArg());
7824 EXPECT_EQ(FromAttr->getFormatIdx(), ToAttr->getFormatIdx());
7827 TEST_P(ImportAttributes, ImportEnableIf) {
7828 EnableIfAttr *FromAttr, *ToAttr;
7829 importAttr<FunctionDecl>(
7830 "void test(int A) __attribute__((enable_if(A == 1, \"message\")));",
7831 FromAttr, ToAttr);
7832 checkImported(FromAttr->getCond(), ToAttr->getCond());
7833 EXPECT_EQ(FromAttr->getMessage(), ToAttr->getMessage());
7836 TEST_P(ImportAttributes, ImportGuardedVar) {
7837 GuardedVarAttr *FromAttr, *ToAttr;
7838 importAttr<VarDecl>("int test __attribute__((guarded_var));", FromAttr,
7839 ToAttr);
7842 TEST_P(ImportAttributes, ImportPtGuardedVar) {
7843 PtGuardedVarAttr *FromAttr, *ToAttr;
7844 importAttr<VarDecl>("int *test __attribute__((pt_guarded_var));", FromAttr,
7845 ToAttr);
7848 TEST_P(ImportAttributes, ImportScopedLockable) {
7849 ScopedLockableAttr *FromAttr, *ToAttr;
7850 importAttr<CXXRecordDecl>("struct __attribute__((scoped_lockable)) test {};",
7851 FromAttr, ToAttr);
7854 TEST_P(ImportAttributes, ImportCapability) {
7855 CapabilityAttr *FromAttr, *ToAttr;
7856 importAttr<CXXRecordDecl>(
7857 "struct __attribute__((capability(\"cap\"))) test {};", FromAttr, ToAttr);
7858 EXPECT_EQ(FromAttr->getName(), ToAttr->getName());
7861 TEST_P(ImportAttributes, ImportAssertCapability) {
7862 AssertCapabilityAttr *FromAttr, *ToAttr;
7863 importAttr<FunctionDecl>(
7864 "void test(int A1, int A2) __attribute__((assert_capability(A1, A2)));",
7865 FromAttr, ToAttr);
7866 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7869 TEST_P(ImportAttributes, ImportAcquireCapability) {
7870 AcquireCapabilityAttr *FromAttr, *ToAttr;
7871 importAttr<FunctionDecl>(
7872 "void test(int A1, int A2) __attribute__((acquire_capability(A1, A2)));",
7873 FromAttr, ToAttr);
7874 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7877 TEST_P(ImportAttributes, ImportTryAcquireCapability) {
7878 TryAcquireCapabilityAttr *FromAttr, *ToAttr;
7879 importAttr<FunctionDecl>(
7880 "void test(int A1, int A2) __attribute__((try_acquire_capability(1, A1, "
7881 "A2)));",
7882 FromAttr, ToAttr);
7883 checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
7884 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7887 TEST_P(ImportAttributes, ImportReleaseCapability) {
7888 ReleaseCapabilityAttr *FromAttr, *ToAttr;
7889 importAttr<FunctionDecl>(
7890 "void test(int A1, int A2) __attribute__((release_capability(A1, A2)));",
7891 FromAttr, ToAttr);
7892 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7895 TEST_P(ImportAttributes, ImportRequiresCapability) {
7896 RequiresCapabilityAttr *FromAttr, *ToAttr;
7897 importAttr<FunctionDecl>(
7898 "void test(int A1, int A2) __attribute__((requires_capability(A1, A2)));",
7899 FromAttr, ToAttr);
7900 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7903 TEST_P(ImportAttributes, ImportNoThreadSafetyAnalysis) {
7904 NoThreadSafetyAnalysisAttr *FromAttr, *ToAttr;
7905 importAttr<FunctionDecl>(
7906 "void test() __attribute__((no_thread_safety_analysis));", FromAttr,
7907 ToAttr);
7910 TEST_P(ImportAttributes, ImportGuardedBy) {
7911 GuardedByAttr *FromAttr, *ToAttr;
7912 importAttr<VarDecl>(
7914 int G;
7915 int test __attribute__((guarded_by(G)));
7917 FromAttr, ToAttr);
7918 checkImported(FromAttr->getArg(), ToAttr->getArg());
7921 TEST_P(ImportAttributes, ImportPtGuardedBy) {
7922 PtGuardedByAttr *FromAttr, *ToAttr;
7923 importAttr<VarDecl>(
7925 int G;
7926 int *test __attribute__((pt_guarded_by(G)));
7928 FromAttr, ToAttr);
7929 checkImported(FromAttr->getArg(), ToAttr->getArg());
7932 TEST_P(ImportAttributes, ImportAcquiredAfter) {
7933 AcquiredAfterAttr *FromAttr, *ToAttr;
7934 importAttr<VarDecl>(
7936 struct __attribute__((lockable)) L {};
7937 L A1;
7938 L A2;
7939 L test __attribute__((acquired_after(A1, A2)));
7941 FromAttr, ToAttr);
7942 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7945 TEST_P(ImportAttributes, ImportAcquiredBefore) {
7946 AcquiredBeforeAttr *FromAttr, *ToAttr;
7947 importAttr<VarDecl>(
7949 struct __attribute__((lockable)) L {};
7950 L A1;
7951 L A2;
7952 L test __attribute__((acquired_before(A1, A2)));
7954 FromAttr, ToAttr);
7955 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7958 TEST_P(ImportAttributes, ImportAssertExclusiveLock) {
7959 AssertExclusiveLockAttr *FromAttr, *ToAttr;
7960 importAttr<FunctionDecl>("void test(int A1, int A2) "
7961 "__attribute__((assert_exclusive_lock(A1, A2)));",
7962 FromAttr, ToAttr);
7963 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7966 TEST_P(ImportAttributes, ImportAssertSharedLock) {
7967 AssertSharedLockAttr *FromAttr, *ToAttr;
7968 importAttr<FunctionDecl>(
7969 "void test(int A1, int A2) __attribute__((assert_shared_lock(A1, A2)));",
7970 FromAttr, ToAttr);
7971 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7974 TEST_P(ImportAttributes, ImportExclusiveTrylockFunction) {
7975 ExclusiveTrylockFunctionAttr *FromAttr, *ToAttr;
7976 importAttr<FunctionDecl>(
7977 "void test(int A1, int A2) __attribute__((exclusive_trylock_function(1, "
7978 "A1, A2)));",
7979 FromAttr, ToAttr);
7980 checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
7981 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7984 TEST_P(ImportAttributes, ImportSharedTrylockFunction) {
7985 SharedTrylockFunctionAttr *FromAttr, *ToAttr;
7986 importAttr<FunctionDecl>(
7987 "void test(int A1, int A2) __attribute__((shared_trylock_function(1, A1, "
7988 "A2)));",
7989 FromAttr, ToAttr);
7990 checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
7991 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7994 TEST_P(ImportAttributes, ImportLockReturned) {
7995 LockReturnedAttr *FromAttr, *ToAttr;
7996 importAttr<FunctionDecl>(
7997 "void test(int A1) __attribute__((lock_returned(A1)));", FromAttr,
7998 ToAttr);
7999 checkImported(FromAttr->getArg(), ToAttr->getArg());
8002 TEST_P(ImportAttributes, ImportLocksExcluded) {
8003 LocksExcludedAttr *FromAttr, *ToAttr;
8004 importAttr<FunctionDecl>(
8005 "void test(int A1, int A2) __attribute__((locks_excluded(A1, A2)));",
8006 FromAttr, ToAttr);
8007 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
8010 TEST_P(ImportAttributes, ImportC99NoThrowAttr) {
8011 NoThrowAttr *FromAttr, *ToAttr;
8012 importAttr<FunctionDecl>("void test () __attribute__ ((__nothrow__));",
8013 FromAttr, ToAttr, Lang_C99);
8014 checkImported(FromAttr->getAttrName(), ToAttr->getAttrName());
8017 template <typename T>
8018 auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {
8019 auto Copy = Values;
8020 for (std::vector<std::string> &ArgV : Copy) {
8021 for (const std::string &Arg : Args) {
8022 ArgV.push_back(Arg);
8025 return ::testing::ValuesIn(Copy);
8028 struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
8029 ImportWithExternalSource() {
8030 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
8031 ASTContext &FromContext, FileManager &FromFileManager,
8032 bool MinimalImport,
8033 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
8034 return new ASTImporter(ToContext, ToFileManager, FromContext,
8035 // Use minimal import for these tests.
8036 FromFileManager, /*MinimalImport=*/true,
8037 // We use the regular lookup.
8038 /*SharedState=*/nullptr);
8043 /// An ExternalASTSource that keeps track of the tags is completed.
8044 struct SourceWithCompletedTagList : clang::ExternalASTSource {
8045 std::vector<clang::TagDecl *> &CompletedTags;
8046 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)
8047 : CompletedTags(CompletedTags) {}
8048 void CompleteType(TagDecl *Tag) override {
8049 auto *Record = cast<CXXRecordDecl>(Tag);
8050 Record->startDefinition();
8051 Record->completeDefinition();
8052 CompletedTags.push_back(Tag);
8054 using clang::ExternalASTSource::CompleteType;
8057 TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
8058 // Create an empty TU.
8059 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cpp");
8061 // Create and add the test ExternalASTSource.
8062 std::vector<clang::TagDecl *> CompletedTags;
8063 IntrusiveRefCntPtr<ExternalASTSource> source =
8064 new SourceWithCompletedTagList(CompletedTags);
8065 clang::ASTContext &Context = FromTU->getASTContext();
8066 Context.setExternalSource(std::move(source));
8068 // Create a dummy class by hand with external lexical storage.
8069 IdentifierInfo &Ident = Context.Idents.get("test_class");
8070 auto *Record =
8071 CXXRecordDecl::Create(Context, TagTypeKind::Class, FromTU,
8072 SourceLocation(), SourceLocation(), &Ident);
8073 Record->setHasExternalLexicalStorage();
8074 FromTU->addDecl(Record);
8076 // Do a minimal import of the created class.
8077 EXPECT_EQ(0U, CompletedTags.size());
8078 Import(Record, Lang_CXX03);
8079 EXPECT_EQ(0U, CompletedTags.size());
8081 // Import the definition of the created class.
8082 llvm::Error Err = findFromTU(Record)->Importer->ImportDefinition(Record);
8083 EXPECT_FALSE((bool)Err);
8084 consumeError(std::move(Err));
8086 // Make sure the class was completed once.
8087 EXPECT_EQ(1U, CompletedTags.size());
8088 EXPECT_EQ(Record, CompletedTags.front());
8091 TEST_P(ImportFunctions, CTADImplicit) {
8092 Decl *FromTU = getTuDecl(
8094 template <typename T> struct A {
8095 A(T);
8097 A a{(int)0};
8099 Lang_CXX17, "input.cc");
8100 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8101 FromTU,
8102 cxxDeductionGuideDecl(hasParameter(0, hasType(asString("A<T>")))));
8103 auto *ToD = Import(FromD, Lang_CXX17);
8104 ASSERT_TRUE(ToD);
8105 EXPECT_EQ(ToD->getDeductionCandidateKind(), DeductionCandidate::Copy);
8106 // Check that the deduced class template is also imported.
8107 EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
8108 FromD->getDeducedTemplate()));
8111 TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
8112 Decl *FromTU = getTuDecl(
8114 template <typename T> struct A {
8115 A(T);
8117 template <typename T> explicit A(T) -> A<float>;
8118 A a{(int)0}; // calls A<float>::A(float)
8120 Lang_CXX17, "input.cc");
8121 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8122 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
8123 // Not-implicit: i.e. not compiler-generated, user defined.
8124 ASSERT_FALSE(FromD->isImplicit());
8125 ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.
8126 auto *ToD = Import(FromD, Lang_CXX17);
8127 ASSERT_TRUE(ToD);
8128 EXPECT_FALSE(FromD->isImplicit());
8129 EXPECT_TRUE(ToD->isExplicit());
8132 TEST_P(ImportFunctions, CTADWithLocalTypedef) {
8133 Decl *TU = getTuDecl(
8135 template <typename T> struct A {
8136 typedef T U;
8137 A(U);
8139 A a{(int)0};
8141 Lang_CXX17, "input.cc");
8142 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8143 TU, cxxDeductionGuideDecl());
8144 auto *ToD = Import(FromD, Lang_CXX17);
8145 ASSERT_TRUE(ToD);
8148 TEST_P(ImportFunctions, ParmVarDeclDeclContext) {
8149 constexpr auto FromTUCode = R"(
8150 void f(int P);
8152 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);
8153 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
8154 FromTU, functionDecl(hasName("f")));
8155 ASSERT_TRUE(FromF);
8157 auto *ImportedF = Import(FromF, Lang_CXX11);
8158 EXPECT_TRUE(ImportedF);
8159 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
8160 ImportedF, ImportedF->getParamDecl(0)));
8163 // FIXME Move these tests out of ASTImporterTest. For that we need to factor
8164 // out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
8165 // into a new test Fixture. Then we should lift up this Fixture to its own
8166 // implementation file and only then could we reuse the Fixture in other AST
8167 // unitttests.
8168 struct CTAD : ASTImporterOptionSpecificTestBase {};
8170 TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
8171 Decl *TU = getTuDecl(
8173 typedef int U;
8174 template <typename T> struct A {
8175 A(U, T);
8177 A a{(int)0, (int)0};
8179 Lang_CXX17, "input.cc");
8180 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8181 TU, cxxDeductionGuideDecl());
8182 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8183 TU, typedefNameDecl(hasName("U")));
8184 ParmVarDecl *Param = Guide->getParamDecl(0);
8185 // The type of the first param (which is a typedef) should match the typedef
8186 // in the global scope.
8187 EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
8190 TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
8191 Decl *TU = getTuDecl(
8193 typedef int U;
8194 template <typename T> struct A {
8195 A(U*, T);
8197 A a{(int*)0, (int)0};
8199 Lang_CXX17, "input.cc");
8200 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8201 TU, cxxDeductionGuideDecl());
8202 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8203 TU, typedefNameDecl(hasName("U")));
8204 ParmVarDecl *Param = Guide->getParamDecl(0);
8205 EXPECT_EQ(Param->getType()
8206 ->getAs<PointerType>()
8207 ->getPointeeType()
8208 ->getAs<TypedefType>()
8209 ->getDecl(),
8210 Typedef);
8213 TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
8214 Decl *TU = getTuDecl(
8216 template <typename T> struct A {
8217 typedef T U;
8218 A(U, T);
8220 A a{(int)0, (int)0};
8222 Lang_CXX17, "input.cc");
8223 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8224 TU, cxxDeductionGuideDecl());
8225 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8226 TU, typedefNameDecl(hasName("U")));
8227 ParmVarDecl *Param = Guide->getParamDecl(0);
8228 EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
8231 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CTAD,
8232 DefaultTestValuesForRunOptions);
8234 TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) {
8235 Decl *TU = getTuDecl(
8237 namespace N {
8238 typedef int X __attribute__((annotate("A")));
8241 Lang_CXX17, "input.cc");
8242 auto *FromD =
8243 FirstDeclMatcher<TypedefDecl>().match(TU, typedefDecl(hasName("X")));
8244 auto *ToD = Import(FromD, Lang_CXX17);
8245 ASSERT_TRUE(ToD);
8246 ASSERT_EQ(ToD->getAttrs().size(), 1U);
8247 auto *ToAttr = dyn_cast<AnnotateAttr>(ToD->getAttrs()[0]);
8248 ASSERT_TRUE(ToAttr);
8249 EXPECT_EQ(ToAttr->getAnnotation(), "A");
8252 TEST_P(ASTImporterOptionSpecificTestBase,
8253 ImportOfTemplatedDeclWhenPreviousDeclHasNoDescribedTemplateSet) {
8254 Decl *FromTU = getTuDecl(
8257 namespace std {
8258 template<typename T>
8259 class basic_stringbuf;
8261 namespace std {
8262 class char_traits;
8263 template<typename T = char_traits>
8264 class basic_stringbuf;
8266 namespace std {
8267 template<typename T>
8268 class basic_stringbuf {};
8272 Lang_CXX11);
8274 auto *From1 = FirstDeclMatcher<ClassTemplateDecl>().match(
8275 FromTU,
8276 classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));
8277 auto *To1 = cast_or_null<ClassTemplateDecl>(Import(From1, Lang_CXX11));
8278 EXPECT_TRUE(To1);
8280 auto *From2 = LastDeclMatcher<ClassTemplateDecl>().match(
8281 FromTU,
8282 classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));
8283 auto *To2 = cast_or_null<ClassTemplateDecl>(Import(From2, Lang_CXX11));
8284 EXPECT_TRUE(To2);
8287 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfCapturedVLAType) {
8288 Decl *FromTU = getTuDecl(
8290 void declToImport(int N) {
8291 int VLA[N];
8292 [&VLA] {}; // FieldDecl inside the lambda.
8295 Lang_CXX14);
8296 auto *FromFD = FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl());
8297 ASSERT_TRUE(FromFD);
8298 ASSERT_TRUE(FromFD->hasCapturedVLAType());
8300 auto *ToFD = Import(FromFD, Lang_CXX14);
8301 EXPECT_TRUE(ToFD);
8302 EXPECT_TRUE(ToFD->hasCapturedVLAType());
8303 EXPECT_NE(FromFD->getCapturedVLAType(), ToFD->getCapturedVLAType());
8306 TEST_P(ASTImporterOptionSpecificTestBase, ImportEnumMemberSpecialization) {
8307 Decl *FromTU = getTuDecl(
8309 template <class T> struct A {
8310 enum tagname { enumerator };
8312 template struct A<int>;
8314 Lang_CXX03);
8315 auto *FromD = FirstDeclMatcher<EnumDecl>().match(
8316 FromTU, enumDecl(hasName("tagname"),
8317 hasParent(classTemplateSpecializationDecl())));
8318 ASSERT_TRUE(FromD);
8319 ASSERT_TRUE(FromD->getMemberSpecializationInfo());
8321 auto *ToD = Import(FromD, Lang_CXX03);
8322 EXPECT_TRUE(ToD);
8323 EXPECT_TRUE(ToD->getMemberSpecializationInfo());
8324 EXPECT_EQ(FromD->getTemplateSpecializationKind(),
8325 ToD->getTemplateSpecializationKind());
8328 TEST_P(ASTImporterOptionSpecificTestBase, ImportIsInheritingConstructorBit) {
8329 Decl *FromTU = getTuDecl(
8331 struct A {
8332 A(int);
8334 struct B : A {
8335 using A::A; // Inherited ctor.
8337 void f() {
8338 (B(0));
8341 Lang_CXX11);
8342 auto *FromD = FirstDeclMatcher<CXXConstructorDecl>().match(
8343 FromTU, cxxConstructorDecl(isInheritingConstructor()));
8344 ASSERT_TRUE(FromD);
8345 ASSERT_TRUE(FromD->isInheritingConstructor());
8347 auto *ToD = Import(FromD, Lang_CXX11);
8348 ASSERT_TRUE(ToD);
8349 EXPECT_TRUE(ToD->isInheritingConstructor());
8352 TEST_P(ASTImporterOptionSpecificTestBase, ImportConstructorUsingShadow) {
8353 TranslationUnitDecl *FromTU = getTuDecl(
8355 struct A {
8356 A(int, int);
8358 struct B : A {
8359 using A::A;
8361 struct C : B {
8362 using B::B;
8365 Lang_CXX11);
8367 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordC) {
8368 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
8369 TU, cxxRecordDecl(hasName("A")));
8370 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
8371 TU, cxxRecordDecl(hasName("B")));
8372 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
8373 TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),
8374 parameterCountIs(2)));
8375 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
8376 FirstDeclMatcher<UsingShadowDecl>().match(
8377 TU, usingShadowDecl(hasParent(equalsNode(RecordB)),
8378 hasTargetDecl(equalsNode(ConstrA)))));
8379 auto *ShadowCA = cast<ConstructorUsingShadowDecl>(
8380 FirstDeclMatcher<UsingShadowDecl>().match(
8381 TU, usingShadowDecl(hasParent(equalsNode(RecordC)),
8382 hasTargetDecl(equalsNode(ConstrA)))));
8383 EXPECT_EQ(ShadowBA->getTargetDecl(), ConstrA);
8384 EXPECT_EQ(ShadowBA->getNominatedBaseClass(), RecordA);
8385 EXPECT_EQ(ShadowBA->getConstructedBaseClass(), RecordA);
8386 EXPECT_EQ(ShadowBA->getNominatedBaseClassShadowDecl(), nullptr);
8387 EXPECT_EQ(ShadowBA->getConstructedBaseClassShadowDecl(), nullptr);
8388 EXPECT_FALSE(ShadowBA->constructsVirtualBase());
8389 EXPECT_EQ(ShadowCA->getTargetDecl(), ConstrA);
8390 EXPECT_EQ(ShadowCA->getNominatedBaseClass(), RecordB);
8391 EXPECT_EQ(ShadowCA->getConstructedBaseClass(), RecordB);
8392 EXPECT_EQ(ShadowCA->getNominatedBaseClassShadowDecl(), ShadowBA);
8393 EXPECT_EQ(ShadowCA->getConstructedBaseClassShadowDecl(), ShadowBA);
8394 EXPECT_FALSE(ShadowCA->constructsVirtualBase());
8397 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
8398 FromTU, cxxRecordDecl(hasName("C")));
8400 auto *ToC = Import(FromC, Lang_CXX11);
8401 TranslationUnitDecl *ToTU = ToC->getTranslationUnitDecl();
8403 CheckAST(FromTU, FromC);
8404 CheckAST(ToTU, ToC);
8407 TEST_P(ASTImporterOptionSpecificTestBase,
8408 ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {
8409 Decl *From, *To;
8410 std::tie(From, To) = getImportedDecl(
8411 R"s(
8412 struct A {
8413 A() : m() {}
8414 int m;
8417 A foo() { A a; return a; }
8418 A bar() { return {}; }
8419 )s",
8420 Lang_CXX17,
8421 R"s(
8422 struct A {
8423 A() : m() {}
8424 int m;
8426 A baz() { return {}; }
8427 )s",
8428 Lang_CXX17, "A");
8430 auto HasCtorInit =
8431 hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
8432 auto ImpMoveCtor =
8433 cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
8435 auto *FromImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
8436 From, ImpMoveCtor);
8437 auto *ToImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
8438 To, ImpMoveCtor);
8440 EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
8441 EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
8443 EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
8444 EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
8445 EXPECT_TRUE(*ToImpMoveCtor->init_begin());
8448 AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher<NamedDecl>,
8449 InnerMatcher) {
8450 return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
8453 TEST_P(ASTImporterOptionSpecificTestBase,
8454 ImportConstructorUsingShadowVirtualBase) {
8455 TranslationUnitDecl *FromTU = getTuDecl(
8457 struct A { A(int, int); };
8458 struct B : A { using A::A; };
8460 struct V1 : virtual B { using B::B; };
8461 struct V2 : virtual B { using B::B; };
8463 struct D2 : V1, V2 {
8464 using V1::V1;
8465 using V2::V2;
8468 Lang_CXX11);
8470 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordD2) {
8471 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
8472 TU, cxxRecordDecl(hasName("A")));
8473 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
8474 TU, cxxRecordDecl(hasName("B")));
8475 auto *RecordV1 = FirstDeclMatcher<CXXRecordDecl>().match(
8476 TU, cxxRecordDecl(hasName("V1")));
8477 auto *RecordV2 = FirstDeclMatcher<CXXRecordDecl>().match(
8478 TU, cxxRecordDecl(hasName("V2")));
8479 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
8480 TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),
8481 parameterCountIs(2)));
8482 auto *ConstrB = FirstDeclMatcher<CXXConstructorDecl>().match(
8483 TU, cxxConstructorDecl(hasParent(equalsNode(RecordB)),
8484 isCopyConstructor()));
8485 auto *UsingD2V1 = FirstDeclMatcher<UsingDecl>().match(
8486 TU, usingDecl(hasParent(equalsNode(RecordD2))));
8487 auto *UsingD2V2 = LastDeclMatcher<UsingDecl>().match(
8488 TU, usingDecl(hasParent(equalsNode(RecordD2))));
8489 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
8490 FirstDeclMatcher<UsingShadowDecl>().match(
8491 TU, usingShadowDecl(hasParent(equalsNode(RecordB)),
8492 hasTargetDecl(equalsNode(ConstrA)))));
8493 auto *ShadowV1A = cast<ConstructorUsingShadowDecl>(
8494 FirstDeclMatcher<UsingShadowDecl>().match(
8495 TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),
8496 hasTargetDecl(equalsNode(ConstrA)))));
8497 auto *ShadowV1B = cast<ConstructorUsingShadowDecl>(
8498 FirstDeclMatcher<UsingShadowDecl>().match(
8499 TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),
8500 hasTargetDecl(equalsNode(ConstrB)))));
8501 auto *ShadowV2A = cast<ConstructorUsingShadowDecl>(
8502 FirstDeclMatcher<UsingShadowDecl>().match(
8503 TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),
8504 hasTargetDecl(equalsNode(ConstrA)))));
8505 auto *ShadowV2B = cast<ConstructorUsingShadowDecl>(
8506 FirstDeclMatcher<UsingShadowDecl>().match(
8507 TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),
8508 hasTargetDecl(equalsNode(ConstrB)))));
8509 auto *ShadowD2V1A = cast<ConstructorUsingShadowDecl>(
8510 FirstDeclMatcher<UsingShadowDecl>().match(
8511 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8512 hasIntroducerDecl(equalsNode(UsingD2V1)),
8513 hasTargetDecl(equalsNode(ConstrA)))));
8514 auto *ShadowD2V1B = cast<ConstructorUsingShadowDecl>(
8515 FirstDeclMatcher<UsingShadowDecl>().match(
8516 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8517 hasIntroducerDecl(equalsNode(UsingD2V1)),
8518 hasTargetDecl(equalsNode(ConstrB)))));
8519 auto *ShadowD2V2A = cast<ConstructorUsingShadowDecl>(
8520 FirstDeclMatcher<UsingShadowDecl>().match(
8521 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8522 hasIntroducerDecl(equalsNode(UsingD2V2)),
8523 hasTargetDecl(equalsNode(ConstrA)))));
8524 auto *ShadowD2V2B = cast<ConstructorUsingShadowDecl>(
8525 FirstDeclMatcher<UsingShadowDecl>().match(
8526 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8527 hasIntroducerDecl(equalsNode(UsingD2V2)),
8528 hasTargetDecl(equalsNode(ConstrB)))));
8530 EXPECT_EQ(ShadowD2V1A->getTargetDecl(), ConstrA);
8531 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClassShadowDecl(), ShadowV1A);
8532 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClass(), RecordV1);
8533 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClassShadowDecl(), ShadowBA);
8534 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClass(), RecordB);
8535 EXPECT_TRUE(ShadowD2V1A->constructsVirtualBase());
8536 EXPECT_EQ(ShadowD2V1B->getTargetDecl(), ConstrB);
8537 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClassShadowDecl(), ShadowV1B);
8538 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClass(), RecordV1);
8539 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClassShadowDecl(), nullptr);
8540 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClass(), RecordB);
8541 EXPECT_TRUE(ShadowD2V1B->constructsVirtualBase());
8542 EXPECT_EQ(ShadowD2V2A->getTargetDecl(), ConstrA);
8543 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClassShadowDecl(), ShadowV2A);
8544 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClass(), RecordV2);
8545 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClassShadowDecl(), ShadowBA);
8546 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClass(), RecordB);
8547 EXPECT_TRUE(ShadowD2V2A->constructsVirtualBase());
8548 EXPECT_EQ(ShadowD2V2B->getTargetDecl(), ConstrB);
8549 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClassShadowDecl(), ShadowV2B);
8550 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClass(), RecordV2);
8551 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClassShadowDecl(), nullptr);
8552 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClass(), RecordB);
8553 EXPECT_TRUE(ShadowD2V2B->constructsVirtualBase());
8555 EXPECT_TRUE(ShadowV1A->constructsVirtualBase());
8556 EXPECT_TRUE(ShadowV1B->constructsVirtualBase());
8557 EXPECT_TRUE(ShadowV2A->constructsVirtualBase());
8558 EXPECT_TRUE(ShadowV2B->constructsVirtualBase());
8559 EXPECT_FALSE(ShadowBA->constructsVirtualBase());
8562 auto *FromD2 = FirstDeclMatcher<CXXRecordDecl>().match(
8563 FromTU, cxxRecordDecl(hasName("D2")));
8565 auto *ToD2 = Import(FromD2, Lang_CXX11);
8566 TranslationUnitDecl *ToTU = ToD2->getTranslationUnitDecl();
8568 CheckAST(FromTU, FromD2);
8569 CheckAST(ToTU, ToD2);
8572 TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingShadowList) {
8573 TranslationUnitDecl *FromTU = getTuDecl(
8575 struct A {
8576 void f();
8577 void f(int);
8579 struct B : A {
8580 using A::f;
8583 Lang_CXX11);
8585 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
8586 FromTU, cxxRecordDecl(hasName("B")));
8588 auto *ToB = Import(FromB, Lang_CXX11);
8589 TranslationUnitDecl *ToTU = ToB->getTranslationUnitDecl();
8591 auto *ToUsing = FirstDeclMatcher<UsingDecl>().match(
8592 ToTU, usingDecl(hasParent(equalsNode(ToB))));
8593 auto *ToUsingShadowF1 = FirstDeclMatcher<UsingShadowDecl>().match(
8594 ToTU, usingShadowDecl(hasTargetDecl(
8595 functionDecl(hasName("f"), parameterCountIs(0)))));
8596 auto *ToUsingShadowF2 = FirstDeclMatcher<UsingShadowDecl>().match(
8597 ToTU, usingShadowDecl(hasTargetDecl(
8598 functionDecl(hasName("f"), parameterCountIs(1)))));
8600 EXPECT_EQ(ToUsing->shadow_size(), 2u);
8601 auto ShadowI = ToUsing->shadow_begin();
8602 EXPECT_EQ(*ShadowI, ToUsingShadowF1);
8603 ++ShadowI;
8604 EXPECT_EQ(*ShadowI, ToUsingShadowF2);
8607 AST_MATCHER_P(FunctionTemplateDecl, templateParameterCountIs, unsigned, Cnt) {
8608 return Node.getTemplateParameters()->size() == Cnt;
8611 TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuide) {
8612 TranslationUnitDecl *FromTU = getTuDecl(
8614 template<class> class A { };
8615 template<class T> class B {
8616 template<class T1, typename = A<T>> B(T1);
8618 template<class T>
8619 B(T, T) -> B<int>;
8621 Lang_CXX17);
8623 // Get the implicit deduction guide for (non-default) constructor of 'B'.
8624 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8625 FromTU, functionTemplateDecl(templateParameterCountIs(3)));
8626 // Implicit deduction guide for copy constructor of 'B'.
8627 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8628 FromTU, functionTemplateDecl(templateParameterCountIs(1), isImplicit()));
8629 // User defined deduction guide.
8630 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8631 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
8633 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();
8634 // Don't know why exactly but this is the DeclContext here.
8635 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),
8636 FromDGCopyCtor->getTemplatedDecl());
8637 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),
8638 FromDGCtor->getTemplatedDecl());
8639 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),
8640 FromDGCtor->getTemplatedDecl());
8641 EXPECT_EQ(
8642 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8643 FromDGCopyCtor->getTemplatedDecl());
8644 EXPECT_EQ(FromDGOther->getDescribedTemplate()
8645 ->getTemplateParameters()
8646 ->getParam(0)
8647 ->getDeclContext(),
8648 FromDGOther);
8650 auto *ToDGCtor = Import(FromDGCtor, Lang_CXX17);
8651 auto *ToDGCopyCtor = Import(FromDGCopyCtor, Lang_CXX17);
8652 auto *ToDGOther = Import(FromDGOther, Lang_CXX17);
8653 ASSERT_TRUE(ToDGCtor);
8654 ASSERT_TRUE(ToDGCopyCtor);
8655 ASSERT_TRUE(ToDGOther);
8657 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();
8658 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),
8659 ToDGCopyCtor->getTemplatedDecl());
8660 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),
8661 ToDGCtor->getTemplatedDecl());
8662 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),
8663 ToDGCtor->getTemplatedDecl());
8664 EXPECT_EQ(
8665 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8666 ToDGCopyCtor->getTemplatedDecl());
8667 EXPECT_EQ(ToDGOther->getDescribedTemplate()
8668 ->getTemplateParameters()
8669 ->getParam(0)
8670 ->getDeclContext(),
8671 ToDGOther);
8674 TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuideDifferentOrder) {
8675 // This test demonstrates that the DeclContext of the imported object is
8676 // dependent on the order of import. The test is an exact copy of the previous
8677 // one except at the indicated locations.
8678 TranslationUnitDecl *FromTU = getTuDecl(
8680 template<class> class A { };
8681 template<class T> class B {
8682 template<class T1, typename = A<T>> B(T1);
8684 template<class T>
8685 B(T, T) -> B<int>;
8687 Lang_CXX17);
8689 // Get the implicit deduction guide for (non-default) constructor of 'B'.
8690 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8691 FromTU, functionTemplateDecl(templateParameterCountIs(3)));
8692 // Implicit deduction guide for copy constructor of 'B'.
8693 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8694 FromTU, functionTemplateDecl(templateParameterCountIs(1), isImplicit()));
8695 // User defined deduction guide.
8696 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8697 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
8699 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();
8700 // Don't know why exactly but this is the DeclContext here.
8701 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),
8702 FromDGCopyCtor->getTemplatedDecl());
8703 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),
8704 FromDGCtor->getTemplatedDecl());
8705 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),
8706 FromDGCtor->getTemplatedDecl());
8707 EXPECT_EQ(
8708 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8709 FromDGCopyCtor->getTemplatedDecl());
8710 EXPECT_EQ(FromDGOther->getDescribedTemplate()
8711 ->getTemplateParameters()
8712 ->getParam(0)
8713 ->getDeclContext(),
8714 FromDGOther);
8716 // Here the import of 'ToDGCopyCtor' and 'ToDGCtor' is reversed relative to
8717 // the previous test.
8718 auto *ToDGCopyCtor = Import(FromDGCopyCtor, Lang_CXX17);
8719 auto *ToDGCtor = Import(FromDGCtor, Lang_CXX17);
8720 auto *ToDGOther = Import(FromDGOther, Lang_CXX17);
8721 ASSERT_TRUE(ToDGCtor);
8722 ASSERT_TRUE(ToDGCopyCtor);
8723 ASSERT_TRUE(ToDGOther);
8725 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();
8726 // Next line: DeclContext is different relative to the previous test.
8727 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),
8728 ToDGCtor->getTemplatedDecl());
8729 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),
8730 ToDGCtor->getTemplatedDecl());
8731 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),
8732 ToDGCtor->getTemplatedDecl());
8733 // Next line: DeclContext is different relative to the previous test.
8734 EXPECT_EQ(
8735 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8736 ToDGCtor->getTemplatedDecl());
8737 EXPECT_EQ(ToDGOther->getDescribedTemplate()
8738 ->getTemplateParameters()
8739 ->getParam(0)
8740 ->getDeclContext(),
8741 ToDGOther);
8744 TEST_P(ASTImporterOptionSpecificTestBase,
8745 ImportFieldsFirstForCorrectRecordLayout) {
8746 // UnaryOperator(&) triggers RecordLayout computation, which relies on
8747 // correctly imported fields.
8748 auto Code =
8750 class A {
8751 int m() {
8752 return &((A *)0)->f1 - &((A *)0)->f2;
8754 int f1;
8755 int f2;
8758 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
8760 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
8761 FromTU, cxxMethodDecl(hasName("A::m")));
8762 Import(FromF, Lang_CXX11);
8765 TEST_P(ASTImporterOptionSpecificTestBase,
8766 ImportCirularRefFieldsWithoutCorruptedRecordLayoutCache) {
8767 // Import sequence: A => A.b => B => B.f() => ... => UnaryOperator(&) => ...
8769 // UnaryOperator(&) should not introduce invalid RecordLayout since 'A' is
8770 // still not completely imported.
8771 auto Code =
8773 class B;
8774 class A {
8775 B* b;
8776 int c;
8778 class B {
8779 A *f() { return &((B *)0)->a; }
8780 A a;
8784 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
8785 getTuDecl(Code, Lang_CXX11), cxxRecordDecl(hasName("A")));
8786 FromR = FromR->getDefinition();
8787 auto &FromAST = FromR->getASTContext();
8788 auto *ToR = Import(FromR, Lang_CXX11);
8789 auto &ToAST = ToR->getASTContext();
8791 uint64_t SecondFieldOffset = FromAST.getTypeSize(FromAST.VoidPtrTy);
8793 EXPECT_TRUE(FromR->isCompleteDefinition());
8794 const auto &FromLayout = FromAST.getASTRecordLayout(FromR);
8795 EXPECT_TRUE(FromLayout.getFieldOffset(0) == 0);
8796 EXPECT_TRUE(FromLayout.getFieldOffset(1) == SecondFieldOffset);
8798 EXPECT_TRUE(ToR->isCompleteDefinition());
8799 const auto &ToLayout = ToAST.getASTRecordLayout(ToR);
8800 EXPECT_TRUE(ToLayout.getFieldOffset(0) == 0);
8801 EXPECT_TRUE(ToLayout.getFieldOffset(1) == SecondFieldOffset);
8804 TEST_P(ASTImporterOptionSpecificTestBase,
8805 ImportRecordWithLayoutRequestingExpr) {
8806 TranslationUnitDecl *FromTU = getTuDecl(
8808 struct A {
8809 int idx;
8810 static void foo(A x) {
8811 (void)&"text"[x.idx];
8815 Lang_CXX11);
8817 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8818 FromTU, cxxRecordDecl(hasName("A")));
8820 // Test that during import of 'foo' the record layout can be obtained without
8821 // crash.
8822 auto *ToA = Import(FromA, Lang_CXX11);
8823 EXPECT_TRUE(ToA);
8824 EXPECT_TRUE(ToA->isCompleteDefinition());
8827 TEST_P(ASTImporterOptionSpecificTestBase,
8828 ImportRecordWithLayoutRequestingExprDifferentRecord) {
8829 TranslationUnitDecl *FromTU = getTuDecl(
8831 struct B;
8832 struct A {
8833 int idx;
8834 B *b;
8836 struct B {
8837 static void foo(A x) {
8838 (void)&"text"[x.idx];
8842 Lang_CXX11);
8844 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8845 FromTU, cxxRecordDecl(hasName("A")));
8847 // Test that during import of 'foo' the record layout (of 'A') can be obtained
8848 // without crash. It is not possible to have all of the fields of 'A' imported
8849 // at that time (without big code changes).
8850 auto *ToA = Import(FromA, Lang_CXX11);
8851 EXPECT_TRUE(ToA);
8852 EXPECT_TRUE(ToA->isCompleteDefinition());
8855 TEST_P(ASTImporterOptionSpecificTestBase, ImportInClassInitializerFromField) {
8856 // Encounter import of a field when the field already exists but has the
8857 // in-class initializer expression not yet set. Such case can occur in the AST
8858 // of generated template specializations.
8859 // The first code forces to create a template specialization of
8860 // `A<int>` but without implicit constructors.
8861 // The second ("From") code contains a variable of type `A<int>`, this
8862 // results in a template specialization that has constructors and
8863 // CXXDefaultInitExpr nodes.
8864 Decl *ToTU = getToTuDecl(
8866 void f();
8867 template<typename> struct A { int X = 1; };
8868 struct B { A<int> Y; };
8870 Lang_CXX11);
8871 auto *ToX = FirstDeclMatcher<FieldDecl>().match(
8872 ToTU,
8873 fieldDecl(hasName("X"), hasParent(classTemplateSpecializationDecl())));
8874 ASSERT_TRUE(ToX->hasInClassInitializer());
8875 ASSERT_FALSE(ToX->getInClassInitializer());
8877 Decl *FromTU = getTuDecl(
8879 void f();
8880 template<typename> struct A { int X = 1; };
8881 struct B { A<int> Y; };
8883 A<int> Z;
8885 Lang_CXX11, "input1.cc");
8886 auto *FromX = FirstDeclMatcher<FieldDecl>().match(
8887 FromTU,
8888 fieldDecl(hasName("X"), hasParent(classTemplateSpecializationDecl())));
8890 auto *ToXImported = Import(FromX, Lang_CXX11);
8891 EXPECT_EQ(ToXImported, ToX);
8892 EXPECT_TRUE(ToX->getInClassInitializer());
8895 TEST_P(ASTImporterOptionSpecificTestBase,
8896 ImportInClassInitializerFromCXXDefaultInitExpr) {
8897 // Encounter AST import of a CXXDefaultInitExpr where the "to-field"
8898 // of it exists but has the in-class initializer not set yet.
8899 Decl *ToTU = getToTuDecl(
8901 namespace N {
8902 template<typename> int b;
8903 struct X;
8905 template<typename> struct A { N::X *X = nullptr; };
8906 struct B { A<int> Y; };
8908 Lang_CXX14);
8909 auto *ToX = FirstDeclMatcher<FieldDecl>().match(
8910 ToTU,
8911 fieldDecl(hasName("X"), hasParent(classTemplateSpecializationDecl())));
8912 ASSERT_TRUE(ToX->hasInClassInitializer());
8913 ASSERT_FALSE(ToX->getInClassInitializer());
8915 Decl *FromTU = getTuDecl(
8917 namespace N {
8918 template<typename> int b;
8919 struct X;
8921 template<typename> struct A { N::X *X = nullptr; };
8922 struct B { A<int> Y; };
8924 void f() {
8925 (void)A<int>{};
8927 struct C {
8928 C(): attr(new A<int>{}){}
8929 A<int> *attr;
8930 const int value = N::b<C>;
8933 Lang_CXX14, "input1.cc");
8934 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
8935 FromTU, functionDecl(hasName("f"), isDefinition()));
8936 auto *ToF = Import(FromF, Lang_CXX11);
8937 EXPECT_TRUE(ToF);
8938 EXPECT_TRUE(ToX->getInClassInitializer());
8941 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer) {
8942 const char *Code =
8944 struct AP_TECS;
8946 struct AP_Landing {
8947 AP_TECS *TECS_controller;
8950 struct AP_TECS {
8951 AP_Landing landing;
8954 class Plane {
8955 AP_TECS TECS_controller{landing};
8956 AP_Landing landing{&TECS_controller};
8959 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
8961 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
8962 FromTU, cxxRecordDecl(hasName("Plane")));
8963 for (FieldDecl *F : FromR->fields())
8964 EXPECT_TRUE(F->getInClassInitializer());
8965 auto *ToR = Import(FromR, Lang_CXX11);
8966 for (FieldDecl *F : ToR->fields())
8967 EXPECT_TRUE(F->getInClassInitializer());
8970 TEST_P(ASTImporterOptionSpecificTestBase, ImportFieldInitializerWithItself) {
8971 const char *Code =
8973 class A {
8974 int a{a};
8977 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
8978 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8979 FromTU, cxxRecordDecl(hasName("A")));
8980 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());
8981 auto *ToA = Import(FromA, Lang_CXX11);
8982 EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());
8985 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer1) {
8986 // FIXME: This is a example of recursive field initialization that is not
8987 // supported.
8988 // The following import chain occurs (not complete):
8989 // import of A => A.a => in-class initializer of A.a => ref_B() => B => B.b
8990 // => in-class initializer of B.b => ref_A() => CXXConstructExpr for A =>
8991 // CXXDefaultInitExpr for A.a => in-class initializer of A.a
8992 // in-class initializer of A.a is created in two different instances in this
8993 // case (import of FieldDecl and CXXDefaultInitExpr). Probably not a big
8994 // problem because it is an Expr (the second construction can be ignored
8995 // instead of assert). But such recursive init code should not occur in
8996 // practice.
8997 const char *Code =
8999 static int ref_A();
9000 static int ref_B();
9001 struct A {
9002 int a = ref_B();
9004 struct B {
9005 int b = ref_A();
9007 int ref_B() { B b; return b.b; }
9008 int ref_A() { A a; return a.a; }
9010 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9011 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9012 FromTU, cxxRecordDecl(hasName("A")));
9013 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());
9014 // auto *ToA = Import(FromA, Lang_CXX11);
9015 // EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());
9018 TEST_P(ASTImporterOptionSpecificTestBase, isNewDecl) {
9019 Decl *FromTU = getTuDecl(
9021 int bar() {
9022 return 0;
9024 void other() {
9025 bar();
9028 Lang_CXX11);
9029 Decl *ToTU = getToTuDecl(
9031 int bar() {
9032 return 0;
9035 Lang_CXX11);
9036 auto *FromOther = FirstDeclMatcher<FunctionDecl>().match(
9037 FromTU, functionDecl(hasName("other")));
9038 ASSERT_TRUE(FromOther);
9040 auto *ToOther = Import(FromOther, Lang_CXX11);
9041 ASSERT_TRUE(ToOther);
9043 auto *ToBar = FirstDeclMatcher<FunctionDecl>().match(
9044 ToTU, functionDecl(hasName("bar")));
9046 EXPECT_TRUE(SharedStatePtr->isNewDecl(ToOther));
9047 EXPECT_FALSE(SharedStatePtr->isNewDecl(ToBar));
9050 struct ImportInjectedClassNameType : public ASTImporterOptionSpecificTestBase {
9051 protected:
9052 const CXXRecordDecl *findInjected(const CXXRecordDecl *Parent) {
9053 for (Decl *Found : Parent->decls()) {
9054 const auto *Record = dyn_cast<CXXRecordDecl>(Found);
9055 if (Record && Record->isInjectedClassName())
9056 return Record;
9058 return nullptr;
9061 void checkInjType(const CXXRecordDecl *D) {
9062 // The whole redecl chain should have the same InjectedClassNameType
9063 // instance. The injected record declaration is a separate chain, this
9064 // should contain the same type too.
9065 const Type *Ty = nullptr;
9066 for (const Decl *ReD : D->redecls()) {
9067 const auto *ReRD = cast<CXXRecordDecl>(ReD);
9068 EXPECT_TRUE(ReRD->getTypeForDecl());
9069 EXPECT_TRUE(!Ty || Ty == ReRD->getTypeForDecl());
9070 Ty = ReRD->getTypeForDecl();
9072 ASSERT_TRUE(Ty);
9073 const auto *InjTy = Ty->castAs<InjectedClassNameType>();
9074 EXPECT_TRUE(InjTy);
9075 if (CXXRecordDecl *Def = D->getDefinition()) {
9076 const CXXRecordDecl *InjRD = findInjected(Def);
9077 EXPECT_TRUE(InjRD);
9078 EXPECT_EQ(InjRD->getTypeForDecl(), InjTy);
9082 void testImport(Decl *ToTU, Decl *FromTU, Decl *FromD) {
9083 checkInjType(cast<CXXRecordDecl>(FromD));
9084 Decl *ToD = Import(FromD, Lang_CXX11);
9085 if (auto *ToRD = dyn_cast<CXXRecordDecl>(ToD))
9086 checkInjType(ToRD);
9089 const char *ToCodeA =
9091 template <class T>
9092 struct A;
9094 const char *ToCodeADef =
9096 template <class T>
9097 struct A {
9098 typedef A T1;
9101 const char *ToCodeC =
9103 template <class T>
9104 struct C;
9106 const char *ToCodeCDef =
9108 template <class T>
9109 struct A {
9110 typedef A T1;
9113 template <class T1, class T2>
9114 struct B {};
9116 template<class T>
9117 struct C {
9118 typedef typename A<T>::T1 T1;
9119 typedef B<T1, T> T2;
9120 typedef B<T1, C> T3;
9123 const char *FromCode =
9125 template <class T>
9126 struct A;
9127 template <class T>
9128 struct A {
9129 typedef A T1;
9131 template <class T>
9132 struct A;
9134 template <class T1, class T2>
9135 struct B {};
9137 template <class T>
9138 struct C;
9139 template <class T>
9140 struct C {
9141 typedef typename A<T>::T1 T1;
9142 typedef B<T1, T> T2;
9143 typedef B<T1, C> T3;
9145 template <class T>
9146 struct C;
9148 template <class T>
9149 struct D {
9150 void f(typename C<T>::T3 *);
9155 TEST_P(ImportInjectedClassNameType, ImportADef) {
9156 Decl *ToTU = getToTuDecl(ToCodeA, Lang_CXX11);
9157 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9158 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9159 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
9160 testImport(ToTU, FromTU, FromA);
9163 TEST_P(ImportInjectedClassNameType, ImportAFirst) {
9164 Decl *ToTU = getToTuDecl(ToCodeA, Lang_CXX11);
9165 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9166 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9167 FromTU, cxxRecordDecl(hasName("A")));
9168 testImport(ToTU, FromTU, FromA);
9171 TEST_P(ImportInjectedClassNameType, ImportALast) {
9172 Decl *ToTU = getToTuDecl(ToCodeA, Lang_CXX11);
9173 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9174 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(
9175 FromTU, cxxRecordDecl(hasName("A")));
9176 testImport(ToTU, FromTU, FromA);
9179 TEST_P(ImportInjectedClassNameType, ImportADefToDef) {
9180 Decl *ToTU = getToTuDecl(ToCodeADef, Lang_CXX11);
9181 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9182 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9183 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
9184 testImport(ToTU, FromTU, FromA);
9187 TEST_P(ImportInjectedClassNameType, ImportAFirstToDef) {
9188 Decl *ToTU = getToTuDecl(ToCodeADef, Lang_CXX11);
9189 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9190 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9191 FromTU, cxxRecordDecl(hasName("A")));
9192 testImport(ToTU, FromTU, FromA);
9195 TEST_P(ImportInjectedClassNameType, ImportALastToDef) {
9196 Decl *ToTU = getToTuDecl(ToCodeADef, Lang_CXX11);
9197 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9198 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(
9199 FromTU, cxxRecordDecl(hasName("A")));
9200 testImport(ToTU, FromTU, FromA);
9203 TEST_P(ImportInjectedClassNameType, ImportCDef) {
9204 Decl *ToTU = getToTuDecl(ToCodeC, Lang_CXX11);
9205 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9206 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
9207 FromTU, cxxRecordDecl(hasName("C"), isDefinition()));
9208 testImport(ToTU, FromTU, FromC);
9211 TEST_P(ImportInjectedClassNameType, ImportCLast) {
9212 Decl *ToTU = getToTuDecl(ToCodeC, Lang_CXX11);
9213 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9214 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(
9215 FromTU, cxxRecordDecl(hasName("C")));
9216 testImport(ToTU, FromTU, FromC);
9219 TEST_P(ImportInjectedClassNameType, ImportCDefToDef) {
9220 Decl *ToTU = getToTuDecl(ToCodeCDef, Lang_CXX11);
9221 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9222 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
9223 FromTU, cxxRecordDecl(hasName("C"), isDefinition()));
9224 testImport(ToTU, FromTU, FromC);
9227 TEST_P(ImportInjectedClassNameType, ImportCLastToDef) {
9228 Decl *ToTU = getToTuDecl(ToCodeCDef, Lang_CXX11);
9229 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9230 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(
9231 FromTU, cxxRecordDecl(hasName("C")));
9232 testImport(ToTU, FromTU, FromC);
9235 TEST_P(ImportInjectedClassNameType, ImportD) {
9236 Decl *ToTU = getToTuDecl("", Lang_CXX11);
9237 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9238 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
9239 FromTU, cxxRecordDecl(hasName("D"), isDefinition()));
9240 testImport(ToTU, FromTU, FromD);
9243 TEST_P(ImportInjectedClassNameType, ImportDToDef) {
9244 Decl *ToTU = getToTuDecl(ToCodeCDef, Lang_CXX11);
9245 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);
9246 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
9247 FromTU, cxxRecordDecl(hasName("D"), isDefinition()));
9248 testImport(ToTU, FromTU, FromD);
9251 TEST_P(ImportInjectedClassNameType, ImportTypedefType) {
9252 Decl *ToTU = getToTuDecl(
9254 template <class T>
9255 struct A {
9256 typedef A A1;
9257 void f(A1 *);
9260 Lang_CXX11);
9261 Decl *FromTU = getTuDecl(
9263 template <class T>
9264 struct A {
9265 typedef A A1;
9266 void f(A1 *);
9268 template<class T>
9269 void A<T>::f(A::A1 *) {}
9271 Lang_CXX11);
9273 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
9274 FromTU, functionDecl(hasName("f"), isDefinition()));
9275 auto *ToF = Import(FromF, Lang_CXX11);
9276 EXPECT_TRUE(ToF);
9277 ASTContext &ToCtx = ToF->getDeclContext()->getParentASTContext();
9279 auto *ToA1 =
9280 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("A1")));
9281 QualType ToInjTypedef = ToA1->getUnderlyingType().getCanonicalType();
9282 QualType ToInjParmVar =
9283 ToF->parameters()[0]->getType().getDesugaredType(ToCtx);
9284 ToInjParmVar =
9285 ToInjParmVar->getAs<PointerType>()->getPointeeType().getCanonicalType();
9286 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjTypedef));
9287 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjParmVar));
9288 EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
9291 TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
9292 Decl *From, *To;
9293 std::tie(From, To) = getImportedDecl(
9295 #define CDECL __attribute__((cdecl))
9296 typedef void (CDECL *X)();
9298 Lang_CXX03, "", Lang_CXX03, "X");
9300 auto *FromTy =
9301 FirstDeclMatcher<MacroQualifiedType>().match(From, macroQualifiedType());
9302 auto *ToTy =
9303 FirstDeclMatcher<MacroQualifiedType>().match(To, macroQualifiedType());
9305 EXPECT_TRUE(isa<AttributedType>(FromTy->getUnderlyingType()));
9306 EXPECT_TRUE(isa<AttributedType>(ToTy->getUnderlyingType()));
9309 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
9310 constexpr auto TestCode = R"(
9311 template <class T>
9312 struct A;
9313 template <class T>
9314 struct A {};
9315 template <template<class> class T = A>
9316 struct B {};
9317 using C = B<>;
9319 Decl *ToTU = getToTuDecl(TestCode, Lang_CXX11);
9320 Decl *FromTU = getTuDecl(TestCode, Lang_CXX11);
9322 auto *ToUsingFirst = FirstDeclMatcher<TypeAliasDecl>().match(
9323 ToTU, typeAliasDecl(hasName("C")));
9325 auto *FromUsing = FirstDeclMatcher<TypeAliasDecl>().match(
9326 FromTU, typeAliasDecl(hasName("C")));
9327 auto *ToUsing = Import(FromUsing, Lang_CXX11);
9328 EXPECT_TRUE(ToUsing);
9330 auto *ToB = FirstDeclMatcher<ClassTemplateDecl>().match(
9331 ToTU, classTemplateDecl(hasName("B")));
9332 auto *ToB1 = LastDeclMatcher<ClassTemplateDecl>().match(
9333 ToTU, classTemplateDecl(hasName("B")));
9334 // One template definition of 'B' should exist.
9335 EXPECT_EQ(ToB, ToB1);
9337 // These declarations are imported separately.
9338 EXPECT_NE(ToUsingFirst, ToUsing);
9340 auto SpB = ToB->spec_begin();
9341 auto SpE = ToB->spec_end();
9342 EXPECT_TRUE(SpB != SpE);
9343 ClassTemplateSpecializationDecl *Spec1 = *SpB;
9344 ++SpB;
9345 // The template 'B' should have one specialization (with default argument).
9346 EXPECT_TRUE(SpB == SpE);
9348 // Even if 'B' has one specialization with the default arguments, the AST
9349 // contains after the import two specializations that are linked in the
9350 // declaration chain. The 'spec_begin' iteration does not find these because
9351 // the template arguments are the same. But the imported type alias has the
9352 // link to the second specialization. The template name object in these
9353 // specializations must point to the same (and one) instance of definition of
9354 // 'B'.
9355 auto *Spec2 = cast<ClassTemplateSpecializationDecl>(
9356 ToUsing->getUnderlyingType()
9357 ->getAs<TemplateSpecializationType>()
9358 ->getAsRecordDecl());
9359 EXPECT_NE(Spec1, Spec2);
9360 EXPECT_TRUE(Spec1->getPreviousDecl() == Spec2 ||
9361 Spec2->getPreviousDecl() == Spec1);
9362 TemplateDecl *Templ1 =
9363 Spec1->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();
9364 TemplateDecl *Templ2 =
9365 Spec2->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();
9366 EXPECT_EQ(Templ1, Templ2);
9369 TEST_P(ASTImporterOptionSpecificTestBase, VaListC) {
9370 Decl *FromTU = getTuDecl(R"(typedef __builtin_va_list va_list;)", Lang_C99);
9372 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(
9373 FromTU, typedefDecl(hasName("va_list")));
9374 ASSERT_TRUE(FromVaList);
9376 auto *ToVaList = Import(FromVaList, Lang_C99);
9377 ASSERT_TRUE(ToVaList);
9379 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(
9380 ToAST->getASTContext().getTranslationUnitDecl(),
9381 typedefDecl(hasName("__builtin_va_list")));
9383 ASSERT_TRUE(ToAST->getASTContext().hasSameType(
9384 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));
9387 TEST_P(ASTImporterOptionSpecificTestBase, VaListCpp) {
9388 Decl *FromTU = getTuDecl(R"(typedef __builtin_va_list va_list;)", Lang_CXX03);
9390 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(
9391 FromTU, typedefDecl(hasName("va_list")));
9392 ASSERT_TRUE(FromVaList);
9394 auto *ToVaList = Import(FromVaList, Lang_CXX03);
9395 ASSERT_TRUE(ToVaList);
9397 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(
9398 ToAST->getASTContext().getTranslationUnitDecl(),
9399 typedefDecl(hasName("__builtin_va_list")));
9401 ASSERT_TRUE(ToAST->getASTContext().hasSameType(
9402 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));
9405 TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingTypedefToRecord) {
9406 const char *Code =
9408 struct S { int i; };
9409 typedef struct S T;
9410 extern T x;
9412 Decl *ToTU = getToTuDecl(Code, Lang_C99);
9413 Decl *FromTU = getTuDecl(Code, Lang_C99);
9415 auto *FromX =
9416 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));
9417 auto *ToX = Import(FromX, Lang_C99);
9418 EXPECT_TRUE(ToX);
9420 auto *Typedef1 =
9421 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
9422 auto *Typedef2 =
9423 LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
9424 EXPECT_EQ(Typedef1, Typedef2);
9427 TEST_P(ASTImporterOptionSpecificTestBase,
9428 ImportExistingTypedefToUnnamedRecord) {
9429 const char *Code =
9431 typedef const struct { int f; } T;
9432 extern T x;
9434 Decl *ToTU = getToTuDecl(Code, Lang_C99);
9435 Decl *FromTU = getTuDecl(Code, Lang_C99);
9437 auto *FromX =
9438 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));
9439 auto *ToX = Import(FromX, Lang_C99);
9440 EXPECT_TRUE(ToX);
9442 auto *Typedef1 =
9443 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
9444 auto *Typedef2 =
9445 LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
9446 EXPECT_NE(Typedef1, Typedef2);
9447 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),
9448 Typedef2->getUnderlyingType().getTypePtr());
9449 EXPECT_EQ(ToX->getType()->getAs<TypedefType>()->getDecl(), Typedef2);
9452 TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) {
9453 const char *Code =
9455 typedef struct { int f; } T1;
9456 typedef struct { int f; } T2;
9457 extern T1 x1;
9458 extern T2 x2;
9460 Decl *ToTU = getToTuDecl("", Lang_C99);
9461 Decl *FromTU = getTuDecl(Code, Lang_C99);
9463 auto *FromX1 =
9464 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x1")));
9465 auto *FromX2 =
9466 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x2")));
9467 auto *ToX1 = Import(FromX1, Lang_C99);
9468 EXPECT_TRUE(ToX1);
9469 auto *ToX2 = Import(FromX2, Lang_C99);
9470 EXPECT_TRUE(ToX2);
9472 auto *Typedef1 =
9473 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T1")));
9474 auto *Typedef2 =
9475 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T2")));
9476 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),
9477 Typedef2->getUnderlyingType().getTypePtr());
9480 TEST_P(ASTImporterOptionSpecificTestBase,
9481 ImportExistingTypedefToUnnamedRecordPtr) {
9482 const char *Code =
9484 typedef const struct { int fff; } * const T;
9485 extern T x;
9487 Decl *ToTU = getToTuDecl(Code, Lang_C99);
9488 Decl *FromTU = getTuDecl(Code, Lang_C99);
9490 auto *FromX =
9491 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));
9492 auto *ToX = Import(FromX, Lang_C99);
9493 EXPECT_TRUE(ToX);
9495 auto *Typedef1 =
9496 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
9497 auto *Typedef2 =
9498 LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
9499 // FIXME: These should be imported separately, like in the test above.
9500 // Or: In the test above these should be merged too.
9501 EXPECT_EQ(Typedef1, Typedef2);
9503 auto *FromR = FirstDeclMatcher<RecordDecl>().match(
9504 FromTU, recordDecl(hasDescendant(fieldDecl(hasName("fff")))));
9505 auto *ToRExisting = FirstDeclMatcher<RecordDecl>().match(
9506 ToTU, recordDecl(hasDescendant(fieldDecl(hasName("fff")))));
9507 ASSERT_TRUE(FromR);
9508 auto *ToRImported = Import(FromR, Lang_C99);
9509 // FIXME: If typedefs are not imported separately, do not import ToRImported
9510 // separately.
9511 EXPECT_NE(ToRExisting, ToRImported);
9514 TEST_P(ASTImporterOptionSpecificTestBase,
9515 ImportTypedefWithDifferentUnderlyingType) {
9516 const char *Code =
9518 using X1 = int;
9519 using Y1 = int;
9521 using RPB1 = X1*;
9522 typedef RPB1 RPX1;
9523 using RPB1 = Y1*; // redeclared
9524 typedef RPB1 RPY1;
9526 auto X = 0 ? (RPX1){} : (RPY1){};
9528 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9530 auto *FromX =
9531 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("X")));
9533 auto *FromXType = FromX->getType()->getAs<TypedefType>();
9534 EXPECT_FALSE(FromXType->typeMatchesDecl());
9536 auto *ToX = Import(FromX, Lang_CXX11);
9537 auto *ToXType = ToX->getType()->getAs<TypedefType>();
9538 // FIXME: This should be false.
9539 EXPECT_TRUE(ToXType->typeMatchesDecl());
9542 TEST_P(ASTImporterOptionSpecificTestBase,
9543 ImportTemplateArgumentWithPointerToDifferentInstantiation) {
9544 const char *CodeTo =
9546 template<class A>
9547 A f1() {
9548 return A();
9550 template<class A, A (B)()>
9551 class X {};
9553 X<int, f1<int>> x;
9555 const char *CodeFrom =
9557 template<class A>
9558 A f1();
9559 template<class A, A (B)()>
9560 class X {};
9562 X<int, f1<int>> x;
9564 Decl *ToTU = getToTuDecl(CodeTo, Lang_CXX11);
9565 Decl *FromTU = getTuDecl(CodeFrom, Lang_CXX11);
9567 auto *ToF1 = FirstDeclMatcher<FunctionDecl>().match(
9568 ToTU, functionDecl(hasName("f1"), isInstantiated()));
9569 auto *FromF1 = FirstDeclMatcher<FunctionDecl>().match(
9570 FromTU, functionDecl(hasName("f1"), isInstantiated()));
9571 EXPECT_TRUE(ToF1->isThisDeclarationADefinition());
9572 EXPECT_FALSE(FromF1->isThisDeclarationADefinition());
9574 auto *ToX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9575 ToTU, classTemplateSpecializationDecl(hasName("X")));
9576 auto *FromX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9577 FromTU, classTemplateSpecializationDecl(hasName("X")));
9579 Decl *ToTArgF = ToX->getTemplateArgs().get(1).getAsDecl();
9580 Decl *FromTArgF = FromX->getTemplateArgs().get(1).getAsDecl();
9581 EXPECT_EQ(ToTArgF, ToF1);
9582 EXPECT_EQ(FromTArgF, FromF1);
9584 auto *ToXImported = Import(FromX, Lang_CXX11);
9585 // The template argument 1 of 'X' in the "From" code points to a function
9586 // that has no definition. The import must ensure that this template argument
9587 // is imported in a way that it will point to the existing 'f1' function, not
9588 // to the 'f1' that is imported. In this way when specialization of 'X' is
9589 // imported it will have the same template arguments as the existing one.
9590 EXPECT_EQ(ToXImported, ToX);
9591 // FIXME: This matcher causes a crash "Tried to match orphan node".
9592 // The code is removed until the problem is fixed.
9593 // auto *ToF1Imported =
9594 // LastDeclMatcher<FunctionDecl>().match(ToTU,
9595 // functionDecl(hasName("f1"),isInstantiated()));
9596 // EXPECT_NE(ToF1Imported, ToF1);
9597 // EXPECT_EQ(ToF1Imported->getPreviousDecl(), ToF1);
9600 TEST_P(ASTImporterOptionSpecificTestBase,
9601 ImportTypeAliasTemplateAfterSimilarCalledTemplateTypeParm) {
9602 const char *Code =
9604 struct S;
9605 template <typename>
9606 using Callable = S;
9607 template <typename Callable>
9608 int bindingFunctionVTable;
9610 Decl *FromTU = getTuDecl(Code, Lang_CXX17);
9612 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
9613 FromTU, typeAliasTemplateDecl(hasName("Callable")));
9615 auto *FromCallableParm = FirstDeclMatcher<TemplateTypeParmDecl>().match(
9616 FromTU, templateTypeParmDecl(hasName("Callable")));
9618 auto *ToFromCallableParm = Import(FromCallableParm, Lang_CXX17);
9619 auto *ToCallable = Import(FromCallable, Lang_CXX17);
9620 EXPECT_TRUE(ToFromCallableParm);
9621 EXPECT_TRUE(ToCallable);
9624 TEST_P(ASTImporterOptionSpecificTestBase, ImportConflictTypeAliasTemplate) {
9625 const char *ToCode =
9627 struct S;
9628 template <typename, typename>
9629 using Callable = S;
9631 const char *Code =
9633 struct S;
9634 template <typename>
9635 using Callable = S;
9637 (void)getToTuDecl(ToCode, Lang_CXX17);
9638 Decl *FromTU = getTuDecl(Code, Lang_CXX17);
9640 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
9641 FromTU, typeAliasTemplateDecl(hasName("Callable")));
9643 auto *ImportedCallable = Import(FromCallable, Lang_CXX17);
9644 EXPECT_FALSE(ImportedCallable);
9647 AST_MATCHER(ClassTemplateSpecializationDecl, hasInstantiatedFromMember) {
9648 if (auto Instantiate = Node.getInstantiatedFrom()) {
9649 if (auto *FromPartialSpecialization =
9650 cast<ClassTemplatePartialSpecializationDecl *>(Instantiate)) {
9651 return nullptr != FromPartialSpecialization->getInstantiatedFromMember();
9654 return false;
9657 TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) {
9658 const char *Code =
9660 template <typename> struct B {
9661 template <typename, bool = false> union D;
9662 template <typename T> union D<T> {};
9663 D<int> d;
9665 B<int> b;
9667 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9668 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9669 FromTU, classTemplateSpecializationDecl(hasName("D"),
9670 hasInstantiatedFromMember()));
9671 auto *FromPartialSpecialization =
9672 cast<ClassTemplatePartialSpecializationDecl *>(
9673 FromD->getInstantiatedFrom());
9674 ASSERT_TRUE(FromPartialSpecialization->getInstantiatedFromMember());
9675 auto *ImportedPartialSpecialization =
9676 Import(FromPartialSpecialization, Lang_CXX11);
9677 EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember());
9680 AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) {
9681 for (EnumConstantDecl *D : Node.enumerators())
9682 if (D->getName() == ConstName)
9683 return true;
9684 return false;
9687 TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnums) {
9688 const char *Code =
9690 struct A {
9691 enum { E1, E2 } x;
9692 enum { E3, E4 } y;
9695 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9696 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9697 FromTU, enumDecl(hasEnumConstName("E1")));
9698 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9699 EXPECT_TRUE(ImportedEnumE1);
9700 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9701 FromTU, enumDecl(hasEnumConstName("E3")));
9702 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9703 EXPECT_TRUE(ImportedEnumE3);
9704 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9707 TEST_P(ASTImporterOptionSpecificTestBase, ImportFreeStandingAnonymousEnums) {
9708 const char *Code =
9710 struct A {
9711 enum { E1, E2 };
9712 enum { E3, E4 };
9715 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9716 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9717 FromTU, enumDecl(hasEnumConstName("E1")));
9718 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9719 EXPECT_TRUE(ImportedEnumE1);
9720 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9721 FromTU, enumDecl(hasEnumConstName("E3")));
9722 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9723 EXPECT_TRUE(ImportedEnumE3);
9724 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9727 TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingAnonymousEnums) {
9728 const char *ToCode =
9730 struct A {
9731 enum { E1, E2 } x;
9732 enum { E3, E4 } y;
9735 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);
9736 auto *ToEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9737 ToTU, enumDecl(hasEnumConstName("E1")));
9738 auto *ToEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9739 ToTU, enumDecl(hasEnumConstName("E3")));
9740 const char *Code =
9742 struct A {
9743 enum { E1, E2 } x;
9744 enum { E3, E4 } y;
9747 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9748 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9749 FromTU, enumDecl(hasEnumConstName("E1")));
9750 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9751 ASSERT_TRUE(ImportedEnumE1);
9752 EXPECT_EQ(ImportedEnumE1, ToEnumE1);
9753 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9754 FromTU, enumDecl(hasEnumConstName("E3")));
9755 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9756 ASSERT_TRUE(ImportedEnumE3);
9757 EXPECT_EQ(ImportedEnumE3, ToEnumE3);
9760 TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingEmptyAnonymousEnums) {
9761 const char *ToCode =
9763 struct A {
9764 enum {};
9767 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);
9768 auto *ToE1 = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl());
9769 const char *Code =
9771 struct A {
9772 enum {};
9773 enum {};
9776 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
9777 auto *FromE1 = FirstDeclMatcher<EnumDecl>().match(FromTU, enumDecl());
9778 auto *ImportedE1 = Import(FromE1, Lang_CXX11);
9779 ASSERT_TRUE(ImportedE1);
9780 EXPECT_EQ(ImportedE1, ToE1);
9781 auto *FromE2 = LastDeclMatcher<EnumDecl>().match(FromTU, enumDecl());
9782 ASSERT_NE(FromE1, FromE2);
9783 auto *ImportedE2 = Import(FromE2, Lang_CXX11);
9784 ASSERT_TRUE(ImportedE2);
9785 // FIXME: These should not be equal, or the import should fail.
9786 EXPECT_EQ(ImportedE2, ToE1);
9789 TEST_P(ASTImporterOptionSpecificTestBase, ImportMultipleAnonymousEnumDecls) {
9790 Decl *ToTU = getToTuDecl("", Lang_CXX03);
9791 Decl *FromTU = getTuDecl(
9793 struct foo {
9794 enum { A };
9795 enum { B };
9798 Lang_CXX03);
9800 auto EnumConstA = enumConstantDecl(hasName("A"));
9801 auto EnumConstB = enumConstantDecl(hasName("B"));
9803 auto *FromA = FirstDeclMatcher<EnumConstantDecl>().match(FromTU, EnumConstA);
9804 auto *FromB = FirstDeclMatcher<EnumConstantDecl>().match(FromTU, EnumConstB);
9806 auto *ToA = Import(FromA, Lang_CXX03);
9807 auto *ToB = Import(FromB, Lang_CXX03);
9809 ASSERT_TRUE(ToA);
9810 ASSERT_TRUE(ToB);
9812 auto *ToFooA = FirstDeclMatcher<CXXRecordDecl>().match(
9813 ToTU, tagDecl(has(enumDecl(has(EnumConstA)))));
9814 auto *ToFooB = FirstDeclMatcher<CXXRecordDecl>().match(
9815 ToTU, tagDecl(has(enumDecl(has(EnumConstB)))));
9816 ASSERT_EQ(ToFooA, ToFooB);
9818 // different EnumDecl
9819 auto *ToEnumDeclA =
9820 FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(has(EnumConstA)));
9821 auto *ToEnumDeclB =
9822 FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(has(EnumConstB)));
9823 ASSERT_NE(ToEnumDeclA, ToEnumDeclB);
9826 struct ImportTemplateParmDeclDefaultValue
9827 : public ASTImporterOptionSpecificTestBase {
9828 protected:
9829 void checkTemplateParams(RedeclarableTemplateDecl *D,
9830 RedeclarableTemplateDecl *InheritedFromD) {
9831 auto *NonTypeP =
9832 cast<NonTypeTemplateParmDecl>(D->getTemplateParameters()->getParam(0));
9833 auto *TypeP =
9834 cast<TemplateTypeParmDecl>(D->getTemplateParameters()->getParam(1));
9835 auto *TemplateP =
9836 cast<TemplateTemplateParmDecl>(D->getTemplateParameters()->getParam(2));
9837 if (InheritedFromD) {
9838 EXPECT_TRUE(NonTypeP->getDefaultArgStorage().isInherited());
9839 EXPECT_TRUE(TypeP->getDefaultArgStorage().isInherited());
9840 EXPECT_TRUE(TemplateP->getDefaultArgStorage().isInherited());
9841 EXPECT_EQ(NonTypeP->getDefaultArgStorage().getInheritedFrom(),
9842 InheritedFromD->getTemplateParameters()->getParam(0));
9843 EXPECT_EQ(TypeP->getDefaultArgStorage().getInheritedFrom(),
9844 InheritedFromD->getTemplateParameters()->getParam(1));
9845 EXPECT_EQ(TemplateP->getDefaultArgStorage().getInheritedFrom(),
9846 InheritedFromD->getTemplateParameters()->getParam(2));
9847 } else {
9848 EXPECT_FALSE(NonTypeP->getDefaultArgStorage().isInherited());
9849 EXPECT_FALSE(TypeP->getDefaultArgStorage().isInherited());
9850 EXPECT_FALSE(TemplateP->getDefaultArgStorage().isInherited());
9854 void testImport(RedeclarableTemplateDecl *FromD1,
9855 RedeclarableTemplateDecl *FromD2,
9856 RedeclarableTemplateDecl *FromD3,
9857 RedeclarableTemplateDecl *ToExistingD1) {
9858 auto *ToD1 = Import(FromD1, Lang_CXX14);
9859 auto *ToD2 = Import(FromD2, Lang_CXX14);
9860 auto *ToD3 = Import(FromD3, Lang_CXX14);
9861 checkTemplateParams(ToD1, nullptr);
9862 checkTemplateParams(ToD2, ToD1);
9863 checkTemplateParams(ToD3, ToExistingD1 ? ToExistingD1 : ToD1);
9866 // In these tests a circular dependency is created between the template
9867 // parameter default value and the template declaration (with the same
9868 // template parameter).
9869 template <class TemplateParmDeclT>
9870 void
9871 testTemplateParmDeclCircularDependency(ClassTemplateDecl *FromD,
9872 ClassTemplateDecl *FromDInherited) {
9873 auto GetTemplateParm =
9874 [](ClassTemplateDecl *D) -> const TemplateParmDeclT * {
9875 return dyn_cast<TemplateParmDeclT>(
9876 D->getTemplateParameters()->getParam(0));
9879 ASSERT_FALSE(GetTemplateParm(FromD)->getDefaultArgStorage().isInherited());
9880 ASSERT_TRUE(
9881 GetTemplateParm(FromDInherited)->getDefaultArgStorage().isInherited());
9883 auto *ToD = Import(FromD, Lang_CXX14);
9884 EXPECT_TRUE(ToD);
9886 auto *ToDInherited = Import(FromDInherited, Lang_CXX14);
9887 EXPECT_TRUE(ToDInherited);
9889 EXPECT_FALSE(GetTemplateParm(ToD)->getDefaultArgStorage().isInherited());
9890 EXPECT_TRUE(
9891 GetTemplateParm(ToDInherited)->getDefaultArgStorage().isInherited());
9892 EXPECT_EQ(GetTemplateParm(ToDInherited)
9893 ->getDefaultArgStorage()
9894 .getInheritedFrom(),
9895 GetTemplateParm(ToD));
9897 EXPECT_EQ(ToD->getPreviousDecl(), ToDInherited);
9900 const char *CodeFunction =
9902 template <class> struct X;
9904 template <int A = 2, typename B = int, template<class> class C = X>
9905 void test();
9906 template <int A, typename B, template<class> class C>
9907 void test();
9908 template <int A, typename B, template<class> class C>
9909 void test() {}
9912 const char *CodeClass =
9914 namespace N {
9915 template <class> struct X;
9917 template <int A = 2, typename B = int, template<class> class C = X>
9918 struct test;
9919 template <int A, typename B, template<class> class C>
9920 struct test;
9921 template <int A, typename B, template<class> class C>
9922 struct test {};
9926 const char *CodeVar =
9928 namespace N {
9929 template <class> struct X;
9931 template <int A = 2, typename B = int, template<class> class C = X>
9932 extern int test;
9933 template <int A, typename B, template<class> class C>
9934 extern int test;
9935 template <int A, typename B, template<class> class C>
9936 int test = A;
9941 TEST_P(ImportTemplateParmDeclDefaultValue, InvisibleInheritedFrom) {
9942 const char *ToCode =
9944 template <int P = 1>
9945 void f() {}
9947 TranslationUnitDecl *ToTU = getToTuDecl(ToCode, Lang_CXX14);
9948 auto *ToFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(
9949 ToTU, functionTemplateDecl(hasName("f")));
9951 const char *FromCode =
9953 template <int P = 1>
9954 void f() {}
9955 template <int P>
9956 void f();
9958 TranslationUnitDecl *FromTU = getTuDecl(FromCode, Lang_CXX14);
9959 auto *FromFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(
9960 FromTU, functionTemplateDecl(hasName("f")));
9961 auto *FromF = LastDeclMatcher<FunctionTemplateDecl>().match(
9962 FromTU, functionTemplateDecl(hasName("f")));
9964 auto *ToFDefImported = Import(FromFDef, Lang_CXX14);
9965 EXPECT_EQ(ToFDefImported, ToFDef);
9966 auto *ToF = Import(FromF, Lang_CXX14);
9967 EXPECT_NE(ToF, ToFDef);
9968 const auto *Parm = dyn_cast<NonTypeTemplateParmDecl>(
9969 ToF->getTemplateParameters()->getParam(0));
9970 EXPECT_TRUE(Parm->defaultArgumentWasInherited());
9971 // FIXME: This behavior may be confusing:
9972 // Default value is not inherited from the existing declaration, instead a new
9973 // is created at import that is similar to the existing but not reachable from
9974 // the AST.
9975 EXPECT_NE(Parm->getDefaultArgStorage().getInheritedFrom(),
9976 ToFDef->getTemplateParameters()->getParam(0));
9979 TEST_P(ImportTemplateParmDeclDefaultValue, DefValImportError) {
9980 const char *ToCode =
9982 class X {
9983 int A;
9986 getToTuDecl(ToCode, Lang_CXX14);
9988 const char *FromCode =
9990 class X;
9992 template <typename P = X>
9993 void f() {}
9995 class X {
9996 char A;
9999 TranslationUnitDecl *FromTU = getTuDecl(FromCode, Lang_CXX14);
10000 auto *FromF = FirstDeclMatcher<FunctionTemplateDecl>().match(
10001 FromTU, functionTemplateDecl(hasName("f")));
10003 auto *ToFImported = Import(FromF, Lang_CXX14);
10004 EXPECT_FALSE(ToFImported);
10007 TEST_P(ImportTemplateParmDeclDefaultValue, ImportFunctionTemplate) {
10008 TranslationUnitDecl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);
10009 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
10010 FromTU, functionTemplateDecl(hasName("test") /*, hasBody(stmt())*/));
10011 auto *D2 = dyn_cast<FunctionTemplateDecl>(D3->getPreviousDecl());
10012 auto *D1 = dyn_cast<FunctionTemplateDecl>(D2->getPreviousDecl());
10013 testImport(D1, D2, D3, nullptr);
10016 TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingFunctionTemplate) {
10017 TranslationUnitDecl *ToTU = getToTuDecl(CodeFunction, Lang_CXX14);
10018 auto *ToD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
10019 ToTU, functionTemplateDecl(hasName("test")));
10020 TranslationUnitDecl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);
10021 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
10022 FromTU, functionTemplateDecl(hasName("test")));
10023 auto *D2 = dyn_cast<FunctionTemplateDecl>(D3->getPreviousDecl());
10024 auto *D1 = dyn_cast<FunctionTemplateDecl>(D2->getPreviousDecl());
10025 testImport(D1, D2, D3, ToD1);
10028 TEST_P(ImportTemplateParmDeclDefaultValue, ImportClassTemplate) {
10029 TranslationUnitDecl *FromTU = getTuDecl(CodeClass, Lang_CXX14);
10030 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(
10031 FromTU, classTemplateDecl(hasName("test")));
10032 auto *D2 = dyn_cast<ClassTemplateDecl>(D3->getPreviousDecl());
10033 auto *D1 = dyn_cast<ClassTemplateDecl>(D2->getPreviousDecl());
10034 testImport(D1, D2, D3, nullptr);
10037 TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingClassTemplate) {
10038 TranslationUnitDecl *ToTU = getToTuDecl(CodeClass, Lang_CXX14);
10039 auto *ToD1 = FirstDeclMatcher<ClassTemplateDecl>().match(
10040 ToTU, classTemplateDecl(hasName("test")));
10041 TranslationUnitDecl *FromTU = getTuDecl(CodeClass, Lang_CXX14);
10042 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(
10043 FromTU, classTemplateDecl(hasName("test")));
10044 auto *D2 = dyn_cast<ClassTemplateDecl>(D3->getPreviousDecl());
10045 auto *D1 = dyn_cast<ClassTemplateDecl>(D2->getPreviousDecl());
10046 testImport(D1, D2, D3, ToD1);
10049 TEST_P(ImportTemplateParmDeclDefaultValue, ImportVarTemplate) {
10050 TranslationUnitDecl *FromTU = getTuDecl(CodeVar, Lang_CXX14);
10051 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(
10052 FromTU, varTemplateDecl(hasName("test")));
10053 auto *D2 = dyn_cast<VarTemplateDecl>(D3->getPreviousDecl());
10054 auto *D1 = dyn_cast<VarTemplateDecl>(D2->getPreviousDecl());
10055 testImport(D1, D2, D3, nullptr);
10058 TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingVarTemplate) {
10059 TranslationUnitDecl *ToTU = getToTuDecl(CodeVar, Lang_CXX14);
10060 auto *ToD1 = FirstDeclMatcher<VarTemplateDecl>().match(
10061 ToTU, varTemplateDecl(hasName("test")));
10062 TranslationUnitDecl *FromTU = getTuDecl(CodeVar, Lang_CXX14);
10063 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(
10064 FromTU, varTemplateDecl(hasName("test")));
10065 auto *D2 = dyn_cast<VarTemplateDecl>(D3->getPreviousDecl());
10066 auto *D1 = dyn_cast<VarTemplateDecl>(D2->getPreviousDecl());
10067 testImport(D1, D2, D3, ToD1);
10070 TEST_P(ImportTemplateParmDeclDefaultValue,
10071 NonTypeTemplateParmDeclCircularDependency) {
10072 const char *Code =
10074 struct Z;
10076 struct Y {
10077 Z *z;
10078 static const int x = 1;
10081 template <int P1 = Y::x>
10082 struct X;
10084 template <int P2>
10085 struct X {
10086 static const int A = 1;
10089 struct Z {
10090 template<int P>
10091 void f(int A = X<P>::A);
10095 Decl *FromTU = getTuDecl(Code, Lang_CXX14);
10096 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10097 FromTU, classTemplateDecl(hasName("X")));
10098 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10099 FromTU, classTemplateDecl(hasName("X")));
10101 testTemplateParmDeclCircularDependency<NonTypeTemplateParmDecl>(
10102 FromD, FromDInherited);
10105 TEST_P(ImportTemplateParmDeclDefaultValue,
10106 TemplateTypeParmDeclCircularDependency) {
10107 const char *Code =
10109 struct Z;
10111 struct Y {
10112 Z *z;
10115 template <typename T1 = Y>
10116 struct X;
10118 template <typename T2>
10119 struct X {
10120 static const int A = 1;
10123 struct Z {
10124 template<typename T>
10125 void f(int A = X<T>::A);
10129 Decl *FromTU = getTuDecl(Code, Lang_CXX14);
10130 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10131 FromTU, classTemplateDecl(hasName("X")));
10132 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10133 FromTU, classTemplateDecl(hasName("X")));
10135 testTemplateParmDeclCircularDependency<TemplateTypeParmDecl>(FromD,
10136 FromDInherited);
10139 TEST_P(ImportTemplateParmDeclDefaultValue,
10140 TemplateTemplateParmDeclCircularDependency) {
10141 const char *Code =
10143 struct Z;
10145 template <int>
10146 struct Y {
10147 Z *z;
10150 template <template <int> class T1 = Y>
10151 struct X;
10153 template <template <int> class T2>
10154 struct X {
10155 static const int A = 1;
10158 struct Z {
10159 template <template <int> class T>
10160 void f(int A = X<T>::A);
10164 Decl *FromTU = getTuDecl(Code, Lang_CXX14);
10165 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10166 FromTU, classTemplateDecl(hasName("X")));
10167 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10168 FromTU, classTemplateDecl(hasName("X")));
10170 testTemplateParmDeclCircularDependency<TemplateTemplateParmDecl>(
10171 FromD, FromDInherited);
10174 TEST_P(ASTImporterOptionSpecificTestBase,
10175 ExistingUndeclaredImportDeclaredFriend) {
10176 Decl *ToTU = getToTuDecl(
10178 template <class A, A>
10179 struct foo;
10181 template <class A>
10182 struct X {
10183 template <class A1, A1>
10184 friend struct foo;
10187 Lang_CXX11);
10188 Decl *FromTU = getTuDecl(
10190 template <class A, A>
10191 struct foo;
10193 template <class A>
10194 struct X {
10195 template <class A1, A1>
10196 friend struct foo;
10199 X<int> x;
10201 Lang_CXX11);
10203 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
10204 auto *ToFrD1 = ToFr1->getFriendDecl();
10206 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
10207 auto *FromFr2 = LastDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
10209 auto *FromFrD1 = FromFr1->getFriendDecl();
10210 auto *FromFrD2 = FromFr2->getFriendDecl();
10212 auto *Ctx1 = cast<Decl>(FromFrD1->getDeclContext());
10213 auto *Ctx2 = cast<Decl>(FromFrD2->getDeclContext());
10215 ASSERT_EQ(Ctx1, Ctx2);
10216 ASSERT_EQ(ToFrD1->getTemplateDepth(), 1u);
10217 ASSERT_EQ(FromFrD2->getTemplateDepth(), 0u);
10218 ASSERT_EQ(ToFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);
10219 ASSERT_EQ(FromFrD2->getFriendObjectKind(), Decl::FOK_Declared);
10221 auto *ToFr2Imp = Import(FromFr2, Lang_CXX11);
10223 EXPECT_TRUE(ToFr2Imp);
10226 TEST_P(ASTImporterOptionSpecificTestBase,
10227 ExistingDeclaredImportUndeclaredFriend) {
10228 Decl *ToTU = getToTuDecl(
10230 template <class A, A>
10231 struct foo;
10233 template <class A>
10234 struct X {
10235 template <class A1, A1>
10236 friend struct foo;
10239 X<int> x;
10241 Lang_CXX11);
10242 Decl *FromTU = getTuDecl(
10244 template <class A, A>
10245 struct foo;
10247 template <class A>
10248 struct X {
10249 template <class A1, A1>
10250 friend struct foo;
10253 Lang_CXX11);
10255 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
10256 auto *ToFr2 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
10258 auto *ToFrD1 = ToFr1->getFriendDecl();
10259 auto *ToFrD2 = ToFr2->getFriendDecl();
10261 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
10262 auto *FromFrD1 = FromFr1->getFriendDecl();
10264 auto *Ctx1 = cast<Decl>(ToFrD1->getDeclContext());
10265 auto *Ctx2 = cast<Decl>(ToFrD2->getDeclContext());
10267 ASSERT_EQ(Ctx1, Ctx2);
10268 ASSERT_EQ(FromFrD1->getTemplateDepth(), 1u);
10269 ASSERT_EQ(ToFrD2->getTemplateDepth(), 0u);
10270 ASSERT_EQ(FromFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);
10271 ASSERT_EQ(ToFrD2->getFriendObjectKind(), Decl::FOK_Declared);
10273 auto *ToFr1Imp = Import(FromFr1, Lang_CXX11);
10275 EXPECT_TRUE(ToFr1Imp);
10276 EXPECT_EQ(ToFr1Imp, ToFr1);
10279 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
10280 DefaultTestValuesForRunOptions);
10282 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportPath,
10283 ::testing::Values(std::vector<std::string>()));
10285 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportExpr,
10286 DefaultTestValuesForRunOptions);
10288 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFixedPointExpr,
10289 ExtendWithOptions(DefaultTestArrayForRunOptions,
10290 std::vector<std::string>{
10291 "-ffixed-point"}));
10293 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportBlock,
10294 ExtendWithOptions(DefaultTestArrayForRunOptions,
10295 std::vector<std::string>{
10296 "-fblocks"}));
10298 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportType,
10299 DefaultTestValuesForRunOptions);
10301 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportDecl,
10302 DefaultTestValuesForRunOptions);
10304 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
10305 DefaultTestValuesForRunOptions);
10307 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ErrorHandlingTest,
10308 DefaultTestValuesForRunOptions);
10310 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, RedirectingImporterTest,
10311 DefaultTestValuesForRunOptions);
10313 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctions,
10314 DefaultTestValuesForRunOptions);
10316 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAutoFunctions,
10317 DefaultTestValuesForRunOptions);
10319 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctionTemplates,
10320 DefaultTestValuesForRunOptions);
10322 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctionTemplates,
10323 DefaultTestValuesForRunOptions);
10325 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportClasses,
10326 DefaultTestValuesForRunOptions);
10328 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctions,
10329 DefaultTestValuesForRunOptions);
10331 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendClasses,
10332 DefaultTestValuesForRunOptions);
10334 INSTANTIATE_TEST_SUITE_P(ParameterizedTests,
10335 ImportFunctionTemplateSpecializations,
10336 DefaultTestValuesForRunOptions);
10338 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportImplicitMethods,
10339 DefaultTestValuesForRunOptions);
10341 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportVariables,
10342 DefaultTestValuesForRunOptions);
10344 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, LLDBLookupTest,
10345 DefaultTestValuesForRunOptions);
10347 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportSourceLocations,
10348 DefaultTestValuesForRunOptions);
10350 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportWithExternalSource,
10351 DefaultTestValuesForRunOptions);
10353 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAttributes,
10354 DefaultTestValuesForRunOptions);
10356 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportInjectedClassNameType,
10357 DefaultTestValuesForRunOptions);
10359 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportMatrixType,
10360 DefaultTestValuesForRunOptions);
10362 INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportTemplateParmDeclDefaultValue,
10363 DefaultTestValuesForRunOptions);
10365 // FIXME: Make ImportOpenCLPipe test work.
10366 // INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportOpenCLPipe,
10367 // DefaultTestValuesForRunOptions);
10368 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImportOpenCLPipe);
10370 } // end namespace ast_matchers
10371 } // end namespace clang