10843 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Tests for the correct import of AST nodes from one AST context to another.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ExprConcepts.h"14#include "clang/AST/RecordLayout.h"15#include "clang/ASTMatchers/ASTMatchers.h"16#include "clang/Testing/CommandLineArgs.h"17#include "llvm/Support/SmallVectorMemoryBuffer.h"18 19#include "clang/AST/DeclContextInternals.h"20#include "gtest/gtest.h"21 22#include "ASTImporterFixtures.h"23#include <optional>24 25namespace clang {26namespace ast_matchers {27 28using internal::Matcher;29 30static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {31 QualType Ty = FD->getFriendType()->getType().getCanonicalType();32 return cast<RecordType>(Ty)->getDecl();33}34 35struct ImportExpr : TestImportBase {};36struct ImportType : TestImportBase {};37struct ImportDecl : TestImportBase {};38struct ImportFixedPointExpr : ImportExpr {};39 40struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};41 42TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {43 Decl *FromTU = getTuDecl("void f();", Lang_CXX03);44 auto Pattern = functionDecl(hasName("f"));45 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);46 47 auto Redecls = getCanonicalForwardRedeclChain(D0);48 ASSERT_EQ(Redecls.size(), 1u);49 EXPECT_EQ(D0, Redecls[0]);50}51 52TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {53 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);54 auto Pattern = functionDecl(hasName("f"));55 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);56 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);57 FunctionDecl *D1 = D2->getPreviousDecl();58 59 auto Redecls = getCanonicalForwardRedeclChain(D0);60 ASSERT_EQ(Redecls.size(), 3u);61 EXPECT_EQ(D0, Redecls[0]);62 EXPECT_EQ(D1, Redecls[1]);63 EXPECT_EQ(D2, Redecls[2]);64}65 66TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {67 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);68 auto Pattern = functionDecl(hasName("f"));69 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);70 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);71 FunctionDecl *D1 = D2->getPreviousDecl();72 73 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);74 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);75 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);76 77 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));78 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));79}80 81namespace {82struct RedirectingImporter : public ASTImporter {83 using ASTImporter::ASTImporter;84 85protected:86 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {87 auto *ND = dyn_cast<NamedDecl>(FromD);88 if (!ND || ND->getName() != "shouldNotBeImported")89 return ASTImporter::ImportImpl(FromD);90 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {91 if (auto *ND = dyn_cast<NamedDecl>(D))92 if (ND->getName() == "realDecl") {93 RegisterImportedDecl(FromD, ND);94 return ND;95 }96 }97 return ASTImporter::ImportImpl(FromD);98 }99};100 101} // namespace102 103struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {104 RedirectingImporterTest() {105 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,106 ASTContext &FromContext, FileManager &FromFileManager,107 bool MinimalImport,108 const std::shared_ptr<ASTImporterSharedState> &SharedState) {109 return new RedirectingImporter(ToContext, ToFileManager, FromContext,110 FromFileManager, MinimalImport,111 SharedState);112 };113 }114};115 116// Test that an ASTImporter subclass can intercept an import call.117TEST_P(RedirectingImporterTest, InterceptImport) {118 Decl *From, *To;119 std::tie(From, To) =120 getImportedDecl("class shouldNotBeImported {};", Lang_CXX03,121 "class realDecl {};", Lang_CXX03, "shouldNotBeImported");122 auto *Imported = cast<CXXRecordDecl>(To);123 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");124 125 // Make sure our importer prevented the importing of the decl.126 auto *ToTU = Imported->getTranslationUnitDecl();127 auto Pattern = functionDecl(hasName("shouldNotBeImported"));128 unsigned count =129 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);130 EXPECT_EQ(0U, count);131}132 133// Test that when we indirectly import a declaration the custom ASTImporter134// is still intercepting the import.135TEST_P(RedirectingImporterTest, InterceptIndirectImport) {136 Decl *From, *To;137 std::tie(From, To) =138 getImportedDecl("class shouldNotBeImported {};"139 "class F { shouldNotBeImported f; };",140 Lang_CXX03, "class realDecl {};", Lang_CXX03, "F");141 142 // Make sure our ASTImporter prevented the importing of the decl.143 auto *ToTU = To->getTranslationUnitDecl();144 auto Pattern = functionDecl(hasName("shouldNotBeImported"));145 unsigned count =146 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);147 EXPECT_EQ(0U, count);148}149 150struct ImportPath : ASTImporterOptionSpecificTestBase {151 Decl *FromTU;152 FunctionDecl *D0, *D1, *D2;153 ImportPath() {154 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX03);155 auto Pattern = functionDecl(hasName("f"));156 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);157 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);158 D1 = D2->getPreviousDecl();159 }160};161 162TEST_P(ImportPath, Push) {163 ASTImporter::ImportPathTy path;164 path.push(D0);165 EXPECT_FALSE(path.hasCycleAtBack());166}167 168TEST_P(ImportPath, SmallCycle) {169 ASTImporter::ImportPathTy path;170 path.push(D0);171 path.push(D0);172 EXPECT_TRUE(path.hasCycleAtBack());173 path.pop();174 EXPECT_FALSE(path.hasCycleAtBack());175 path.push(D0);176 EXPECT_TRUE(path.hasCycleAtBack());177}178 179TEST_P(ImportPath, GetSmallCycle) {180 ASTImporter::ImportPathTy path;181 path.push(D0);182 path.push(D0);183 EXPECT_TRUE(path.hasCycleAtBack());184 std::array<Decl* ,2> Res;185 int i = 0;186 for (Decl *Di : path.getCycleAtBack()) {187 Res[i++] = Di;188 }189 ASSERT_EQ(i, 2);190 EXPECT_EQ(Res[0], D0);191 EXPECT_EQ(Res[1], D0);192}193 194TEST_P(ImportPath, GetCycle) {195 ASTImporter::ImportPathTy path;196 path.push(D0);197 path.push(D1);198 path.push(D2);199 path.push(D0);200 EXPECT_TRUE(path.hasCycleAtBack());201 std::array<Decl* ,4> Res;202 int i = 0;203 for (Decl *Di : path.getCycleAtBack()) {204 Res[i++] = Di;205 }206 ASSERT_EQ(i, 4);207 EXPECT_EQ(Res[0], D0);208 EXPECT_EQ(Res[1], D2);209 EXPECT_EQ(Res[2], D1);210 EXPECT_EQ(Res[3], D0);211}212 213TEST_P(ImportPath, CycleAfterCycle) {214 ASTImporter::ImportPathTy path;215 path.push(D0);216 path.push(D1);217 path.push(D0);218 path.push(D1);219 path.push(D2);220 path.push(D0);221 EXPECT_TRUE(path.hasCycleAtBack());222 std::array<Decl* ,4> Res;223 int i = 0;224 for (Decl *Di : path.getCycleAtBack()) {225 Res[i++] = Di;226 }227 ASSERT_EQ(i, 4);228 EXPECT_EQ(Res[0], D0);229 EXPECT_EQ(Res[1], D2);230 EXPECT_EQ(Res[2], D1);231 EXPECT_EQ(Res[3], D0);232 233 path.pop();234 path.pop();235 path.pop();236 EXPECT_TRUE(path.hasCycleAtBack());237 i = 0;238 for (Decl *Di : path.getCycleAtBack()) {239 Res[i++] = Di;240 }241 ASSERT_EQ(i, 3);242 EXPECT_EQ(Res[0], D0);243 EXPECT_EQ(Res[1], D1);244 EXPECT_EQ(Res[2], D0);245 246 path.pop();247 EXPECT_FALSE(path.hasCycleAtBack());248}249 250const internal::VariadicDynCastAllOfMatcher<Stmt, SourceLocExpr> sourceLocExpr;251 252AST_MATCHER_P(SourceLocExpr, hasBuiltinStr, StringRef, Str) {253 return Node.getBuiltinStr() == Str;254}255 256TEST_P(ImportExpr, ImportSourceLocExpr) {257 MatchVerifier<Decl> Verifier;258 testImport("void declToImport() { (void)__builtin_FILE(); }", Lang_CXX03, "",259 Lang_CXX03, Verifier,260 functionDecl(hasDescendant(261 sourceLocExpr(hasBuiltinStr("__builtin_FILE")))));262 testImport("void declToImport() { (void)__builtin_FILE_NAME(); }", Lang_CXX03,263 "", Lang_CXX03, Verifier,264 functionDecl(hasDescendant(265 sourceLocExpr(hasBuiltinStr("__builtin_FILE_NAME")))));266 testImport("void declToImport() { (void)__builtin_COLUMN(); }", Lang_CXX03,267 "", Lang_CXX03, Verifier,268 functionDecl(hasDescendant(269 sourceLocExpr(hasBuiltinStr("__builtin_COLUMN")))));270}271 272TEST_P(ImportExpr, ImportStringLiteral) {273 MatchVerifier<Decl> Verifier;274 testImport("void declToImport() { (void)\"foo\"; }", Lang_CXX03, "",275 Lang_CXX03, Verifier,276 functionDecl(hasDescendant(277 stringLiteral(hasType(asString("const char[4]"))))));278 testImport("void declToImport() { (void)L\"foo\"; }", Lang_CXX03, "",279 Lang_CXX03, Verifier,280 functionDecl(hasDescendant(281 stringLiteral(hasType(asString("const wchar_t[4]"))))));282 testImport("void declToImport() { (void) \"foo\" \"bar\"; }", Lang_CXX03, "",283 Lang_CXX03, Verifier,284 functionDecl(hasDescendant(285 stringLiteral(hasType(asString("const char[7]"))))));286}287 288TEST_P(ImportExpr, ImportChooseExpr) {289 MatchVerifier<Decl> Verifier;290 291 // This case tests C code that is not condition-dependent and has a true292 // condition.293 testImport("void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",294 Lang_C99, "", Lang_C99, Verifier,295 functionDecl(hasDescendant(chooseExpr())));296}297 298const internal::VariadicDynCastAllOfMatcher<Stmt, ShuffleVectorExpr>299 shuffleVectorExpr;300 301TEST_P(ImportExpr, ImportShuffleVectorExpr) {302 MatchVerifier<Decl> Verifier;303 constexpr auto Code = R"code(304 typedef double vector4double __attribute__((__vector_size__(32)));305 vector4double declToImport(vector4double a, vector4double b) {306 return __builtin_shufflevector(a, b, 0, 1, 2, 3);307 }308 )code";309 const auto Pattern = functionDecl(hasDescendant(shuffleVectorExpr(310 allOf(has(declRefExpr(to(parmVarDecl(hasName("a"))))),311 has(declRefExpr(to(parmVarDecl(hasName("b"))))),312 has(constantExpr(has(integerLiteral(equals(0))))),313 has(constantExpr(has(integerLiteral(equals(1))))),314 has(constantExpr(has(integerLiteral(equals(2))))),315 has(constantExpr(has(integerLiteral(equals(3)))))))));316 testImport(Code, Lang_C99, "", Lang_C99, Verifier, Pattern);317}318 319TEST_P(ImportExpr, ImportGNUNullExpr) {320 MatchVerifier<Decl> Verifier;321 testImport("void declToImport() { (void)__null; }", Lang_CXX03, "",322 Lang_CXX03, Verifier,323 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));324}325 326TEST_P(ImportExpr, ImportGenericSelectionExpr) {327 MatchVerifier<Decl> Verifier;328 329 testImport(330 "void declToImport() { int x; (void)_Generic(x, int: 0, float: 1); }",331 Lang_C99, "", Lang_C99, Verifier,332 functionDecl(hasDescendant(genericSelectionExpr())));333}334 335TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {336 MatchVerifier<Decl> Verifier;337 testImport(338 "void declToImport() { (void)nullptr; }",339 Lang_CXX11, "", Lang_CXX11, Verifier,340 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));341}342 343 344TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {345 MatchVerifier<Decl> Verifier;346 testImport("void declToImport() { (void)1.0; }", Lang_C99, "", Lang_C99,347 Verifier,348 functionDecl(hasDescendant(349 floatLiteral(equals(1.0), hasType(asString("double"))))));350 testImport("void declToImport() { (void)1.0e-5f; }", Lang_C99, "", Lang_C99,351 Verifier,352 functionDecl(hasDescendant(353 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));354}355 356TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {357 MatchVerifier<Decl> Verifier;358 testImport("void declToImport() { (void)1.0k; }", Lang_C99, "", Lang_C99,359 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));360 testImport("void declToImport() { (void)0.75r; }", Lang_C99, "", Lang_C99,361 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));362}363 364TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {365 MatchVerifier<Decl> Verifier;366 testImport(367 "void declToImport() { (void)1.0i; }",368 Lang_CXX14, "", Lang_CXX14, Verifier,369 functionDecl(hasDescendant(imaginaryLiteral())));370}371 372TEST_P(ImportExpr, ImportCompoundLiteralExpr) {373 MatchVerifier<Decl> Verifier;374 testImport("void declToImport() {"375 " struct s { int x; long y; unsigned z; }; "376 " (void)(struct s){ 42, 0L, 1U }; }",377 Lang_CXX03, "", Lang_CXX03, Verifier,378 functionDecl(hasDescendant(compoundLiteralExpr(379 hasType(asString("struct s")),380 has(initListExpr(381 hasType(asString("struct s")),382 has(integerLiteral(equals(42), hasType(asString("int")))),383 has(integerLiteral(equals(0), hasType(asString("long")))),384 has(integerLiteral(385 equals(1), hasType(asString("unsigned int"))))))))));386}387 388TEST_P(ImportExpr, ImportCXXThisExpr) {389 MatchVerifier<Decl> Verifier;390 testImport("class declToImport { void f() { (void)this; } };", Lang_CXX03, "",391 Lang_CXX03, Verifier,392 cxxRecordDecl(hasMethod(hasDescendant(393 cxxThisExpr(hasType(asString("class declToImport *")))))));394}395 396TEST_P(ImportExpr, ImportAtomicExpr) {397 MatchVerifier<Decl> Verifier;398 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",399 Lang_C99, "", Lang_C99, Verifier,400 functionDecl(hasDescendant(atomicExpr(401 has(ignoringParenImpCasts(402 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),403 hasType(asString("int *"))))),404 has(integerLiteral(equals(1), hasType(asString("int"))))))));405}406 407TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {408 MatchVerifier<Decl> Verifier;409 testImport("void declToImport() { loop: goto loop; (void)&&loop; }", Lang_C99,410 "", Lang_C99, Verifier,411 functionDecl(hasDescendant(labelStmt(412 hasDeclaration(labelDecl(hasName("loop"))))),413 hasDescendant(addrLabelExpr(414 hasDeclaration(labelDecl(hasName("loop")))))));415}416 417AST_MATCHER_P(TemplateDecl, hasTemplateDecl,418 internal::Matcher<NamedDecl>, InnerMatcher) {419 const NamedDecl *Template = Node.getTemplatedDecl();420 return Template && InnerMatcher.matches(*Template, Finder, Builder);421}422 423TEST_P(ImportExpr, ImportParenListExpr) {424 MatchVerifier<Decl> Verifier;425 testImport(426 "template<typename T> class dummy { void f() { dummy X(*this); } };"427 "typedef dummy<int> declToImport;"428 "template class dummy<int>;",429 Lang_CXX03, "", Lang_CXX03, Verifier,430 typedefDecl(hasType(templateSpecializationType(431 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(432 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(433 hasName("f"),434 hasBody(compoundStmt(has(declStmt(hasSingleDecl(435 varDecl(hasInitializer(parenListExpr(has(unaryOperator(436 hasOperatorName("*"),437 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));438}439 440TEST_P(ImportExpr, ImportSwitch) {441 MatchVerifier<Decl> Verifier;442 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",443 Lang_C99, "", Lang_C99, Verifier,444 functionDecl(hasDescendant(445 switchStmt(has(compoundStmt(has(caseStmt())))))));446}447 448TEST_P(ImportExpr, ImportStmtExpr) {449 MatchVerifier<Decl> Verifier;450 testImport(451 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",452 Lang_C99, "", Lang_C99, Verifier,453 traverse(TK_AsIs,454 functionDecl(hasDescendant(varDecl(455 hasName("C"), hasType(asString("int")),456 hasInitializer(stmtExpr(457 hasAnySubstatement(declStmt(hasSingleDecl(varDecl(458 hasName("X"), hasType(asString("int")),459 hasInitializer(integerLiteral(equals(4))))))),460 hasDescendant(implicitCastExpr()))))))));461}462 463TEST_P(ImportExpr, ImportConditionalOperator) {464 MatchVerifier<Decl> Verifier;465 testImport("void declToImport() { (void)(true ? 1 : -5); }", Lang_CXX03, "",466 Lang_CXX03, Verifier,467 functionDecl(hasDescendant(conditionalOperator(468 hasCondition(cxxBoolLiteral(equals(true))),469 hasTrueExpression(integerLiteral(equals(1))),470 hasFalseExpression(unaryOperator(471 hasUnaryOperand(integerLiteral(equals(5)))))))));472}473 474TEST_P(ImportExpr, ImportBinaryConditionalOperator) {475 MatchVerifier<Decl> Verifier;476 testImport(477 "void declToImport() { (void)(1 ?: -5); }", Lang_CXX03, "", Lang_CXX03,478 Verifier,479 traverse(TK_AsIs,480 functionDecl(hasDescendant(binaryConditionalOperator(481 hasCondition(implicitCastExpr(482 hasSourceExpression(opaqueValueExpr(483 hasSourceExpression(integerLiteral(equals(1))))),484 hasType(booleanType()))),485 hasTrueExpression(opaqueValueExpr(486 hasSourceExpression(integerLiteral(equals(1))))),487 hasFalseExpression(unaryOperator(488 hasOperatorName("-"),489 hasUnaryOperand(integerLiteral(equals(5))))))))));490}491 492TEST_P(ImportExpr, ImportDesignatedInitExpr) {493 MatchVerifier<Decl> Verifier;494 testImport(495 "void declToImport() {"496 " struct point { double x; double y; };"497 " struct point ptarray[10] = "498 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",499 Lang_C99, "", Lang_C99, Verifier,500 functionDecl(hasDescendant(initListExpr(501 has(designatedInitExpr(designatorCountIs(2),502 hasDescendant(floatLiteral(equals(1.0))),503 hasDescendant(integerLiteral(equals(2))))),504 has(designatedInitExpr(designatorCountIs(2),505 hasDescendant(floatLiteral(equals(2.0))),506 hasDescendant(integerLiteral(equals(2))))),507 has(designatedInitExpr(designatorCountIs(2),508 hasDescendant(floatLiteral(equals(1.0))),509 hasDescendant(integerLiteral(equals(0)))))))));510}511 512TEST_P(ImportExpr, ImportPredefinedExpr) {513 MatchVerifier<Decl> Verifier;514 // __func__ expands as StringLiteral("declToImport")515 testImport("void declToImport() { (void)__func__; }", Lang_CXX03, "",516 Lang_CXX03, Verifier,517 functionDecl(hasDescendant(predefinedExpr(518 hasType(asString("const char[13]")),519 has(stringLiteral(hasType(asString("const char[13]"))))))));520}521 522TEST_P(ImportExpr, ImportInitListExpr) {523 MatchVerifier<Decl> Verifier;524 testImport("void declToImport() {"525 " struct point { double x; double y; };"526 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"527 " [0].x = 1.0 }; }",528 Lang_CXX03, "", Lang_CXX03, Verifier,529 functionDecl(hasDescendant(initListExpr(530 has(cxxConstructExpr(requiresZeroInitialization())),531 has(initListExpr(532 hasType(asString("point")), has(floatLiteral(equals(1.0))),533 has(implicitValueInitExpr(hasType(asString("double")))))),534 has(initListExpr(hasType(asString("point")),535 has(floatLiteral(equals(2.0))),536 has(floatLiteral(equals(1.0)))))))));537}538 539const internal::VariadicDynCastAllOfMatcher<Expr, CXXDefaultInitExpr>540 cxxDefaultInitExpr;541 542TEST_P(ImportExpr, ImportCXXDefaultInitExpr) {543 MatchVerifier<Decl> Verifier;544 testImport("class declToImport { int DefInit = 5; }; declToImport X;",545 Lang_CXX11, "", Lang_CXX11, Verifier,546 cxxRecordDecl(hasDescendant(cxxConstructorDecl(547 hasAnyConstructorInitializer(cxxCtorInitializer(548 withInitializer(cxxDefaultInitExpr())))))));549 testImport(550 "struct X { int A = 5; }; X declToImport{};", Lang_CXX17, "", Lang_CXX17,551 Verifier,552 varDecl(hasInitializer(initListExpr(hasInit(0, cxxDefaultInitExpr())))));553}554 555const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;556 557TEST_P(ImportExpr, ImportVAArgExpr) {558 MatchVerifier<Decl> Verifier;559 testImport("void declToImport(__builtin_va_list list, ...) {"560 " (void)__builtin_va_arg(list, int); }",561 Lang_CXX03, "", Lang_CXX03, Verifier,562 functionDecl(hasDescendant(563 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));564}565 566const internal::VariadicDynCastAllOfMatcher<Stmt, BuiltinBitCastExpr>567 builtinBitCastExpr;568 569TEST_P(ImportExpr, ImportBuiltinBitCastExpr) {570 MatchVerifier<Decl> Verifier;571 testImport("void declToImport(int X) {"572 " (void)__builtin_bit_cast(float, X); }",573 Lang_CXX20, "", Lang_CXX20, Verifier,574 functionDecl(hasDescendant(575 cStyleCastExpr(hasSourceExpression(builtinBitCastExpr())))));576}577 578TEST_P(ImportExpr, CXXTemporaryObjectExpr) {579 MatchVerifier<Decl> Verifier;580 testImport(581 "struct C {};"582 "void declToImport() { C c = C(); }",583 Lang_CXX03, "", Lang_CXX03, Verifier,584 traverse(TK_AsIs,585 functionDecl(hasDescendant(exprWithCleanups(has(cxxConstructExpr(586 has(materializeTemporaryExpr(has(implicitCastExpr(587 has(cxxTemporaryObjectExpr()))))))))))));588}589 590TEST_P(ImportType, ImportAtomicType) {591 MatchVerifier<Decl> Verifier;592 testImport(593 "void declToImport() { typedef _Atomic(int) a_int; }",594 Lang_CXX11, "", Lang_CXX11, Verifier,595 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));596}597 598TEST_P(ImportType, ImportBitIntType) {599 const AstTypeMatcher<BitIntType> bitIntType;600 MatchVerifier<Decl> Verifier;601 testImport("_BitInt(10) declToImport;", Lang_CXX11, "", Lang_CXX11, Verifier,602 varDecl(hasType(bitIntType())));603}604 605TEST_P(ImportType, ImportDependentBitIntType) {606 const AstTypeMatcher<DependentBitIntType> dependentBitIntType;607 MatchVerifier<Decl> Verifier;608 testImport("template<int Width> using declToImport = _BitInt(Width);",609 Lang_CXX11, "", Lang_CXX11, Verifier,610 typeAliasTemplateDecl(611 has(typeAliasDecl(hasType(dependentBitIntType())))));612}613 614TEST_P(ImportType, ImportDependentAddressSpaceType) {615 const AstTypeMatcher<DependentAddressSpaceType> dependentAddressSpaceType;616 MatchVerifier<Decl> Verifier;617 testImport(618 R"(619 template<typename T, int AddrSpace>620 using declToImport = T __attribute__((address_space(AddrSpace)));621 )",622 Lang_CXX11, "", Lang_CXX11, Verifier,623 typeAliasTemplateDecl(624 has(typeAliasDecl(hasType(dependentAddressSpaceType())))));625}626 627TEST_P(ImportType, ImportVectorType) {628 const AstTypeMatcher<VectorType> vectorType;629 MatchVerifier<Decl> Verifier;630 testImport("typedef int __attribute__((vector_size(12))) declToImport;",631 Lang_CXX11, "", Lang_CXX11, Verifier,632 typedefDecl(hasType(vectorType())));633}634 635TEST_P(ImportType, ImportDependentVectorType) {636 const AstTypeMatcher<DependentVectorType> dependentVectorType;637 MatchVerifier<Decl> Verifier;638 testImport(639 R"(640 template<typename T, int Size>641 using declToImport = T __attribute__((vector_size(Size)));642 )",643 Lang_CXX11, "", Lang_CXX11, Verifier,644 typeAliasTemplateDecl(645 has(typeAliasDecl(hasType(dependentVectorType())))));646}647 648struct ImportOpenCLPipe : ImportType {649 std::vector<std::string> getExtraArgs() const override {650 return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};651 }652};653 654TEST_P(ImportOpenCLPipe, ImportPipeType) {655 const AstTypeMatcher<PipeType> pipeType;656 MatchVerifier<Decl> Verifier;657 testImport("typedef pipe int declToImport;", Lang_OpenCL, "", Lang_OpenCL,658 Verifier, typedefDecl(hasType(pipeType())));659}660 661struct ImportMatrixType : ImportType {662 std::vector<std::string> getExtraArgs() const override {663 return {"-fenable-matrix"};664 }665};666 667TEST_P(ImportMatrixType, ImportConstantMatrixType) {668 const AstTypeMatcher<ConstantMatrixType> constantMatrixType;669 MatchVerifier<Decl> Verifier;670 testImport("typedef int __attribute__((matrix_type(5, 5))) declToImport;",671 Lang_CXX11, "", Lang_CXX11, Verifier,672 typedefDecl(hasType(constantMatrixType())));673}674 675TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {676 const AstTypeMatcher<DependentSizedMatrixType> dependentSizedMatrixType;677 MatchVerifier<Decl> Verifier;678 testImport(679 R"(680 template<typename T, int Rows, int Cols>681 using declToImport = T __attribute__((matrix_type(Rows, Cols)));682 )",683 Lang_CXX11, "", Lang_CXX11, Verifier,684 typeAliasTemplateDecl(685 has(typeAliasDecl(hasType(dependentSizedMatrixType())))));686}687 688TEST_P(ImportType, ImportUsingType) {689 MatchVerifier<Decl> Verifier;690 testImport("struct C {};"691 "void declToImport() { using ::C; new C{}; }",692 Lang_CXX11, "", Lang_CXX11, Verifier,693 functionDecl(hasDescendant(694 cxxNewExpr(hasType(pointerType(pointee(usingType())))))));695}696 697TEST_P(ImportDecl, ImportFunctionTemplateDecl) {698 MatchVerifier<Decl> Verifier;699 testImport("template <typename T> void declToImport() { };", Lang_CXX03, "",700 Lang_CXX03, Verifier, functionTemplateDecl());701}702 703TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {704 MatchVerifier<Decl> Verifier;705 testImport("template <typename T> struct C { T t; };"706 "template <typename T> void declToImport() {"707 " C<T> d;"708 " (void)d.t;"709 "}"710 "void instantiate() { declToImport<int>(); }",711 Lang_CXX03, "", Lang_CXX03, Verifier,712 functionTemplateDecl(hasDescendant(713 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));714 testImport("template <typename T> struct C { T t; };"715 "template <typename T> void declToImport() {"716 " C<T> d;"717 " (void)(&d)->t;"718 "}"719 "void instantiate() { declToImport<int>(); }",720 Lang_CXX03, "", Lang_CXX03, Verifier,721 functionTemplateDecl(hasDescendant(722 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));723}724 725TEST_P(ImportType, ImportTypeAliasTemplate) {726 MatchVerifier<Decl> Verifier;727 testImport(728 "template <int K>"729 "struct dummy { static const int i = K; };"730 "template <int K> using dummy2 = dummy<K>;"731 "int declToImport() { return dummy2<3>::i; }",732 Lang_CXX11, "", Lang_CXX11, Verifier,733 traverse(TK_AsIs,734 functionDecl(hasDescendant(implicitCastExpr(has(declRefExpr()))),735 unless(hasAncestor(736 translationUnitDecl(has(typeAliasDecl())))))));737}738 739const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>740 varTemplateSpecializationDecl;741 742TEST_P(ImportDecl, ImportVarTemplate) {743 MatchVerifier<Decl> Verifier;744 testImport(745 "template <typename T>"746 "T pi = T(3.1415926535897932385L);"747 "void declToImport() { (void)pi<int>; }",748 Lang_CXX14, "", Lang_CXX14, Verifier,749 functionDecl(750 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),751 unless(hasAncestor(translationUnitDecl(has(varDecl(752 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));753}754 755TEST_P(ImportType, ImportPackExpansion) {756 MatchVerifier<Decl> Verifier;757 testImport("template <typename... Args>"758 "struct dummy {"759 " dummy(Args... args) {}"760 " static const int i = 4;"761 "};"762 "int declToImport() { return dummy<int>::i; }",763 Lang_CXX11, "", Lang_CXX11, Verifier,764 traverse(TK_AsIs, functionDecl(hasDescendant(returnStmt(has(765 implicitCastExpr(has(declRefExpr()))))))));766}767 768TEST_P(ImportType, ImportDependentTemplateSpecialization) {769 MatchVerifier<Decl> Verifier;770 testImport("template<typename T>"771 "struct A;"772 "template<typename T>"773 "struct declToImport {"774 " typename A<T>::template B<T> a;"775 "};",776 Lang_CXX03, "", Lang_CXX03, Verifier,777 classTemplateDecl(has(cxxRecordDecl(778 has(fieldDecl(hasType(templateSpecializationType())))))));779}780 781TEST_P(ImportType, ImportDeducedTemplateSpecialization) {782 MatchVerifier<Decl> Verifier;783 testImport("template <typename T>"784 "class C { public: C(T); };"785 "C declToImport(123);",786 Lang_CXX17, "", Lang_CXX17, Verifier,787 varDecl(hasType(deducedTemplateSpecializationType())));788}789 790const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>791 sizeOfPackExpr;792 793TEST_P(ImportExpr, ImportSizeOfPackExpr) {794 MatchVerifier<Decl> Verifier;795 testImport(796 "template <typename... Ts>"797 "void declToImport() {"798 " const int i = sizeof...(Ts);"799 "};"800 "void g() { declToImport<int>(); }",801 Lang_CXX11, "", Lang_CXX11, Verifier,802 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));803 testImport(804 "template <typename... Ts>"805 "using X = int[sizeof...(Ts)];"806 "template <typename... Us>"807 "struct Y {"808 " X<Us..., int, double, int, Us...> f;"809 "};"810 "Y<float, int> declToImport;",811 Lang_CXX11, "", Lang_CXX11, Verifier,812 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(813 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));814}815 816TEST_P(ImportExpr, ImportCXXFoldExpr) {817 auto Match1 = cxxFoldExpr(hasOperatorName("+"), isLeftFold(),818 unless(hasFoldInit(expr())));819 auto Match2 =820 cxxFoldExpr(hasOperatorName("-"), isLeftFold(), hasFoldInit(expr()));821 auto Match3 = cxxFoldExpr(hasOperatorName("*"), isRightFold(),822 unless(hasFoldInit(expr())));823 auto Match4 =824 cxxFoldExpr(hasOperatorName("/"), isRightFold(), hasFoldInit(expr()));825 826 MatchVerifier<Decl> Verifier;827 testImport("template <typename... Ts>"828 "void declToImport(Ts... args) {"829 " const int i1 = (... + args);"830 " const int i2 = (1 - ... - args);"831 " const int i3 = (args * ...);"832 " const int i4 = (args / ... / 1);"833 "};"834 "void g() { declToImport(1, 2, 3, 4, 5); }",835 Lang_CXX17, "", Lang_CXX17, Verifier,836 functionTemplateDecl(hasDescendant(Match1), hasDescendant(Match2),837 hasDescendant(Match3),838 hasDescendant(Match4)));839}840 841/// \brief Matches __builtin_types_compatible_p:842/// GNU extension to check equivalent types843/// Given844/// \code845/// __builtin_types_compatible_p(int, int)846/// \endcode847// will generate TypeTraitExpr <...> 'int'848const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;849 850TEST_P(ImportExpr, ImportTypeTraitExpr) {851 MatchVerifier<Decl> Verifier;852 testImport(853 "void declToImport() { "854 " (void)__builtin_types_compatible_p(int, int);"855 "}",856 Lang_C99, "", Lang_C99, Verifier,857 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));858}859 860const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;861 862TEST_P(ImportExpr, ImportCXXTypeidExpr) {863 MatchVerifier<Decl> Verifier;864 testImport(865 "namespace std { class type_info {}; }"866 "void declToImport() {"867 " int x;"868 " auto a = typeid(int); auto b = typeid(x);"869 "}",870 Lang_CXX11, "", Lang_CXX11, Verifier,871 traverse(872 TK_AsIs,873 functionDecl(874 hasDescendant(varDecl(hasName("a"), hasInitializer(hasDescendant(875 cxxTypeidExpr())))),876 hasDescendant(varDecl(hasName("b"), hasInitializer(hasDescendant(877 cxxTypeidExpr())))))));878}879 880TEST_P(ImportExpr, ImportTypeTraitExprValDep) {881 MatchVerifier<Decl> Verifier;882 testImport(883 "template<typename T> struct declToImport {"884 " void m() { (void)__is_pod(T); }"885 "};"886 "void f() { declToImport<int>().m(); }",887 Lang_CXX11, "", Lang_CXX11, Verifier,888 classTemplateDecl(has(cxxRecordDecl(has(889 functionDecl(hasDescendant(890 typeTraitExpr(hasType(booleanType())))))))));891}892 893TEST_P(ImportDecl, ImportRecordDeclInFunc) {894 MatchVerifier<Decl> Verifier;895 testImport("int declToImport() { "896 " struct data_t {int a;int b;};"897 " struct data_t d;"898 " return 0;"899 "}",900 Lang_C99, "", Lang_C99, Verifier,901 functionDecl(hasBody(compoundStmt(902 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));903}904 905TEST_P(ImportDecl, ImportedVarDeclPreservesThreadLocalStorage) {906 MatchVerifier<Decl> Verifier;907 testImport("thread_local int declToImport;", Lang_CXX11, "", Lang_CXX11,908 Verifier, varDecl(hasThreadStorageDuration()));909}910 911TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {912 Decl *FromTU = getTuDecl("int declToImport() { "913 " struct data_t {int a;int b;};"914 " struct data_t d;"915 " return 0;"916 "}",917 Lang_C99, "input.c");918 auto *FromVar =919 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));920 ASSERT_TRUE(FromVar);921 auto ToType =922 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C99);923 EXPECT_FALSE(ToType.isNull());924}925 926TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {927 // This construct is not supported by ASTImporter.928 Decl *FromTU = getTuDecl(929 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",930 Lang_C99, "input.c");931 auto *From = FirstDeclMatcher<FunctionDecl>().match(932 FromTU, functionDecl(hasName("declToImport")));933 ASSERT_TRUE(From);934 auto *To = Import(From, Lang_C99);935 EXPECT_EQ(To, nullptr);936}937 938TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {939 Decl *FromTU =940 getTuDecl("#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"941 "int declToImport(){ return NONAME_SIZEOF(int); }",942 Lang_C99, "input.c");943 auto *From = FirstDeclMatcher<FunctionDecl>().match(944 FromTU, functionDecl(hasName("declToImport")));945 ASSERT_TRUE(From);946 auto *To = Import(From, Lang_C99);947 ASSERT_TRUE(To);948 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(949 To, functionDecl(hasName("declToImport"),950 hasDescendant(unaryExprOrTypeTraitExpr()))));951}952 953TEST_P(ASTImporterOptionSpecificTestBase,954 ImportRecordDeclInFuncParamsFromMacro) {955 // This construct is not supported by ASTImporter.956 Decl *FromTU =957 getTuDecl("#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"958 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",959 Lang_C99, "input.c");960 auto *From = FirstDeclMatcher<FunctionDecl>().match(961 FromTU, functionDecl(hasName("declToImport")));962 ASSERT_TRUE(From);963 auto *To = Import(From, Lang_C99);964 EXPECT_EQ(To, nullptr);965}966 967const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>968 cxxPseudoDestructorExpr;969 970TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {971 MatchVerifier<Decl> Verifier;972 testImport(973 "typedef int T;"974 "void declToImport(int *p) {"975 " T t;"976 " p->T::~T();"977 "}",978 Lang_CXX03, "", Lang_CXX03, Verifier,979 functionDecl(hasDescendant(callExpr(has(cxxPseudoDestructorExpr())))));980}981 982TEST_P(ImportDecl, ImportUsingDecl) {983 MatchVerifier<Decl> Verifier;984 testImport("namespace foo { int bar; }"985 "void declToImport() { using foo::bar; }",986 Lang_CXX03, "", Lang_CXX03, Verifier,987 functionDecl(hasDescendant(usingDecl(hasName("bar")))));988}989 990TEST_P(ImportDecl, ImportUsingTemplate) {991 MatchVerifier<Decl> Verifier;992 testImport("namespace ns { template <typename T> struct S {}; }"993 "template <template <typename> class T> class X {};"994 "void declToImport() {"995 "using ns::S; X<S> xi; }",996 Lang_CXX11, "", Lang_CXX11, Verifier,997 functionDecl(998 hasDescendant(varDecl(hasTypeLoc(templateSpecializationTypeLoc(999 hasAnyTemplateArgumentLoc(templateArgumentLoc())))))));1000}1001 1002TEST_P(ImportDecl, ImportUsingEnumDecl) {1003 MatchVerifier<Decl> Verifier;1004 testImport("namespace foo { enum bar { baz, toto, quux }; }"1005 "void declToImport() { using enum foo::bar; }",1006 Lang_CXX20, "", Lang_CXX20, Verifier,1007 functionDecl(hasDescendant(usingEnumDecl(hasName("bar")))));1008}1009 1010const internal::VariadicDynCastAllOfMatcher<Decl, UsingPackDecl> usingPackDecl;1011 1012TEST_P(ImportDecl, ImportUsingPackDecl) {1013 MatchVerifier<Decl> Verifier;1014 testImport(1015 "struct A { int operator()() { return 1; } };"1016 "struct B { int operator()() { return 2; } };"1017 "template<typename ...T> struct C : T... { using T::operator()...; };"1018 "C<A, B> declToImport;",1019 Lang_CXX20, "", Lang_CXX20, Verifier,1020 varDecl(hasType(templateSpecializationType(hasDeclaration(1021 classTemplateSpecializationDecl(hasDescendant(usingPackDecl())))))));1022}1023 1024TEST_P(ImportDecl, ImportUsingShadowDecl) {1025 MatchVerifier<Decl> Verifier;1026 // from using-decl1027 testImport("namespace foo { int bar; }"1028 "namespace declToImport { using foo::bar; }",1029 Lang_CXX03, "", Lang_CXX03, Verifier,1030 namespaceDecl(has(usingShadowDecl(hasName("bar")))));1031 // from using-enum-decl1032 testImport("namespace foo { enum bar {baz, toto, quux }; }"1033 "namespace declToImport { using enum foo::bar; }",1034 Lang_CXX20, "", Lang_CXX20, Verifier,1035 namespaceDecl(has(usingShadowDecl(hasName("baz")))));1036}1037 1038TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {1039 MatchVerifier<Decl> Verifier;1040 testImport("template<typename T> int foo();"1041 "template <typename T> void declToImport() {"1042 " (void)::foo<T>;"1043 " (void)::template foo<T>;"1044 "}"1045 "void instantiate() { declToImport<int>(); }",1046 Lang_CXX03, "", Lang_CXX03, Verifier,1047 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));1048}1049 1050TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {1051 MatchVerifier<Decl> Verifier;1052 testImport("template <typename T> struct C { T t; };"1053 "template <typename T> void declToImport() {"1054 " C<T> d;"1055 " d.t = T();"1056 "}"1057 "void instantiate() { declToImport<int>(); }",1058 Lang_CXX03, "", Lang_CXX03, Verifier,1059 functionTemplateDecl(hasDescendant(1060 binaryOperator(has(cxxUnresolvedConstructExpr())))));1061 testImport("template <typename T> struct C { T t; };"1062 "template <typename T> void declToImport() {"1063 " C<T> d;"1064 " (&d)->t = T();"1065 "}"1066 "void instantiate() { declToImport<int>(); }",1067 Lang_CXX03, "", Lang_CXX03, Verifier,1068 functionTemplateDecl(hasDescendant(1069 binaryOperator(has(cxxUnresolvedConstructExpr())))));1070}1071 1072/// Check that function "declToImport()" (which is the templated function1073/// for corresponding FunctionTemplateDecl) is not added into DeclContext.1074/// Same for class template declarations.1075TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {1076 MatchVerifier<Decl> Verifier;1077 testImport("template <typename T> void declToImport() { T a = 1; }"1078 "void instantiate() { declToImport<int>(); }",1079 Lang_CXX03, "", Lang_CXX03, Verifier,1080 functionTemplateDecl(hasAncestor(translationUnitDecl(1081 unless(has(functionDecl(hasName("declToImport"))))))));1082 testImport("template <typename T> struct declToImport { T t; };"1083 "void instantiate() { declToImport<int>(); }",1084 Lang_CXX03, "", Lang_CXX03, Verifier,1085 classTemplateDecl(hasAncestor(translationUnitDecl(1086 unless(has(cxxRecordDecl(hasName("declToImport"))))))));1087}1088 1089TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {1090 MatchVerifier<Decl> Verifier;1091 auto Code =1092 R"s(1093 struct declToImport {1094 template <typename T0> struct X;1095 template <typename T0> struct X<T0 *> {};1096 };1097 )s";1098 testImport(Code, Lang_CXX03, "", Lang_CXX03, Verifier,1099 recordDecl(has(classTemplateDecl()),1100 has(classTemplateSpecializationDecl())));1101}1102 1103TEST_P(ImportExpr, CXXOperatorCallExpr) {1104 MatchVerifier<Decl> Verifier;1105 testImport(1106 "class declToImport {"1107 " void f() { *this = declToImport(); }"1108 "};",1109 Lang_CXX03, "", Lang_CXX03, Verifier,1110 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(cxxOperatorCallExpr())))));1111}1112 1113TEST_P(ImportExpr, DependentSizedArrayType) {1114 MatchVerifier<Decl> Verifier;1115 testImport("template<typename T, int Size> class declToImport {"1116 " T data[Size];"1117 "};",1118 Lang_CXX03, "", Lang_CXX03, Verifier,1119 classTemplateDecl(has(cxxRecordDecl(1120 has(fieldDecl(hasType(dependentSizedArrayType())))))));1121}1122 1123TEST_P(ImportExpr, DependentSizedExtVectorType) {1124 MatchVerifier<Decl> Verifier;1125 testImport("template<typename T, int Size>"1126 "class declToImport {"1127 " typedef T __attribute__((ext_vector_type(Size))) type;"1128 "};",1129 Lang_CXX03, "", Lang_CXX03, Verifier,1130 classTemplateDecl(has(cxxRecordDecl(1131 has(typedefDecl(hasType(dependentSizedExtVectorType())))))));1132}1133 1134TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingPackDecl) {1135 Decl *FromTU = getTuDecl(1136 "struct A { int operator()() { return 1; } };"1137 "struct B { int operator()() { return 2; } };"1138 "template<typename ...T> struct C : T... { using T::operator()...; };"1139 "C<A, B> Var;",1140 Lang_CXX20);1141 1142 auto From = FirstDeclMatcher<UsingPackDecl>().match(FromTU, usingPackDecl());1143 ASSERT_TRUE(From);1144 auto To = cast<UsingPackDecl>(Import(From, Lang_CXX20));1145 ASSERT_TRUE(To);1146 1147 ArrayRef<NamedDecl *> FromExpansions = From->expansions();1148 ArrayRef<NamedDecl *> ToExpansions = To->expansions();1149 ASSERT_EQ(FromExpansions.size(), ToExpansions.size());1150 for (unsigned int I = 0; I < FromExpansions.size(); ++I) {1151 auto ImportedExpansion = Import(FromExpansions[I], Lang_CXX20);1152 EXPECT_EQ(ImportedExpansion, ToExpansions[I]);1153 }1154 1155 auto ImportedDC = cast<Decl>(Import(From->getDeclContext(), Lang_CXX20));1156 EXPECT_EQ(ImportedDC, cast<Decl>(To->getDeclContext()));1157}1158 1159TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) {1160 Decl *FromTU = getTuDecl("template<typename T> struct X {};", Lang_CXX03);1161 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(1162 FromTU, templateTypeParmDecl(hasName("T")));1163 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);1164 ASSERT_FALSE(To->hasDefaultArgument());1165}1166 1167TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) {1168 Decl *FromTU =1169 getTuDecl("template<typename T = int> struct X {};", Lang_CXX03);1170 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(1171 FromTU, templateTypeParmDecl(hasName("T")));1172 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);1173 ASSERT_TRUE(To->hasDefaultArgument());1174 QualType ToArg = To->getDefaultArgument().getArgument().getAsType();1175 ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy));1176}1177 1178TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {1179 Decl *FromTU =1180 getTuDecl("class A { public: static int X; }; void f() { (void)A::X; }",1181 Lang_CXX03);1182 auto From = FirstDeclMatcher<FunctionDecl>().match(1183 FromTU, functionDecl(hasName("f")));1184 ASSERT_TRUE(From);1185 ASSERT_TRUE(1186 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())1187 ->getSubExpr()1188 ->getBeginLoc()1189 .isValid());1190 FunctionDecl *To = Import(From, Lang_CXX03);1191 ASSERT_TRUE(To);1192 ASSERT_TRUE(1193 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())1194 ->getSubExpr()1195 ->getBeginLoc()1196 .isValid());1197}1198 1199TEST_P(ASTImporterOptionSpecificTestBase,1200 TemplateTemplateParmDeclNoDefaultArg) {1201 Decl *FromTU = getTuDecl(R"(1202 template<template<typename> typename TT> struct Y {};1203 )",1204 Lang_CXX17);1205 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(1206 FromTU, templateTemplateParmDecl(hasName("TT")));1207 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);1208 ASSERT_FALSE(To->hasDefaultArgument());1209}1210 1211TEST_P(ASTImporterOptionSpecificTestBase, TemplateTemplateParmDeclDefaultArg) {1212 Decl *FromTU = getTuDecl(R"(1213 template<typename T> struct X {};1214 template<template<typename> typename TT = X> struct Y {};1215 )",1216 Lang_CXX17);1217 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(1218 FromTU, templateTemplateParmDecl(hasName("TT")));1219 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);1220 ASSERT_TRUE(To->hasDefaultArgument());1221 const TemplateArgument &ToDefaultArg = To->getDefaultArgument().getArgument();1222 ASSERT_TRUE(To->isTemplateDecl());1223 TemplateDecl *ToTemplate = ToDefaultArg.getAsTemplate().getAsTemplateDecl();1224 1225 // Find the default argument template 'X' in the AST and compare it against1226 // the default argument we got.1227 auto ToExpectedDecl = FirstDeclMatcher<ClassTemplateDecl>().match(1228 To->getTranslationUnitDecl(), classTemplateDecl(hasName("X")));1229 ASSERT_EQ(ToTemplate, ToExpectedDecl);1230}1231 1232TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclNoDefaultArg) {1233 Decl *FromTU = getTuDecl("template<int N> struct X {};", Lang_CXX03);1234 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(1235 FromTU, nonTypeTemplateParmDecl(hasName("N")));1236 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);1237 ASSERT_FALSE(To->hasDefaultArgument());1238}1239 1240TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {1241 Decl *FromTU = getTuDecl("template<int S = 1> struct X {};", Lang_CXX03);1242 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(1243 FromTU, nonTypeTemplateParmDecl(hasName("S")));1244 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);1245 ASSERT_TRUE(To->hasDefaultArgument());1246 Stmt *ToArg = To->getDefaultArgument().getArgument().getAsExpr();1247 ASSERT_TRUE(isa<IntegerLiteral>(ToArg));1248 ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);1249}1250 1251TEST_P(ASTImporterOptionSpecificTestBase, TemplateArgumentsDefaulted) {1252 Decl *FromTU = getTuDecl(R"(1253 template<typename T> struct X {};1254 template<typename TP = double,1255 int NTTP = 50,1256 template<typename> typename TT = X> struct S {};1257 S<> s;1258 )",1259 Lang_CXX17);1260 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(1261 FromTU, classTemplateSpecializationDecl(hasName("S")));1262 ASSERT_TRUE(FromSpec);1263 auto *ToSpec = Import(FromSpec, Lang_CXX03);1264 ASSERT_TRUE(ToSpec);1265 auto const &TList = ToSpec->getTemplateArgs();1266 for (auto const &Arg : TList.asArray()) {1267 ASSERT_TRUE(Arg.getIsDefaulted());1268 }1269}1270 1271TEST_P(ASTImporterOptionSpecificTestBase,1272 ImportOfTemplatedDeclOfClassTemplateDecl) {1273 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);1274 auto From =1275 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());1276 ASSERT_TRUE(From);1277 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX03));1278 ASSERT_TRUE(To);1279 Decl *ToTemplated = To->getTemplatedDecl();1280 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);1281 EXPECT_TRUE(ToTemplated1);1282 EXPECT_EQ(ToTemplated1, ToTemplated);1283}1284 1285TEST_P(ASTImporterOptionSpecificTestBase,1286 ImportOfTemplatedDeclOfFunctionTemplateDecl) {1287 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);1288 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(1289 FromTU, functionTemplateDecl());1290 ASSERT_TRUE(From);1291 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX03));1292 ASSERT_TRUE(To);1293 Decl *ToTemplated = To->getTemplatedDecl();1294 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);1295 EXPECT_TRUE(ToTemplated1);1296 EXPECT_EQ(ToTemplated1, ToTemplated);1297}1298 1299TEST_P(ASTImporterOptionSpecificTestBase,1300 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {1301 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03);1302 auto FromFT =1303 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());1304 ASSERT_TRUE(FromFT);1305 1306 auto ToTemplated =1307 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));1308 EXPECT_TRUE(ToTemplated);1309 auto ToTU = ToTemplated->getTranslationUnitDecl();1310 auto ToFT =1311 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());1312 EXPECT_TRUE(ToFT);1313}1314 1315TEST_P(ASTImporterOptionSpecificTestBase,1316 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {1317 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX03);1318 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(1319 FromTU, functionTemplateDecl());1320 ASSERT_TRUE(FromFT);1321 1322 auto ToTemplated =1323 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));1324 EXPECT_TRUE(ToTemplated);1325 auto ToTU = ToTemplated->getTranslationUnitDecl();1326 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(1327 ToTU, functionTemplateDecl());1328 EXPECT_TRUE(ToFT);1329}1330 1331TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {1332 auto Code =1333 R"(1334 namespace x {1335 template<class X> struct S1{};1336 template<class X> struct S2{};1337 template<class X> struct S3{};1338 }1339 )";1340 Decl *FromTU = getTuDecl(Code, Lang_CXX03);1341 auto FromNs =1342 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());1343 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX03));1344 ASSERT_TRUE(ToNs);1345 auto From =1346 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,1347 classTemplateDecl(1348 hasName("S2")));1349 auto To =1350 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,1351 classTemplateDecl(1352 hasName("S2")));1353 ASSERT_TRUE(From);1354 ASSERT_TRUE(To);1355 auto ToTemplated = To->getTemplatedDecl();1356 auto ToTemplated1 =1357 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX03));1358 EXPECT_TRUE(ToTemplated1);1359 ASSERT_EQ(ToTemplated1, ToTemplated);1360}1361 1362TEST_P(ASTImporterOptionSpecificTestBase,1363 ImportTemplateSpecializationStaticMember) {1364 auto FromCode =1365 R"(1366 template <typename H> class Test{1367 public:1368 static const unsigned int length;1369 };1370 1371 template<> const unsigned int Test<int>::length;1372 template<> const unsigned int Test<int>::length = 0;1373 )";1374 auto ToCode =1375 R"(1376 template <typename H> class Test {1377 public:1378 static const unsigned int length;1379 };1380 1381 template <> const unsigned int Test<int>::length;1382 1383 void foo() { int i = 1 / Test<int>::length; }1384 )";1385 Decl *FromTU = getTuDecl(FromCode, Lang_CXX14);1386 auto FromDecl = FirstDeclMatcher<VarDecl>().match(1387 FromTU, varDecl(hasName("length"), isDefinition()));1388 Decl *ToTu = getToTuDecl(ToCode, Lang_CXX14);1389 auto ToX = Import(FromDecl, Lang_CXX03);1390 auto ToDecl = FirstDeclMatcher<VarDecl>().match(1391 ToTu, varDecl(hasName("length"), isDefinition()));1392 EXPECT_TRUE(ToX);1393 EXPECT_EQ(ToX, ToDecl);1394}1395 1396TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {1397 // This tests the import of isConditionTrue directly to make sure the importer1398 // gets it right.1399 Decl *From, *To;1400 std::tie(From, To) = getImportedDecl(1401 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", Lang_C99,1402 "", Lang_C99);1403 1404 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());1405 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());1406 1407 const ChooseExpr *FromChooseExpr =1408 selectFirst<ChooseExpr>("choose", FromResults);1409 ASSERT_TRUE(FromChooseExpr);1410 1411 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);1412 ASSERT_TRUE(ToChooseExpr);1413 1414 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());1415 EXPECT_EQ(FromChooseExpr->isConditionDependent(),1416 ToChooseExpr->isConditionDependent());1417}1418 1419TEST_P(ASTImporterOptionSpecificTestBase, ImportConvertVectorExpr) {1420 Decl *From, *To;1421 std::tie(From, To) = getImportedDecl(1422 "typedef double v4double __attribute__((__vector_size__(32)));"1423 "typedef float v4float __attribute__((__vector_size__(16)));"1424 "v4float vf;"1425 "void declToImport() { (void)__builtin_convertvector(vf, v4double); }",1426 Lang_CXX03, "", Lang_CXX03);1427 1428 auto ToResults =1429 match(convertVectorExpr().bind("convert"), To->getASTContext());1430 auto FromResults =1431 match(convertVectorExpr().bind("convert"), From->getASTContext());1432 1433 const ConvertVectorExpr *FromConvertVectorExpr =1434 selectFirst<ConvertVectorExpr>("convert", FromResults);1435 ASSERT_TRUE(FromConvertVectorExpr);1436 1437 const ConvertVectorExpr *ToConvertVectorExpr =1438 selectFirst<ConvertVectorExpr>("convert", ToResults);1439 ASSERT_TRUE(ToConvertVectorExpr);1440}1441 1442TEST_P(ASTImporterOptionSpecificTestBase, ImportGenericSelectionExpr) {1443 Decl *From, *To;1444 std::tie(From, To) = getImportedDecl(1445 R"(1446 int declToImport() {1447 int x;1448 return _Generic(x, int: 0, default: 1);1449 }1450 )",1451 Lang_C99, "", Lang_C99);1452 1453 auto ToResults =1454 match(genericSelectionExpr().bind("expr"), To->getASTContext());1455 auto FromResults =1456 match(genericSelectionExpr().bind("expr"), From->getASTContext());1457 1458 const GenericSelectionExpr *FromGenericSelectionExpr =1459 selectFirst<GenericSelectionExpr>("expr", FromResults);1460 ASSERT_TRUE(FromGenericSelectionExpr);1461 1462 const GenericSelectionExpr *ToGenericSelectionExpr =1463 selectFirst<GenericSelectionExpr>("expr", ToResults);1464 ASSERT_TRUE(ToGenericSelectionExpr);1465 1466 EXPECT_EQ(FromGenericSelectionExpr->isResultDependent(),1467 ToGenericSelectionExpr->isResultDependent());1468 EXPECT_EQ(FromGenericSelectionExpr->getResultIndex(),1469 ToGenericSelectionExpr->getResultIndex());1470}1471 1472TEST_P(ASTImporterOptionSpecificTestBase,1473 ImportFunctionWithBackReferringParameter) {1474 Decl *From, *To;1475 std::tie(From, To) = getImportedDecl(1476 R"(1477 template <typename T> struct X {};1478 1479 void declToImport(int y, X<int> &x) {}1480 1481 template <> struct X<int> {1482 void g() {1483 X<int> x;1484 declToImport(0, x);1485 }1486 };1487 )",1488 Lang_CXX03, "", Lang_CXX03);1489 1490 MatchVerifier<Decl> Verifier;1491 auto Matcher = functionDecl(hasName("declToImport"),1492 parameterCountIs(2),1493 hasParameter(0, hasName("y")),1494 hasParameter(1, hasName("x")),1495 hasParameter(1, hasType(asString("X<int> &"))));1496 ASSERT_TRUE(Verifier.match(From, Matcher));1497 EXPECT_TRUE(Verifier.match(To, Matcher));1498}1499 1500TEST_P(ASTImporterOptionSpecificTestBase,1501 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {1502 Decl *From, *To;1503 std::tie(From, To) =1504 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"1505 "void instantiate() { declToImport<int>(); }",1506 Lang_CXX03, "", Lang_CXX03);1507 1508 auto Check = [](Decl *D) -> bool {1509 auto TU = D->getTranslationUnitDecl();1510 for (auto Child : TU->decls()) {1511 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {1512 if (FD->getNameAsString() == "declToImport") {1513 GTEST_NONFATAL_FAILURE_(1514 "TU should not contain any FunctionDecl with name declToImport");1515 return false;1516 }1517 }1518 }1519 return true;1520 };1521 1522 ASSERT_TRUE(Check(From));1523 EXPECT_TRUE(Check(To));1524}1525 1526TEST_P(ASTImporterOptionSpecificTestBase,1527 TUshouldNotContainTemplatedDeclOfClassTemplates) {1528 Decl *From, *To;1529 std::tie(From, To) =1530 getImportedDecl("template <typename T> struct declToImport { T t; };"1531 "void instantiate() { declToImport<int>(); }",1532 Lang_CXX03, "", Lang_CXX03);1533 1534 auto Check = [](Decl *D) -> bool {1535 auto TU = D->getTranslationUnitDecl();1536 for (auto Child : TU->decls()) {1537 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {1538 if (RD->getNameAsString() == "declToImport") {1539 GTEST_NONFATAL_FAILURE_(1540 "TU should not contain any CXXRecordDecl with name declToImport");1541 return false;1542 }1543 }1544 }1545 return true;1546 };1547 1548 ASSERT_TRUE(Check(From));1549 EXPECT_TRUE(Check(To));1550}1551 1552TEST_P(ASTImporterOptionSpecificTestBase,1553 TUshouldNotContainTemplatedDeclOfTypeAlias) {1554 Decl *From, *To;1555 std::tie(From, To) =1556 getImportedDecl(1557 "template <typename T> struct X {};"1558 "template <typename T> using declToImport = X<T>;"1559 "void instantiate() { declToImport<int> a; }",1560 Lang_CXX11, "", Lang_CXX11);1561 1562 auto Check = [](Decl *D) -> bool {1563 auto TU = D->getTranslationUnitDecl();1564 for (auto Child : TU->decls()) {1565 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {1566 if (AD->getNameAsString() == "declToImport") {1567 GTEST_NONFATAL_FAILURE_(1568 "TU should not contain any TypeAliasDecl with name declToImport");1569 return false;1570 }1571 }1572 }1573 return true;1574 };1575 1576 ASSERT_TRUE(Check(From));1577 EXPECT_TRUE(Check(To));1578}1579 1580TEST_P(ASTImporterOptionSpecificTestBase,1581 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {1582 1583 Decl *From, *To;1584 std::tie(From, To) = getImportedDecl(1585 R"(1586 template<class T>1587 class Base {};1588 class declToImport : public Base<declToImport> {};1589 )",1590 Lang_CXX03, "", Lang_CXX03);1591 1592 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.1593 auto Pattern =1594 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));1595 ASSERT_TRUE(1596 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));1597 EXPECT_TRUE(1598 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));1599 1600 // Check that the ClassTemplateSpecializationDecl is the child of the1601 // ClassTemplateDecl.1602 Pattern = translationUnitDecl(has(classTemplateDecl(1603 hasName("Base"), has(classTemplateSpecializationDecl()))));1604 ASSERT_TRUE(1605 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));1606 EXPECT_TRUE(1607 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));1608}1609 1610AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {1611 size_t Index = 0;1612 for (Decl *D : Node.decls()) {1613 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {1614 auto *ND = cast<NamedDecl>(D);1615 if (Index == Order.size())1616 return false;1617 if (ND->getName() != Order[Index])1618 return false;1619 ++Index;1620 }1621 }1622 return Index == Order.size();1623}1624 1625TEST_P(ASTImporterOptionSpecificTestBase,1626 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {1627 Decl *From, *To;1628 std::tie(From, To) = getImportedDecl(1629 R"(1630 namespace NS {1631 template<class T>1632 class X {};1633 template class X<int>;1634 }1635 )",1636 Lang_CXX03, "", Lang_CXX03, "NS");1637 1638 // Check that the ClassTemplateSpecializationDecl is NOT the child of the1639 // ClassTemplateDecl.1640 auto Pattern = namespaceDecl(has(classTemplateDecl(1641 hasName("X"), unless(has(classTemplateSpecializationDecl())))));1642 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));1643 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));1644 1645 // Check that the ClassTemplateSpecializationDecl is the child of the1646 // NamespaceDecl.1647 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));1648 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));1649 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));1650}1651 1652TEST_P(ASTImporterOptionSpecificTestBase,1653 CXXRecordDeclFieldsShouldBeInCorrectOrder) {1654 Decl *From, *To;1655 std::tie(From, To) =1656 getImportedDecl(1657 "struct declToImport { int a; int b; };",1658 Lang_CXX11, "", Lang_CXX11);1659 1660 MatchVerifier<Decl> Verifier;1661 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));1662 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));1663}1664 1665TEST_P(ASTImporterOptionSpecificTestBase,1666 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {1667 Decl *From, *To;1668 std::tie(From, To) = getImportedDecl(1669 // The original recursive algorithm of ASTImporter first imports 'c' then1670 // 'b' and lastly 'a'. Therefore we must restore the order somehow.1671 R"s(1672 struct declToImport {1673 int a = c + b;1674 int b = 1;1675 int c = 2;1676 };1677 )s",1678 Lang_CXX11, "", Lang_CXX11);1679 1680 MatchVerifier<Decl> Verifier;1681 ASSERT_TRUE(1682 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));1683 EXPECT_TRUE(1684 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));1685}1686 1687TEST_P(ASTImporterOptionSpecificTestBase,1688 CXXRecordDeclFieldAndIndirectFieldOrder) {1689 Decl *From, *To;1690 std::tie(From, To) = getImportedDecl(1691 // First field is "a", then the field for unnamed union, then "b" and "c"1692 // from it (indirect fields), then "d".1693 R"s(1694 struct declToImport {1695 int a = d;1696 union {1697 int b;1698 int c;1699 };1700 int d;1701 };1702 )s",1703 Lang_CXX11, "", Lang_CXX11);1704 1705 MatchVerifier<Decl> Verifier;1706 ASSERT_TRUE(Verifier.match(1707 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));1708 EXPECT_TRUE(Verifier.match(1709 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));1710}1711 1712TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {1713 Decl *From, *To;1714 std::tie(From, To) = getImportedDecl(1715 R"(1716 struct declToImport {1717 };1718 )",1719 Lang_CXX03, "", Lang_CXX03);1720 1721 MatchVerifier<Decl> Verifier;1722 // Match the implicit Decl.1723 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));1724 ASSERT_TRUE(Verifier.match(From, Matcher));1725 EXPECT_TRUE(Verifier.match(To, Matcher));1726}1727 1728TEST_P(ASTImporterOptionSpecificTestBase,1729 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {1730 Decl *From, *To;1731 std::tie(From, To) = getImportedDecl(1732 R"(1733 template <typename U>1734 struct declToImport {1735 };1736 )",1737 Lang_CXX03, "", Lang_CXX03);1738 1739 MatchVerifier<Decl> Verifier;1740 // Match the implicit Decl.1741 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));1742 ASSERT_TRUE(Verifier.match(From, Matcher));1743 EXPECT_TRUE(Verifier.match(To, Matcher));1744}1745 1746TEST_P(ASTImporterOptionSpecificTestBase,1747 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {1748 Decl *From, *To;1749 std::tie(From, To) = getImportedDecl(1750 R"(1751 template<class T>1752 class Base {};1753 class declToImport : public Base<declToImport> {};1754 )",1755 Lang_CXX03, "", Lang_CXX03);1756 1757 auto hasImplicitClass = has(cxxRecordDecl());1758 auto Pattern = translationUnitDecl(has(classTemplateDecl(1759 hasName("Base"),1760 has(classTemplateSpecializationDecl(hasImplicitClass)))));1761 ASSERT_TRUE(1762 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));1763 EXPECT_TRUE(1764 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));1765}1766 1767TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {1768 Decl *From, *To;1769 std::tie(From, To) =1770 getImportedDecl("void declToImport() {}", Lang_CXX03, "", Lang_CXX03);1771 1772 MatchVerifier<Decl> Verifier;1773 auto Matcher = functionDecl();1774 ASSERT_TRUE(Verifier.match(From, Matcher));1775 EXPECT_TRUE(Verifier.match(To, Matcher));1776 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());1777}1778 1779TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {1780 Decl *FromTU = getTuDecl(1781 R"(1782 struct X {};1783 void operator<<(int, X);1784 )",1785 Lang_CXX03);1786 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());1787 const Decl *To = Import(From, Lang_CXX03);1788 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());1789}1790 1791TEST_P(ASTImporterOptionSpecificTestBase,1792 ShouldImportMembersOfClassTemplateSpecializationDecl) {1793 Decl *From, *To;1794 std::tie(From, To) = getImportedDecl(1795 R"(1796 template<class T>1797 class Base { int a; };1798 class declToImport : Base<declToImport> {};1799 )",1800 Lang_CXX03, "", Lang_CXX03);1801 1802 auto Pattern = translationUnitDecl(has(classTemplateDecl(1803 hasName("Base"),1804 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));1805 ASSERT_TRUE(1806 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));1807 EXPECT_TRUE(1808 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));1809}1810 1811TEST_P(ASTImporterOptionSpecificTestBase,1812 ImportDefinitionOfClassTemplateAfterFwdDecl) {1813 {1814 Decl *FromTU = getTuDecl(1815 R"(1816 template <typename T>1817 struct B;1818 )",1819 Lang_CXX03, "input0.cc");1820 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(1821 FromTU, classTemplateDecl(hasName("B")));1822 1823 Import(FromD, Lang_CXX03);1824 }1825 1826 {1827 Decl *FromTU = getTuDecl(1828 R"(1829 template <typename T>1830 struct B {1831 void f();1832 };1833 )",1834 Lang_CXX03, "input1.cc");1835 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(1836 FromTU, functionDecl(hasName("f")));1837 Import(FromD, Lang_CXX03);1838 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(1839 FromTU, classTemplateDecl(hasName("B")));1840 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));1841 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());1842 }1843}1844 1845TEST_P(ASTImporterOptionSpecificTestBase,1846 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {1847 Decl *ToTU = getToTuDecl(1848 R"(1849 template <typename T>1850 struct B {1851 void f();1852 };1853 1854 template <typename T>1855 struct B;1856 )",1857 Lang_CXX03);1858 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(1859 [](const ClassTemplateDecl *T) {1860 return T->isThisDeclarationADefinition();1861 })1862 .match(ToTU, classTemplateDecl()));1863 1864 Decl *FromTU = getTuDecl(1865 R"(1866 template <typename T>1867 struct B {1868 void f();1869 };1870 )",1871 Lang_CXX03, "input1.cc");1872 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(1873 FromTU, classTemplateDecl(hasName("B")));1874 1875 Import(FromD, Lang_CXX03);1876 1877 // We should have only one definition.1878 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(1879 [](const ClassTemplateDecl *T) {1880 return T->isThisDeclarationADefinition();1881 })1882 .match(ToTU, classTemplateDecl()));1883}1884 1885TEST_P(ASTImporterOptionSpecificTestBase,1886 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {1887 Decl *ToTU = getToTuDecl(1888 R"(1889 struct B {1890 void f();1891 };1892 1893 struct B;1894 )",1895 Lang_CXX03);1896 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(1897 ToTU, cxxRecordDecl(unless(isImplicit()))));1898 1899 Decl *FromTU = getTuDecl(1900 R"(1901 struct B {1902 void f();1903 };1904 )",1905 Lang_CXX03, "input1.cc");1906 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(1907 FromTU, cxxRecordDecl(hasName("B")));1908 1909 Import(FromD, Lang_CXX03);1910 1911 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(1912 ToTU, cxxRecordDecl(unless(isImplicit()))));1913}1914 1915static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {1916 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());1917 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());1918 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());1919 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());1920}1921static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,1922 SourceManager &SM1, SourceManager &SM2) {1923 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },1924 FullSourceLoc{ Range2.getBegin(), SM2 });1925 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },1926 FullSourceLoc{ Range2.getEnd(), SM2 });1927}1928TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {1929 Decl *FromTU = getTuDecl(1930 R"(1931 #define MFOO(arg) arg = arg + 11932 1933 void foo() {1934 int a = 5;1935 MFOO(a);1936 }1937 )",1938 Lang_CXX03);1939 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());1940 auto ToD = Import(FromD, Lang_CXX03);1941 1942 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());1943 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());1944 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());1945 auto FromRHS =1946 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());1947 1948 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();1949 SourceManager &FromSM = FromD->getASTContext().getSourceManager();1950 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,1951 FromSM);1952 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,1953 FromSM);1954 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,1955 FromSM);1956}1957 1958TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {1959 Decl *FromTU = getTuDecl(1960 R"(1961 #define FUNC_INT void declToImport1962 #define FUNC FUNC_INT1963 FUNC(int a);1964 )",1965 Lang_CXX03);1966 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());1967 auto ToD = Import(FromD, Lang_CXX03);1968 1969 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();1970 SourceManager &FromSM = FromD->getASTContext().getSourceManager();1971 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,1972 FromSM);1973}1974 1975TEST_P(1976 ASTImporterOptionSpecificTestBase,1977 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {1978 Decl *ToTU = getToTuDecl(1979 R"(1980 template <typename T>1981 struct B;1982 1983 template <>1984 struct B<int> {};1985 1986 template <>1987 struct B<int>;1988 )",1989 Lang_CXX03);1990 // We should have only one definition.1991 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(1992 [](const ClassTemplateSpecializationDecl *T) {1993 return T->isThisDeclarationADefinition();1994 })1995 .match(ToTU, classTemplateSpecializationDecl()));1996 1997 Decl *FromTU = getTuDecl(1998 R"(1999 template <typename T>2000 struct B;2001 2002 template <>2003 struct B<int> {};2004 )",2005 Lang_CXX03, "input1.cc");2006 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(2007 FromTU, classTemplateSpecializationDecl(hasName("B")));2008 2009 Import(FromD, Lang_CXX03);2010 2011 // We should have only one definition.2012 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(2013 [](const ClassTemplateSpecializationDecl *T) {2014 return T->isThisDeclarationADefinition();2015 })2016 .match(ToTU, classTemplateSpecializationDecl()));2017}2018 2019TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {2020 Decl *FromTU = getTuDecl(2021 R"(2022 struct { int a; int b; } object0 = { 2, 3 };2023 struct { int x; int y; int z; } object1;2024 )",2025 Lang_CXX03, "input0.cc");2026 2027 auto *Obj0 =2028 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));2029 auto *From0 = getRecordDecl(Obj0);2030 auto *Obj1 =2031 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));2032 auto *From1 = getRecordDecl(Obj1);2033 2034 auto *To0 = Import(From0, Lang_CXX03);2035 auto *To1 = Import(From1, Lang_CXX03);2036 2037 EXPECT_TRUE(To0);2038 EXPECT_TRUE(To1);2039 EXPECT_NE(To0, To1);2040 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());2041}2042 2043TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {2044 auto *Code =2045 R"(2046 struct X {2047 struct { int a; };2048 struct { int b; };2049 };2050 )";2051 Decl *FromTU0 = getTuDecl(Code, Lang_C99, "input0.c");2052 2053 Decl *FromTU1 = getTuDecl(Code, Lang_C99, "input1.c");2054 2055 auto *X0 =2056 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));2057 auto *X1 =2058 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));2059 Import(X0, Lang_C99);2060 Import(X1, Lang_C99);2061 2062 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2063 // We expect no (ODR) warning during the import.2064 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());2065 EXPECT_EQ(1u,2066 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));2067}2068 2069TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {2070 Decl *FromTU0 = getTuDecl(2071 R"(2072 struct X {2073 struct { int a; };2074 struct { int b; };2075 };2076 )",2077 Lang_C99, "input0.c");2078 2079 Decl *FromTU1 = getTuDecl(2080 R"(2081 struct X { // reversed order2082 struct { int b; };2083 struct { int a; };2084 };2085 )",2086 Lang_C99, "input1.c");2087 2088 auto *X0 =2089 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));2090 auto *X1 =2091 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));2092 Import(X0, Lang_C99);2093 Import(X1, Lang_C99);2094 2095 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2096 // We expect one (ODR) warning during the import.2097 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());2098 EXPECT_EQ(1u,2099 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));2100}2101 2102TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {2103 auto Pattern = varDecl(hasName("x"));2104 VarDecl *Imported1;2105 {2106 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX03, "input0.cc");2107 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);2108 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));2109 }2110 VarDecl *Imported2;2111 {2112 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input1.cc");2113 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);2114 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));2115 }2116 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());2117 EXPECT_FALSE(Imported2->isUsed(false));2118 {2119 Decl *FromTU = getTuDecl("extern int x; int f() { return x; }", Lang_CXX03,2120 "input2.cc");2121 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2122 FromTU, functionDecl(hasName("f")));2123 Import(FromD, Lang_CXX03);2124 }2125 EXPECT_TRUE(Imported2->isUsed(false));2126}2127 2128TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {2129 auto Pattern = varDecl(hasName("x"));2130 VarDecl *ExistingD;2131 {2132 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX03);2133 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);2134 }2135 EXPECT_FALSE(ExistingD->isUsed(false));2136 {2137 Decl *FromTU =2138 getTuDecl("int x = 1; int f() { return x; }", Lang_CXX03, "input1.cc");2139 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2140 FromTU, functionDecl(hasName("f")));2141 Import(FromD, Lang_CXX03);2142 }2143 EXPECT_TRUE(ExistingD->isUsed(false));2144}2145 2146TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {2147 auto Pattern = varDecl(hasName("a"));2148 VarDecl *ExistingD;2149 {2150 Decl *ToTU = getToTuDecl(2151 R"(2152 struct A {2153 static const int a = 1;2154 };2155 )",2156 Lang_CXX03);2157 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);2158 }2159 EXPECT_FALSE(ExistingD->isUsed(false));2160 {2161 Decl *FromTU = getTuDecl(2162 R"(2163 struct A {2164 static const int a = 1;2165 };2166 const int *f() { return &A::a; } // requires storage,2167 // thus used flag will be set2168 )",2169 Lang_CXX03, "input1.cc");2170 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(2171 FromTU, functionDecl(hasName("f")));2172 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);2173 ASSERT_TRUE(FromD->isUsed(false));2174 Import(FromFunD, Lang_CXX03);2175 }2176 EXPECT_TRUE(ExistingD->isUsed(false));2177}2178 2179TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {2180 auto Pattern = varDecl(hasName("x"));2181 2182 Decl *FromTU = getTuDecl("int x;", Lang_CXX03, "input0.cc");2183 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);2184 2185 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));2186 2187 ASSERT_FALSE(Imported1->isUsed(false));2188 2189 FromD->setIsUsed();2190 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));2191 2192 EXPECT_EQ(Imported1, Imported2);2193 EXPECT_TRUE(Imported2->isUsed(false));2194}2195 2196struct ImportFunctions : ASTImporterOptionSpecificTestBase {};2197 2198TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {2199 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);2200 auto Pattern = functionDecl(hasName("f"));2201 auto *From =2202 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto2203 2204 Decl *ImportedD = Import(From, Lang_CXX03);2205 Decl *ToTU = ImportedD->getTranslationUnitDecl();2206 2207 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2208 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2209 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2210 EXPECT_TRUE(ImportedD == To0);2211 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());2212 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());2213 EXPECT_EQ(To1->getPreviousDecl(), To0);2214}2215 2216TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {2217 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX03);2218 auto Pattern = functionDecl(hasName("f"));2219 auto *From =2220 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def2221 2222 Decl *ImportedD = Import(From, Lang_CXX03);2223 Decl *ToTU = ImportedD->getTranslationUnitDecl();2224 2225 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2226 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2227 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2228 EXPECT_TRUE(ImportedD == To1);2229 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());2230 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());2231 EXPECT_EQ(To1->getPreviousDecl(), To0);2232}2233 2234TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {2235 auto Code =2236 R"(2237 struct B { virtual void f(); };2238 void B::f() {}2239 struct D : B { void f(); };2240 )";2241 auto Pattern =2242 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));2243 Decl *FromTU = getTuDecl(Code, Lang_CXX03);2244 CXXMethodDecl *Proto =2245 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);2246 2247 ASSERT_EQ(Proto->size_overridden_methods(), 1u);2248 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));2249 EXPECT_EQ(To->size_overridden_methods(), 1u);2250}2251 2252TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {2253 auto Code =2254 R"(2255 struct B { virtual void f(); };2256 void B::f() {}2257 )";2258 auto Pattern =2259 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));2260 Decl *FromTU = getTuDecl(Code, Lang_CXX03);2261 CXXMethodDecl *Proto =2262 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);2263 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);2264 2265 ASSERT_TRUE(Proto->isVirtual());2266 ASSERT_TRUE(Def->isVirtual());2267 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX03));2268 EXPECT_TRUE(To->isVirtual());2269}2270 2271TEST_P(ImportFunctions,2272 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {2273 Decl *ToTU = getToTuDecl(2274 R"(2275 void f() {}2276 void f();2277 )",2278 Lang_CXX03);2279 ASSERT_EQ(1u,2280 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {2281 return FD->doesThisDeclarationHaveABody();2282 }).match(ToTU, functionDecl()));2283 2284 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX03, "input0.cc");2285 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());2286 2287 Import(FromD, Lang_CXX03);2288 2289 EXPECT_EQ(1u,2290 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {2291 return FD->doesThisDeclarationHaveABody();2292 }).match(ToTU, functionDecl()));2293}2294 2295TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {2296 auto Code =2297 R"(2298 struct B { virtual void f(); };2299 struct D:B { void f(); };2300 )";2301 auto BFP =2302 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));2303 auto DFP =2304 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));2305 2306 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);2307 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);2308 Import(DF, Lang_CXX03);2309 2310 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");2311 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);2312 Import(BF, Lang_CXX03);2313 2314 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2315 2316 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);2317 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);2318}2319 2320TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {2321 auto CodeWithoutDef =2322 R"(2323 struct B { virtual void f(); };2324 struct D:B { void f(); };2325 )";2326 auto CodeWithDef =2327 R"(2328 struct B { virtual void f(){}; };2329 struct D:B { void f(){}; };2330 )";2331 auto BFP =2332 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));2333 auto DFP =2334 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));2335 auto BFDefP = cxxMethodDecl(2336 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());2337 auto DFDefP = cxxMethodDecl(2338 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());2339 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());2340 2341 {2342 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX03, "input0.cc");2343 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);2344 Import(FromD, Lang_CXX03);2345 }2346 {2347 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX03, "input1.cc");2348 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);2349 Import(FromB, Lang_CXX03);2350 }2351 2352 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2353 2354 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);2355 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);2356 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);2357 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);2358 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);2359}2360 2361TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {2362 auto Code =2363 R"(2364 struct B { virtual void f(); };2365 struct D:B { void f(); };2366 void B::f(){};2367 )";2368 2369 auto BFP =2370 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));2371 auto BFDefP = cxxMethodDecl(2372 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());2373 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),2374 unless(isDefinition()));2375 2376 Decl *FromTU0 = getTuDecl(Code, Lang_CXX03);2377 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);2378 Import(D, Lang_CXX03);2379 2380 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");2381 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);2382 Import(B, Lang_CXX03);2383 2384 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2385 2386 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);2387 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);2388 2389 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(2390 ToTU, cxxRecordDecl(hasName("B")));2391 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);2392 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(2393 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));2394 2395 // The definition should be out-of-class.2396 EXPECT_NE(ToBFInClass, ToBFOutOfClass);2397 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),2398 ToBFOutOfClass->getLexicalDeclContext());2399 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);2400 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);2401 2402 // Check that the redecl chain is intact.2403 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);2404}2405 2406TEST_P(ImportFunctions,2407 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {2408 auto CodeTU0 =2409 R"(2410 struct B { virtual void f(); };2411 struct D:B { void f(); };2412 )";2413 auto CodeTU1 =2414 R"(2415 struct B { virtual void f(); };2416 struct D:B { void f(); };2417 void B::f(){}2418 void D::f(){}2419 void foo(B &b, D &d) { b.f(); d.f(); }2420 )";2421 2422 auto BFP =2423 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));2424 auto BFDefP = cxxMethodDecl(2425 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());2426 auto DFP =2427 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));2428 auto DFDefP = cxxMethodDecl(2429 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());2430 auto FooDef = functionDecl(hasName("foo"));2431 2432 {2433 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX03, "input0.cc");2434 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);2435 Import(D, Lang_CXX03);2436 }2437 2438 {2439 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX03, "input1.cc");2440 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);2441 Import(Foo, Lang_CXX03);2442 }2443 2444 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2445 2446 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);2447 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);2448 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);2449 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);2450 2451 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(2452 ToTU, cxxRecordDecl(hasName("B")));2453 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(2454 ToTU, cxxRecordDecl(hasName("D")));2455 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);2456 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(2457 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));2458 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);2459 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(2460 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));2461 2462 // The definition should be out-of-class.2463 EXPECT_NE(ToBFInClass, ToBFOutOfClass);2464 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),2465 ToBFOutOfClass->getLexicalDeclContext());2466 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);2467 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);2468 2469 EXPECT_NE(ToDFInClass, ToDFOutOfClass);2470 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),2471 ToDFOutOfClass->getLexicalDeclContext());2472 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);2473 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);2474 2475 // Check that the redecl chain is intact.2476 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);2477 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);2478}2479 2480TEST_P(ASTImporterOptionSpecificTestBase,2481 ImportVirtualOverriddenMethodOnALoop) {2482 // B::f() calls => f1() ==> C ==> C::f()2483 // \2484 // \---- A::f()2485 //2486 // C::f()'s ImportOverriddenMethods() asserts B::isVirtual(), so B::f()'s2487 // ImportOverriddenMethods() should be completed before B::f()'s body2488 const char *Code =2489 R"(2490 void f1();2491 class A {2492 virtual void f(){}2493 };2494 class B: public A {2495 void f() override {2496 f1();2497 }2498 };2499 class C: public B {2500 void f() override {}2501 };2502 void f1() { C c; }2503 )";2504 Decl *FromTU = getTuDecl(Code, Lang_CXX11);2505 2506 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(2507 FromTU, cxxMethodDecl(hasName("B::f")));2508 2509 auto *ToBF = Import(FromF, Lang_CXX11);2510 EXPECT_TRUE(ToBF->isVirtual());2511 2512 auto *ToCF = FirstDeclMatcher<CXXMethodDecl>().match(2513 ToBF->getTranslationUnitDecl(), cxxMethodDecl(hasName("C::f")));2514 EXPECT_TRUE(ToCF->isVirtual());2515}2516 2517TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {2518 std::string Code = "static int v; static int v = 0;";2519 auto Pattern = varDecl(hasName("v"));2520 2521 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C99, "input0.c");2522 2523 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);2524 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);2525 2526 auto *To0 = Import(From0, Lang_C99);2527 auto *To1 = Import(From1, Lang_C99);2528 2529 EXPECT_TRUE(To0);2530 ASSERT_TRUE(To1);2531 EXPECT_NE(To0, To1);2532 EXPECT_EQ(To1->getPreviousDecl(), To0);2533}2534 2535TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {2536 TranslationUnitDecl *FromTu =2537 getTuDecl("namespace NS0 { namespace { void f(); } }"2538 "namespace NS1 { namespace { void f(); } }",2539 Lang_CXX03, "input0.cc");2540 auto Pattern = functionDecl(hasName("f"));2541 2542 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);2543 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);2544 2545 auto *ToF0 = Import(FromF0, Lang_CXX03);2546 auto *ToF1 = Import(FromF1, Lang_CXX03);2547 2548 EXPECT_TRUE(ToF0);2549 ASSERT_TRUE(ToF1);2550 EXPECT_NE(ToF0, ToF1);2551 EXPECT_FALSE(ToF1->getPreviousDecl());2552}2553 2554TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {2555 {2556 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",2557 Lang_CXX03, "input0.cc");2558 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2559 FromTU, functionDecl(hasName("g0")));2560 2561 Import(FromD, Lang_CXX03);2562 }2563 {2564 Decl *FromTU =2565 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",2566 Lang_CXX03, "input1.cc");2567 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2568 FromTU, functionDecl(hasName("g1")));2569 Import(FromD, Lang_CXX03);2570 }2571 2572 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2573 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),2574 2u);2575}2576 2577TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {2578 Decl *FromTU = getTuDecl(2579 R"(2580 void foo() {2581 (void)[]() { ; };2582 }2583 )",2584 Lang_CXX11);2585 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2586 FromTU, functionDecl(hasName("foo")));2587 auto *ToD = Import(FromD, Lang_CXX03);2588 EXPECT_TRUE(ToD);2589 CXXRecordDecl *LambdaRec =2590 cast<LambdaExpr>(cast<CStyleCastExpr>(2591 *cast<CompoundStmt>(ToD->getBody())->body_begin())2592 ->getSubExpr())2593 ->getLambdaClass();2594 EXPECT_TRUE(LambdaRec->getDestructor());2595}2596 2597TEST_P(ImportFunctions,2598 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {2599 Decl *FromTU = getTuDecl(2600 R"(2601 struct X {2602 template <typename T>2603 void foo(){}2604 };2605 void f() {2606 X x;2607 x.foo<int>();2608 }2609 )",2610 Lang_CXX03);2611 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2612 FromTU, functionDecl(hasName("f")));2613 auto *ToD = Import(FromD, Lang_CXX03);2614 EXPECT_TRUE(ToD);2615 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(2616 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));2617}2618 2619TEST_P(ImportFunctions,2620 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {2621 Decl *FromTU = getTuDecl(2622 R"(2623 struct X {2624 template <typename T>2625 void foo(){}2626 };2627 template <typename T>2628 void f() {2629 X x;2630 x.foo<T>();2631 }2632 void g() {2633 f<int>();2634 }2635 )",2636 Lang_CXX03);2637 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2638 FromTU, functionDecl(hasName("g")));2639 auto *ToD = Import(FromD, Lang_CXX03);2640 EXPECT_TRUE(ToD);2641 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2642 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(2643 ToTU, translationUnitDecl(hasDescendant(2644 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));2645}2646 2647struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};2648 2649TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {2650 auto Code =2651 R"(2652 class X {2653 template <class T>2654 void f(T t);2655 };2656 )";2657 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");2658 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(2659 FromTU1, functionTemplateDecl(hasName("f")));2660 auto *ToD1 = Import(FromD1, Lang_CXX03);2661 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");2662 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(2663 FromTU2, functionTemplateDecl(hasName("f")));2664 auto *ToD2 = Import(FromD2, Lang_CXX03);2665 EXPECT_EQ(ToD1, ToD2);2666}2667 2668TEST_P(ImportFunctionTemplates,2669 ImportFunctionTemplateWithDefInRecordDeclTwice) {2670 auto Code =2671 R"(2672 class X {2673 template <class T>2674 void f(T t);2675 };2676 template <class T>2677 void X::f(T t) {};2678 )";2679 Decl *FromTU1 = getTuDecl(Code, Lang_CXX03, "input1.cc");2680 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(2681 FromTU1, functionTemplateDecl(hasName("f")));2682 auto *ToD1 = Import(FromD1, Lang_CXX03);2683 Decl *FromTU2 = getTuDecl(Code, Lang_CXX03, "input2.cc");2684 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(2685 FromTU2, functionTemplateDecl(hasName("f")));2686 auto *ToD2 = Import(FromD2, Lang_CXX03);2687 EXPECT_EQ(ToD1, ToD2);2688}2689 2690TEST_P(ImportFunctionTemplates,2691 ImportFunctionWhenThereIsAFunTemplateWithSameName) {2692 getToTuDecl(2693 R"(2694 template <typename T>2695 void foo(T) {}2696 void foo();2697 )",2698 Lang_CXX03);2699 Decl *FromTU = getTuDecl("void foo();", Lang_CXX03);2700 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(2701 FromTU, functionDecl(hasName("foo")));2702 auto *ImportedD = Import(FromD, Lang_CXX03);2703 EXPECT_TRUE(ImportedD);2704}2705 2706TEST_P(ImportFunctionTemplates,2707 ImportConstructorWhenThereIsAFunTemplateWithSameName) {2708 auto Code =2709 R"(2710 struct Foo {2711 template <typename T>2712 Foo(T) {}2713 Foo();2714 };2715 )";2716 getToTuDecl(Code, Lang_CXX03);2717 Decl *FromTU = getTuDecl(Code, Lang_CXX03);2718 auto *FromD =2719 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());2720 auto *ImportedD = Import(FromD, Lang_CXX03);2721 EXPECT_TRUE(ImportedD);2722}2723 2724TEST_P(ImportFunctionTemplates,2725 ImportOperatorWhenThereIsAFunTemplateWithSameName) {2726 getToTuDecl(2727 R"(2728 template <typename T>2729 void operator<(T,T) {}2730 struct X{};2731 void operator<(X, X);2732 )",2733 Lang_CXX03);2734 Decl *FromTU = getTuDecl(2735 R"(2736 struct X{};2737 void operator<(X, X);2738 )",2739 Lang_CXX03);2740 auto *FromD = LastDeclMatcher<FunctionDecl>().match(2741 FromTU, functionDecl(hasOverloadedOperatorName("<")));2742 auto *ImportedD = Import(FromD, Lang_CXX03);2743 EXPECT_TRUE(ImportedD);2744}2745 2746struct ImportFriendFunctions : ImportFunctions {};2747 2748TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {2749 auto Pattern = functionDecl(hasName("f"));2750 2751 Decl *FromTU = getTuDecl("struct X { friend void f(); };"2752 "void f();",2753 Lang_CXX03, "input0.cc");2754 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2755 2756 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2757 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2758 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2759 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());2760 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2761 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());2762 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);2763}2764 2765TEST_P(ImportFriendFunctions,2766 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {2767 auto Pattern = functionDecl(hasName("f"));2768 2769 Decl *FromTU = getTuDecl("void f();"2770 "struct X { friend void f(); };",2771 Lang_CXX03, "input0.cc");2772 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2773 2774 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2775 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2776 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2777 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());2778 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2779 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());2780 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);2781}2782 2783TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {2784 auto Pattern = functionDecl(hasName("f"));2785 2786 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"2787 "void f();",2788 Lang_CXX03, "input0.cc");2789 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2790 2791 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2792 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2793 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2794 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());2795 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2796 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());2797 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);2798}2799 2800TEST_P(ImportFriendFunctions,2801 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {2802 auto Pattern = functionDecl(hasName("f"));2803 2804 Decl *FromTU = getTuDecl("struct X { friend void f(); };"2805 "void f(){}",2806 Lang_CXX03, "input0.cc");2807 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2808 2809 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2810 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2811 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2812 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());2813 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);2814 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());2815 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);2816}2817 2818TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {2819 auto Pattern = functionDecl(hasName("f"));2820 2821 Decl *FromTU = getTuDecl(2822 R"(2823 class X;2824 void f(X *x){}2825 class X{2826 friend void f(X *x);2827 };2828 )",2829 Lang_CXX03, "input0.cc");2830 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2831 2832 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2833 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2834 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2835 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());2836 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()2837 .match(ToTU, friendDecl())2838 ->getFriendDecl());2839 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());2840 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);2841 // The parameters must refer the same type2842 EXPECT_TRUE(ToTU->getASTContext().hasSameType(2843 (*InClassFD->param_begin())->getOriginalType(),2844 (*ImportedD->param_begin())->getOriginalType()));2845}2846 2847TEST_P(ImportFriendFunctions,2848 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {2849 auto Pattern = functionDecl(hasName("f"));2850 2851 Decl *FromTU = getTuDecl(2852 R"(2853 class X;2854 void f(X *x){}2855 class X{2856 friend void f(X *x);2857 };2858 )",2859 Lang_CXX03, "input0.cc");2860 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2861 2862 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2863 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2864 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2865 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());2866 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(2867 ToTU, functionDecl(unless(hasParent(friendDecl()))));2868 2869 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());2870 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);2871 // The parameters must refer the same type2872 EXPECT_TRUE(ToTU->getASTContext().hasSameType(2873 (*OutOfClassFD->param_begin())->getOriginalType(),2874 (*ImportedD->param_begin())->getOriginalType()));2875}2876 2877TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {2878 auto Pattern = functionDecl(hasName("f"));2879 2880 FunctionDecl *ImportedD;2881 {2882 Decl *FromTU =2883 getTuDecl("struct X { friend void f(){} };", Lang_CXX03, "input0.cc");2884 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2885 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2886 }2887 FunctionDecl *ImportedD1;2888 {2889 Decl *FromTU = getTuDecl("void f();", Lang_CXX03, "input1.cc");2890 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);2891 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2892 }2893 2894 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2895 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);2896 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());2897 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());2898 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);2899}2900 2901TEST_P(ImportFriendFunctions, Lookup) {2902 auto FunctionPattern = functionDecl(hasName("f"));2903 auto ClassPattern = cxxRecordDecl(hasName("X"));2904 2905 TranslationUnitDecl *FromTU =2906 getTuDecl("struct X { friend void f(); };", Lang_CXX03, "input0.cc");2907 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);2908 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2909 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));2910 {2911 auto FromName = FromD->getDeclName();2912 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);2913 auto LookupRes = Class->noload_lookup(FromName);2914 ASSERT_TRUE(LookupRes.empty());2915 LookupRes = FromTU->noload_lookup(FromName);2916 ASSERT_TRUE(LookupRes.isSingleResult());2917 }2918 2919 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));2920 auto ToName = ToD->getDeclName();2921 2922 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2923 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);2924 auto LookupRes = Class->noload_lookup(ToName);2925 EXPECT_TRUE(LookupRes.empty());2926 LookupRes = ToTU->noload_lookup(ToName);2927 EXPECT_TRUE(LookupRes.isSingleResult());2928 2929 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);2930 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);2931 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2932 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));2933}2934 2935TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {2936 auto FunctionPattern = functionDecl(hasName("f"));2937 auto ClassPattern = cxxRecordDecl(hasName("X"));2938 2939 TranslationUnitDecl *FromTU =2940 getTuDecl("struct X { friend void f(); };"2941 // This proto decl makes f available to normal2942 // lookup, otherwise it is hidden.2943 // Normal C++ lookup (implemented in2944 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)2945 // returns the found `NamedDecl` only if the set IDNS is matched2946 "void f();",2947 Lang_CXX03, "input0.cc");2948 auto *FromFriend =2949 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);2950 auto *FromNormal =2951 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);2952 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2953 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));2954 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2955 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));2956 2957 auto FromName = FromFriend->getDeclName();2958 auto *FromClass =2959 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);2960 auto LookupRes = FromClass->noload_lookup(FromName);2961 ASSERT_TRUE(LookupRes.empty());2962 LookupRes = FromTU->noload_lookup(FromName);2963 ASSERT_TRUE(LookupRes.isSingleResult());2964 2965 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX03));2966 auto ToName = ToFriend->getDeclName();2967 2968 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();2969 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);2970 LookupRes = ToClass->noload_lookup(ToName);2971 EXPECT_TRUE(LookupRes.empty());2972 LookupRes = ToTU->noload_lookup(ToName);2973 // Test is disabled because this result is 2.2974 EXPECT_TRUE(LookupRes.isSingleResult());2975 2976 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);2977 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);2978 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);2979 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2980 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));2981 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2982 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));2983}2984 2985TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {2986 auto FunctionPattern = functionDecl(hasName("f"));2987 auto ClassPattern = cxxRecordDecl(hasName("X"));2988 2989 TranslationUnitDecl *FromTU = getTuDecl("void f();"2990 "struct X { friend void f(); };",2991 Lang_CXX03, "input0.cc");2992 auto *FromNormal =2993 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);2994 auto *FromFriend =2995 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);2996 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2997 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));2998 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));2999 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));3000 3001 auto FromName = FromNormal->getDeclName();3002 auto *FromClass =3003 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);3004 auto LookupRes = FromClass->noload_lookup(FromName);3005 ASSERT_TRUE(LookupRes.empty());3006 LookupRes = FromTU->noload_lookup(FromName);3007 ASSERT_TRUE(LookupRes.isSingleResult());3008 3009 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX03));3010 auto ToName = ToNormal->getDeclName();3011 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();3012 3013 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);3014 LookupRes = ToClass->noload_lookup(ToName);3015 EXPECT_TRUE(LookupRes.empty());3016 LookupRes = ToTU->noload_lookup(ToName);3017 EXPECT_TRUE(LookupRes.isSingleResult());3018 3019 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);3020 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);3021 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);3022 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3023 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));3024 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3025 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));3026}3027 3028TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {3029 auto Pattern = functionDecl(hasName("f"));3030 3031 TranslationUnitDecl *FromNormalTU =3032 getTuDecl("void f();", Lang_CXX03, "input0.cc");3033 auto *FromNormalF =3034 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);3035 TranslationUnitDecl *FromFriendTU =3036 getTuDecl("class X { friend void f(); };", Lang_CXX03, "input1.cc");3037 auto *FromFriendF =3038 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);3039 auto FromNormalName = FromNormalF->getDeclName();3040 auto FromFriendName = FromFriendF->getDeclName();3041 3042 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));3043 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3044 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));3045 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3046 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);3047 ASSERT_TRUE(LookupRes.isSingleResult());3048 LookupRes = FromFriendTU->noload_lookup(FromFriendName);3049 ASSERT_TRUE(LookupRes.isSingleResult());3050 3051 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX03));3052 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();3053 auto ToName = ToNormalF->getDeclName();3054 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));3055 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3056 LookupRes = ToTU->noload_lookup(ToName);3057 EXPECT_TRUE(LookupRes.isSingleResult());3058 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);3059 3060 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX03));3061 LookupRes = ToTU->noload_lookup(ToName);3062 EXPECT_TRUE(LookupRes.isSingleResult());3063 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);3064 3065 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));3066 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3067 3068 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));3069 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));3070}3071 3072TEST_P(ImportFriendFunctions, ImportFriendList) {3073 TranslationUnitDecl *FromTU = getTuDecl("struct X { friend void f(); };"3074 "void f();",3075 Lang_CXX03, "input0.cc");3076 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(3077 FromTU, functionDecl(hasName("f")));3078 3079 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(3080 FromTU, cxxRecordDecl(hasName("X")));3081 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());3082 auto FromFriends = FromClass->friends();3083 unsigned int FrN = 0;3084 for (auto Fr : FromFriends) {3085 ASSERT_EQ(Fr, FromFriend);3086 ++FrN;3087 }3088 ASSERT_EQ(FrN, 1u);3089 3090 Import(FromFriendF, Lang_CXX03);3091 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();3092 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(3093 ToTU, cxxRecordDecl(hasName("X")));3094 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());3095 auto ToFriends = ToClass->friends();3096 FrN = 0;3097 for (auto Fr : ToFriends) {3098 EXPECT_EQ(Fr, ToFriend);3099 ++FrN;3100 }3101 EXPECT_EQ(FrN, 1u);3102}3103 3104AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,3105 InnerMatcher) {3106 if (auto *Typedef = Node.getTypedefNameForAnonDecl())3107 return InnerMatcher.matches(*Typedef, Finder, Builder);3108 return false;3109}3110 3111TEST_P(ImportDecl, ImportEnumSequential) {3112 CodeFiles Samples{{"main.c",3113 {"void foo();"3114 "void moo();"3115 "int main() { foo(); moo(); }",3116 Lang_C99}},3117 3118 {"foo.c",3119 {"typedef enum { THING_VALUE } thing_t;"3120 "void conflict(thing_t type);"3121 "void foo() { (void)THING_VALUE; }"3122 "void conflict(thing_t type) {}",3123 Lang_C99}},3124 3125 {"moo.c",3126 {"typedef enum { THING_VALUE } thing_t;"3127 "void conflict(thing_t type);"3128 "void moo() { conflict(THING_VALUE); }",3129 Lang_C99}}};3130 3131 auto VerificationMatcher =3132 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),3133 hasTypedefForAnonDecl(hasName("thing_t")));3134 3135 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},3136 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};3137 3138 testImportSequence(3139 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".3140 // Just check that there is only one enum decl in the result AST.3141 "main.c", enumDecl(), VerificationMatcher);3142 3143 // For different import order, result should be the same.3144 testImportSequence(3145 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".3146 // Check that there is only one enum decl in the result AST.3147 "main.c", enumDecl(), VerificationMatcher);3148}3149 3150TEST_P(ImportDecl, ImportFieldOrder) {3151 MatchVerifier<Decl> Verifier;3152 testImport("struct declToImport {"3153 " int b = a + 2;"3154 " int a = 5;"3155 "};",3156 Lang_CXX11, "", Lang_CXX11, Verifier,3157 recordDecl(hasFieldOrder({"b", "a"})));3158}3159 3160TEST_P(ImportExpr, DependentScopeDeclRefExpr) {3161 MatchVerifier<Decl> Verifier;3162 testImport("template <typename T> struct S { static T foo; };"3163 "template <typename T> void declToImport() {"3164 " (void) S<T>::foo;"3165 "}"3166 "void instantiate() { declToImport<int>(); }"3167 "template <typename T> T S<T>::foo;",3168 Lang_CXX11, "", Lang_CXX11, Verifier,3169 functionTemplateDecl(has(functionDecl(has(compoundStmt(3170 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));3171 3172 testImport("template <typename T> struct S {"3173 "template<typename S> static void foo(){};"3174 "};"3175 "template <typename T> void declToImport() {"3176 " S<T>::template foo<T>();"3177 "}"3178 "void instantiate() { declToImport<int>(); }",3179 Lang_CXX11, "", Lang_CXX11, Verifier,3180 functionTemplateDecl(has(functionDecl(has(compoundStmt(3181 has(callExpr(has(dependentScopeDeclRefExpr())))))))));3182}3183 3184TEST_P(ImportExpr, DependentNameType) {3185 MatchVerifier<Decl> Verifier;3186 testImport("template <typename T> struct declToImport {"3187 " typedef typename T::type dependent_name;"3188 "};",3189 Lang_CXX11, "", Lang_CXX11, Verifier,3190 classTemplateDecl(has(3191 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));3192}3193 3194TEST_P(ImportExpr, UnresolvedMemberExpr) {3195 MatchVerifier<Decl> Verifier;3196 testImport("struct S { template <typename T> void mem(); };"3197 "template <typename U> void declToImport() {"3198 " S s;"3199 " s.mem<U>();"3200 "}"3201 "void instantiate() { declToImport<int>(); }",3202 Lang_CXX11, "", Lang_CXX11, Verifier,3203 functionTemplateDecl(has(functionDecl(has(3204 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));3205}3206 3207TEST_P(ImportDecl, CycleInAutoTemplateSpec) {3208 MatchVerifier<Decl> Verifier;3209 const char *Code = R"(3210 template <class _CharT>3211 struct basic_string {3212 using value_type = _CharT;3213 };3214 3215 template<typename T>3216 struct basic_string_view {3217 using value_type = T;3218 };3219 3220 using string_view = basic_string_view<char>;3221 using string = basic_string<char>;3222 3223 template<typename T>3224 struct span {3225 };3226 3227 template <typename StringT>3228 auto StrCatT(span<const StringT> pieces) {3229 basic_string<typename StringT::value_type> result;3230 return result;3231 }3232 3233 string StrCat(span<const string_view> pieces) {3234 return StrCatT(pieces);3235 }3236 3237 string StrCat(span<const string> pieces) {3238 return StrCatT(pieces);3239 }3240 3241 template <typename T>3242 auto declToImport(T pieces) {3243 return StrCat(pieces);3244 }3245 3246 void test() {3247 span<const string> pieces;3248 auto result = declToImport(pieces);3249 }3250)";3251 // This test reproduces the StrCatT recursion pattern with concepts and span3252 // that may cause infinite recursion during AST import due to circular3253 // dependencies3254 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3255 functionTemplateDecl(hasName("declToImport")));3256}3257 3258TEST_P(ImportExpr, ConceptNoRequirement) {3259 MatchVerifier<Decl> Verifier;3260 const char *Code = R"(3261 template<typename T>3262 struct is_int { static const bool value = false; };3263 template<> struct is_int<int> { static const bool value = true; };3264 template<typename T>3265 concept declToImport = is_int<T>::value;3266 )";3267 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3268 conceptDecl(unless(has(requiresExpr()))));3269}3270 3271TEST_P(ImportExpr, ConceptSimpleRequirement) {3272 MatchVerifier<Decl> Verifier;3273 const char *Code = R"(3274 template <class T1, class T2>3275 concept declToImport = requires(T1 i, T2 j) {3276 i + j;3277 };3278 )";3279 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3280 conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));3281}3282 3283TEST_P(ImportExpr, ConceptCompoundNonTypeRequirement) {3284 MatchVerifier<Decl> Verifier;3285 const char *Code = R"(3286 template <class T1, class T2>3287 concept declToImport = requires(T1 i, T2 j) {3288 {i + j};3289 };3290 )";3291 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3292 conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));3293}3294 3295TEST_P(ImportExpr, ConceptCompoundTypeRequirement) {3296 MatchVerifier<Decl> Verifier;3297 const char *Code = R"(3298 template<typename T>3299 struct is_int { static const bool value = false; };3300 template<> struct is_int<int> { static const bool value = true; };3301 3302 template<typename T>3303 concept type_is_int = is_int<T>::value;3304 3305 template<typename T>3306 concept declToImport = requires(T x) {3307 {x * 1} -> type_is_int;3308 };3309 )";3310 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3311 conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));3312}3313 3314TEST_P(ImportExpr, ConceptTypeRequirement) {3315 MatchVerifier<Decl> Verifier;3316 const char *Code = R"(3317 template <class T>3318 concept declToImport = requires {3319 typename T::value;3320 };3321 )";3322 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3323 conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));3324}3325 3326TEST_P(ImportExpr, ConceptNestedRequirement) {3327 MatchVerifier<Decl> Verifier;3328 const char *Code = R"(3329 template<typename T>3330 struct is_int { static const bool value = false; };3331 template<> struct is_int<int> { static const bool value = true; };3332 3333 template<typename T>3334 concept declToImport = requires(T x) {3335 requires is_int<T>::value;3336 };3337 )";3338 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3339 conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));3340}3341 3342TEST_P(ImportExpr, ConceptNestedNonInstantiationDependentRequirement) {3343 MatchVerifier<Decl> Verifier;3344 const char *Code = R"(3345 template<typename T>3346 concept declToImport = requires {3347 requires sizeof(long) == sizeof(int);3348 };3349 )";3350 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3351 conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));3352}3353 3354TEST_P(ImportExpr, ImportSubstNonTypeTemplateParmPackExpr) {3355 MatchVerifier<Decl> Verifier;3356 const char *Code = R"(3357 template<auto ...> struct X {};3358 template<typename ...> struct Z {};3359 3360 template<int ...N> struct E {3361 template<int ...M> using B = Z<X<N, M>...>;3362 template<int M1, int M2> E(B<M1, M2>);3363 };3364 using declToImport = E<1, 3>;3365 )";3366 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3367 typedefNameDecl(hasName("declToImport")));3368}3369 3370TEST_P(ImportExpr, ImportCXXParenListInitExpr) {3371 MatchVerifier<Decl> Verifier;3372 const char *Code = R"(3373 struct Node {3374 int val;3375 double d;3376 };3377 Node* declToImport() { return new Node(2, 3.14); }3378 )";3379 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3380 functionDecl(hasName("declToImport")));3381}3382 3383TEST_P(ImportExpr, ImportPseudoObjectExpr) {3384 MatchVerifier<Decl> Verifier;3385 const char *Code = R"(3386 namespace std {3387 struct strong_ordering {3388 int n;3389 constexpr operator int() const { return n; }3390 static const strong_ordering less, equal, greater;3391 };3392 constexpr strong_ordering strong_ordering::less{-1},3393 strong_ordering::equal{0}, strong_ordering::greater{1};3394 }3395 3396 struct A {3397 std::strong_ordering operator<=>(const A&) const;3398 };3399 struct B {3400 bool operator==(const B&) const;3401 bool operator<(const B&) const;3402 };3403 3404 template<typename T> struct Cmp : T {3405 std::strong_ordering operator<=>(const Cmp&) const = default;3406 };3407 3408 void use(...);3409 void declToImport() {3410 use(3411 Cmp<A>() <=> Cmp<A>(),3412 Cmp<B>() <=> Cmp<B>()3413 );3414 }3415 )";3416 testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,3417 functionDecl(hasName("declToImport")));3418}3419 3420class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {3421public:3422 static constexpr auto DefaultCode = R"(3423 struct A { int x; };3424 void f() {3425 A a;3426 A a1(a);3427 A a2(A{});3428 a = a1;3429 a = A{};3430 a.~A();3431 })";3432 3433 template <typename MatcherType>3434 void testImportOf(3435 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {3436 test(MethodMatcher, Code, /*ExpectedCount=*/1u);3437 }3438 3439 template <typename MatcherType>3440 void testNoImportOf(3441 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {3442 test(MethodMatcher, Code, /*ExpectedCount=*/0u);3443 }3444 3445private:3446 template <typename MatcherType>3447 void test(const MatcherType &MethodMatcher,3448 const char *Code, unsigned int ExpectedCount) {3449 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));3450 3451 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);3452 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(3453 ToTU, ClassMatcher);3454 3455 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);3456 3457 {3458 CXXMethodDecl *Method =3459 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);3460 ToClass->removeDecl(Method);3461 SharedStatePtr->getLookupTable()->remove(Method);3462 }3463 3464 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);3465 3466 Decl *ImportedClass = nullptr;3467 {3468 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");3469 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(3470 FromTU, ClassMatcher);3471 ImportedClass = Import(FromClass, Lang_CXX11);3472 }3473 3474 EXPECT_EQ(ToClass, ImportedClass);3475 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),3476 ExpectedCount);3477 }3478};3479 3480TEST_P(ImportImplicitMethods, DefaultConstructor) {3481 testImportOf(cxxConstructorDecl(isDefaultConstructor()));3482}3483 3484TEST_P(ImportImplicitMethods, CopyConstructor) {3485 testImportOf(cxxConstructorDecl(isCopyConstructor()));3486}3487 3488TEST_P(ImportImplicitMethods, MoveConstructor) {3489 testImportOf(cxxConstructorDecl(isMoveConstructor()));3490}3491 3492TEST_P(ImportImplicitMethods, Destructor) {3493 testImportOf(cxxDestructorDecl());3494}3495 3496TEST_P(ImportImplicitMethods, CopyAssignment) {3497 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));3498}3499 3500TEST_P(ImportImplicitMethods, MoveAssignment) {3501 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));3502}3503 3504TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {3505 auto Code = R"(3506 struct A { A() { int x; } };3507 )";3508 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);3509}3510 3511TEST_P(ImportImplicitMethods, DoNotImportDefault) {3512 auto Code = R"(3513 struct A { A() = default; };3514 )";3515 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);3516}3517 3518TEST_P(ImportImplicitMethods, DoNotImportDeleted) {3519 auto Code = R"(3520 struct A { A() = delete; };3521 )";3522 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);3523}3524 3525TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {3526 auto Code = R"(3527 struct A { void f() { } };3528 )";3529 testNoImportOf(cxxMethodDecl(hasName("f")), Code);3530}3531 3532TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {3533 Decl *ToR1;3534 {3535 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input0.cc");3536 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(3537 FromTU, cxxRecordDecl(hasName("A")));3538 3539 ToR1 = Import(FromR, Lang_CXX03);3540 }3541 3542 Decl *ToR2;3543 {3544 Decl *FromTU = getTuDecl("struct A { };", Lang_CXX03, "input1.cc");3545 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(3546 FromTU, cxxRecordDecl(hasName("A")));3547 3548 ToR2 = Import(FromR, Lang_CXX03);3549 }3550 3551 EXPECT_EQ(ToR1, ToR2);3552}3553 3554TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {3555 Decl *ToR1;3556 {3557 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");3558 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(3559 FromTU, cxxRecordDecl(hasName("A")));3560 ToR1 = Import(FromR, Lang_CXX03);3561 }3562 Decl *ToR2;3563 {3564 Decl *FromTU =3565 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");3566 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(3567 FromTU, cxxRecordDecl(hasName("A")));3568 ToR2 = Import(FromR, Lang_CXX03);3569 }3570 EXPECT_NE(ToR1, ToR2);3571}3572 3573TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {3574 Decl *ToF1;3575 {3576 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");3577 auto *FromF = FirstDeclMatcher<FieldDecl>().match(3578 FromTU, fieldDecl(hasName("x")));3579 ToF1 = Import(FromF, Lang_CXX03);3580 }3581 Decl *ToF2;3582 {3583 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input1.cc");3584 auto *FromF = FirstDeclMatcher<FieldDecl>().match(3585 FromTU, fieldDecl(hasName("x")));3586 ToF2 = Import(FromF, Lang_CXX03);3587 }3588 EXPECT_EQ(ToF1, ToF2);3589}3590 3591TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) {3592 Decl *FromTU = getTuDecl("struct A { unsigned x : 3; };", Lang_CXX03);3593 auto *FromF =3594 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("x")));3595 3596 ASSERT_TRUE(FromF->isBitField());3597 ASSERT_EQ(3u, FromF->getBitWidthValue());3598 auto *ToField = Import(FromF, Lang_CXX03);3599 3600 EXPECT_TRUE(ToField->isBitField());3601 EXPECT_EQ(3u, ToField->getBitWidthValue());3602 3603 const auto *FromBT = FromF->getBitWidth()->getType()->getAs<BuiltinType>();3604 const auto *ToBT = ToField->getBitWidth()->getType()->getAs<BuiltinType>();3605 ASSERT_TRUE(FromBT);3606 ASSERT_EQ(BuiltinType::Int, FromBT->getKind());3607 EXPECT_TRUE(ToBT);3608 EXPECT_EQ(BuiltinType::Int, ToBT->getKind());3609}3610 3611struct ImportBlock : ASTImporterOptionSpecificTestBase {};3612TEST_P(ImportBlock, ImportBlocksAreUnsupported) {3613 const auto *Code = R"(3614 void test_block__capture_null() {3615 int *p = 0;3616 ^(){3617 *p = 1;3618 }();3619 })";3620 Decl *FromTU = getTuDecl(Code, Lang_CXX03);3621 auto *FromBlock = FirstDeclMatcher<BlockDecl>().match(FromTU, blockDecl());3622 ASSERT_TRUE(FromBlock);3623 3624 auto ToBlockOrError = importOrError(FromBlock, Lang_CXX03);3625 3626 const auto ExpectUnsupportedConstructError = [](const ASTImportError &Error) {3627 EXPECT_EQ(ASTImportError::UnsupportedConstruct, Error.Error);3628 };3629 llvm::handleAllErrors(ToBlockOrError.takeError(),3630 ExpectUnsupportedConstructError);3631}3632 3633TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl) {3634 const auto *Code = R"(3635 template <typename T> struct Wrapper {3636 Wrapper(T Value = {}) {}3637 };3638 template class Wrapper<int>;3639 )";3640 Decl *FromTU = getTuDecl(Code, Lang_CXX11);3641 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(3642 FromTU, parmVarDecl(hasType(asString("int"))));3643 ASSERT_TRUE(FromVar);3644 ASSERT_TRUE(FromVar->hasUninstantiatedDefaultArg());3645 ASSERT_TRUE(FromVar->getUninstantiatedDefaultArg());3646 ASSERT_FALSE(FromVar->isExplicitObjectParameter());3647 3648 const auto *ToVar = Import(FromVar, Lang_CXX11);3649 EXPECT_TRUE(ToVar);3650 EXPECT_TRUE(ToVar->hasUninstantiatedDefaultArg());3651 EXPECT_TRUE(ToVar->getUninstantiatedDefaultArg());3652 EXPECT_NE(FromVar->getUninstantiatedDefaultArg(),3653 ToVar->getUninstantiatedDefaultArg());3654 EXPECT_FALSE(ToVar->isExplicitObjectParameter());3655}3656 3657TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl_Explicit) {3658 const auto *Code = R"(3659 struct Wrapper {3660 void func(this Wrapper) {}3661 };3662 )";3663 Decl *FromTU = getTuDecl(Code, Lang_CXX23);3664 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(FromTU, parmVarDecl());3665 ASSERT_TRUE(FromVar);3666 ASSERT_TRUE(FromVar->isExplicitObjectParameter());3667 3668 const auto *ToVar = Import(FromVar, Lang_CXX23);3669 EXPECT_TRUE(ToVar);3670 EXPECT_TRUE(ToVar->isExplicitObjectParameter());3671 EXPECT_NE(ToVar->getExplicitObjectParamThisLoc(),3672 FromVar->getExplicitObjectParamThisLoc());3673}3674 3675TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {3676 Decl *ToF1;3677 {3678 Decl *FromTU = getTuDecl("struct A { int x; };", Lang_CXX03, "input0.cc");3679 auto *FromF = FirstDeclMatcher<FieldDecl>().match(3680 FromTU, fieldDecl(hasName("x")));3681 ToF1 = Import(FromF, Lang_CXX03);3682 }3683 Decl *ToF2;3684 {3685 Decl *FromTU =3686 getTuDecl("struct A { unsigned x; };", Lang_CXX03, "input1.cc");3687 auto *FromF = FirstDeclMatcher<FieldDecl>().match(3688 FromTU, fieldDecl(hasName("x")));3689 ToF2 = Import(FromF, Lang_CXX03);3690 }3691 EXPECT_NE(ToF1, ToF2);3692}3693 3694TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {3695 Decl *ToM1;3696 {3697 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",3698 Lang_CXX03, "input0.cc");3699 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(3700 FromTU, functionDecl(hasName("x"), isDefinition()));3701 ToM1 = Import(FromM, Lang_CXX03);3702 }3703 Decl *ToM2;3704 {3705 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",3706 Lang_CXX03, "input1.cc");3707 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(3708 FromTU, functionDecl(hasName("x"), isDefinition()));3709 ToM2 = Import(FromM, Lang_CXX03);3710 }3711 EXPECT_EQ(ToM1, ToM2);3712}3713 3714TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {3715 Decl *ToM1;3716 {3717 Decl *FromTU = getTuDecl("struct A { void x(); }; void A::x() { }",3718 Lang_CXX03, "input0.cc");3719 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(3720 FromTU, functionDecl(hasName("x"), isDefinition()));3721 ToM1 = Import(FromM, Lang_CXX03);3722 }3723 Decl *ToM2;3724 {3725 Decl *FromTU =3726 getTuDecl("struct A { void x() const; }; void A::x() const { }",3727 Lang_CXX03, "input1.cc");3728 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(3729 FromTU, functionDecl(hasName("x"), isDefinition()));3730 ToM2 = Import(FromM, Lang_CXX03);3731 }3732 EXPECT_NE(ToM1, ToM2);3733}3734 3735TEST_P(ASTImporterOptionSpecificTestBase,3736 ImportUnnamedStructsWithRecursingField) {3737 Decl *FromTU = getTuDecl(3738 R"(3739 struct A {3740 struct {3741 struct A *next;3742 } entry0;3743 struct {3744 struct A *next;3745 } entry1;3746 };3747 )",3748 Lang_C99, "input0.cc");3749 auto *From =3750 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));3751 3752 Import(From, Lang_C99);3753 3754 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();3755 auto *Entry0 =3756 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));3757 auto *Entry1 =3758 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));3759 auto *R0 = getRecordDecl(Entry0);3760 auto *R1 = getRecordDecl(Entry1);3761 EXPECT_NE(R0, R1);3762 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(3763 R0, recordDecl(has(fieldDecl(hasName("next"))))));3764 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(3765 R1, recordDecl(has(fieldDecl(hasName("next"))))));3766}3767 3768TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {3769 Decl *FromTU = getTuDecl(3770 R"(3771 void f(int X, int Y, bool Z) {3772 (void)[X, Y, Z] { (void)Z; };3773 }3774 )",3775 Lang_CXX11, "input0.cc");3776 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(3777 FromTU, functionDecl(hasName("f")));3778 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));3779 EXPECT_TRUE(ToF);3780 3781 CXXRecordDecl *FromLambda =3782 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(3783 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();3784 3785 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));3786 EXPECT_TRUE(ToLambda);3787 3788 // Check if the fields of the lambda class are imported in correct order.3789 unsigned FromIndex = 0u;3790 for (auto *FromField : FromLambda->fields()) {3791 ASSERT_FALSE(FromField->getDeclName());3792 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));3793 EXPECT_TRUE(ToField);3794 UnsignedOrNone ToIndex = ASTImporter::getFieldIndex(ToField);3795 EXPECT_TRUE(ToIndex);3796 EXPECT_EQ(*ToIndex, FromIndex);3797 ++FromIndex;3798 }3799 3800 EXPECT_EQ(FromIndex, 3u);3801}3802 3803TEST_P(ASTImporterOptionSpecificTestBase,3804 MergeFieldDeclsOfClassTemplateSpecialization) {3805 std::string ClassTemplate =3806 R"(3807 template <typename T>3808 struct X {3809 int a{0}; // FieldDecl with InitListExpr3810 X(char) : a(3) {} // (1)3811 X(int) {} // (2)3812 };3813 )";3814 Decl *ToTU = getToTuDecl(ClassTemplate +3815 R"(3816 void foo() {3817 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr3818 X<char> xc('c');3819 }3820 )", Lang_CXX11);3821 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3822 ToTU, classTemplateSpecializationDecl(hasName("X")));3823 // FieldDecl without InitlistExpr:3824 auto *ToField = *ToSpec->field_begin();3825 ASSERT_TRUE(ToField);3826 ASSERT_FALSE(ToField->getInClassInitializer());3827 Decl *FromTU = getTuDecl(ClassTemplate +3828 R"(3829 void bar() {3830 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr3831 X<char> xc(1);3832 }3833 )", Lang_CXX11);3834 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3835 FromTU, classTemplateSpecializationDecl(hasName("X")));3836 // FieldDecl with InitlistExpr:3837 auto *FromField = *FromSpec->field_begin();3838 ASSERT_TRUE(FromField);3839 ASSERT_TRUE(FromField->getInClassInitializer());3840 3841 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);3842 ASSERT_TRUE(ImportedSpec);3843 EXPECT_EQ(ImportedSpec, ToSpec);3844 // After the import, the FieldDecl has to be merged, thus it should have the3845 // InitListExpr.3846 EXPECT_TRUE(ToField->getInClassInitializer());3847}3848 3849TEST_P(ASTImporterOptionSpecificTestBase,3850 MergeFunctionOfClassTemplateSpecialization) {3851 std::string ClassTemplate =3852 R"(3853 template <typename T>3854 struct X {3855 void f() {}3856 void g() {}3857 };3858 )";3859 Decl *ToTU = getToTuDecl(ClassTemplate +3860 R"(3861 void foo() {3862 X<char> x;3863 x.f();3864 }3865 )", Lang_CXX11);3866 Decl *FromTU = getTuDecl(ClassTemplate +3867 R"(3868 void bar() {3869 X<char> x;3870 x.g();3871 }3872 )", Lang_CXX11);3873 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3874 FromTU, classTemplateSpecializationDecl(hasName("X")));3875 auto FunPattern = functionDecl(hasName("g"),3876 hasParent(classTemplateSpecializationDecl()));3877 auto *FromFun =3878 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);3879 auto *ToFun =3880 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);3881 ASSERT_TRUE(FromFun->hasBody());3882 ASSERT_FALSE(ToFun->hasBody());3883 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);3884 ASSERT_TRUE(ImportedSpec);3885 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3886 ToTU, classTemplateSpecializationDecl(hasName("X")));3887 EXPECT_EQ(ImportedSpec, ToSpec);3888 EXPECT_TRUE(ToFun->hasBody());3889}3890 3891TEST_P(ASTImporterOptionSpecificTestBase, MergeTemplateSpecWithForwardDecl) {3892 std::string ClassTemplate =3893 R"(3894 template<typename T>3895 struct X { int m; };3896 template<>3897 struct X<int> { int m; };3898 )";3899 // Append a forward decl for our template specialization.3900 getToTuDecl(ClassTemplate + "template<> struct X<int>;", Lang_CXX11);3901 Decl *FromTU = getTuDecl(ClassTemplate, Lang_CXX11);3902 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3903 FromTU, classTemplateSpecializationDecl(hasName("X"), isDefinition()));3904 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);3905 // Check that our definition got merged with the existing definition.3906 EXPECT_TRUE(FromSpec->isThisDeclarationADefinition());3907 EXPECT_TRUE(ImportedSpec->isThisDeclarationADefinition());3908}3909 3910TEST_P(ASTImporterOptionSpecificTestBase,3911 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {3912 std::string ClassTemplate =3913 R"(3914 template <typename T>3915 struct X {};3916 )";3917 Decl *ToTU = getToTuDecl(ClassTemplate +3918 R"(3919 template <>3920 struct X<char> {3921 int a;3922 };3923 void foo() {3924 X<char> x;3925 }3926 )",3927 Lang_CXX11);3928 Decl *FromTU = getTuDecl(ClassTemplate +3929 R"(3930 template <>3931 struct X<char> {3932 int b;3933 };3934 void foo() {3935 X<char> x;3936 }3937 )",3938 Lang_CXX11);3939 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3940 FromTU, classTemplateSpecializationDecl(hasName("X")));3941 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);3942 3943 // We expect one (ODR) warning during the import.3944 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());3945 3946 // The second specialization is different from the first, thus it violates3947 // ODR, consequently we expect to keep the first specialization only, which is3948 // already in the "To" context.3949 EXPECT_FALSE(ImportedSpec);3950 EXPECT_EQ(1u,3951 DeclCounter<ClassTemplateSpecializationDecl>().match(3952 ToTU, classTemplateSpecializationDecl(hasName("X"))));3953}3954 3955TEST_P(ASTImporterOptionSpecificTestBase,3956 MergeCtorOfClassTemplateSpecialization) {3957 std::string ClassTemplate =3958 R"(3959 template <typename T>3960 struct X {3961 X(char) {}3962 X(int) {}3963 };3964 )";3965 Decl *ToTU = getToTuDecl(ClassTemplate +3966 R"(3967 void foo() {3968 X<char> x('c');3969 }3970 )", Lang_CXX11);3971 Decl *FromTU = getTuDecl(ClassTemplate +3972 R"(3973 void bar() {3974 X<char> x(1);3975 }3976 )", Lang_CXX11);3977 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3978 FromTU, classTemplateSpecializationDecl(hasName("X")));3979 // Match the void(int) ctor.3980 auto CtorPattern =3981 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),3982 hasParent(classTemplateSpecializationDecl()));3983 auto *FromCtor =3984 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);3985 auto *ToCtor =3986 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);3987 ASSERT_TRUE(FromCtor->hasBody());3988 ASSERT_FALSE(ToCtor->hasBody());3989 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);3990 ASSERT_TRUE(ImportedSpec);3991 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(3992 ToTU, classTemplateSpecializationDecl(hasName("X")));3993 EXPECT_EQ(ImportedSpec, ToSpec);3994 EXPECT_TRUE(ToCtor->hasBody());3995}3996 3997TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateFriendDecl) {3998 const auto *Code =3999 R"(4000 template <class T> class X { friend T; };4001 struct Y {};4002 template class X<Y>;4003 )";4004 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);4005 Decl *FromTU = getTuDecl(Code, Lang_CXX11);4006 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4007 FromTU, classTemplateSpecializationDecl());4008 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4009 ToTU, classTemplateSpecializationDecl());4010 4011 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);4012 EXPECT_EQ(ImportedSpec, ToSpec);4013 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(4014 ToTU, classTemplateSpecializationDecl()));4015}4016 4017TEST_P(ASTImporterOptionSpecificTestBase,4018 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {4019 auto Code =4020 R"(4021 // primary template4022 template<class T1, class T2, int I>4023 class A {};4024 4025 // partial specialization4026 template<class T, int I>4027 class A<T, T*, I> {};4028 )";4029 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);4030 Decl *FromTU = getTuDecl(Code, Lang_CXX11);4031 auto *FromSpec =4032 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(4033 FromTU, classTemplatePartialSpecializationDecl());4034 auto *ToSpec =4035 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(4036 ToTU, classTemplatePartialSpecializationDecl());4037 4038 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);4039 EXPECT_EQ(ImportedSpec, ToSpec);4040 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(4041 ToTU, classTemplatePartialSpecializationDecl()));4042}4043 4044TEST_P(ASTImporterOptionSpecificTestBase,4045 ClassTemplateSpecializationsShouldNotBeDuplicated) {4046 auto Code =4047 R"(4048 // primary template4049 template<class T1, class T2, int I>4050 class A {};4051 4052 // full specialization4053 template<>4054 class A<int, int, 1> {};4055 )";4056 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);4057 Decl *FromTU = getTuDecl(Code, Lang_CXX11);4058 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4059 FromTU, classTemplateSpecializationDecl());4060 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4061 ToTU, classTemplateSpecializationDecl());4062 4063 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);4064 EXPECT_EQ(ImportedSpec, ToSpec);4065 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(4066 ToTU, classTemplateSpecializationDecl()));4067}4068 4069TEST_P(ASTImporterOptionSpecificTestBase,4070 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {4071 std::string PrimaryTemplate =4072 R"(4073 template<class T1, class T2, int I>4074 class A {};4075 )";4076 auto PartialSpec =4077 R"(4078 template<class T, int I>4079 class A<T, T*, I> {};4080 )";4081 auto FullSpec =4082 R"(4083 template<>4084 class A<int, int, 1> {};4085 )";4086 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);4087 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);4088 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4089 FromTU, classTemplateSpecializationDecl());4090 4091 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);4092 EXPECT_TRUE(ImportedSpec);4093 // Check the number of partial specializations.4094 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(4095 ToTU, classTemplatePartialSpecializationDecl()));4096 // Check the number of full specializations.4097 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(4098 ToTU, classTemplateSpecializationDecl(4099 unless(classTemplatePartialSpecializationDecl()))));4100}4101 4102TEST_P(ASTImporterOptionSpecificTestBase,4103 InitListExprValueKindShouldBeImported) {4104 Decl *TU = getTuDecl(4105 R"(4106 const int &init();4107 void foo() { const int &a{init()}; }4108 )", Lang_CXX11, "input0.cc");4109 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));4110 ASSERT_TRUE(FromD->getAnyInitializer());4111 auto *InitExpr = FromD->getAnyInitializer();4112 ASSERT_TRUE(InitExpr);4113 ASSERT_TRUE(InitExpr->isGLValue());4114 4115 auto *ToD = Import(FromD, Lang_CXX11);4116 EXPECT_TRUE(ToD);4117 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();4118 EXPECT_TRUE(ToInitExpr);4119 EXPECT_TRUE(ToInitExpr->isGLValue());4120}4121 4122struct ImportVariables : ASTImporterOptionSpecificTestBase {};4123 4124TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {4125 Decl *FromTU = getTuDecl(4126 R"(4127 struct A {4128 static const int a = 1 + 2;4129 };4130 const int A::a;4131 )",4132 Lang_CXX03, "input1.cc");4133 4134 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(4135 FromTU, varDecl(hasName("a"))); // Decl with init4136 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(4137 FromTU, varDecl(hasName("a"))); // Decl with definition4138 ASSERT_NE(FromDWithInit, FromDWithDef);4139 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);4140 4141 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));4142 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));4143 ASSERT_TRUE(ToD0);4144 ASSERT_TRUE(ToD1);4145 EXPECT_NE(ToD0, ToD1);4146 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);4147}4148 4149TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {4150 auto StructA =4151 R"(4152 struct A {4153 static const int a = 1 + 2;4154 };4155 )";4156 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);4157 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX03,4158 "input1.cc");4159 4160 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(4161 FromTU, varDecl(hasName("a"))); // Decl with init4162 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(4163 FromTU, varDecl(hasName("a"))); // Decl with definition4164 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());4165 ASSERT_TRUE(FromDWithInit->getInit());4166 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());4167 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());4168 ASSERT_FALSE(FromDWithDef->getInit());4169 4170 auto *ToD = FirstDeclMatcher<VarDecl>().match(4171 ToTU, varDecl(hasName("a"))); // Decl with init4172 ASSERT_TRUE(ToD->getInit());4173 ASSERT_FALSE(ToD->getDefinition());4174 4175 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));4176 EXPECT_TRUE(ImportedD->getAnyInitializer());4177 EXPECT_TRUE(ImportedD->getDefinition());4178}4179 4180TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {4181 auto StructA =4182 R"(4183 struct A {4184 static const int a;4185 };4186 )";4187 Decl *ToTU = getToTuDecl(StructA, Lang_CXX03);4188 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",4189 Lang_CXX03, "input1.cc");4190 4191 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(4192 FromTU, varDecl(hasName("a")));4193 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(4194 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.4195 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());4196 ASSERT_FALSE(FromDDeclarationOnly->getInit());4197 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());4198 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());4199 ASSERT_TRUE(FromDWithDef->getInit());4200 4201 auto *ToD = FirstDeclMatcher<VarDecl>().match(4202 ToTU, varDecl(hasName("a")));4203 ASSERT_FALSE(ToD->getInit());4204 ASSERT_FALSE(ToD->getDefinition());4205 4206 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));4207 EXPECT_TRUE(ImportedD->getAnyInitializer());4208 EXPECT_TRUE(ImportedD->getDefinition());4209}4210 4211TEST_P(ImportVariables, ImportBindingDecl) {4212 Decl *From, *To;4213 std::tie(From, To) = getImportedDecl(4214 R"(4215 void declToImport() {4216 int a[2] = {1,2};4217 auto [x1,y1] = a;4218 auto& [x2,y2] = a;4219 4220 struct S {4221 mutable int x1 : 2;4222 volatile double y1;4223 };4224 S b;4225 const auto [x3, y3] = b;4226 };4227 )",4228 Lang_CXX17, "", Lang_CXX17);4229 4230 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();4231 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(4232 FromTU, functionDecl(hasName("declToImport")));4233 auto *ToF = Import(FromF, Lang_CXX17);4234 EXPECT_TRUE(ToF);4235 4236 auto VerifyImport = [&](llvm::StringRef BindName) {4237 auto *FromB = FirstDeclMatcher<BindingDecl>().match(4238 FromF, bindingDecl(hasName(BindName)));4239 ASSERT_TRUE(FromB);4240 auto *ToB = Import(FromB, Lang_CXX17);4241 EXPECT_TRUE(ToB);4242 EXPECT_EQ(FromB->getBinding() != nullptr, ToB->getBinding() != nullptr);4243 EXPECT_EQ(FromB->getDecomposedDecl() != nullptr,4244 ToB->getDecomposedDecl() != nullptr);4245 EXPECT_EQ(FromB->getHoldingVar() != nullptr,4246 ToB->getHoldingVar() != nullptr);4247 };4248 4249 VerifyImport("x1");4250 VerifyImport("y1");4251 VerifyImport("x2");4252 VerifyImport("y2");4253 VerifyImport("x3");4254 VerifyImport("y3");4255}4256 4257TEST_P(ImportVariables, ImportDecompositionDeclArray) {4258 Decl *From, *To;4259 std::tie(From, To) = getImportedDecl(4260 R"(4261 void declToImport() {4262 int a[2] = {1,2};4263 auto [x1,y1] = a;4264 };4265 )",4266 Lang_CXX17, "", Lang_CXX17);4267 4268 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();4269 auto *FromDecomp =4270 FirstDeclMatcher<DecompositionDecl>().match(FromTU, decompositionDecl());4271 auto *ToDecomp = Import(FromDecomp, Lang_CXX17);4272 EXPECT_TRUE(ToDecomp);4273 4274 ArrayRef<BindingDecl *> FromB = FromDecomp->bindings();4275 ArrayRef<BindingDecl *> ToB = ToDecomp->bindings();4276 EXPECT_EQ(FromB.size(), ToB.size());4277 for (unsigned int I = 0; I < FromB.size(); ++I) {4278 auto *ToBI = Import(FromB[I], Lang_CXX17);4279 EXPECT_EQ(ToBI, ToB[I]);4280 }4281}4282 4283struct ImportClasses : ASTImporterOptionSpecificTestBase {};4284 4285TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {4286 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C99);4287 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");4288 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));4289 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);4290 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);4291 4292 Decl *ImportedDef = Import(FromDef, Lang_C99);4293 4294 EXPECT_NE(ImportedDef, ToProto);4295 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);4296 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);4297 EXPECT_TRUE(ImportedDef == ToDef);4298 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());4299 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());4300 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);4301}4302 4303TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {4304 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX03);4305 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX03, "input1.cc");4306 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));4307 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);4308 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);4309 4310 Decl *ImportedDef = Import(FromDef, Lang_CXX03);4311 4312 EXPECT_NE(ImportedDef, ToProto);4313 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);4314 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);4315 EXPECT_TRUE(ImportedDef == ToDef);4316 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());4317 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());4318 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);4319}4320 4321TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {4322 Decl *FromTU0 =4323 getTuDecl("struct A { struct X *Xp; };", Lang_C99, "input0.cc");4324 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C99, "input1.cc");4325 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));4326 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);4327 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);4328 4329 Decl *ImportedProto = Import(FromProto, Lang_C99);4330 Decl *ImportedDef = Import(FromDef, Lang_C99);4331 Decl *ToTU = ImportedDef->getTranslationUnitDecl();4332 4333 EXPECT_NE(ImportedDef, ImportedProto);4334 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);4335 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);4336 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);4337 EXPECT_TRUE(ImportedDef == ToDef);4338 EXPECT_TRUE(ImportedProto == ToProto);4339 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());4340 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());4341 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);4342}4343 4344struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {4345 void testRecursiveFriendClassTemplate(Decl *FromTu) {4346 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(4347 FromTu, classTemplateDecl());4348 4349 auto Pattern = classTemplateDecl(4350 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));4351 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));4352 4353 auto *FromFriend =4354 FirstDeclMatcher<FriendDecl>().match(FromD, friendDecl());4355 auto *FromRecordOfFriend =4356 cast<ClassTemplateDecl>(FromFriend->getFriendDecl())4357 ->getTemplatedDecl();4358 EXPECT_NE(FromRecordOfFriend, FromD->getTemplatedDecl());4359 EXPECT_TRUE(FromRecordOfFriend->getPreviousDecl() == nullptr);4360 4361 auto *FromDC = FromRecordOfFriend->getDeclContext();4362 auto *FromLexicalDC = FromRecordOfFriend->getLexicalDeclContext();4363 ASSERT_EQ(FromDC, cast<DeclContext>(FromTu));4364 ASSERT_EQ(FromLexicalDC, cast<DeclContext>(FromD->getTemplatedDecl()));4365 4366 ASSERT_FALSE(FromDC->containsDecl(FromRecordOfFriend));4367 ASSERT_FALSE(FromLexicalDC->containsDecl(FromRecordOfFriend));4368 ASSERT_FALSE(cast<RecordDecl>(FromRecordOfFriend)4369 ->getLookupParent()4370 ->lookup(FromRecordOfFriend->getDeclName())4371 .empty());4372 4373 auto *ToD = Import(FromD, Lang_CXX03);4374 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));4375 4376 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());4377 auto *ToRecordOfFriend =4378 cast<ClassTemplateDecl>(ToFriend->getFriendDecl())->getTemplatedDecl();4379 4380 EXPECT_NE(ToRecordOfFriend, ToD->getTemplatedDecl());4381 EXPECT_TRUE(ToRecordOfFriend->getPreviousDecl() == nullptr);4382 4383 auto *ToDC = ToRecordOfFriend->getDeclContext();4384 auto *ToLexicalDC = ToRecordOfFriend->getLexicalDeclContext();4385 ASSERT_EQ(ToDC, cast<DeclContext>(ToD->getTranslationUnitDecl()));4386 ASSERT_EQ(ToLexicalDC, cast<DeclContext>(ToD->getTemplatedDecl()));4387 4388 ASSERT_FALSE(ToDC->containsDecl(ToRecordOfFriend));4389 ASSERT_FALSE(ToLexicalDC->containsDecl(ToRecordOfFriend));4390 ASSERT_FALSE(cast<RecordDecl>(ToRecordOfFriend)4391 ->getLookupParent()4392 ->lookup(ToRecordOfFriend->getDeclName())4393 .empty());4394 }4395 4396 void testRepeatedFriendImport(const char *Code) {4397 Decl *ToTu = getToTuDecl(Code, Lang_CXX03);4398 Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");4399 4400 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());4401 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(ToTu, friendDecl());4402 auto *FromFriend1 =4403 FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());4404 auto *FromFriend2 =4405 LastDeclMatcher<FriendDecl>().match(FromTu, friendDecl());4406 4407 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);4408 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);4409 4410 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);4411 EXPECT_EQ(ToFriend1, ToImportedFriend1);4412 EXPECT_EQ(ToFriend2, ToImportedFriend2);4413 }4414};4415 4416TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {4417 Decl *FromTU = getTuDecl(4418 R"(4419 class A {4420 template <int I> class F {};4421 class X {4422 template <int I> friend class F;4423 };4424 };4425 )",4426 Lang_CXX03, "input0.cc");4427 4428 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(4429 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));4430 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(4431 FromTU, cxxRecordDecl(hasName("F")));4432 4433 ASSERT_TRUE(FromClass);4434 ASSERT_TRUE(FromFriendClass);4435 ASSERT_NE(FromClass, FromFriendClass);4436 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);4437 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);4438 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),4439 FromClass->getDescribedClassTemplate());4440 4441 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX03));4442 auto *ToFriendClass =4443 cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX03));4444 4445 EXPECT_TRUE(ToClass);4446 EXPECT_TRUE(ToFriendClass);4447 EXPECT_NE(ToClass, ToFriendClass);4448 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);4449 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);4450 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),4451 ToClass->getDescribedClassTemplate());4452}4453 4454TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {4455 Decl *FromTu = getTuDecl(4456 R"(4457 class declToImport {4458 friend class declToImport;4459 };4460 )",4461 Lang_CXX03, "input.cc");4462 4463 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(4464 FromTu, cxxRecordDecl(hasName("declToImport")));4465 auto *ToD = Import(FromD, Lang_CXX03);4466 auto Pattern = cxxRecordDecl(has(friendDecl()));4467 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));4468 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));4469}4470 4471TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {4472 Decl *FromTu =4473 getTuDecl("class X { friend class Y; };", Lang_CXX03, "from.cc");4474 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(4475 FromTu, cxxRecordDecl(hasName("X")));4476 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());4477 RecordDecl *FromRecordOfFriend =4478 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));4479 4480 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));4481 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),4482 cast<DeclContext>(FromX));4483 ASSERT_FALSE(4484 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));4485 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(4486 FromRecordOfFriend));4487 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()4488 ->lookup(FromRecordOfFriend->getDeclName())4489 .empty());4490 4491 auto *ToX = Import(FromX, Lang_CXX03);4492 ASSERT_TRUE(ToX);4493 4494 Decl *ToTu = ToX->getTranslationUnitDecl();4495 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());4496 RecordDecl *ToRecordOfFriend =4497 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));4498 4499 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));4500 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));4501 EXPECT_FALSE(4502 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));4503 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(4504 ToRecordOfFriend));4505 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()4506 ->lookup(ToRecordOfFriend->getDeclName())4507 .empty());4508}4509 4510TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {4511 Decl *FromTu = getTuDecl(4512 R"(4513 template<class A> class declToImport {4514 template<class A1> friend class declToImport;4515 };4516 )",4517 Lang_CXX03, "input.cc");4518 4519 testRecursiveFriendClassTemplate(FromTu);4520}4521 4522TEST_P(ImportFriendClasses,4523 ImportOfRecursiveFriendClassTemplateWithNonTypeParm) {4524 Decl *FromTu = getTuDecl(4525 R"(4526 template<class A1, A1 A> class declToImport {4527 template<class B1, B1> friend class declToImport;4528 };4529 )",4530 Lang_CXX03, "input.cc");4531 testRecursiveFriendClassTemplate(FromTu);4532}4533 4534TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {4535 auto Pattern = classTemplateSpecializationDecl(hasName("X"));4536 4537 ClassTemplateSpecializationDecl *Imported1;4538 {4539 Decl *FromTU = getTuDecl("template<class T> class X;"4540 "struct Y { friend class X<int>; };",4541 Lang_CXX03, "input0.cc");4542 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4543 FromTU, Pattern);4544 4545 Imported1 =4546 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));4547 }4548 ClassTemplateSpecializationDecl *Imported2;4549 {4550 Decl *FromTU = getTuDecl("template<class T> class X;"4551 "template<> class X<int>{};"4552 "struct Z { friend class X<int>; };",4553 Lang_CXX03, "input1.cc");4554 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4555 FromTU, Pattern);4556 4557 Imported2 =4558 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));4559 }4560 4561 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();4562 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),4563 2u);4564 ASSERT_TRUE(Imported2->getPreviousDecl());4565 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);4566}4567 4568TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {4569 Decl *FromTU0 = getTuDecl(4570 R"(4571 class X {4572 class Y;4573 };4574 class X::Y {4575 template <typename T>4576 friend class F; // The decl context of F is the global namespace.4577 };4578 )",4579 Lang_CXX03, "input0.cc");4580 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(4581 FromTU0, classTemplateDecl(hasName("F")));4582 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));4583 Decl *FromTU1 = getTuDecl(4584 R"(4585 template <typename T>4586 class F {};4587 )",4588 Lang_CXX03, "input1.cc");4589 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(4590 FromTU1, classTemplateDecl(hasName("F")));4591 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));4592 EXPECT_TRUE(declaresSameEntity(Imported0, Imported1));4593}4594 4595TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {4596 Decl *From, *To;4597 std::tie(From, To) =4598 getImportedDecl("class declToImport {};", Lang_CXX03,4599 "class Y { friend class declToImport; };", Lang_CXX03);4600 auto *Imported = cast<CXXRecordDecl>(To);4601 4602 EXPECT_TRUE(Imported->getPreviousDecl());4603}4604 4605TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) {4606 Decl *ToTU = getToTuDecl(4607 R"(4608 template <class T, T U>4609 class A;4610 4611 template <class T, T U>4612 class A {4613 public:4614 template <class P, P Q>4615 friend class A;4616 4617 A(T x) :x(x) {}4618 4619 private:4620 T x;4621 };4622 )",4623 Lang_CXX11);4624 4625 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(4626 ToTU,4627 classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A")))));4628 Decl *FromTU = getTuDecl(4629 R"(4630 template <class T, T U>4631 class A;4632 4633 template <class T, T U>4634 class A {4635 public:4636 template <class P, P Q>4637 friend class A;4638 4639 A(T x) : x(x) {}4640 4641 private:4642 T x;4643 };4644 4645 A<int,3> a1(0);4646 )",4647 Lang_CXX11, "input1.cc");4648 auto *FromA = FirstDeclMatcher<ClassTemplateDecl>().match(4649 FromTU,4650 classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A")))));4651 auto *ToA = Import(FromA, Lang_CXX11);4652 EXPECT_TRUE(ToA);4653 const ASTContext &Ctx = ToTU->getASTContext();4654 EXPECT_TRUE(4655 Ctx.hasSameType(Ctx.getCanonicalTagType(Fwd->getTemplatedDecl()),4656 Ctx.getCanonicalTagType(ToA->getTemplatedDecl())));4657}4658 4659TEST_P(ImportFriendClasses,4660 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {4661 Decl *ToTU = getToTuDecl(4662 R"(4663 class X {4664 class Y;4665 };4666 class X::Y {4667 template <typename T>4668 friend class F; // The decl context of F is the global namespace.4669 };4670 )",4671 Lang_CXX03);4672 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(4673 ToTU, classTemplateDecl(hasName("F")));4674 Decl *FromTU = getTuDecl(4675 R"(4676 template <typename T>4677 class F {};4678 )",4679 Lang_CXX03, "input0.cc");4680 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(4681 FromTU, classTemplateDecl(hasName("F")));4682 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));4683 EXPECT_TRUE(ImportedDef->getPreviousDecl());4684 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());4685 EXPECT_EQ(ToDecl->getTemplatedDecl(),4686 ImportedDef->getTemplatedDecl()->getPreviousDecl());4687}4688 4689TEST_P(ImportFriendClasses,4690 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {4691 Decl *FromTU0 = getTuDecl(4692 R"(4693 class X {4694 class Y;4695 };4696 class X::Y {4697 template <typename T>4698 friend class F; // The decl context of F is the global namespace.4699 };4700 )",4701 Lang_CXX03, "input0.cc");4702 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(4703 FromTU0, classTemplateDecl(hasName("F")));4704 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));4705 Decl *FromTU1 = getTuDecl(4706 R"(4707 template <typename T>4708 class F {};4709 )",4710 Lang_CXX03, "input1.cc");4711 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(4712 FromTU1, classTemplateDecl(hasName("F")));4713 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));4714 EXPECT_TRUE(ImportedDef->getPreviousDecl());4715 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());4716 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),4717 ImportedDef->getTemplatedDecl()->getPreviousDecl());4718}4719 4720TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {4721 Decl *FromTU0 = getTuDecl(4722 R"(4723 class X {4724 class Y;4725 };4726 class X::Y {4727 friend class F; // The decl context of F is the global namespace.4728 };4729 )",4730 Lang_CXX03, "input0.cc");4731 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());4732 QualType FT = Friend->getFriendType()->getType();4733 FT = FromTU0->getASTContext().getCanonicalType(FT);4734 auto *Fwd = cast<TagType>(FT)->getDecl();4735 auto *ImportedFwd = Import(Fwd, Lang_CXX03);4736 Decl *FromTU1 = getTuDecl(4737 R"(4738 class F {};4739 )",4740 Lang_CXX03, "input1.cc");4741 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(4742 FromTU1, cxxRecordDecl(hasName("F")));4743 auto *ImportedDef = Import(Definition, Lang_CXX03);4744 EXPECT_TRUE(ImportedDef->getPreviousDecl());4745 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());4746}4747 4748TEST_P(ImportFriendClasses,4749 ImportFriendTemplatesInDependentContext_DefToFriend) {4750 Decl *ToTU = getToTuDecl(4751 R"(4752 template<class T1>4753 struct X {4754 template<class T2>4755 friend struct Y;4756 };4757 )",4758 Lang_CXX03);4759 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(4760 ToTU, classTemplateDecl(hasName("Y")));4761 Decl *FromTU = getTuDecl(4762 R"(4763 template<class T1>4764 struct Y {};4765 )",4766 Lang_CXX03, "input0.cc");4767 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(4768 FromTU, classTemplateDecl(hasName("Y")));4769 auto *ImportedYDef = Import(FromYDef, Lang_CXX03);4770 EXPECT_TRUE(ImportedYDef);4771 EXPECT_FALSE(ImportedYDef->getPreviousDecl());4772 EXPECT_NE(ImportedYDef, ToYFriend);4773}4774 4775TEST_P(ImportFriendClasses,4776 ImportFriendTemplatesInDependentContext_DefToFriend_NE) {4777 getToTuDecl(4778 R"(4779 template<class T1>4780 struct X {4781 template<class T2>4782 friend struct Y;4783 };4784 )",4785 Lang_CXX03);4786 Decl *FromTU = getTuDecl(4787 R"(4788 template<class T1, class T2>4789 struct Y {};4790 )",4791 Lang_CXX03, "input0.cc");4792 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(4793 FromTU, classTemplateDecl(hasName("Y")));4794 auto *ImportedYDef = Import(FromYDef, Lang_CXX03);4795 EXPECT_FALSE(ImportedYDef);4796}4797 4798TEST_P(ImportFriendClasses,4799 ImportFriendTemplatesInDependentContext_FriendToFriend) {4800 Decl *ToTU = getToTuDecl(4801 R"(4802 template<class T1>4803 struct X {4804 template<class T2>4805 friend struct Y;4806 };4807 )",4808 Lang_CXX03);4809 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(4810 ToTU, classTemplateDecl(hasName("Y")));4811 Decl *FromTU = getTuDecl(4812 R"(4813 template<class T1>4814 struct X {4815 template<class T2>4816 friend struct Y;4817 };4818 )",4819 Lang_CXX03, "input0.cc");4820 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(4821 FromTU, classTemplateDecl(hasName("Y")));4822 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);4823 EXPECT_TRUE(ImportedYFriend);4824 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());4825 EXPECT_NE(ImportedYFriend, ToYFriend);4826}4827 4828TEST_P(ImportFriendClasses,4829 ImportFriendTemplatesInDependentContext_FriendToFriend_NE) {4830 getToTuDecl(4831 R"(4832 template<class T1>4833 struct X {4834 template<class T2>4835 friend struct Y;4836 };4837 )",4838 Lang_CXX03);4839 Decl *FromTU = getTuDecl(4840 R"(4841 template<class T1>4842 struct X {4843 template<class T2, class T3>4844 friend struct Y;4845 };4846 )",4847 Lang_CXX03, "input0.cc");4848 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(4849 FromTU, classTemplateDecl(hasName("Y")));4850 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);4851 EXPECT_FALSE(ImportedYFriend);4852}4853 4854TEST_P(ImportFriendClasses,4855 ImportFriendTemplatesInDependentContext_FriendToDef) {4856 Decl *ToTU = getToTuDecl(4857 R"(4858 template<class T1>4859 struct Y {};4860 )",4861 Lang_CXX03);4862 auto *ToYDef = FirstDeclMatcher<ClassTemplateDecl>().match(4863 ToTU, classTemplateDecl(hasName("Y")));4864 Decl *FromTU = getTuDecl(4865 R"(4866 template<class T1>4867 struct X {4868 template<class T2>4869 friend struct Y;4870 };4871 )",4872 Lang_CXX03, "input0.cc");4873 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(4874 FromTU, classTemplateDecl(hasName("Y")));4875 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);4876 EXPECT_TRUE(ImportedYFriend);4877 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());4878 EXPECT_NE(ImportedYFriend, ToYDef);4879}4880 4881TEST_P(ImportFriendClasses,4882 ImportFriendTemplatesInDependentContext_FriendToDef_NE) {4883 getToTuDecl(4884 R"(4885 template<class T1>4886 struct Y {};4887 )",4888 Lang_CXX03);4889 Decl *FromTU = getTuDecl(4890 R"(4891 template<class T1>4892 struct X {4893 template<class T2, class T3>4894 friend struct Y;4895 };4896 )",4897 Lang_CXX03, "input0.cc");4898 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(4899 FromTU, classTemplateDecl(hasName("Y")));4900 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);4901 EXPECT_FALSE(ImportedYFriend);4902}4903 4904TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) {4905 const char *Code =4906 R"(4907 class Container {4908 friend class X;4909 friend class X;4910 };4911 )";4912 testRepeatedFriendImport(Code);4913}4914 4915TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {4916 const char *Code =4917 R"(4918 class Container {4919 friend void f();4920 friend void f();4921 };4922 )";4923 testRepeatedFriendImport(Code);4924}4925 4926TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {4927 const char *Code =4928 R"(4929 template <class T>4930 class Container {4931 template <class U> friend void m();4932 template <class U> friend void m();4933 };4934 )";4935 testRepeatedFriendImport(Code);4936}4937 4938TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {4939 const char *Code =4940 R"(4941 template <class T>4942 class Container {4943 template <class U> friend class X;4944 template <class U> friend class X;4945 };4946 )";4947 testRepeatedFriendImport(Code);4948}4949 4950TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {4951 auto *Code = R"(4952 template <class T>4953 struct X {4954 friend void foo(){}4955 };4956 )";4957 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);4958 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(4959 ToTU, functionDecl(hasName("foo")));4960 4961 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");4962 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(4963 FromTU, functionDecl(hasName("foo")));4964 auto *ImportedFoo = Import(FromFoo, Lang_CXX03);4965 EXPECT_EQ(ImportedFoo, ToFoo);4966}4967 4968struct DeclContextTest : ASTImporterOptionSpecificTestBase {};4969 4970TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {4971 Decl *TU = getTuDecl(4972 R"(4973 namespace NS {4974 4975 template <typename T>4976 struct S {};4977 template struct S<int>;4978 4979 inline namespace INS {4980 template <typename T>4981 struct S {};4982 template struct S<int>;4983 }4984 4985 }4986 )", Lang_CXX11, "input0.cc");4987 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(4988 TU, namespaceDecl());4989 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(4990 TU, classTemplateSpecializationDecl());4991 ASSERT_TRUE(NS->containsDecl(Spec));4992 4993 NS->removeDecl(Spec);4994 EXPECT_FALSE(NS->containsDecl(Spec));4995}4996 4997TEST_P(DeclContextTest,4998 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {4999 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX03);5000 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));5001 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));5002 5003 // Investigate the list.5004 auto *DC = A0->getDeclContext();5005 ASSERT_TRUE(DC->containsDecl(A0));5006 ASSERT_TRUE(DC->containsDecl(A1));5007 5008 // Investigate the lookup table.5009 auto *Map = DC->getLookupPtr();5010 ASSERT_TRUE(Map);5011 auto I = Map->find(A0->getDeclName());5012 ASSERT_NE(I, Map->end());5013 StoredDeclsList &L = I->second;5014 // The lookup table contains the most recent decl of A.5015 ASSERT_NE(L.getAsDecl(), A0);5016 ASSERT_EQ(L.getAsDecl(), A1);5017 5018 ASSERT_TRUE(L.getAsDecl());5019 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.5020 // We do not have a list with one element.5021 L.setHasExternalDecls();5022 ASSERT_FALSE(L.getAsList());5023 auto Results = L.getLookupResult();5024 ASSERT_EQ(1u, std::distance(Results.begin(), Results.end()));5025 5026 // This asserts in the old implementation.5027 DC->removeDecl(A0);5028 EXPECT_FALSE(DC->containsDecl(A0));5029 5030 // Make sure we do not leave a StoredDeclsList with no entries.5031 DC->removeDecl(A1);5032 ASSERT_EQ(Map->find(A1->getDeclName()), Map->end());5033}5034 5035struct ImportFunctionTemplateSpecializations5036 : ASTImporterOptionSpecificTestBase {};5037 5038TEST_P(ImportFunctionTemplateSpecializations,5039 TUshouldNotContainFunctionTemplateImplicitInstantiation) {5040 5041 Decl *FromTU = getTuDecl(5042 R"(5043 template<class T>5044 int f() { return 0; }5045 void foo() { f<int>(); }5046 )",5047 Lang_CXX03, "input0.cc");5048 5049 // Check that the function template instantiation is NOT the child of the TU.5050 auto Pattern = translationUnitDecl(5051 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));5052 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));5053 5054 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(5055 FromTU, functionDecl(hasName("foo")));5056 ASSERT_TRUE(Import(Foo, Lang_CXX03));5057 5058 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();5059 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));5060}5061 5062TEST_P(ImportFunctionTemplateSpecializations,5063 TUshouldNotContainFunctionTemplateExplicitInstantiation) {5064 5065 Decl *FromTU = getTuDecl(5066 R"(5067 template<class T>5068 int f() { return 0; }5069 template int f<int>();5070 )",5071 Lang_CXX03, "input0.cc");5072 5073 // Check that the function template instantiation is NOT the child of the TU.5074 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());5075 auto Pattern = translationUnitDecl(unless(has(Instantiation)));5076 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));5077 5078 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),5079 Lang_CXX03));5080 5081 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();5082 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));5083}5084 5085TEST_P(ImportFunctionTemplateSpecializations,5086 TUshouldContainFunctionTemplateSpecialization) {5087 5088 Decl *FromTU = getTuDecl(5089 R"(5090 template<class T>5091 int f() { return 0; }5092 template <> int f<int>() { return 4; }5093 )",5094 Lang_CXX03, "input0.cc");5095 5096 // Check that the function template specialization is the child of the TU.5097 auto Specialization =5098 functionDecl(hasName("f"), isExplicitTemplateSpecialization());5099 auto Pattern = translationUnitDecl(has(Specialization));5100 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));5101 5102 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization),5103 Lang_CXX03));5104 5105 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();5106 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));5107}5108 5109TEST_P(ImportFunctionTemplateSpecializations,5110 FunctionTemplateSpecializationRedeclChain) {5111 5112 Decl *FromTU = getTuDecl(5113 R"(5114 template<class T>5115 int f() { return 0; }5116 template <> int f<int>() { return 4; }5117 )",5118 Lang_CXX03, "input0.cc");5119 5120 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),5121 hasParent(translationUnitDecl()));5122 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);5123 {5124 auto *TU = FromTU;5125 auto *SpecD = FromSpecD;5126 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(5127 TU, functionTemplateDecl());5128 auto *FirstSpecD = *(TemplateD->spec_begin());5129 ASSERT_EQ(SpecD, FirstSpecD);5130 ASSERT_TRUE(SpecD->getPreviousDecl());5131 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())5132 ->doesThisDeclarationHaveABody());5133 }5134 5135 ASSERT_TRUE(Import(FromSpecD, Lang_CXX03));5136 5137 {5138 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();5139 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);5140 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(5141 TU, functionTemplateDecl());5142 auto *FirstSpecD = *(TemplateD->spec_begin());5143 EXPECT_EQ(SpecD, FirstSpecD);5144 ASSERT_TRUE(SpecD->getPreviousDecl());5145 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())5146 ->doesThisDeclarationHaveABody());5147 }5148}5149 5150TEST_P(ImportFunctionTemplateSpecializations,5151 MatchNumberOfFunctionTemplateSpecializations) {5152 5153 Decl *FromTU = getTuDecl(5154 R"(5155 template <typename T> constexpr int f() { return 0; }5156 template <> constexpr int f<int>() { return 4; }5157 void foo() {5158 static_assert(f<char>() == 0, "");5159 static_assert(f<int>() == 4, "");5160 }5161 )",5162 Lang_CXX11, "input0.cc");5163 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(5164 FromTU, functionDecl(hasName("foo")));5165 5166 Import(FromD, Lang_CXX11);5167 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();5168 EXPECT_EQ(5169 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),5170 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));5171}5172 5173TEST_P(ASTImporterOptionSpecificTestBase,5174 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {5175 {5176 Decl *FromTU = getTuDecl(5177 R"(5178 template <typename T>5179 struct B;5180 )",5181 Lang_CXX03, "input0.cc");5182 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(5183 FromTU, classTemplateDecl(hasName("B")));5184 5185 Import(FromD, Lang_CXX03);5186 }5187 5188 {5189 Decl *FromTU = getTuDecl(5190 R"(5191 template <typename T>5192 struct B {5193 void f();5194 B* b;5195 };5196 )",5197 Lang_CXX03, "input1.cc");5198 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(5199 FromTU, functionDecl(hasName("f")));5200 Import(FromD, Lang_CXX03);5201 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(5202 FromTU, classTemplateDecl(hasName("B")));5203 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));5204 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());5205 5206 // We expect no (ODR) warning during the import.5207 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();5208 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());5209 }5210}5211 5212TEST_P(ASTImporterOptionSpecificTestBase,5213 ImportingTypedefShouldImportTheCompleteType) {5214 // We already have an incomplete underlying type in the "To" context.5215 auto Code =5216 R"(5217 template <typename T>5218 struct S {5219 void foo();5220 };5221 using U = S<int>;5222 )";5223 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);5224 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,5225 typedefNameDecl(hasName("U")));5226 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());5227 5228 // The "From" context has the same typedef, but the underlying type is5229 // complete this time.5230 Decl *FromTU = getTuDecl(std::string(Code) +5231 R"(5232 void foo(U* u) {5233 u->foo();5234 }5235 )", Lang_CXX11);5236 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,5237 typedefNameDecl(hasName("U")));5238 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());5239 5240 // The imported type should be complete.5241 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));5242 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());5243}5244 5245TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {5246 auto Code =5247 R"(5248 template<class T>5249 int f() { return 0; }5250 template <> int f<int>() { return 4; }5251 )";5252 5253 Decl *FromTU = getTuDecl(Code, Lang_CXX03);5254 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,5255 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));5256 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);5257 5258 auto *ToD = Import(FromD, Lang_CXX03);5259 // The template parameter list should exist.5260 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);5261}5262 5263const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>5264 varTemplateDecl;5265 5266const internal::VariadicDynCastAllOfMatcher<5267 Decl, VarTemplatePartialSpecializationDecl>5268 varTemplatePartialSpecializationDecl;5269 5270TEST_P(ASTImporterOptionSpecificTestBase,5271 FunctionTemplateParameterDeclContext) {5272 constexpr auto Code =5273 R"(5274 template<class T>5275 void f() {};5276 )";5277 5278 Decl *FromTU = getTuDecl(Code, Lang_CXX11);5279 5280 auto *FromD = FirstDeclMatcher<FunctionTemplateDecl>().match(5281 FromTU, functionTemplateDecl(hasName("f")));5282 5283 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),5284 FromD->getTemplatedDecl());5285 5286 auto *ToD = Import(FromD, Lang_CXX11);5287 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),5288 ToD->getTemplatedDecl());5289 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5290 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));5291}5292 5293TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateParameterDeclContext) {5294 constexpr auto Code =5295 R"(5296 template<class T1, class T2>5297 struct S {};5298 template<class T2>5299 struct S<int, T2> {};5300 )";5301 5302 Decl *FromTU = getTuDecl(Code, Lang_CXX11);5303 5304 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(5305 FromTU, classTemplateDecl(hasName("S")));5306 auto *FromDPart =5307 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(5308 FromTU, classTemplatePartialSpecializationDecl(hasName("S")));5309 5310 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),5311 FromD->getTemplatedDecl());5312 ASSERT_EQ(FromDPart->getTemplateParameters()->getParam(0)->getDeclContext(),5313 FromDPart);5314 5315 auto *ToD = Import(FromD, Lang_CXX11);5316 auto *ToDPart = Import(FromDPart, Lang_CXX11);5317 5318 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),5319 ToD->getTemplatedDecl());5320 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5321 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));5322 5323 EXPECT_EQ(ToDPart->getTemplateParameters()->getParam(0)->getDeclContext(),5324 ToDPart);5325 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5326 ToDPart, ToDPart->getTemplateParameters()->getParam(0)));5327}5328 5329TEST_P(ASTImporterOptionSpecificTestBase,5330 CXXDeductionGuideTemplateParameterDeclContext) {5331 Decl *FromTU = getTuDecl(5332 R"(5333 template <typename T> struct A {5334 A(T);5335 };5336 A a{(int)0};5337 )",5338 Lang_CXX17, "input.cc");5339// clang-format off5340/*5341|-ClassTemplateDecl 0x1fe5000 <input.cc:2:7, line:4:7> line:2:36 A5342| |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T5343| |-CXXRecordDecl 0x1fe4f70 <col:29, line:4:7> line:2:36 struct A definition5344 5345|-FunctionTemplateDecl 0x1fe5860 <line:2:7, line:3:12> col:9 implicit <deduction guide for A>5346| |-TemplateTypeParmDecl 0x1fe4eb0 <line:2:17, col:26> col:26 referenced typename depth 0 index 0 T5347| |-CXXDeductionGuideDecl 0x1fe57a8 <line:3:9, col:12> col:9 implicit <deduction guide for A> 'auto (T) -> A<T>'5348| | `-ParmVarDecl 0x1fe56b0 <col:11> col:12 'T'5349| `-CXXDeductionGuideDecl 0x20515d8 <col:9, col:12> col:9 implicit used <deduction guide for A> 'auto (int) -> A<int>'5350| |-TemplateArgument type 'int'5351| | `-BuiltinType 0x20587e0 'int'5352| `-ParmVarDecl 0x2051388 <col:11> col:12 'int'5353`-FunctionTemplateDecl 0x1fe5a78 <line:2:7, col:36> col:36 implicit <deduction guide for A>5354 |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T5355 `-CXXDeductionGuideDecl 0x1fe59c0 <col:36> col:36 implicit <deduction guide for A> 'auto (A<T>) -> A<T>'5356 `-ParmVarDecl 0x1fe5958 <col:36> col:36 'A<T>'5357*/5358// clang-format on5359 auto *FromD1 = FirstDeclMatcher<CXXDeductionGuideDecl>().match(5360 FromTU, cxxDeductionGuideDecl());5361 auto *FromD2 = LastDeclMatcher<CXXDeductionGuideDecl>().match(5362 FromTU, cxxDeductionGuideDecl());5363 5364 NamedDecl *P1 =5365 FromD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(5366 0);5367 NamedDecl *P2 =5368 FromD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(5369 0);5370 DeclContext *DC = P1->getDeclContext();5371 5372 ASSERT_EQ(P1, P2);5373 ASSERT_TRUE(DC == FromD1 || DC == FromD2);5374 5375 auto *ToD1 = Import(FromD1, Lang_CXX17);5376 auto *ToD2 = Import(FromD2, Lang_CXX17);5377 ASSERT_TRUE(ToD1 && ToD2);5378 5379 P1 = ToD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(5380 0);5381 P2 = ToD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(5382 0);5383 DC = P1->getDeclContext();5384 5385 EXPECT_EQ(P1, P2);5386 EXPECT_TRUE(DC == ToD1 || DC == ToD2);5387 5388 ASTImporterLookupTable *Tbl = SharedStatePtr->getLookupTable();5389 if (Tbl->contains(ToD1, P1)) {5390 EXPECT_FALSE(Tbl->contains(ToD2, P1));5391 } else {5392 EXPECT_TRUE(Tbl->contains(ToD2, P1));5393 }5394}5395 5396TEST_P(ASTImporterOptionSpecificTestBase, RecordVarTemplateDecl) {5397 Decl *ToTU = getToTuDecl(5398 R"(5399 template <class T>5400 class A {5401 public:5402 template <class U>5403 static constexpr bool X = true;5404 };5405 )",5406 Lang_CXX14);5407 5408 auto *ToTUX = FirstDeclMatcher<VarTemplateDecl>().match(5409 ToTU, varTemplateDecl(hasName("X")));5410 Decl *FromTU = getTuDecl(5411 R"(5412 template <class T>5413 class A {5414 public:5415 template <class U>5416 static constexpr bool X = true;5417 };5418 )",5419 Lang_CXX14, "input1.cc");5420 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(5421 FromTU, varTemplateDecl(hasName("X")));5422 auto *ToX = Import(FromX, Lang_CXX11);5423 EXPECT_TRUE(ToX);5424 EXPECT_EQ(ToTUX, ToX);5425}5426 5427TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {5428 getToTuDecl(5429 R"(5430 template <class U>5431 constexpr int X = 1;5432 )",5433 Lang_CXX14);5434 5435 Decl *FromTU = getTuDecl(5436 R"(5437 template <class U>5438 constexpr int X = 2;5439 )",5440 Lang_CXX14, "input1.cc");5441 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(5442 FromTU, varTemplateDecl(hasName("X")));5443 auto *ToX = Import(FromX, Lang_CXX11);5444 // FIXME: This import should fail.5445 EXPECT_TRUE(ToX);5446}5447 5448TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {5449 Decl *ToTU = getToTuDecl(5450 R"(5451 struct A {5452 template <class U>5453 static int X;5454 };5455 )",5456 Lang_CXX14);5457 auto *ToX = FirstDeclMatcher<VarTemplateDecl>().match(5458 ToTU, varTemplateDecl(hasName("X")));5459 ASSERT_FALSE(ToX->isThisDeclarationADefinition());5460 5461 Decl *FromTU = getTuDecl(5462 R"(5463 struct A {5464 template <class U>5465 static int X;5466 };5467 template <class U>5468 int A::X = 2;5469 )",5470 Lang_CXX14, "input1.cc");5471 auto *FromXDef = LastDeclMatcher<VarTemplateDecl>().match(5472 FromTU, varTemplateDecl(hasName("X")));5473 ASSERT_TRUE(FromXDef->isThisDeclarationADefinition());5474 auto *ToXDef = Import(FromXDef, Lang_CXX14);5475 EXPECT_TRUE(ToXDef);5476 EXPECT_TRUE(ToXDef->isThisDeclarationADefinition());5477 EXPECT_EQ(ToXDef->getPreviousDecl(), ToX);5478}5479 5480TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateSpecializationDeclValue) {5481 Decl *ToTU = getToTuDecl(5482 R"(5483 template <class U>5484 constexpr int X = U::Value;5485 struct A { static constexpr int Value = 1; };5486 constexpr int Y = X<A>;5487 )",5488 Lang_CXX14);5489 5490 auto *ToTUX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(5491 ToTU, varTemplateSpecializationDecl(hasName("X")));5492 Decl *FromTU = getTuDecl(5493 R"(5494 template <class U>5495 constexpr int X = U::Value;5496 struct A { static constexpr int Value = 1; };5497 constexpr int Y = X<A>;5498 )",5499 Lang_CXX14, "input1.cc");5500 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(5501 FromTU, varTemplateSpecializationDecl(hasName("X")));5502 auto *ToX = Import(FromX, Lang_CXX14);5503 EXPECT_TRUE(ToX);5504 EXPECT_EQ(ToTUX, ToX);5505}5506 5507TEST_P(ASTImporterOptionSpecificTestBase,5508 VarTemplateSpecializationDeclValueConflict) {5509 getToTuDecl(5510 R"(5511 template <class U>5512 constexpr int X = U::Value;5513 struct A { static constexpr int Value = 1; };5514 constexpr int Y = X<A>;5515 )",5516 Lang_CXX14);5517 5518 Decl *FromTU = getTuDecl(5519 R"(5520 template <class U>5521 constexpr int X = U::Value;5522 struct A { static constexpr int Value = 2; };5523 constexpr int Y = X<A>;5524 )",5525 Lang_CXX14, "input1.cc");5526 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(5527 FromTU, varTemplateSpecializationDecl(hasName("X")));5528 auto *ToX = Import(FromX, Lang_CXX14);5529 EXPECT_FALSE(ToX);5530}5531 5532TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclInlineWithCXX17) {5533 Decl *FromTU = getTuDecl(5534 R"(5535 struct S {5536 template <unsigned> static constexpr bool X = true;5537 };5538 )",5539 Lang_CXX17, "input1.cc");5540 Decl *FromTU2 = getTuDecl(5541 R"(5542 struct S {5543 template <unsigned> static constexpr bool X = true;5544 template <typename T> void get() { X<sizeof(T)>; }5545 };5546 template <typename U> U qvariant_cast(const S &v) { return v.get; }5547 )",5548 Lang_CXX17, "input2.cc");5549 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(5550 FromTU, varTemplateDecl(hasName("X")));5551 auto *ToX = Import(FromX, Lang_CXX17);5552 ASSERT_TRUE(ToX);5553 auto *FromX2 = FirstDeclMatcher<VarTemplateDecl>().match(5554 FromTU2, varTemplateDecl(hasName("X")));5555 auto *ToX2 = Import(FromX2, Lang_CXX17);5556 EXPECT_TRUE(ToX2);5557 EXPECT_EQ(ToX, ToX2);5558}5559 5560TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {5561 constexpr auto Code =5562 R"(5563 template<class T1, class T2>5564 int X1;5565 template<class T2>5566 int X1<int, T2>;5567 5568 namespace Ns {5569 template<class T1, class T2>5570 int X2;5571 template<class T2>5572 int X2<int, T2>;5573 }5574 )";5575 5576 Decl *FromTU = getTuDecl(Code, Lang_CXX14);5577 5578 auto *FromD1 = FirstDeclMatcher<VarTemplateDecl>().match(5579 FromTU, varTemplateDecl(hasName("X1")));5580 auto *FromD1Part =5581 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(5582 FromTU, varTemplatePartialSpecializationDecl(hasName("X1")));5583 auto *FromD2 = FirstDeclMatcher<VarTemplateDecl>().match(5584 FromTU, varTemplateDecl(hasName("X2")));5585 auto *FromD2Part =5586 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(5587 FromTU, varTemplatePartialSpecializationDecl(hasName("X2")));5588 5589 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),5590 FromD1->getDeclContext());5591 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),5592 FromD2->getDeclContext());5593 5594 ASSERT_EQ(FromD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),5595 FromD1Part->getDeclContext());5596 // FIXME: VarTemplatePartialSpecializationDecl does not update ("adopt")5597 // template parameter decl context5598 // ASSERT_EQ(FromD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),5599 // FromD2Part->getDeclContext());5600 5601 auto *ToD1 = Import(FromD1, Lang_CXX14);5602 auto *ToD2 = Import(FromD2, Lang_CXX14);5603 5604 auto *ToD1Part = Import(FromD1Part, Lang_CXX14);5605 auto *ToD2Part = Import(FromD2Part, Lang_CXX14);5606 5607 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),5608 ToD1->getDeclContext());5609 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5610 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));5611 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),5612 ToD2->getDeclContext());5613 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5614 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));5615 5616 EXPECT_EQ(ToD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),5617 ToD1Part->getDeclContext());5618 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5619 ToD1Part->getDeclContext(),5620 ToD1Part->getTemplateParameters()->getParam(0)));5621 // EXPECT_EQ(ToD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),5622 // ToD2Part->getDeclContext());5623 // EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5624 // ToD2Part->getDeclContext(),5625 // ToD2Part->getTemplateParameters()->getParam(0)));5626 (void)ToD2Part;5627}5628 5629TEST_P(ASTImporterOptionSpecificTestBase,5630 TypeAliasTemplateParameterDeclContext) {5631 constexpr auto Code =5632 R"(5633 template<class T1, class T2>5634 struct S {};5635 template<class T> using S1 = S<T, int>;5636 namespace Ns {5637 template<class T> using S2 = S<T, int>;5638 }5639 )";5640 5641 Decl *FromTU = getTuDecl(Code, Lang_CXX11);5642 5643 auto *FromD1 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(5644 FromTU, typeAliasTemplateDecl(hasName("S1")));5645 auto *FromD2 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(5646 FromTU, typeAliasTemplateDecl(hasName("S2")));5647 5648 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),5649 FromD1->getDeclContext());5650 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),5651 FromD2->getDeclContext());5652 5653 auto *ToD1 = Import(FromD1, Lang_CXX11);5654 auto *ToD2 = Import(FromD2, Lang_CXX11);5655 5656 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),5657 ToD1->getDeclContext());5658 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5659 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));5660 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),5661 ToD2->getDeclContext());5662 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(5663 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));5664}5665 5666TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmType) {5667 constexpr auto Code = R"(5668 template <class A1, class... A2> struct A {5669 using B = A1(A2...);5670 };5671 template struct A<void, char, float, int, short>;5672 )";5673 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input.cpp");5674 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(5675 FromTU, classTemplateSpecializationDecl());5676 5677 auto testType = [&](ASTContext &Ctx, const char *Name,5678 UnsignedOrNone PackIndex) {5679 const auto *Subst = selectFirst<SubstTemplateTypeParmType>(5680 "sttp", match(substTemplateTypeParmType(5681 hasReplacementType(hasCanonicalType(asString(Name))))5682 .bind("sttp"),5683 Ctx));5684 const char *ExpectedTemplateParamName = PackIndex ? "A2" : "A1";5685 ASSERT_TRUE(Subst);5686 ASSERT_EQ(Subst->getReplacedParameter()->getIdentifier()->getName(),5687 ExpectedTemplateParamName);5688 ASSERT_EQ(Subst->getPackIndex(), PackIndex);5689 };5690 auto tests = [&](ASTContext &Ctx) {5691 testType(Ctx, "void", std::nullopt);5692 testType(Ctx, "char", 3u);5693 testType(Ctx, "float", 2u);5694 testType(Ctx, "int", 1u);5695 testType(Ctx, "short", 0u);5696 };5697 5698 tests(FromTU->getASTContext());5699 5700 ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);5701 tests(ToClass->getASTContext());5702}5703 5704const AstTypeMatcher<SubstTemplateTypeParmPackType>5705 substTemplateTypeParmPackType;5706 5707TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmPackType) {5708 constexpr auto Code = R"(5709 template<typename ...T> struct D {5710 template<typename... U> using B = int(int (*...p)(T, U));5711 template<typename U1, typename U2> D(B<U1, U2>*);5712 };5713 int f(int(int, int), int(int, int));5714 5715 using asd = D<float, double, float>::B<int, long, int>;5716 )";5717 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input.cpp");5718 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(5719 FromTU, classTemplateSpecializationDecl());5720 5721 {5722 ASTContext &FromCtx = FromTU->getASTContext();5723 const auto *FromSubstPack = selectFirst<SubstTemplateTypeParmPackType>(5724 "pack", match(substTemplateTypeParmPackType().bind("pack"), FromCtx));5725 5726 ASSERT_TRUE(FromSubstPack);5727 ASSERT_EQ(FromSubstPack->getIdentifier()->getName(), "T");5728 ArrayRef<TemplateArgument> FromArgPack =5729 FromSubstPack->getArgumentPack().pack_elements();5730 ASSERT_EQ(FromArgPack.size(), 3u);5731 ASSERT_EQ(FromArgPack[0].getAsType(), FromCtx.FloatTy);5732 ASSERT_EQ(FromArgPack[1].getAsType(), FromCtx.DoubleTy);5733 ASSERT_EQ(FromArgPack[2].getAsType(), FromCtx.FloatTy);5734 }5735 {5736 // Let's do the import.5737 ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);5738 ASTContext &ToCtx = ToClass->getASTContext();5739 5740 const auto *ToSubstPack = selectFirst<SubstTemplateTypeParmPackType>(5741 "pack", match(substTemplateTypeParmPackType().bind("pack"), ToCtx));5742 5743 // Check if it meets the requirements.5744 ASSERT_TRUE(ToSubstPack);5745 ASSERT_EQ(ToSubstPack->getIdentifier()->getName(), "T");5746 ArrayRef<TemplateArgument> ToArgPack =5747 ToSubstPack->getArgumentPack().pack_elements();5748 ASSERT_EQ(ToArgPack.size(), 3u);5749 ASSERT_EQ(ToArgPack[0].getAsType(), ToCtx.FloatTy);5750 ASSERT_EQ(ToArgPack[1].getAsType(), ToCtx.DoubleTy);5751 ASSERT_EQ(ToArgPack[2].getAsType(), ToCtx.FloatTy);5752 }5753}5754 5755struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};5756 5757TEST_P(ASTImporterLookupTableTest, OneDecl) {5758 auto *ToTU = getToTuDecl("int a;", Lang_CXX03);5759 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));5760 ASTImporterLookupTable LT(*ToTU);5761 auto Res = LT.lookup(ToTU, D->getDeclName());5762 ASSERT_EQ(Res.size(), 1u);5763 EXPECT_EQ(*Res.begin(), D);5764}5765 5766static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {5767 for (Decl *D : DC->decls()) {5768 if (auto *ND = dyn_cast<NamedDecl>(D))5769 if (ND->getDeclName() == Name)5770 return ND;5771 }5772 return nullptr;5773}5774 5775TEST_P(ASTImporterLookupTableTest,5776 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {5777 auto *Code = R"(5778 template <class T>5779 struct X {5780 friend void foo(){}5781 };5782 )";5783 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);5784 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(5785 ToTU, classTemplateDecl(hasName("X")));5786 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(5787 ToTU, functionDecl(hasName("foo")));5788 DeclContext *FooDC = Foo->getDeclContext();5789 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();5790 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());5791 ASSERT_EQ(cast<Decl>(FooDC), ToTU);5792 DeclarationName FooName = Foo->getDeclName();5793 5794 // Cannot find in the LookupTable of its DC (TUDecl)5795 SmallVector<NamedDecl *, 2> FoundDecls;5796 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);5797 EXPECT_EQ(FoundDecls.size(), 0u);5798 5799 // Cannot find in the LookupTable of its LexicalDC (X)5800 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);5801 EXPECT_EQ(FoundDecls.size(), 0u);5802 5803 // Can't find in the list of Decls of the DC.5804 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);5805 5806 // Can't find in the list of Decls of the LexicalDC5807 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);5808 5809 // ASTImporter specific lookup finds it.5810 ASTImporterLookupTable LT(*ToTU);5811 auto Res = LT.lookup(FooDC, Foo->getDeclName());5812 ASSERT_EQ(Res.size(), 1u);5813 EXPECT_EQ(*Res.begin(), Foo);5814}5815 5816TEST_P(ASTImporterLookupTableTest,5817 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {5818 TranslationUnitDecl *ToTU =5819 getToTuDecl("struct A { struct Foo *p; };", Lang_C99);5820 auto *Foo =5821 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));5822 auto *A =5823 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));5824 DeclContext *FooDC = Foo->getDeclContext();5825 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();5826 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);5827 ASSERT_EQ(cast<Decl>(FooDC), ToTU);5828 DeclarationName FooName = Foo->getDeclName();5829 5830 // Cannot find in the LookupTable of its DC (TUDecl).5831 SmallVector<NamedDecl *, 2> FoundDecls;5832 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);5833 EXPECT_EQ(FoundDecls.size(), 0u);5834 5835 // Finds via linear search of its LexicalDC (A).5836 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);5837 EXPECT_EQ(FoundDecls.size(), 1u);5838 5839 // Can't find in the list of Decls of the DC.5840 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);5841 5842 // Can find in the list of Decls of the LexicalDC.5843 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);5844 5845 // ASTImporter specific lookup finds it.5846 ASTImporterLookupTable LT(*ToTU);5847 auto Res = LT.lookup(FooDC, Foo->getDeclName());5848 ASSERT_EQ(Res.size(), 1u);5849 EXPECT_EQ(*Res.begin(), Foo);5850}5851 5852TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {5853 TranslationUnitDecl *ToTU =5854 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C99);5855 DeclarationName VName = FirstDeclMatcher<VarDecl>()5856 .match(ToTU, varDecl(hasName("V")))5857 ->getDeclName();5858 auto *A =5859 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));5860 auto *B =5861 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));5862 5863 ASTImporterLookupTable LT(*ToTU);5864 5865 auto Res = LT.lookup(cast<DeclContext>(A), VName);5866 ASSERT_EQ(Res.size(), 1u);5867 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(5868 ToTU, fieldDecl(hasName("V"),5869 hasParent(recordDecl(hasName("A"))))));5870 Res = LT.lookup(cast<DeclContext>(B), VName);5871 ASSERT_EQ(Res.size(), 1u);5872 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(5873 ToTU, fieldDecl(hasName("V"),5874 hasParent(recordDecl(hasName("B"))))));5875 Res = LT.lookup(ToTU, VName);5876 ASSERT_EQ(Res.size(), 1u);5877 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(5878 ToTU, varDecl(hasName("V"),5879 hasParent(translationUnitDecl()))));5880}5881 5882TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {5883 TranslationUnitDecl *ToTU = getToTuDecl(5884 R"(5885 void foo();5886 void foo(int);5887 void foo(int, int);5888 )",5889 Lang_CXX03);5890 5891 ASTImporterLookupTable LT(*ToTU);5892 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());5893 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());5894 DeclarationName Name = F0->getDeclName();5895 auto Res = LT.lookup(ToTU, Name);5896 EXPECT_EQ(Res.size(), 3u);5897 EXPECT_EQ(Res.count(F0), 1u);5898 EXPECT_EQ(Res.count(F2), 1u);5899}5900 5901TEST_P(ASTImporterLookupTableTest,5902 DifferentOperatorsShouldHaveDifferentResultSet) {5903 TranslationUnitDecl *ToTU = getToTuDecl(5904 R"(5905 struct X{};5906 void operator+(X, X);5907 void operator-(X, X);5908 )",5909 Lang_CXX03);5910 5911 ASTImporterLookupTable LT(*ToTU);5912 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(5913 ToTU, functionDecl(hasOverloadedOperatorName("+")));5914 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(5915 ToTU, functionDecl(hasOverloadedOperatorName("-")));5916 DeclarationName NamePlus = FPlus->getDeclName();5917 auto ResPlus = LT.lookup(ToTU, NamePlus);5918 EXPECT_EQ(ResPlus.size(), 1u);5919 EXPECT_EQ(ResPlus.count(FPlus), 1u);5920 EXPECT_EQ(ResPlus.count(FMinus), 0u);5921 DeclarationName NameMinus = FMinus->getDeclName();5922 auto ResMinus = LT.lookup(ToTU, NameMinus);5923 EXPECT_EQ(ResMinus.size(), 1u);5924 EXPECT_EQ(ResMinus.count(FMinus), 1u);5925 EXPECT_EQ(ResMinus.count(FPlus), 0u);5926 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());5927}5928 5929TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {5930 TranslationUnitDecl *ToTU = getToTuDecl(5931 R"(5932 struct X {};5933 void operator+(X, X);5934 )",5935 Lang_CXX03);5936 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(5937 ToTU, functionDecl(hasOverloadedOperatorName("+")));5938 5939 Decl *FromTU = getTuDecl(5940 R"(5941 struct X {};5942 void operator+(X, X);5943 )",5944 Lang_CXX03);5945 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(5946 FromTU, functionDecl(hasOverloadedOperatorName("+")));5947 5948 // FromPlus have a different TU, thus its DeclarationName is different too.5949 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());5950 5951 ASTImporterLookupTable LT(*ToTU);5952 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());5953 ASSERT_EQ(Res.size(), 1u);5954 EXPECT_EQ(*Res.begin(), ToPlus);5955 5956 // FromPlus have a different TU, thus its DeclarationName is different too.5957 Res = LT.lookup(ToTU, FromPlus->getDeclName());5958 ASSERT_EQ(Res.size(), 0u);5959}5960 5961TEST_P(ASTImporterLookupTableTest,5962 LookupFindsFwdFriendClassDeclWithElaboratedType) {5963 TranslationUnitDecl *ToTU = getToTuDecl(5964 R"(5965 class Y { friend class F; };5966 )",5967 Lang_CXX03);5968 5969 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.5970 // So we must dig up the underlying CXXRecordDecl.5971 ASTImporterLookupTable LT(*ToTU);5972 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());5973 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);5974 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(5975 ToTU, cxxRecordDecl(hasName("Y")));5976 5977 DeclarationName Name = RD->getDeclName();5978 auto Res = LT.lookup(ToTU, Name);5979 EXPECT_EQ(Res.size(), 1u);5980 EXPECT_EQ(*Res.begin(), RD);5981 5982 Res = LT.lookup(Y, Name);5983 EXPECT_EQ(Res.size(), 0u);5984}5985 5986TEST_P(ASTImporterLookupTableTest,5987 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {5988 TranslationUnitDecl *ToTU = getToTuDecl(5989 R"(5990 class F;5991 class Y { friend F; };5992 )",5993 Lang_CXX11);5994 5995 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.5996 // So we must dig up the underlying CXXRecordDecl.5997 ASTImporterLookupTable LT(*ToTU);5998 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());5999 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);6000 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));6001 6002 DeclarationName Name = RD->getDeclName();6003 auto Res = LT.lookup(ToTU, Name);6004 EXPECT_EQ(Res.size(), 1u);6005 EXPECT_EQ(*Res.begin(), RD);6006 6007 Res = LT.lookup(Y, Name);6008 EXPECT_EQ(Res.size(), 0u);6009}6010 6011TEST_P(ASTImporterLookupTableTest,6012 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {6013 TranslationUnitDecl *ToTU = getToTuDecl(6014 R"(6015 class F;6016 using alias_of_f = F;6017 class Y { friend alias_of_f; };6018 )",6019 Lang_CXX11);6020 6021 // ASTImporterLookupTable constructor handles using declarations correctly,6022 // no assert is expected.6023 ASTImporterLookupTable LT(*ToTU);6024 6025 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(6026 ToTU, typeAliasDecl(hasName("alias_of_f")));6027 DeclarationName Name = Alias->getDeclName();6028 auto Res = LT.lookup(ToTU, Name);6029 EXPECT_EQ(Res.count(Alias), 1u);6030}6031 6032TEST_P(ASTImporterLookupTableTest,6033 LookupFindsFriendClassDeclWithUsingTypeDoesNotAssert) {6034 TranslationUnitDecl *ToTU = getToTuDecl(6035 R"(6036 namespace a {6037 namespace b { class InnerClass; }6038 using b::InnerClass;6039 }6040 class B {6041 friend a::InnerClass;6042 };6043 )",6044 Lang_CXX11);6045 6046 // ASTImporterLookupTable constructor handles friend with using-type without6047 // asserts.6048 ASTImporterLookupTable LT(*ToTU);6049 6050 auto *Using = FirstDeclMatcher<UsingDecl>().match(6051 ToTU, usingDecl(hasName("InnerClass")));6052 DeclarationName Name = Using->getDeclName();6053 auto Res = LT.lookup(ToTU, Name);6054 EXPECT_EQ(Res.size(), 0u);6055 auto *NsA = FirstDeclMatcher<NamespaceDecl>().match(6056 ToTU, namespaceDecl(hasName("a")));6057 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(6058 ToTU, cxxRecordDecl(hasName("B")));6059 auto Res1 = LT.lookup(NsA, Name);6060 EXPECT_EQ(Res1.count(Using), 1u);6061 auto Res2 = LT.lookup(RecordB, Name);6062 EXPECT_EQ(Res2.size(), 0u);6063}6064 6065TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {6066 TranslationUnitDecl *ToTU = getToTuDecl(6067 R"(6068 class Y { template <class T> friend class F; };6069 )",6070 Lang_CXX03);6071 6072 ASTImporterLookupTable LT(*ToTU);6073 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(6074 ToTU, classTemplateDecl(hasName("F")));6075 DeclarationName Name = F->getDeclName();6076 auto Res = LT.lookup(ToTU, Name);6077 EXPECT_EQ(Res.size(), 2u);6078 EXPECT_EQ(Res.count(F), 1u);6079 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);6080}6081 6082TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {6083 TranslationUnitDecl *ToTU = getToTuDecl(6084 R"(6085 template <typename T>6086 class F;6087 6088 template <typename T>6089 class Y {6090 friend class F<T>;6091 };6092 )",6093 Lang_CXX03);6094 6095 ASTImporterLookupTable LT(*ToTU);6096 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(6097 ToTU, classTemplateDecl(hasName("F")));6098 DeclarationName Name = F->getDeclName();6099 auto Res = LT.lookup(ToTU, Name);6100 EXPECT_EQ(Res.size(), 2u);6101 EXPECT_EQ(Res.count(F), 1u);6102 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);6103}6104 6105TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {6106 TranslationUnitDecl *ToTU = getToTuDecl(6107 R"(6108 template <typename T>6109 class F;6110 6111 class Y {6112 friend class F<int>;6113 };6114 )",6115 Lang_CXX03);6116 6117 ASTImporterLookupTable LT(*ToTU);6118 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(6119 ToTU, classTemplateDecl(hasName("F")));6120 DeclarationName Name = F->getDeclName();6121 auto Res = LT.lookup(ToTU, Name);6122 ASSERT_EQ(Res.size(), 3u);6123 EXPECT_EQ(Res.count(F), 1u);6124 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);6125 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);6126}6127 6128TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {6129 TranslationUnitDecl *ToTU = getToTuDecl(6130 R"(6131 class Y { friend void F(); };6132 )",6133 Lang_CXX03);6134 6135 ASTImporterLookupTable LT(*ToTU);6136 auto *F =6137 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));6138 DeclarationName Name = F->getDeclName();6139 auto Res = LT.lookup(ToTU, Name);6140 EXPECT_EQ(Res.size(), 1u);6141 EXPECT_EQ(*Res.begin(), F);6142}6143 6144TEST_P(ASTImporterLookupTableTest,6145 LookupFindsDeclsInClassTemplateSpecialization) {6146 TranslationUnitDecl *ToTU = getToTuDecl(6147 R"(6148 template <typename T>6149 struct X {6150 int F;6151 };6152 void foo() {6153 X<char> xc;6154 }6155 )",6156 Lang_CXX03);6157 6158 ASTImporterLookupTable LT(*ToTU);6159 6160 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(6161 ToTU, classTemplateDecl(hasName("X")));6162 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(6163 ToTU,6164 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));6165 6166 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(6167 ToTU, classTemplateSpecializationDecl(hasName("X")));6168 FieldDecl *FieldInSpec = *Spec->field_begin();6169 ASSERT_TRUE(FieldInSpec);6170 6171 DeclarationName Name = FieldInSpec->getDeclName();6172 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());6173 6174 SmallVector<NamedDecl *, 2> FoundDecls;6175 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);6176 EXPECT_EQ(FoundDecls.size(), 1u);6177 EXPECT_EQ(FoundDecls[0], FieldInTemplate);6178 6179 auto Res = LT.lookup(TemplateDC, Name);6180 ASSERT_EQ(Res.size(), 1u);6181 EXPECT_EQ(*Res.begin(), FieldInTemplate);6182 6183 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,6184 FoundDecls);6185 EXPECT_EQ(FoundDecls.size(), 1u);6186 EXPECT_EQ(FoundDecls[0], FieldInSpec);6187 6188 Res = LT.lookup(cast<DeclContext>(Spec), Name);6189 ASSERT_EQ(Res.size(), 1u);6190 EXPECT_EQ(*Res.begin(), FieldInSpec);6191}6192 6193TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {6194 TranslationUnitDecl *ToTU = getToTuDecl(6195 R"(6196 class Y { template <class T> friend void F(); };6197 )",6198 Lang_CXX03);6199 6200 ASTImporterLookupTable LT(*ToTU);6201 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(6202 ToTU, functionTemplateDecl(hasName("F")));6203 DeclarationName Name = F->getDeclName();6204 auto Res = LT.lookup(ToTU, Name);6205 EXPECT_EQ(Res.size(), 2u);6206 EXPECT_EQ(Res.count(F), 1u);6207 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);6208}6209 6210TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {6211 TranslationUnitDecl *ToTU = getToTuDecl(6212 R"(6213 struct X;6214 struct A {6215 friend struct X;6216 };6217 struct B {6218 friend struct X;6219 };6220 )",6221 Lang_CXX03);6222 6223 ASTImporterLookupTable LT(*ToTU);6224 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(6225 ToTU, cxxRecordDecl(hasName("X")));6226 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());6227 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());6228 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);6229 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);6230 ASSERT_EQ(RD0, RD1);6231 ASSERT_EQ(RD1, X);6232 6233 DeclarationName Name = X->getDeclName();6234 auto Res = LT.lookup(ToTU, Name);6235 EXPECT_EQ(Res.size(), 1u);6236 EXPECT_EQ(*Res.begin(), X);6237}6238 6239TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {6240 TranslationUnitDecl *ToTU = getToTuDecl(6241 R"(6242 enum E {6243 A,6244 B6245 };6246 )",6247 Lang_C99);6248 6249 ASTImporterLookupTable LT(*ToTU);6250 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));6251 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(6252 ToTU, enumConstantDecl(hasName("A")));6253 6254 DeclarationName Name = A->getDeclName();6255 // Redecl context is the TU.6256 ASSERT_EQ(E->getRedeclContext(), ToTU);6257 6258 SmallVector<NamedDecl *, 2> FoundDecls;6259 // Normal lookup finds in the DC.6260 E->localUncachedLookup(Name, FoundDecls);6261 EXPECT_EQ(FoundDecls.size(), 1u);6262 6263 // Normal lookup finds in the Redecl context.6264 ToTU->localUncachedLookup(Name, FoundDecls);6265 EXPECT_EQ(FoundDecls.size(), 1u);6266 6267 // Import specific lookup finds in the DC.6268 auto Res = LT.lookup(E, Name);6269 ASSERT_EQ(Res.size(), 1u);6270 EXPECT_EQ(*Res.begin(), A);6271 6272 // Import specific lookup finds in the Redecl context.6273 Res = LT.lookup(ToTU, Name);6274 ASSERT_EQ(Res.size(), 1u);6275 EXPECT_EQ(*Res.begin(), A);6276}6277 6278TEST_P(ASTImporterLookupTableTest, LookupSearchesInActualNamespaceOnly) {6279 TranslationUnitDecl *ToTU = getToTuDecl(6280 R"(6281 namespace N {6282 int A;6283 }6284 namespace N {6285 }6286 )",6287 Lang_CXX03);6288 auto *N1 = FirstDeclMatcher<NamespaceDecl>().match(6289 ToTU, namespaceDecl(hasName("N")));6290 auto *N2 =6291 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));6292 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));6293 DeclarationName Name = A->getDeclName();6294 6295 ASTImporterLookupTable LT(*ToTU);6296 auto Res = LT.lookup(N1, Name);6297 ASSERT_EQ(Res.size(), 1u);6298 EXPECT_EQ(*Res.begin(), A);6299 EXPECT_TRUE(LT.lookup(N2, Name).empty());6300}6301 6302TEST_P(ASTImporterOptionSpecificTestBase,6303 RedeclChainShouldBeCorrectAmongstNamespaces) {6304 Decl *FromTU = getTuDecl(6305 R"(6306 namespace NS {6307 struct X;6308 struct Y {6309 static const int I = 3;6310 };6311 }6312 namespace NS {6313 struct X { // <--- To be imported6314 void method(int i = Y::I) {}6315 int f;6316 };6317 }6318 )",6319 Lang_CXX03);6320 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(6321 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));6322 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(6323 FromTU,6324 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));6325 ASSERT_NE(FromFwd, FromDef);6326 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());6327 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());6328 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());6329 6330 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX03));6331 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX03));6332 EXPECT_NE(ToFwd, ToDef);6333 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());6334 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());6335 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());6336 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();6337 // We expect no (ODR) warning during the import.6338 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());6339}6340 6341struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};6342 6343TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {6344 Decl *ToTU = getToTuDecl(6345 R"(6346 class X {6347 template <typename T> friend void foo();6348 };6349 )",6350 Lang_CXX03);6351 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(6352 ToTU, functionTemplateDecl(hasName("foo")));6353 6354 Decl *FromTU = getTuDecl(6355 R"(6356 template <typename T> void foo();6357 )",6358 Lang_CXX03);6359 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(6360 FromTU, functionTemplateDecl(hasName("foo")));6361 auto *Imported = Import(FromFoo, Lang_CXX03);6362 6363 EXPECT_EQ(Imported->getPreviousDecl(), Friend);6364}6365 6366TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) {6367 Decl *From, *To;6368 std::tie(From, To) = getImportedDecl(6369 R"(6370 template <typename T> struct X {6371 template <typename U> friend void f();6372 };6373 )",6374 Lang_CXX03, "", Lang_CXX03, "X");6375 6376 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(From, friendDecl());6377 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(To, friendDecl());6378 6379 EXPECT_TRUE(FromFriend ==6380 LastDeclMatcher<FriendDecl>().match(From, friendDecl()));6381 EXPECT_TRUE(ToFriend ==6382 LastDeclMatcher<FriendDecl>().match(To, friendDecl()));6383 6384 auto *FromDecl = FromFriend->getFriendDecl();6385 auto *FromDC = FromFriend->getDeclContext();6386 auto *FromLexicalDC = FromFriend->getLexicalDeclContext();6387 6388 EXPECT_TRUE(FromDC->containsDecl(FromFriend));6389 EXPECT_FALSE(FromDC->containsDecl(FromDecl));6390 EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));6391 EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));6392 6393 auto *ToDecl = ToFriend->getFriendDecl();6394 auto *ToDC = ToFriend->getDeclContext();6395 auto *ToLexicalDC = ToFriend->getLexicalDeclContext();6396 6397 EXPECT_TRUE(ToDC->containsDecl(ToFriend));6398 EXPECT_FALSE(ToDC->containsDecl(ToDecl));6399 EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));6400 EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));6401}6402 6403struct ASTImporterWithFakeErrors : ASTImporter {6404 using ASTImporter::ASTImporter;6405 bool returnWithErrorInTest() override { return true; }6406};6407 6408struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {6409 ErrorHandlingTest() {6410 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,6411 ASTContext &FromContext, FileManager &FromFileManager,6412 bool MinimalImport,6413 const std::shared_ptr<ASTImporterSharedState> &SharedState) {6414 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,6415 FromContext, FromFileManager,6416 MinimalImport, SharedState);6417 };6418 }6419 // In this test we purposely report an error (UnsupportedConstruct) when6420 // importing the below stmt.6421 static constexpr auto* ErroneousStmt = R"( asm(""); )";6422};6423 6424// Check a case when no new AST node is created in the AST before encountering6425// the error.6426TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {6427 TranslationUnitDecl *ToTU = getToTuDecl(6428 R"(6429 template <typename T>6430 class X {};6431 template <>6432 class X<int> { int a; };6433 )",6434 Lang_CXX03);6435 TranslationUnitDecl *FromTU = getTuDecl(6436 R"(6437 template <typename T>6438 class X {};6439 template <>6440 class X<int> { double b; };6441 )",6442 Lang_CXX03);6443 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(6444 FromTU, classTemplateSpecializationDecl(hasName("X")));6445 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX03);6446 EXPECT_FALSE(ImportedSpec);6447 6448 // The original Decl is kept, no new decl is created.6449 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(6450 ToTU, classTemplateSpecializationDecl(hasName("X"))),6451 1u);6452 6453 // But an error is set to the counterpart in the "from" context.6454 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();6455 std::optional<ASTImportError> OptErr =6456 Importer->getImportDeclErrorIfAny(FromSpec);6457 ASSERT_TRUE(OptErr);6458 EXPECT_EQ(OptErr->Error, ASTImportError::NameConflict);6459}6460 6461// Check a case when a new AST node is created but not linked to the AST before6462// encountering the error.6463TEST_P(ErrorHandlingTest,6464 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {6465 TranslationUnitDecl *FromTU = getTuDecl(6466 std::string("void foo() { ") + ErroneousStmt + " }", Lang_CXX03);6467 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(6468 FromTU, functionDecl(hasName("foo")));6469 6470 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX03);6471 EXPECT_FALSE(ImportedFoo);6472 6473 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();6474 // Created, but not linked.6475 EXPECT_EQ(6476 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),6477 0u);6478 6479 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();6480 std::optional<ASTImportError> OptErr =6481 Importer->getImportDeclErrorIfAny(FromFoo);6482 ASSERT_TRUE(OptErr);6483 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6484}6485 6486// Check a case when a new AST node is created and linked to the AST before6487// encountering the error. The error is set for the counterpart of the nodes in6488// the "from" context.6489TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {6490 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(6491 void f();6492 void f() { )") + ErroneousStmt + R"( }6493 )",6494 Lang_CXX03);6495 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(6496 FromTU, functionDecl(hasName("f")));6497 auto *FromDef =6498 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));6499 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX03);6500 EXPECT_FALSE(ImportedProto); // Could not import.6501 // However, we created two nodes in the AST. 1) the fwd decl 2) the6502 // definition. The definition is not added to its DC, but the fwd decl is6503 // there.6504 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();6505 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),6506 1u);6507 // Match the fwd decl.6508 auto *ToProto =6509 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));6510 EXPECT_TRUE(ToProto);6511 // An error is set to the counterpart in the "from" context both for the fwd6512 // decl and the definition.6513 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();6514 std::optional<ASTImportError> OptErr =6515 Importer->getImportDeclErrorIfAny(FromProto);6516 ASSERT_TRUE(OptErr);6517 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6518 OptErr = Importer->getImportDeclErrorIfAny(FromDef);6519 ASSERT_TRUE(OptErr);6520 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6521}6522 6523// An error should be set for a class if we cannot import one member.6524TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {6525 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(6526 class X {6527 void f() { )") + ErroneousStmt + R"( } // This member has the error6528 // during import.6529 void ok(); // The error should not prevent importing this.6530 }; // An error will be set for X too.6531 )",6532 Lang_CXX03);6533 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(6534 FromTU, cxxRecordDecl(hasName("X")));6535 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);6536 6537 // An error is set for X.6538 EXPECT_FALSE(ImportedX);6539 ASTImporter *Importer = findFromTU(FromX)->Importer.get();6540 std::optional<ASTImportError> OptErr =6541 Importer->getImportDeclErrorIfAny(FromX);6542 ASSERT_TRUE(OptErr);6543 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6544 6545 // An error is set for f().6546 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(6547 FromTU, cxxMethodDecl(hasName("f")));6548 OptErr = Importer->getImportDeclErrorIfAny(FromF);6549 ASSERT_TRUE(OptErr);6550 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6551 // And any subsequent import should fail.6552 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX03);6553 EXPECT_FALSE(ImportedF);6554 6555 // There is an error set for the other member too.6556 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(6557 FromTU, cxxMethodDecl(hasName("ok")));6558 OptErr = Importer->getImportDeclErrorIfAny(FromOK);6559 EXPECT_TRUE(OptErr);6560 // Cannot import the other member.6561 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX03);6562 EXPECT_FALSE(ImportedOK);6563}6564 6565// Check that an error propagates to the dependent AST nodes.6566// In the below code it means that an error in X should propagate to A.6567// And even to F since the containing A is erroneous.6568// And to all AST nodes which we visit during the import process which finally6569// ends up in a failure (in the error() function).6570TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {6571 Decl *FromTU = getTuDecl(std::string(R"(6572 namespace NS {6573 class A {6574 template <int I> class F {};6575 class X {6576 template <int I> friend class F;6577 void error() { )") +6578 ErroneousStmt + R"( }6579 };6580 };6581 6582 class B {};6583 } // NS6584 )",6585 Lang_CXX03, "input0.cc");6586 6587 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(6588 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));6589 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(6590 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));6591 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(6592 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));6593 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(6594 FromTU, namespaceDecl(hasName("NS")));6595 6596 // Start by importing the templated CXXRecordDecl of F.6597 // Import fails for that.6598 EXPECT_FALSE(Import(FromFRD, Lang_CXX03));6599 // Import fails for A.6600 EXPECT_FALSE(Import(FromA, Lang_CXX03));6601 // But we should be able to import the independent B.6602 EXPECT_TRUE(Import(FromB, Lang_CXX03));6603 // And the namespace.6604 EXPECT_TRUE(Import(FromNS, Lang_CXX03));6605 6606 // An error is set to the templated CXXRecordDecl of F.6607 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();6608 std::optional<ASTImportError> OptErr =6609 Importer->getImportDeclErrorIfAny(FromFRD);6610 EXPECT_TRUE(OptErr);6611 6612 // An error is set to A.6613 OptErr = Importer->getImportDeclErrorIfAny(FromA);6614 EXPECT_TRUE(OptErr);6615 6616 // There is no error set to B.6617 OptErr = Importer->getImportDeclErrorIfAny(FromB);6618 EXPECT_FALSE(OptErr);6619 6620 // There is no error set to NS.6621 OptErr = Importer->getImportDeclErrorIfAny(FromNS);6622 EXPECT_FALSE(OptErr);6623 6624 // Check some of those decls whose ancestor is X, they all should have an6625 // error set if we visited them during an import process which finally failed.6626 // These decls are part of a cycle in an ImportPath.6627 // There would not be any error set for these decls if we hadn't follow the6628 // ImportPaths and the cycles.6629 OptErr = Importer->getImportDeclErrorIfAny(6630 FirstDeclMatcher<ClassTemplateDecl>().match(6631 FromTU, classTemplateDecl(hasName("F"))));6632 // An error is set to the 'F' ClassTemplateDecl.6633 EXPECT_TRUE(OptErr);6634 // An error is set to the FriendDecl.6635 OptErr = Importer->getImportDeclErrorIfAny(6636 FirstDeclMatcher<FriendDecl>().match(6637 FromTU, friendDecl()));6638 EXPECT_TRUE(OptErr);6639 // An error is set to the implicit class of A.6640 OptErr =6641 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(6642 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));6643 EXPECT_TRUE(OptErr);6644 // An error is set to the implicit class of X.6645 OptErr =6646 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(6647 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));6648 EXPECT_TRUE(OptErr);6649}6650 6651TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {6652 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(6653 namespace X {6654 void f() { )") + ErroneousStmt + R"( } // This member has the error6655 // during import.6656 void ok(); // The error should not prevent importing this.6657 }; // An error will be set for X too.6658 )",6659 Lang_CXX03);6660 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(6661 FromTU, namespaceDecl(hasName("X")));6662 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX03);6663 6664 // There is no error set for X.6665 EXPECT_TRUE(ImportedX);6666 ASTImporter *Importer = findFromTU(FromX)->Importer.get();6667 std::optional<ASTImportError> OptErr =6668 Importer->getImportDeclErrorIfAny(FromX);6669 ASSERT_FALSE(OptErr);6670 6671 // An error is set for f().6672 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(6673 FromTU, functionDecl(hasName("f")));6674 OptErr = Importer->getImportDeclErrorIfAny(FromF);6675 ASSERT_TRUE(OptErr);6676 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6677 // And any subsequent import should fail.6678 FunctionDecl *ImportedF = Import(FromF, Lang_CXX03);6679 EXPECT_FALSE(ImportedF);6680 6681 // There is no error set for ok().6682 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(6683 FromTU, functionDecl(hasName("ok")));6684 OptErr = Importer->getImportDeclErrorIfAny(FromOK);6685 EXPECT_FALSE(OptErr);6686 // And we should be able to import.6687 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX03);6688 EXPECT_TRUE(ImportedOK);6689}6690 6691TEST_P(ErrorHandlingTest, ODRViolationWithinTypedefDecls) {6692 // Importing `z` should fail - instead of crashing - due to an ODR violation.6693 // The `bar::e` typedef sets it's DeclContext after the import is done.6694 // However, if the importation fails, it will be left as a nullptr.6695 // During the cleanup of the failed import, we should check whether the6696 // DeclContext is null or not - instead of dereferencing that unconditionally.6697 constexpr auto ToTUCode = R"(6698 namespace X {6699 struct bar {6700 int odr_violation;6701 };6702 })";6703 constexpr auto FromTUCode = R"(6704 namespace X {6705 enum b {};6706 struct bar {6707 typedef b e;6708 static e d;6709 };6710 }6711 int z = X::bar::d;6712 )";6713 Decl *ToTU = getToTuDecl(ToTUCode, Lang_CXX11);6714 static_cast<void>(ToTU);6715 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);6716 auto *FromZ =6717 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("z")));6718 ASSERT_TRUE(FromZ);6719 ASSERT_TRUE(FromZ->hasInit());6720 6721 auto *ImportedZ = Import(FromZ, Lang_CXX11);6722 EXPECT_FALSE(ImportedZ);6723}6724 6725// An error should be set for a class if it had a previous import with an error6726// from another TU.6727TEST_P(ErrorHandlingTest,6728 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {6729 // We already have a fwd decl.6730 TranslationUnitDecl *ToTU = getToTuDecl("class X;", Lang_CXX03);6731 // Then we import a definition.6732 {6733 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(6734 class X {6735 void f() { )") + ErroneousStmt + R"( }6736 void ok();6737 };6738 )",6739 Lang_CXX03);6740 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(6741 FromTU, cxxRecordDecl(hasName("X")));6742 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);6743 6744 // An error is set for X ...6745 EXPECT_FALSE(ImportedX);6746 ASTImporter *Importer = findFromTU(FromX)->Importer.get();6747 std::optional<ASTImportError> OptErr =6748 Importer->getImportDeclErrorIfAny(FromX);6749 ASSERT_TRUE(OptErr);6750 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6751 }6752 // ... but the node had been created.6753 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(6754 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));6755 // An error is set for "ToXDef" in the shared state.6756 std::optional<ASTImportError> OptErr =6757 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);6758 ASSERT_TRUE(OptErr);6759 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6760 6761 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(6762 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));6763 // An error is NOT set for the fwd Decl of X in the shared state.6764 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);6765 ASSERT_FALSE(OptErr);6766 6767 // Try to import X again but from another TU.6768 {6769 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(6770 class X {6771 void f() { )") + ErroneousStmt + R"( }6772 void ok();6773 };6774 )",6775 Lang_CXX03, "input1.cc");6776 6777 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(6778 FromTU, cxxRecordDecl(hasName("X")));6779 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);6780 6781 // If we did not save the errors for the "to" context then the below checks6782 // would fail, because the lookup finds the fwd Decl of the existing6783 // definition in the "to" context. We can reach the existing definition via6784 // the found fwd Decl. That existing definition is structurally equivalent6785 // (we check only the fields) with this one we want to import, so we return6786 // with the existing definition, which is erroneous (one method is missing).6787 6788 // The import should fail.6789 EXPECT_FALSE(ImportedX);6790 ASTImporter *Importer = findFromTU(FromX)->Importer.get();6791 std::optional<ASTImportError> OptErr =6792 Importer->getImportDeclErrorIfAny(FromX);6793 // And an error is set for this new X in the "from" ctx.6794 ASSERT_TRUE(OptErr);6795 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6796 }6797}6798 6799TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {6800 auto MatchFooA =6801 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));6802 auto MatchFooB =6803 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));6804 auto MatchFooC =6805 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));6806 6807 // Provoke import of a method that has overridden methods with import error.6808 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(6809 struct C;6810 struct A {6811 virtual void foo();6812 void f1(C *);6813 };6814 void A::foo() {6815 )") + ErroneousStmt + R"(6816 }6817 struct B : public A {6818 void foo() override;6819 };6820 struct C : public B {6821 void foo() override;6822 };6823 )",6824 Lang_CXX11);6825 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);6826 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);6827 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);6828 6829 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));6830 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();6831 auto CheckError = [&Importer](Decl *FromD) {6832 std::optional<ASTImportError> OptErr =6833 Importer->getImportDeclErrorIfAny(FromD);6834 ASSERT_TRUE(OptErr);6835 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);6836 };6837 CheckError(FromFooA);6838 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));6839 CheckError(FromFooB);6840 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));6841 CheckError(FromFooC);6842}6843 6844TEST_P(ErrorHandlingTest, ODRViolationWithinParmVarDecls) {6845 // Importing of 'f' and parameter 'P' should cause an ODR error.6846 // The error happens after the ParmVarDecl for 'P' was already created.6847 // This is a special case because the ParmVarDecl has a temporary DeclContext.6848 // Expected is no crash at error handling of ASTImporter.6849 constexpr auto ToTUCode = R"(6850 struct X {6851 char A;6852 };6853 )";6854 constexpr auto FromTUCode = R"(6855 struct X {6856 enum Y { Z };6857 };6858 void f(int P = X::Z);6859 )";6860 Decl *ToTU = getToTuDecl(ToTUCode, Lang_CXX11);6861 static_cast<void>(ToTU);6862 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);6863 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(6864 FromTU, functionDecl(hasName("f")));6865 ASSERT_TRUE(FromF);6866 6867 auto *ImportedF = Import(FromF, Lang_CXX11);6868 EXPECT_FALSE(ImportedF);6869}6870 6871TEST_P(ErrorHandlingTest, DoNotInheritErrorFromNonDependentChild) {6872 // Declarations should not inherit an import error from a child object6873 // if the declaration has no direct dependence to such a child.6874 // For example a namespace should not get import error if one of the6875 // declarations inside it fails to import.6876 // There was a special case in error handling (when "import path circles" are6877 // encountered) when this property was not held. This case is provoked by the6878 // following code.6879 constexpr auto ToTUCode = R"(6880 namespace ns {6881 struct Err {6882 char A;6883 };6884 }6885 )";6886 constexpr auto FromTUCode = R"(6887 namespace ns {6888 struct A {6889 using U = struct Err;6890 };6891 }6892 namespace ns {6893 struct Err {}; // ODR violation6894 void f(A) {}6895 }6896 )";6897 6898 Decl *ToTU = getToTuDecl(ToTUCode, Lang_CXX11);6899 static_cast<void>(ToTU);6900 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);6901 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(6902 FromTU, cxxRecordDecl(hasName("A"), hasDefinition()));6903 ASSERT_TRUE(FromA);6904 auto *ImportedA = Import(FromA, Lang_CXX11);6905 // 'A' can not be imported: ODR error at 'Err'6906 EXPECT_FALSE(ImportedA);6907 // When import of 'A' failed there was a "saved import path circle" that6908 // contained namespace 'ns' (A - U - Err - ns - f - A). This should not mean6909 // that every object in this path fails to import.6910 6911 Decl *FromNS = FirstDeclMatcher<NamespaceDecl>().match(6912 FromTU, namespaceDecl(hasName("ns")));6913 EXPECT_TRUE(FromNS);6914 auto *ImportedNS = Import(FromNS, Lang_CXX11);6915 EXPECT_TRUE(ImportedNS);6916}6917 6918TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {6919 Decl *FromTU = getTuDecl(6920 R"(6921 void f() {6922 auto L = [](){};6923 }6924 )",6925 Lang_CXX11, "input0.cc");6926 auto Pattern = lambdaExpr();6927 CXXRecordDecl *FromL =6928 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();6929 6930 auto ToL = Import(FromL, Lang_CXX11);6931 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());6932 unsigned FromLSize =6933 std::distance(FromL->decls().begin(), FromL->decls().end());6934 EXPECT_NE(ToLSize, 0u);6935 EXPECT_EQ(ToLSize, FromLSize);6936 EXPECT_FALSE(FromL->isDependentLambda());6937}6938 6939TEST_P(ASTImporterOptionSpecificTestBase,6940 ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) {6941 Decl *From, *To;6942 std::tie(From, To) = getImportedDecl(6943 R"(6944 void foo() {6945 (void) []() {6946 struct X {};6947 return X();6948 };6949 }6950 )",6951 Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only6952 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(To, lambdaExpr());6953 EXPECT_TRUE(ToLambda);6954}6955 6956TEST_P(ASTImporterOptionSpecificTestBase,6957 ReturnTypeDeclaredInsideOfCXX11LambdaWithTrailingReturn) {6958 Decl *From, *To;6959 std::tie(From, To) = getImportedDecl(6960 R"(6961 void foo() {6962 (void) [] {6963 struct X {};6964 return X();6965 };6966 }6967 )",6968 Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only6969 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(To, lambdaExpr());6970 EXPECT_TRUE(ToLambda);6971}6972 6973TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {6974 Decl *FromTU = getTuDecl(6975 R"(6976 template <typename F>6977 void f(F L = [](){}) {}6978 )",6979 Lang_CXX11, "input0.cc");6980 auto Pattern = lambdaExpr();6981 CXXRecordDecl *FromL =6982 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();6983 6984 auto ToL = Import(FromL, Lang_CXX11);6985 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());6986 unsigned FromLSize =6987 std::distance(FromL->decls().begin(), FromL->decls().end());6988 EXPECT_NE(ToLSize, 0u);6989 EXPECT_EQ(ToLSize, FromLSize);6990 EXPECT_TRUE(FromL->isDependentLambda());6991}6992 6993TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {6994 Decl *FromTU = getTuDecl(6995 R"(6996 auto l1 = [](unsigned lp) { return 1; };6997 auto l2 = [](int lp) { return 2; };6998 int f(int p) {6999 return l1(p) + l2(p);7000 }7001 )",7002 Lang_CXX11, "input0.cc");7003 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(7004 FromTU, functionDecl(hasName("f")));7005 FunctionDecl *ToF = Import(FromF, Lang_CXX11);7006 EXPECT_TRUE(ToF);7007}7008 7009TEST_P(ASTImporterOptionSpecificTestBase,7010 ImportExistingFriendClassTemplateDef) {7011 auto Code =7012 R"(7013 template <class T1, class T2>7014 struct Base {7015 template <class U1, class U2>7016 friend struct Class;7017 };7018 template <class T1, class T2>7019 struct Class { };7020 )";7021 7022 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX03);7023 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX03, "input.cc");7024 7025 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(7026 ToTU, classTemplateDecl(hasName("Class")));7027 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(7028 ToTU, classTemplateDecl(hasName("Class")));7029 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());7030 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());7031 // Previous friend decl is not linked to it!7032 ASSERT_FALSE(ToClassDef->getPreviousDecl());7033 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);7034 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);7035 7036 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(7037 FromTU, classTemplateDecl(hasName("Class")));7038 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(7039 FromTU, classTemplateDecl(hasName("Class")));7040 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());7041 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());7042 ASSERT_FALSE(FromClassDef->getPreviousDecl());7043 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);7044 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);7045 7046 auto *ImportedDef = Import(FromClassDef, Lang_CXX03);7047 // At import we should find the definition for 'Class' even if the7048 // prototype (inside 'friend') for it comes first in the AST and is not7049 // linked to the definition.7050 EXPECT_EQ(ImportedDef, ToClassDef);7051}7052 7053struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {7054 LLDBLookupTest() {7055 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,7056 ASTContext &FromContext, FileManager &FromFileManager,7057 bool MinimalImport,7058 const std::shared_ptr<ASTImporterSharedState> &SharedState) {7059 return new ASTImporter(ToContext, ToFileManager, FromContext,7060 FromFileManager, MinimalImport,7061 // We use the regular lookup.7062 /*SharedState=*/nullptr);7063 };7064 }7065};7066 7067TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {7068 TranslationUnitDecl *ToTU = getToTuDecl(7069 R"(7070 extern "C" {7071 class X{};7072 };7073 )",7074 Lang_CXX03);7075 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(7076 ToTU, cxxRecordDecl(hasName("X")));7077 7078 // Set up a stub external storage.7079 ToTU->setHasExternalLexicalStorage(true);7080 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.7081 ToTU->setMustBuildLookupTable();7082 struct TestExternalASTSource : ExternalASTSource {};7083 ToTU->getASTContext().setExternalSource(7084 llvm::makeIntrusiveRefCnt<TestExternalASTSource>());7085 7086 Decl *FromTU = getTuDecl(7087 R"(7088 class X;7089 )",7090 Lang_CXX03);7091 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(7092 FromTU, cxxRecordDecl(hasName("X")));7093 auto *ImportedX = Import(FromX, Lang_CXX03);7094 // The lookup must find the existing class definition in the LinkageSpecDecl.7095 // Then the importer renders the existing and the new decl into one chain.7096 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());7097}7098 7099struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};7100 7101TEST_P(SVEBuiltins, ImportTypes) {7102 static const char *const TypeNames[] = {7103 "__SVInt8_t", "__SVInt16_t", "__SVInt32_t", "__SVInt64_t",7104 "__SVUint8_t", "__SVUint16_t", "__SVUint32_t", "__SVUint64_t",7105 "__SVFloat16_t", "__SVBfloat16_t", "__SVFloat32_t", "__SVFloat64_t",7106 "__SVBool_t"};7107 7108 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX03);7109 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cc");7110 for (auto *TypeName : TypeNames) {7111 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(7112 ToTU, typedefDecl(hasName(TypeName)));7113 QualType ToType = ToTypedef->getUnderlyingType();7114 7115 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(7116 FromTU, typedefDecl(hasName(TypeName)));7117 QualType FromType = FromTypedef->getUnderlyingType();7118 7119 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX03);7120 EXPECT_EQ(ImportedType, ToType);7121 }7122}7123 7124TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {7125 // Test that import of implicit functions works and the functions7126 // are merged into one chain.7127 auto GetDeclToImport = [this](StringRef File) {7128 Decl *FromTU = getTuDecl(7129 R"(7130 struct X { };7131 // Force generating some implicit operator definitions for X.7132 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }7133 )",7134 Lang_CXX11, File);7135 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(7136 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));7137 // Destructor is picked as one example of implicit function.7138 return FromD->getDestructor();7139 };7140 7141 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);7142 ASSERT_TRUE(ToD1);7143 7144 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);7145 ASSERT_TRUE(ToD2);7146 7147 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());7148}7149 7150TEST_P(ASTImporterOptionSpecificTestBase,7151 ImportOfExplicitlyDefaultedOrDeleted) {7152 Decl *FromTU = getTuDecl(7153 R"(7154 struct X { X() = default; X(const X&) = delete; };7155 )",7156 Lang_CXX11);7157 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(7158 FromTU, cxxRecordDecl(hasName("X")));7159 auto *ImportedX = Import(FromX, Lang_CXX11);7160 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(7161 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));7162 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(7163 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));7164 7165 ASSERT_TRUE(ImportedX);7166 EXPECT_TRUE(Constr1->isDefaulted());7167 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());7168 EXPECT_TRUE(Constr2->isDeletedAsWritten());7169 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());7170}7171 7172INSTANTIATE_TEST_SUITE_P(ParameterizedTests, SVEBuiltins,7173 ::testing::Values(std::vector<std::string>{7174 "-target", "aarch64-linux-gnu"}));7175 7176INSTANTIATE_TEST_SUITE_P(ParameterizedTests, DeclContextTest,7177 ::testing::Values(std::vector<std::string>()));7178 7179INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CanonicalRedeclChain,7180 ::testing::Values(std::vector<std::string>()));7181 7182TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {7183 Decl *FromTU = getTuDecl(7184 R"(7185 void f() {7186 auto L0 = [](){};7187 auto L1 = [](){};7188 }7189 )",7190 Lang_CXX11, "input0.cc");7191 auto Pattern = lambdaExpr();7192 CXXRecordDecl *FromL0 =7193 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();7194 CXXRecordDecl *FromL1 =7195 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();7196 ASSERT_NE(FromL0, FromL1);7197 7198 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);7199 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);7200 EXPECT_NE(ToL0, ToL1);7201}7202 7203TEST_P(ASTImporterOptionSpecificTestBase,7204 LambdasInFunctionParamsAreDifferentiated) {7205 Decl *FromTU = getTuDecl(7206 R"(7207 template <typename F0, typename F1>7208 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}7209 )",7210 Lang_CXX11, "input0.cc");7211 auto Pattern = cxxRecordDecl(isLambda());7212 CXXRecordDecl *FromL0 =7213 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);7214 CXXRecordDecl *FromL1 =7215 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);7216 ASSERT_NE(FromL0, FromL1);7217 7218 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);7219 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);7220 ASSERT_NE(ToL0, ToL1);7221}7222 7223TEST_P(ASTImporterOptionSpecificTestBase,7224 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {7225 Decl *FromTU = getTuDecl(7226 R"(7227 #define LAMBDA [](){}7228 template <typename F0, typename F1>7229 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}7230 )",7231 Lang_CXX11, "input0.cc");7232 auto Pattern = cxxRecordDecl(isLambda());7233 CXXRecordDecl *FromL0 =7234 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);7235 CXXRecordDecl *FromL1 =7236 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);7237 ASSERT_NE(FromL0, FromL1);7238 7239 Import(FromL0, Lang_CXX11);7240 Import(FromL1, Lang_CXX11);7241 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);7242 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);7243 ASSERT_NE(ToL0, ToL1);7244}7245 7246TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {7247 Decl *FromTU = getTuDecl(7248 R"(7249 void f() {7250 auto x = []{} = {}; auto x2 = x;7251 }7252 )",7253 Lang_CXX20, "input0.cc");7254 auto FromF = FirstDeclMatcher<FunctionDecl>().match(7255 FromTU, functionDecl(hasName("f")));7256 // We have only one lambda class.7257 ASSERT_EQ(7258 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),7259 1u);7260 7261 FunctionDecl *ToF = Import(FromF, Lang_CXX20);7262 EXPECT_TRUE(ToF);7263 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();7264 // We have only one lambda class after the import.7265 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),7266 1u);7267}7268 7269TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {7270 Decl *FromTU = getTuDecl(7271 R"(7272 void f() {7273 auto x = []{} = {};7274 auto xb = []{} = {};7275 }7276 )",7277 Lang_CXX20, "input0.cc");7278 auto FromF = FirstDeclMatcher<FunctionDecl>().match(7279 FromTU, functionDecl(hasName("f")));7280 // We have two lambda classes.7281 ASSERT_EQ(7282 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),7283 2u);7284 7285 FunctionDecl *ToF = Import(FromF, Lang_CXX20);7286 EXPECT_TRUE(ToF);7287 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();7288 // We have two lambda classes after the import.7289 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),7290 2u);7291}7292 7293TEST_P(ASTImporterOptionSpecificTestBase,7294 ImportFunctionDeclWithTypeSourceInfoWithSourceDecl) {7295 // This code results in a lambda with implicit constructor.7296 // The constructor's TypeSourceInfo points out the function prototype.7297 // This prototype has an EST_Unevaluated in its exception information and a7298 // SourceDecl that is the function declaration itself.7299 // The test verifies that AST import of such AST does not crash.7300 // (Here the function's TypeSourceInfo references the function itself.)7301 Decl *FromTU = getTuDecl(7302 R"(7303 template<typename T> void f(T) { auto X = [](){}; }7304 void g() { f(10); }7305 )",7306 Lang_CXX11, "input0.cc");7307 7308 // Use LastDeclMatcher to find the LambdaExpr in the template specialization.7309 CXXRecordDecl *FromL = LastDeclMatcher<LambdaExpr>()7310 .match(FromTU, lambdaExpr())7311 ->getLambdaClass();7312 7313 CXXConstructorDecl *FromCtor = *FromL->ctor_begin();7314 ASSERT_TRUE(FromCtor->isCopyConstructor());7315 ASSERT_TRUE(FromCtor->getTypeSourceInfo());7316 const auto *FromFPT = FromCtor->getType()->getAs<FunctionProtoType>();7317 ASSERT_TRUE(FromFPT);7318 EXPECT_EQ(FromCtor->getTypeSourceInfo()->getType().getTypePtr(), FromFPT);7319 FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();7320 // If type is EST_Unevaluated, SourceDecl should be set to the parent Decl.7321 EXPECT_EQ(FromEPI.ExceptionSpec.Type, EST_Unevaluated);7322 EXPECT_EQ(FromEPI.ExceptionSpec.SourceDecl, FromCtor);7323 7324 auto ToL = Import(FromL, Lang_CXX11);7325 7326 // Check if the import was correct.7327 CXXConstructorDecl *ToCtor = *ToL->ctor_begin();7328 EXPECT_TRUE(ToCtor->getTypeSourceInfo());7329 const auto *ToFPT = ToCtor->getType()->getAs<FunctionProtoType>();7330 ASSERT_TRUE(ToFPT);7331 EXPECT_EQ(ToCtor->getTypeSourceInfo()->getType().getTypePtr(), ToFPT);7332 FunctionProtoType::ExtProtoInfo ToEPI = ToFPT->getExtProtoInfo();7333 EXPECT_EQ(ToEPI.ExceptionSpec.Type, EST_Unevaluated);7334 EXPECT_EQ(ToEPI.ExceptionSpec.SourceDecl, ToCtor);7335}7336 7337struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {7338 void testImport(llvm::StringRef Code, clang::TestLanguage Lang = Lang_CXX14,7339 bool FindLast = false) {7340 Decl *FromTU = getTuDecl(Code, Lang, "input0.cc");7341 FunctionDecl *From = FindLast ? LastDeclMatcher<FunctionDecl>().match(7342 FromTU, functionDecl(hasName("foo")))7343 : FirstDeclMatcher<FunctionDecl>().match(7344 FromTU, functionDecl(hasName("foo")));7345 7346 FunctionDecl *To = Import(From, Lang);7347 EXPECT_TRUE(To);7348 // We check here only that the type is auto type.7349 // These tests are to verify that no crash happens.7350 // The crash possibility is the presence of a reference to a declaration7351 // in the function's body from the return type, if the function has auto7352 // return type.7353 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));7354 }7355};7356 7357TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate1) {7358 testImport(7359 R"(7360 template<class C>7361 C f1() { return C(); }7362 auto foo() {7363 struct B {};7364 return f1<B>();7365 }7366 )");7367}7368 7369TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate2) {7370 testImport(7371 R"(7372 template<class T>7373 int f1(T t) { return 1; }7374 auto foo() {7375 struct B {};7376 return f1(B());7377 }7378 )");7379}7380 7381TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate3) {7382 testImport(7383 R"(7384 template<class A> struct S1 {};7385 template<class A> struct S2 {};7386 template<class C>7387 S1<C> f1() { return S1<C>(); }7388 auto foo() {7389 struct B {};7390 return f1<S2<B *>>();7391 }7392 )");7393}7394 7395TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate4) {7396 testImport(7397 R"(7398 template<class... A> struct S1 {};7399 template<class... A> struct S2 {};7400 template<class... C>7401 S1<C...> f1() { return S1<C...>(); }7402 auto foo() {7403 struct B {};7404 return f1<S2<int, B *>, bool>();7405 }7406 )");7407}7408 7409TEST_P(ImportAutoFunctions, ReturnWithVarTemplate1) {7410 testImport(7411 R"(7412 template<class T> T X;7413 auto foo() {7414 struct A {};7415 return X<A>;7416 }7417 )");7418}7419 7420TEST_P(ImportAutoFunctions, ReturnWithVarTemplate2) {7421 testImport(7422 R"(7423 template<class A> struct S1 {};7424 template<class T> S1<T> X;7425 auto foo() {7426 struct A {};7427 return X<S1<A>>;7428 }7429 )");7430}7431 7432TEST_P(ImportAutoFunctions, ReturnWithVarTemplate3) {7433 testImport(7434 R"(7435 template<class... A> struct S1 {};7436 template<class... T> S1<T...> X;7437 auto foo() {7438 struct A {};7439 return X<bool, S1<A, int>>;7440 }7441 )");7442}7443 7444TEST_P(ImportAutoFunctions, ReturnWithAutoUnresolvedArg) {7445 testImport(7446 R"(7447 template<int A>7448 auto foo() {7449 return 22;7450 }7451 )");7452}7453 7454TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTemplateTemplateArg) {7455 // FIXME: Is it possible to have the template arg inside the function?7456 testImport(7457 R"(7458 template<int> struct Tmpl {};7459 template<template<int> class> struct TmplTmpl {};7460 auto foo() {7461 return TmplTmpl<Tmpl>();7462 }7463 )");7464}7465 7466TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDeclarationTemplateArg) {7467 // FIXME: Is it possible to have the template arg inside the function?7468 testImport(7469 R"(7470 template<const int *> struct Tmpl {};7471 int A[10];7472 auto foo() {7473 return Tmpl<A>();7474 }7475 )");7476}7477 7478TEST_P(ImportAutoFunctions, ReturnWithTemplateWithNullPtrTemplateArg) {7479 testImport(7480 R"(7481 template<int *> struct Tmpl {};7482 auto foo() {7483 constexpr int* A = nullptr;7484 return Tmpl<A>();7485 }7486 )");7487}7488 7489TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegralTemplateArg) {7490 testImport(7491 R"(7492 template<int> struct Tmpl {};7493 auto foo() {7494 using Int = int;7495 constexpr Int A = 7;7496 return Tmpl<A>();7497 }7498 )");7499}7500 7501TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDecltypeTypeDeclaredInside) {7502 testImport(7503 R"(7504 template<class> struct Tmpl {};7505 auto foo() {7506 struct X {};7507 X x;7508 return Tmpl<decltype(x)>();7509 }7510 )");7511}7512 7513TEST_P(ImportAutoFunctions, ReturnWithTemplateWithUsingTypeDeclaredInside) {7514 testImport(7515 R"(7516 template<class> struct Tmpl {};7517 namespace A { struct X {}; }7518 auto foo() {7519 using A::X;7520 return Tmpl<X>();7521 }7522 )");7523}7524 7525TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArrayTypeDeclaredInside) {7526 testImport(7527 R"(7528 template<class> struct Tmpl {};7529 auto foo() {7530 struct X {};7531 return Tmpl<X[10]>();7532 }7533 )");7534}7535 7536TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArraySizeExprDeclaredInside) {7537 testImport(7538 R"(7539 template<class> struct Tmpl {};7540 auto foo() {7541 constexpr int S = 10;7542 return Tmpl<int[S]>();7543 }7544 )");7545}7546 7547TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPackArgDeclaredInside) {7548 testImport(7549 R"(7550 template<class ...> struct Tmpl {};7551 auto foo() {7552 using X = bool;7553 return Tmpl<int, X>();7554 }7555 )");7556}7557 7558TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegerArgDeclaredInside) {7559 testImport(7560 R"(7561 template<int> struct Tmpl {};7562 auto foo() {7563 constexpr int X = 1;7564 return Tmpl<X>();7565 }7566 )");7567}7568 7569TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPtrToStructDeclaredInside) {7570 testImport(7571 R"(7572 template<class> struct Tmpl {};7573 auto foo() {7574 struct X {};7575 return Tmpl<X *>();7576 }7577 )");7578}7579 7580TEST_P(ImportAutoFunctions, ReturnWithTemplateWithRefToStructDeclaredInside) {7581 testImport(7582 R"(7583 template<class> struct Tmpl {};7584 struct X {};7585 auto foo() {7586 using Y = X;7587 return Tmpl<Y &>();7588 }7589 )");7590}7591 7592TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) {7593 testImport(7594 R"(7595 template<class> struct Tmpl {};7596 auto foo() {7597 struct X {};7598 return Tmpl<X>();7599 }7600 )");7601}7602 7603TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) {7604 testImport(7605 R"(7606 template<class> struct Tmpl {};7607 auto foo() {7608 struct X {};7609 return Tmpl<Tmpl<X>>();7610 }7611 )");7612}7613 7614TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) {7615 testImport(7616 R"(7617 template<class> struct Tmpl {};7618 auto foo() {7619 struct X {};7620 using x_type = X;7621 return Tmpl<x_type>();7622 }7623 )");7624}7625 7626TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {7627 Decl *FromTU = getTuDecl(7628 R"(7629 auto X = [](long l) {7630 using int_type = long;7631 auto dur = 13;7632 return static_cast<int_type>(dur);7633 };7634 )",7635 Lang_CXX14, "input0.cc");7636 CXXMethodDecl *From =7637 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, cxxMethodDecl());7638 7639 // Explicitly set the return type of the lambda's operator() to the TypeAlias.7640 // Normally the return type would be the built-in 'long' type. However, there7641 // are cases when Clang does not use the canonical type and the TypeAlias is7642 // used. I could not create such an AST from regular source code, it requires7643 // some special state in the preprocessor. I've found such an AST when Clang7644 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce7645 // that with creduce, because after preprocessing, the AST no longer7646 // contained the TypeAlias as a return type of the lambda.7647 ASTContext &Ctx = From->getASTContext();7648 TypeAliasDecl *FromTA =7649 FirstDeclMatcher<TypeAliasDecl>().match(FromTU, typeAliasDecl());7650 QualType TT = Ctx.getTypedefType(ElaboratedTypeKeyword::None,7651 /*Qualifier=*/std::nullopt, FromTA);7652 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());7653 QualType NewFunType =7654 Ctx.getFunctionType(TT, FPT->getParamTypes(), FPT->getExtProtoInfo());7655 From->setType(NewFunType);7656 7657 CXXMethodDecl *To = Import(From, Lang_CXX14);7658 EXPECT_TRUE(To);7659 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));7660}7661 7662TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {7663 testImport(7664 R"(7665 auto foo() {7666 struct X {};7667 return X();7668 }7669 )");7670}7671 7672TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {7673 Decl *FromTU = getTuDecl(7674 R"(7675 auto foo() {7676 struct X {};7677 return X();7678 }7679 )",7680 Lang_CXX14, "input0.cc");7681 FunctionDecl *From =7682 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());7683 7684 // This time import the type directly.7685 QualType ToT = ImportType(From->getType(), From, Lang_CXX14);7686 const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);7687 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));7688}7689 7690TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside3) {7691 Decl *FromTU = getTuDecl(7692 R"(7693 struct S {7694 constexpr auto foo();7695 };7696 constexpr auto S::foo() {7697 struct X {};7698 return X();7699 }7700 )",7701 Lang_CXX14, "input0.cc");7702 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(7703 FromTU, functionDecl(hasName("foo"), unless(hasBody(stmt()))));7704 ASSERT_FALSE(From->isThisDeclarationADefinition());7705 7706 FunctionDecl *To = Import(From, Lang_CXX17);7707 EXPECT_TRUE(To);7708 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));7709 EXPECT_FALSE(To->isThisDeclarationADefinition());7710}7711 7712TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {7713 testImport(7714 R"(7715 auto foo() {7716 struct X {};7717 using Y = X;7718 return Y();7719 }7720 )");7721}7722 7723TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {7724 testImport(7725 R"(7726 auto foo() {7727 struct X { struct Y{}; };7728 return X::Y();7729 }7730 )");7731}7732 7733TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {7734 testImport(7735 R"(7736 auto foo() {7737 auto l = []() {7738 struct X {};7739 return X();7740 };7741 return l();7742 }7743 )",7744 Lang_CXX17);7745}7746 7747TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {7748 testImport(7749 R"(7750 auto foo() {7751 if (struct X {} x; true)7752 return X();7753 else7754 return X();7755 }7756 )",7757 Lang_CXX17);7758}7759 7760TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {7761 testImport(7762 R"(7763 auto foo() {7764 for (struct X {} x;;)7765 return X();7766 }7767 )",7768 Lang_CXX17);7769}7770 7771TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {7772 testImport(7773 R"(7774 auto foo() {7775 switch (struct X {} x; 10) {7776 case 10:7777 return X();7778 }7779 }7780 )",7781 Lang_CXX17);7782}7783 7784TEST_P(ImportAutoFunctions, ReturnWithAutoTemplateType) {7785 testImport(7786 R"(7787 template<class T>7788 struct S {};7789 template<class T>7790 auto foo() {7791 return S<T>{};7792 }7793 auto a = foo<int>();7794 )",7795 Lang_CXX14, /*FindLast=*/true);7796}7797 7798TEST_P(ImportAutoFunctions, ReturnWithSubstNonTypeTemplateParmExpr) {7799 const char *Code =7800 R"(7801 template<int>7802 struct array {};7803 7804 template <int N>7805 auto foo() { return array<N>(); }7806 7807 void bar() { foo<0>(); }7808 )";7809 Decl *FromTU = getTuDecl(Code, Lang_CXX17);7810 7811 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(7812 FromTU, functionDecl(hasName("bar")));7813 7814 auto *ToBar = Import(FromBar, Lang_CXX17);7815 EXPECT_TRUE(ToBar);7816}7817 7818TEST_P(ImportAutoFunctions, ReturnWithUnaryTransformType) {7819 const char *Code =7820 R"(7821 enum E { E1 };7822 7823 template<typename T>7824 auto foo(T v) { return static_cast<__underlying_type(T)>(v); }7825 7826 bool bar() { return foo(E1); }7827 )";7828 Decl *FromTU = getTuDecl(Code, Lang_CXX17);7829 7830 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(7831 FromTU, functionDecl(hasName("bar")));7832 7833 auto *ToBar = Import(FromBar, Lang_CXX17);7834 EXPECT_TRUE(ToBar);7835}7836 7837struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};7838 7839TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {7840 // Tests that the FileID tree structure (with the links being the include7841 // chains) is preserved while importing other files (which need to be7842 // added to this structure with fake include locations.7843 7844 SourceLocation Location1;7845 {7846 auto Pattern = varDecl(hasName("X"));7847 Decl *FromTU = getTuDecl("int X;", Lang_C99, "input0.c");7848 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);7849 7850 Location1 = Import(FromD, Lang_C99)->getLocation();7851 }7852 SourceLocation Location2;7853 {7854 auto Pattern = varDecl(hasName("Y"));7855 Decl *FromTU = getTuDecl("int Y;", Lang_C99, "input1.c");7856 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);7857 7858 Location2 = Import(FromD, Lang_C99)->getLocation();7859 }7860 7861 SourceManager &ToSM = ToAST->getSourceManager();7862 FileID FileID1 = ToSM.getFileID(Location1);7863 FileID FileID2 = ToSM.getFileID(Location2);7864 7865 // Check that the imported files look like as if they were included from the7866 // start of the main file.7867 SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID());7868 EXPECT_NE(FileID1, ToSM.getMainFileID());7869 EXPECT_NE(FileID2, ToSM.getMainFileID());7870 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);7871 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);7872 7873 // Let the SourceManager check the order of the locations. The order should7874 // be the order in which the declarations are imported.7875 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));7876 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));7877}7878 7879TEST_P(ImportSourceLocations, NormalFileBuffer) {7880 // Test importing normal file buffers.7881 7882 std::string Path = "input0.c";7883 std::string Source = "int X;";7884 TranslationUnitDecl *FromTU = getTuDecl(Source, Lang_C99, Path);7885 7886 SourceLocation ImportedLoc;7887 {7888 // Import the VarDecl to trigger the importing of the FileID.7889 auto Pattern = varDecl(hasName("X"));7890 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);7891 ImportedLoc = Import(FromD, Lang_C99)->getLocation();7892 }7893 7894 // Make sure the imported buffer has the original contents.7895 SourceManager &ToSM = ToAST->getSourceManager();7896 FileID ImportedID = ToSM.getFileID(ImportedLoc);7897 EXPECT_EQ(Source,7898 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());7899}7900 7901TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {7902 // Test importing overwritten file buffers.7903 7904 std::string Path = "input0.c";7905 TranslationUnitDecl *FromTU = getTuDecl("int X;", Lang_C99, Path);7906 7907 // Overwrite the file buffer for our input file with new content.7908 const std::string Contents = "overwritten contents";7909 SourceLocation ImportedLoc;7910 {7911 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();7912 clang::FileManager &FM = FromSM.getFileManager();7913 clang::FileEntryRef FE =7914 FM.getVirtualFileRef(Path, static_cast<off_t>(Contents.size()), 0);7915 7916 llvm::SmallVector<char, 64> Buffer;7917 Buffer.append(Contents.begin(), Contents.end());7918 auto FileContents = std::make_unique<llvm::SmallVectorMemoryBuffer>(7919 std::move(Buffer), Path, /*RequiresNullTerminator=*/false);7920 FromSM.overrideFileContents(FE, std::move(FileContents));7921 7922 // Import the VarDecl to trigger the importing of the FileID.7923 auto Pattern = varDecl(hasName("X"));7924 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);7925 ImportedLoc = Import(FromD, Lang_C99)->getLocation();7926 }7927 7928 // Make sure the imported buffer has the overwritten contents.7929 SourceManager &ToSM = ToAST->getSourceManager();7930 FileID ImportedID = ToSM.getFileID(ImportedLoc);7931 EXPECT_EQ(Contents,7932 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());7933}7934 7935struct ImportAttributes : public ASTImporterOptionSpecificTestBase {7936 void checkAttrImportCommon(const Attr *From, const Attr *To,7937 const Decl *ToD) {7938 7939 // Verify that dump does not crash because invalid data.7940 ToD->dump(llvm::nulls());7941 7942 EXPECT_EQ(From->getParsedKind(), To->getParsedKind());7943 EXPECT_EQ(From->getSyntax(), To->getSyntax());7944 if (From->getAttrName()) {7945 EXPECT_TRUE(To->getAttrName());7946 EXPECT_STREQ(From->getAttrName()->getNameStart(),7947 To->getAttrName()->getNameStart());7948 } else {7949 EXPECT_FALSE(To->getAttrName());7950 }7951 if (From->getScopeName()) {7952 EXPECT_TRUE(To->getScopeName());7953 EXPECT_STREQ(From->getScopeName()->getNameStart(),7954 To->getScopeName()->getNameStart());7955 } else {7956 EXPECT_FALSE(To->getScopeName());7957 }7958 EXPECT_EQ(From->getSpellingListIndex(), To->getSpellingListIndex());7959 EXPECT_STREQ(From->getSpelling(), To->getSpelling());7960 EXPECT_EQ(From->isInherited(), To->isInherited());7961 EXPECT_EQ(From->isImplicit(), To->isImplicit());7962 EXPECT_EQ(From->isPackExpansion(), To->isPackExpansion());7963 EXPECT_EQ(From->isLateParsed(), To->isLateParsed());7964 }7965 7966 template <class DT, class AT>7967 void importAttr(const char *Code, AT *&FromAttr, AT *&ToAttr,7968 TestLanguage Lang = Lang_CXX11) {7969 static_assert(std::is_base_of<Attr, AT>::value, "AT should be an Attr");7970 static_assert(std::is_base_of<Decl, DT>::value, "DT should be a Decl");7971 7972 Decl *FromTU = getTuDecl(Code, Lang, "input.cc");7973 DT *FromD =7974 FirstDeclMatcher<DT>().match(FromTU, namedDecl(hasName("test")));7975 ASSERT_TRUE(FromD);7976 7977 DT *ToD = Import(FromD, Lang_CXX11);7978 ASSERT_TRUE(ToD);7979 7980 FromAttr = FromD->template getAttr<AT>();7981 ToAttr = ToD->template getAttr<AT>();7982 ASSERT_TRUE(FromAttr);7983 EXPECT_TRUE(ToAttr);7984 7985 checkAttrImportCommon(FromAttr, ToAttr, ToD);7986 }7987 7988 template <class T> void checkImported(const T *From, const T *To) {7989 EXPECT_TRUE(To);7990 EXPECT_NE(From, To);7991 }7992 7993 template <class T>7994 void checkImportVariadicArg(const llvm::iterator_range<T **> &From,7995 const llvm::iterator_range<T **> &To) {7996 for (auto FromI = From.begin(), ToI = To.begin(); FromI != From.end();7997 ++FromI, ++ToI) {7998 ASSERT_NE(ToI, To.end());7999 checkImported(*FromI, *ToI);8000 }8001 }8002};8003 8004template <>8005void ImportAttributes::checkImported<Decl>(const Decl *From, const Decl *To) {8006 EXPECT_TRUE(To);8007 EXPECT_NE(From, To);8008 EXPECT_EQ(To->getTranslationUnitDecl(),8009 ToAST->getASTContext().getTranslationUnitDecl());8010}8011 8012TEST_P(ImportAttributes, ImportAligned) {8013 AlignedAttr *FromAttr, *ToAttr;8014 importAttr<RecordDecl>(8015 R"(8016 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };8017 struct alignas(alignof(A)) test {};8018 )",8019 FromAttr, ToAttr);8020 checkImported(FromAttr->getAlignmentExpr(), ToAttr->getAlignmentExpr());8021 8022 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(8023 ToAST->getASTContext().getTranslationUnitDecl(),8024 cxxRecordDecl(hasName("A"), unless(isImplicit())));8025 // Ensure that 'struct A' was imported (through reference from attribute of8026 // struct 'test').8027 EXPECT_TRUE(ToA);8028}8029 8030TEST_P(ImportAttributes, ImportAlignValue) {8031 AlignValueAttr *FromAttr, *ToAttr;8032 importAttr<VarDecl>(8033 R"(8034 void *test __attribute__((align_value(64)));8035 )",8036 FromAttr, ToAttr);8037 checkImported(FromAttr->getAlignment(), ToAttr->getAlignment());8038}8039 8040TEST_P(ImportAttributes, ImportFormat) {8041 FormatAttr *FromAttr, *ToAttr;8042 importAttr<FunctionDecl>(8043 R"(8044 int test(const char * fmt, ...)8045 __attribute__ ((__format__ (__scanf__, 1, 2)));8046 )",8047 FromAttr, ToAttr);8048 8049 EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());8050 EXPECT_EQ(FromAttr->getFirstArg(), ToAttr->getFirstArg());8051 EXPECT_EQ(FromAttr->getFormatIdx(), ToAttr->getFormatIdx());8052}8053 8054TEST_P(ImportAttributes, ImportEnableIf) {8055 EnableIfAttr *FromAttr, *ToAttr;8056 importAttr<FunctionDecl>(8057 "void test(int A) __attribute__((enable_if(A == 1, \"message\")));",8058 FromAttr, ToAttr);8059 checkImported(FromAttr->getCond(), ToAttr->getCond());8060 EXPECT_EQ(FromAttr->getMessage(), ToAttr->getMessage());8061}8062 8063TEST_P(ImportAttributes, ImportGuardedVar) {8064 GuardedVarAttr *FromAttr, *ToAttr;8065 importAttr<VarDecl>("int test __attribute__((guarded_var));", FromAttr,8066 ToAttr);8067}8068 8069TEST_P(ImportAttributes, ImportPtGuardedVar) {8070 PtGuardedVarAttr *FromAttr, *ToAttr;8071 importAttr<VarDecl>("int *test __attribute__((pt_guarded_var));", FromAttr,8072 ToAttr);8073}8074 8075TEST_P(ImportAttributes, ImportScopedLockable) {8076 ScopedLockableAttr *FromAttr, *ToAttr;8077 importAttr<CXXRecordDecl>("struct __attribute__((scoped_lockable)) test {};",8078 FromAttr, ToAttr);8079}8080 8081TEST_P(ImportAttributes, ImportCapability) {8082 CapabilityAttr *FromAttr, *ToAttr;8083 importAttr<CXXRecordDecl>(8084 "struct __attribute__((capability(\"cap\"))) test {};", FromAttr, ToAttr);8085 EXPECT_EQ(FromAttr->getName(), ToAttr->getName());8086}8087 8088TEST_P(ImportAttributes, ImportAssertCapability) {8089 AssertCapabilityAttr *FromAttr, *ToAttr;8090 importAttr<FunctionDecl>(8091 "void test(int A1, int A2) __attribute__((assert_capability(A1, A2)));",8092 FromAttr, ToAttr);8093 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8094}8095 8096TEST_P(ImportAttributes, ImportAcquireCapability) {8097 AcquireCapabilityAttr *FromAttr, *ToAttr;8098 importAttr<FunctionDecl>(8099 "void test(int A1, int A2) __attribute__((acquire_capability(A1, A2)));",8100 FromAttr, ToAttr);8101 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8102}8103 8104TEST_P(ImportAttributes, ImportTryAcquireCapability) {8105 TryAcquireCapabilityAttr *FromAttr, *ToAttr;8106 importAttr<FunctionDecl>(8107 "void test(int A1, int A2) __attribute__((try_acquire_capability(1, A1, "8108 "A2)));",8109 FromAttr, ToAttr);8110 checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());8111 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8112}8113 8114TEST_P(ImportAttributes, ImportReleaseCapability) {8115 ReleaseCapabilityAttr *FromAttr, *ToAttr;8116 importAttr<FunctionDecl>(8117 "void test(int A1, int A2) __attribute__((release_capability(A1, A2)));",8118 FromAttr, ToAttr);8119 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8120}8121 8122TEST_P(ImportAttributes, ImportRequiresCapability) {8123 RequiresCapabilityAttr *FromAttr, *ToAttr;8124 importAttr<FunctionDecl>(8125 "void test(int A1, int A2) __attribute__((requires_capability(A1, A2)));",8126 FromAttr, ToAttr);8127 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8128}8129 8130TEST_P(ImportAttributes, ImportNoThreadSafetyAnalysis) {8131 NoThreadSafetyAnalysisAttr *FromAttr, *ToAttr;8132 importAttr<FunctionDecl>(8133 "void test() __attribute__((no_thread_safety_analysis));", FromAttr,8134 ToAttr);8135}8136 8137TEST_P(ImportAttributes, ImportGuardedBy) {8138 GuardedByAttr *FromAttr, *ToAttr;8139 importAttr<VarDecl>(8140 R"(8141 int G;8142 int test __attribute__((guarded_by(G)));8143 )",8144 FromAttr, ToAttr);8145 checkImported(FromAttr->getArg(), ToAttr->getArg());8146}8147 8148TEST_P(ImportAttributes, ImportPtGuardedBy) {8149 PtGuardedByAttr *FromAttr, *ToAttr;8150 importAttr<VarDecl>(8151 R"(8152 int G;8153 int *test __attribute__((pt_guarded_by(G)));8154 )",8155 FromAttr, ToAttr);8156 checkImported(FromAttr->getArg(), ToAttr->getArg());8157}8158 8159TEST_P(ImportAttributes, ImportAcquiredAfter) {8160 AcquiredAfterAttr *FromAttr, *ToAttr;8161 importAttr<VarDecl>(8162 R"(8163 struct __attribute__((lockable)) L {};8164 L A1;8165 L A2;8166 L test __attribute__((acquired_after(A1, A2)));8167 )",8168 FromAttr, ToAttr);8169 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8170}8171 8172TEST_P(ImportAttributes, ImportAcquiredBefore) {8173 AcquiredBeforeAttr *FromAttr, *ToAttr;8174 importAttr<VarDecl>(8175 R"(8176 struct __attribute__((lockable)) L {};8177 L A1;8178 L A2;8179 L test __attribute__((acquired_before(A1, A2)));8180 )",8181 FromAttr, ToAttr);8182 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8183}8184 8185TEST_P(ImportAttributes, ImportLockReturned) {8186 LockReturnedAttr *FromAttr, *ToAttr;8187 importAttr<FunctionDecl>(8188 "void test(int A1) __attribute__((lock_returned(A1)));", FromAttr,8189 ToAttr);8190 checkImported(FromAttr->getArg(), ToAttr->getArg());8191}8192 8193TEST_P(ImportAttributes, ImportLocksExcluded) {8194 LocksExcludedAttr *FromAttr, *ToAttr;8195 importAttr<FunctionDecl>(8196 "void test(int A1, int A2) __attribute__((locks_excluded(A1, A2)));",8197 FromAttr, ToAttr);8198 checkImportVariadicArg(FromAttr->args(), ToAttr->args());8199}8200 8201TEST_P(ImportAttributes, ImportReentrantCapability) {8202 ReentrantCapabilityAttr *FromAttr, *ToAttr;8203 importAttr<CXXRecordDecl>(8204 R"(8205 struct __attribute__((capability("x"), reentrant_capability)) test {};8206 )",8207 FromAttr, ToAttr);8208}8209 8210TEST_P(ImportAttributes, ImportC99NoThrowAttr) {8211 NoThrowAttr *FromAttr, *ToAttr;8212 importAttr<FunctionDecl>("void test () __attribute__ ((__nothrow__));",8213 FromAttr, ToAttr, Lang_C99);8214 checkImported(FromAttr->getAttrName(), ToAttr->getAttrName());8215}8216 8217template <typename T>8218auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {8219 auto Copy = Values;8220 for (std::vector<std::string> &ArgV : Copy) {8221 for (const std::string &Arg : Args) {8222 ArgV.push_back(Arg);8223 }8224 }8225 return ::testing::ValuesIn(Copy);8226}8227 8228struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {8229 ImportWithExternalSource() {8230 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,8231 ASTContext &FromContext, FileManager &FromFileManager,8232 bool MinimalImport,8233 const std::shared_ptr<ASTImporterSharedState> &SharedState) {8234 return new ASTImporter(ToContext, ToFileManager, FromContext,8235 // Use minimal import for these tests.8236 FromFileManager, /*MinimalImport=*/true,8237 // We use the regular lookup.8238 /*SharedState=*/nullptr);8239 };8240 }8241};8242 8243/// An ExternalASTSource that keeps track of the tags is completed.8244struct SourceWithCompletedTagList : clang::ExternalASTSource {8245 std::vector<clang::TagDecl *> &CompletedTags;8246 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)8247 : CompletedTags(CompletedTags) {}8248 void CompleteType(TagDecl *Tag) override {8249 auto *Record = cast<CXXRecordDecl>(Tag);8250 Record->startDefinition();8251 Record->completeDefinition();8252 CompletedTags.push_back(Tag);8253 }8254 using clang::ExternalASTSource::CompleteType;8255};8256 8257TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {8258 // Create an empty TU.8259 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX03, "input.cpp");8260 8261 // Create and add the test ExternalASTSource.8262 std::vector<clang::TagDecl *> CompletedTags;8263 auto source =8264 llvm::makeIntrusiveRefCnt<SourceWithCompletedTagList>(CompletedTags);8265 clang::ASTContext &Context = FromTU->getASTContext();8266 Context.setExternalSource(std::move(source));8267 8268 // Create a dummy class by hand with external lexical storage.8269 IdentifierInfo &Ident = Context.Idents.get("test_class");8270 auto *Record =8271 CXXRecordDecl::Create(Context, TagTypeKind::Class, FromTU,8272 SourceLocation(), SourceLocation(), &Ident);8273 Record->setHasExternalLexicalStorage();8274 FromTU->addDecl(Record);8275 8276 // Do a minimal import of the created class.8277 EXPECT_EQ(0U, CompletedTags.size());8278 Import(Record, Lang_CXX03);8279 EXPECT_EQ(0U, CompletedTags.size());8280 8281 // Import the definition of the created class.8282 llvm::Error Err = findFromTU(Record)->Importer->ImportDefinition(Record);8283 EXPECT_FALSE((bool)Err);8284 consumeError(std::move(Err));8285 8286 // Make sure the class was completed once.8287 EXPECT_EQ(1U, CompletedTags.size());8288 EXPECT_EQ(Record, CompletedTags.front());8289}8290 8291TEST_P(ImportFunctions, CTADImplicit) {8292 Decl *FromTU = getTuDecl(8293 R"(8294 template <typename T> struct A {8295 A(T);8296 };8297 A a{(int)0};8298 )",8299 Lang_CXX17, "input.cc");8300 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8301 FromTU,8302 cxxDeductionGuideDecl(hasParameter(0, hasType(asString("A<T>")))));8303 auto *ToD = Import(FromD, Lang_CXX17);8304 ASSERT_TRUE(ToD);8305 EXPECT_EQ(ToD->getDeductionCandidateKind(), DeductionCandidate::Copy);8306 EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);8307 EXPECT_EQ(ToD->getSourceDeductionGuideKind(),8308 CXXDeductionGuideDecl::SourceDeductionGuideKind::None);8309 // Check that the deduced class template is also imported.8310 EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(8311 FromD->getDeducedTemplate()));8312}8313 8314TEST_P(ImportFunctions, CTADUserDefinedExplicit) {8315 Decl *FromTU = getTuDecl(8316 R"(8317 template <typename T> struct A {8318 A(T);8319 };8320 template <typename T> explicit A(T) -> A<float>;8321 A a{(int)0}; // calls A<float>::A(float)8322 )",8323 Lang_CXX17, "input.cc");8324 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8325 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));8326 // Not-implicit: i.e. not compiler-generated, user defined.8327 ASSERT_FALSE(FromD->isImplicit());8328 ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.8329 auto *ToD = Import(FromD, Lang_CXX17);8330 ASSERT_TRUE(ToD);8331 EXPECT_FALSE(FromD->isImplicit());8332 EXPECT_TRUE(ToD->isExplicit());8333 EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);8334 EXPECT_EQ(ToD->getSourceDeductionGuideKind(),8335 CXXDeductionGuideDecl::SourceDeductionGuideKind::None);8336}8337 8338TEST_P(ImportFunctions, CTADWithLocalTypedef) {8339 Decl *TU = getTuDecl(8340 R"(8341 template <typename T> struct A {8342 typedef T U;8343 A(U);8344 };8345 A a{(int)0};8346 )",8347 Lang_CXX17, "input.cc");8348 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8349 TU, cxxDeductionGuideDecl());8350 auto *ToD = Import(FromD, Lang_CXX17);8351 ASSERT_TRUE(ToD);8352}8353 8354TEST_P(ImportFunctions, CTADAliasTemplate) {8355 Decl *TU = getTuDecl(8356 R"(8357 template <typename T> struct A {8358 A(T);8359 };8360 template<typename T>8361 using B = A<T>;8362 B b{(int)0};8363 )",8364 Lang_CXX20, "input.cc");8365 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8366 TU, cxxDeductionGuideDecl(hasParameter(0, hasType(asString("int")))));8367 auto *ToD = Import(FromD, Lang_CXX20);8368 ASSERT_TRUE(ToD);8369 EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==8370 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);8371 EXPECT_TRUE(ToD->getSourceDeductionGuide());8372}8373 8374TEST_P(ImportFunctions, CTADAliasTemplateWithExplicitSourceDeductionGuide) {8375 Decl *TU = getTuDecl(8376 R"(8377 template <typename T> struct A {8378 A(T);8379 };8380 template<typename T>8381 using B = A<T>;8382 A(int) -> A<double>; // explicit8383 B b{(int)0};8384 )",8385 Lang_CXX20, "input.cc");8386 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8387 TU, cxxDeductionGuideDecl(hasParameter(0, hasType(asString("int"))),8388 hasName("<deduction guide for B>"),8389 hasReturnTypeLoc(loc(asString("A<double>")))));8390 auto *ToD = Import(FromD, Lang_CXX20);8391 ASSERT_TRUE(ToD);8392 EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==8393 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);8394 EXPECT_TRUE(ToD->getSourceDeductionGuide());8395}8396 8397TEST_P(ImportFunctions, ParmVarDeclDeclContext) {8398 constexpr auto FromTUCode = R"(8399 void f(int P);8400 )";8401 Decl *FromTU = getTuDecl(FromTUCode, Lang_CXX11);8402 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(8403 FromTU, functionDecl(hasName("f")));8404 ASSERT_TRUE(FromF);8405 8406 auto *ImportedF = Import(FromF, Lang_CXX11);8407 EXPECT_TRUE(ImportedF);8408 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(8409 ImportedF, ImportedF->getParamDecl(0)));8410}8411 8412// FIXME Move these tests out of ASTImporterTest. For that we need to factor8413// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase8414// into a new test Fixture. Then we should lift up this Fixture to its own8415// implementation file and only then could we reuse the Fixture in other AST8416// unitttests.8417struct CTAD : ASTImporterOptionSpecificTestBase {};8418 8419TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {8420 Decl *TU = getTuDecl(8421 R"(8422 typedef int U;8423 template <typename T> struct A {8424 A(U, T);8425 };8426 A a{(int)0, (int)0};8427 )",8428 Lang_CXX17, "input.cc");8429 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8430 TU, cxxDeductionGuideDecl());8431 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(8432 TU, typedefNameDecl(hasName("U")));8433 ParmVarDecl *Param = Guide->getParamDecl(0);8434 // The type of the first param (which is a typedef) should match the typedef8435 // in the global scope.8436 EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);8437}8438 8439TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {8440 Decl *TU = getTuDecl(8441 R"(8442 typedef int U;8443 template <typename T> struct A {8444 A(U*, T);8445 };8446 A a{(int*)0, (int)0};8447 )",8448 Lang_CXX17, "input.cc");8449 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8450 TU, cxxDeductionGuideDecl());8451 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(8452 TU, typedefNameDecl(hasName("U")));8453 ParmVarDecl *Param = Guide->getParamDecl(0);8454 EXPECT_EQ(Param->getType()8455 ->getAs<PointerType>()8456 ->getPointeeType()8457 ->getAs<TypedefType>()8458 ->getDecl(),8459 Typedef);8460}8461 8462TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {8463 Decl *TU = getTuDecl(8464 R"(8465 template <typename T> struct A {8466 typedef T U;8467 A(U, T);8468 };8469 A a{(int)0, (int)0};8470 )",8471 Lang_CXX17, "input.cc");8472 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8473 TU, cxxDeductionGuideDecl());8474 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(8475 TU, typedefNameDecl(hasName("U")));8476 ParmVarDecl *Param = Guide->getParamDecl(0);8477 EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);8478}8479 8480INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CTAD,8481 DefaultTestValuesForRunOptions);8482 8483TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) {8484 Decl *TU = getTuDecl(8485 R"(8486 namespace N {8487 typedef int X __attribute__((annotate("A")));8488 }8489 )",8490 Lang_CXX17, "input.cc");8491 auto *FromD =8492 FirstDeclMatcher<TypedefDecl>().match(TU, typedefDecl(hasName("X")));8493 auto *ToD = Import(FromD, Lang_CXX17);8494 ASSERT_TRUE(ToD);8495 ASSERT_EQ(ToD->getAttrs().size(), 1U);8496 auto *ToAttr = dyn_cast<AnnotateAttr>(ToD->getAttrs()[0]);8497 ASSERT_TRUE(ToAttr);8498 EXPECT_EQ(ToAttr->getAnnotation(), "A");8499}8500 8501TEST_P(ASTImporterOptionSpecificTestBase,8502 ImportOfTemplatedDeclWhenPreviousDeclHasNoDescribedTemplateSet) {8503 Decl *FromTU = getTuDecl(8504 R"(8505 8506 namespace std {8507 template<typename T>8508 class basic_stringbuf;8509 }8510 namespace std {8511 class char_traits;8512 template<typename T = char_traits>8513 class basic_stringbuf;8514 }8515 namespace std {8516 template<typename T>8517 class basic_stringbuf {};8518 }8519 8520 )",8521 Lang_CXX11);8522 8523 auto *From1 = FirstDeclMatcher<ClassTemplateDecl>().match(8524 FromTU,8525 classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));8526 auto *To1 = cast_or_null<ClassTemplateDecl>(Import(From1, Lang_CXX11));8527 EXPECT_TRUE(To1);8528 8529 auto *From2 = LastDeclMatcher<ClassTemplateDecl>().match(8530 FromTU,8531 classTemplateDecl(hasName("basic_stringbuf"), unless(isImplicit())));8532 auto *To2 = cast_or_null<ClassTemplateDecl>(Import(From2, Lang_CXX11));8533 EXPECT_TRUE(To2);8534}8535 8536TEST_P(ASTImporterOptionSpecificTestBase, ImportOfCapturedVLAType) {8537 Decl *FromTU = getTuDecl(8538 R"(8539 void declToImport(int N) {8540 int VLA[N];8541 [&VLA] {}; // FieldDecl inside the lambda.8542 }8543 )",8544 Lang_CXX14);8545 auto *FromFD = FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl());8546 ASSERT_TRUE(FromFD);8547 ASSERT_TRUE(FromFD->hasCapturedVLAType());8548 8549 auto *ToFD = Import(FromFD, Lang_CXX14);8550 EXPECT_TRUE(ToFD);8551 EXPECT_TRUE(ToFD->hasCapturedVLAType());8552 EXPECT_NE(FromFD->getCapturedVLAType(), ToFD->getCapturedVLAType());8553}8554 8555TEST_P(ASTImporterOptionSpecificTestBase, ImportEnumMemberSpecialization) {8556 Decl *FromTU = getTuDecl(8557 R"(8558 template <class T> struct A {8559 enum tagname { enumerator };8560 };8561 template struct A<int>;8562 )",8563 Lang_CXX03);8564 auto *FromD = FirstDeclMatcher<EnumDecl>().match(8565 FromTU, enumDecl(hasName("tagname"),8566 hasParent(classTemplateSpecializationDecl())));8567 ASSERT_TRUE(FromD);8568 ASSERT_TRUE(FromD->getMemberSpecializationInfo());8569 8570 auto *ToD = Import(FromD, Lang_CXX03);8571 EXPECT_TRUE(ToD);8572 EXPECT_TRUE(ToD->getMemberSpecializationInfo());8573 EXPECT_EQ(FromD->getTemplateSpecializationKind(),8574 ToD->getTemplateSpecializationKind());8575}8576 8577TEST_P(ASTImporterOptionSpecificTestBase, ImportIsInheritingConstructorBit) {8578 Decl *FromTU = getTuDecl(8579 R"(8580 struct A {8581 A(int);8582 };8583 struct B : A {8584 using A::A; // Inherited ctor.8585 };8586 void f() {8587 (B(0));8588 }8589 )",8590 Lang_CXX11);8591 auto *FromD = FirstDeclMatcher<CXXConstructorDecl>().match(8592 FromTU, cxxConstructorDecl(isInheritingConstructor()));8593 ASSERT_TRUE(FromD);8594 ASSERT_TRUE(FromD->isInheritingConstructor());8595 8596 auto *ToD = Import(FromD, Lang_CXX11);8597 ASSERT_TRUE(ToD);8598 EXPECT_TRUE(ToD->isInheritingConstructor());8599}8600 8601TEST_P(ASTImporterOptionSpecificTestBase, ImportConstructorUsingShadow) {8602 TranslationUnitDecl *FromTU = getTuDecl(8603 R"(8604 struct A {8605 A(int, int);8606 };8607 struct B : A {8608 using A::A;8609 };8610 struct C : B {8611 using B::B;8612 };8613 )",8614 Lang_CXX11);8615 8616 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordC) {8617 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(8618 TU, cxxRecordDecl(hasName("A")));8619 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(8620 TU, cxxRecordDecl(hasName("B")));8621 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(8622 TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),8623 parameterCountIs(2)));8624 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(8625 FirstDeclMatcher<UsingShadowDecl>().match(8626 TU, usingShadowDecl(hasParent(equalsNode(RecordB)),8627 hasTargetDecl(equalsNode(ConstrA)))));8628 auto *ShadowCA = cast<ConstructorUsingShadowDecl>(8629 FirstDeclMatcher<UsingShadowDecl>().match(8630 TU, usingShadowDecl(hasParent(equalsNode(RecordC)),8631 hasTargetDecl(equalsNode(ConstrA)))));8632 EXPECT_EQ(ShadowBA->getTargetDecl(), ConstrA);8633 EXPECT_EQ(ShadowBA->getNominatedBaseClass(), RecordA);8634 EXPECT_EQ(ShadowBA->getConstructedBaseClass(), RecordA);8635 EXPECT_EQ(ShadowBA->getNominatedBaseClassShadowDecl(), nullptr);8636 EXPECT_EQ(ShadowBA->getConstructedBaseClassShadowDecl(), nullptr);8637 EXPECT_FALSE(ShadowBA->constructsVirtualBase());8638 EXPECT_EQ(ShadowCA->getTargetDecl(), ConstrA);8639 EXPECT_EQ(ShadowCA->getNominatedBaseClass(), RecordB);8640 EXPECT_EQ(ShadowCA->getConstructedBaseClass(), RecordB);8641 EXPECT_EQ(ShadowCA->getNominatedBaseClassShadowDecl(), ShadowBA);8642 EXPECT_EQ(ShadowCA->getConstructedBaseClassShadowDecl(), ShadowBA);8643 EXPECT_FALSE(ShadowCA->constructsVirtualBase());8644 };8645 8646 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(8647 FromTU, cxxRecordDecl(hasName("C")));8648 8649 auto *ToC = Import(FromC, Lang_CXX11);8650 TranslationUnitDecl *ToTU = ToC->getTranslationUnitDecl();8651 8652 CheckAST(FromTU, FromC);8653 CheckAST(ToTU, ToC);8654}8655 8656TEST_P(ASTImporterOptionSpecificTestBase,8657 ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {8658 Decl *From, *To;8659 std::tie(From, To) = getImportedDecl(8660 R"s(8661 struct A {8662 A() : m() {}8663 int m;8664 };8665 8666 A foo() { A a; return a; }8667 A bar() { return {}; }8668 )s",8669 Lang_CXX17,8670 R"s(8671 struct A {8672 A() : m() {}8673 int m;8674 };8675 A baz() { return {}; }8676 )s",8677 Lang_CXX17, "A");8678 8679 auto HasCtorInit =8680 hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));8681 auto ImpMoveCtor =8682 cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);8683 8684 auto *FromImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(8685 From, ImpMoveCtor);8686 auto *ToImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(8687 To, ImpMoveCtor);8688 8689 EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);8690 EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());8691 8692 EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);8693 EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());8694 EXPECT_TRUE(*ToImpMoveCtor->init_begin());8695}8696 8697AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher<NamedDecl>,8698 InnerMatcher) {8699 return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);8700}8701 8702TEST_P(ASTImporterOptionSpecificTestBase,8703 ImportConstructorUsingShadowVirtualBase) {8704 TranslationUnitDecl *FromTU = getTuDecl(8705 R"(8706 struct A { A(int, int); };8707 struct B : A { using A::A; };8708 8709 struct V1 : virtual B { using B::B; };8710 struct V2 : virtual B { using B::B; };8711 8712 struct D2 : V1, V2 {8713 using V1::V1;8714 using V2::V2;8715 };8716 )",8717 Lang_CXX11);8718 8719 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordD2) {8720 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(8721 TU, cxxRecordDecl(hasName("A")));8722 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(8723 TU, cxxRecordDecl(hasName("B")));8724 auto *RecordV1 = FirstDeclMatcher<CXXRecordDecl>().match(8725 TU, cxxRecordDecl(hasName("V1")));8726 auto *RecordV2 = FirstDeclMatcher<CXXRecordDecl>().match(8727 TU, cxxRecordDecl(hasName("V2")));8728 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(8729 TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),8730 parameterCountIs(2)));8731 auto *ConstrB = FirstDeclMatcher<CXXConstructorDecl>().match(8732 TU, cxxConstructorDecl(hasParent(equalsNode(RecordB)),8733 isCopyConstructor()));8734 auto *UsingD2V1 = FirstDeclMatcher<UsingDecl>().match(8735 TU, usingDecl(hasParent(equalsNode(RecordD2))));8736 auto *UsingD2V2 = LastDeclMatcher<UsingDecl>().match(8737 TU, usingDecl(hasParent(equalsNode(RecordD2))));8738 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(8739 FirstDeclMatcher<UsingShadowDecl>().match(8740 TU, usingShadowDecl(hasParent(equalsNode(RecordB)),8741 hasTargetDecl(equalsNode(ConstrA)))));8742 auto *ShadowV1A = cast<ConstructorUsingShadowDecl>(8743 FirstDeclMatcher<UsingShadowDecl>().match(8744 TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),8745 hasTargetDecl(equalsNode(ConstrA)))));8746 auto *ShadowV1B = cast<ConstructorUsingShadowDecl>(8747 FirstDeclMatcher<UsingShadowDecl>().match(8748 TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),8749 hasTargetDecl(equalsNode(ConstrB)))));8750 auto *ShadowV2A = cast<ConstructorUsingShadowDecl>(8751 FirstDeclMatcher<UsingShadowDecl>().match(8752 TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),8753 hasTargetDecl(equalsNode(ConstrA)))));8754 auto *ShadowV2B = cast<ConstructorUsingShadowDecl>(8755 FirstDeclMatcher<UsingShadowDecl>().match(8756 TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),8757 hasTargetDecl(equalsNode(ConstrB)))));8758 auto *ShadowD2V1A = cast<ConstructorUsingShadowDecl>(8759 FirstDeclMatcher<UsingShadowDecl>().match(8760 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),8761 hasIntroducerDecl(equalsNode(UsingD2V1)),8762 hasTargetDecl(equalsNode(ConstrA)))));8763 auto *ShadowD2V1B = cast<ConstructorUsingShadowDecl>(8764 FirstDeclMatcher<UsingShadowDecl>().match(8765 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),8766 hasIntroducerDecl(equalsNode(UsingD2V1)),8767 hasTargetDecl(equalsNode(ConstrB)))));8768 auto *ShadowD2V2A = cast<ConstructorUsingShadowDecl>(8769 FirstDeclMatcher<UsingShadowDecl>().match(8770 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),8771 hasIntroducerDecl(equalsNode(UsingD2V2)),8772 hasTargetDecl(equalsNode(ConstrA)))));8773 auto *ShadowD2V2B = cast<ConstructorUsingShadowDecl>(8774 FirstDeclMatcher<UsingShadowDecl>().match(8775 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),8776 hasIntroducerDecl(equalsNode(UsingD2V2)),8777 hasTargetDecl(equalsNode(ConstrB)))));8778 8779 EXPECT_EQ(ShadowD2V1A->getTargetDecl(), ConstrA);8780 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClassShadowDecl(), ShadowV1A);8781 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClass(), RecordV1);8782 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClassShadowDecl(), ShadowBA);8783 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClass(), RecordB);8784 EXPECT_TRUE(ShadowD2V1A->constructsVirtualBase());8785 EXPECT_EQ(ShadowD2V1B->getTargetDecl(), ConstrB);8786 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClassShadowDecl(), ShadowV1B);8787 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClass(), RecordV1);8788 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClassShadowDecl(), nullptr);8789 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClass(), RecordB);8790 EXPECT_TRUE(ShadowD2V1B->constructsVirtualBase());8791 EXPECT_EQ(ShadowD2V2A->getTargetDecl(), ConstrA);8792 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClassShadowDecl(), ShadowV2A);8793 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClass(), RecordV2);8794 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClassShadowDecl(), ShadowBA);8795 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClass(), RecordB);8796 EXPECT_TRUE(ShadowD2V2A->constructsVirtualBase());8797 EXPECT_EQ(ShadowD2V2B->getTargetDecl(), ConstrB);8798 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClassShadowDecl(), ShadowV2B);8799 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClass(), RecordV2);8800 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClassShadowDecl(), nullptr);8801 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClass(), RecordB);8802 EXPECT_TRUE(ShadowD2V2B->constructsVirtualBase());8803 8804 EXPECT_TRUE(ShadowV1A->constructsVirtualBase());8805 EXPECT_TRUE(ShadowV1B->constructsVirtualBase());8806 EXPECT_TRUE(ShadowV2A->constructsVirtualBase());8807 EXPECT_TRUE(ShadowV2B->constructsVirtualBase());8808 EXPECT_FALSE(ShadowBA->constructsVirtualBase());8809 };8810 8811 auto *FromD2 = FirstDeclMatcher<CXXRecordDecl>().match(8812 FromTU, cxxRecordDecl(hasName("D2")));8813 8814 auto *ToD2 = Import(FromD2, Lang_CXX11);8815 TranslationUnitDecl *ToTU = ToD2->getTranslationUnitDecl();8816 8817 CheckAST(FromTU, FromD2);8818 CheckAST(ToTU, ToD2);8819}8820 8821TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingShadowList) {8822 TranslationUnitDecl *FromTU = getTuDecl(8823 R"(8824 struct A {8825 void f();8826 void f(int);8827 };8828 struct B : A {8829 using A::f;8830 };8831 )",8832 Lang_CXX11);8833 8834 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(8835 FromTU, cxxRecordDecl(hasName("B")));8836 8837 auto *ToB = Import(FromB, Lang_CXX11);8838 TranslationUnitDecl *ToTU = ToB->getTranslationUnitDecl();8839 8840 auto *ToUsing = FirstDeclMatcher<UsingDecl>().match(8841 ToTU, usingDecl(hasParent(equalsNode(ToB))));8842 auto *ToUsingShadowF1 = FirstDeclMatcher<UsingShadowDecl>().match(8843 ToTU, usingShadowDecl(hasTargetDecl(8844 functionDecl(hasName("f"), parameterCountIs(0)))));8845 auto *ToUsingShadowF2 = FirstDeclMatcher<UsingShadowDecl>().match(8846 ToTU, usingShadowDecl(hasTargetDecl(8847 functionDecl(hasName("f"), parameterCountIs(1)))));8848 8849 EXPECT_EQ(ToUsing->shadow_size(), 2u);8850 auto ShadowI = ToUsing->shadow_begin();8851 EXPECT_EQ(*ShadowI, ToUsingShadowF1);8852 ++ShadowI;8853 EXPECT_EQ(*ShadowI, ToUsingShadowF2);8854}8855 8856AST_MATCHER_P(FunctionTemplateDecl, templateParameterCountIs, unsigned, Cnt) {8857 return Node.getTemplateParameters()->size() == Cnt;8858}8859 8860TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuide) {8861 TranslationUnitDecl *FromTU = getTuDecl(8862 R"(8863 template<class> class A { };8864 template<class T> class B {8865 template<class T1, typename = A<T>> B(T1);8866 };8867 template<class T>8868 B(T, T) -> B<int>;8869 )",8870 Lang_CXX17);8871 8872 // Get the implicit deduction guide for (non-default) constructor of 'B'.8873 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(8874 FromTU, functionTemplateDecl(templateParameterCountIs(3)));8875 // Implicit deduction guide for copy constructor of 'B'.8876 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(8877 FromTU, functionTemplateDecl(templateParameterCountIs(1), isImplicit()));8878 // User defined deduction guide.8879 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8880 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));8881 8882 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();8883 // Don't know why exactly but this is the DeclContext here.8884 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),8885 FromDGCopyCtor->getTemplatedDecl());8886 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),8887 FromDGCtor->getTemplatedDecl());8888 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),8889 FromDGCtor->getTemplatedDecl());8890 EXPECT_EQ(8891 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),8892 FromDGCopyCtor->getTemplatedDecl());8893 EXPECT_EQ(FromDGOther->getDescribedTemplate()8894 ->getTemplateParameters()8895 ->getParam(0)8896 ->getDeclContext(),8897 FromDGOther);8898 8899 auto *ToDGCtor = Import(FromDGCtor, Lang_CXX17);8900 auto *ToDGCopyCtor = Import(FromDGCopyCtor, Lang_CXX17);8901 auto *ToDGOther = Import(FromDGOther, Lang_CXX17);8902 ASSERT_TRUE(ToDGCtor);8903 ASSERT_TRUE(ToDGCopyCtor);8904 ASSERT_TRUE(ToDGOther);8905 8906 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();8907 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),8908 ToDGCopyCtor->getTemplatedDecl());8909 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),8910 ToDGCtor->getTemplatedDecl());8911 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),8912 ToDGCtor->getTemplatedDecl());8913 EXPECT_EQ(8914 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),8915 ToDGCopyCtor->getTemplatedDecl());8916 EXPECT_EQ(ToDGOther->getDescribedTemplate()8917 ->getTemplateParameters()8918 ->getParam(0)8919 ->getDeclContext(),8920 ToDGOther);8921}8922 8923TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuideDifferentOrder) {8924 // This test demonstrates that the DeclContext of the imported object is8925 // dependent on the order of import. The test is an exact copy of the previous8926 // one except at the indicated locations.8927 TranslationUnitDecl *FromTU = getTuDecl(8928 R"(8929 template<class> class A { };8930 template<class T> class B {8931 template<class T1, typename = A<T>> B(T1);8932 };8933 template<class T>8934 B(T, T) -> B<int>;8935 )",8936 Lang_CXX17);8937 8938 // Get the implicit deduction guide for (non-default) constructor of 'B'.8939 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(8940 FromTU, functionTemplateDecl(templateParameterCountIs(3)));8941 // Implicit deduction guide for copy constructor of 'B'.8942 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(8943 FromTU, functionTemplateDecl(templateParameterCountIs(1), isImplicit()));8944 // User defined deduction guide.8945 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(8946 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));8947 8948 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();8949 // Don't know why exactly but this is the DeclContext here.8950 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),8951 FromDGCopyCtor->getTemplatedDecl());8952 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),8953 FromDGCtor->getTemplatedDecl());8954 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),8955 FromDGCtor->getTemplatedDecl());8956 EXPECT_EQ(8957 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),8958 FromDGCopyCtor->getTemplatedDecl());8959 EXPECT_EQ(FromDGOther->getDescribedTemplate()8960 ->getTemplateParameters()8961 ->getParam(0)8962 ->getDeclContext(),8963 FromDGOther);8964 8965 // Here the import of 'ToDGCopyCtor' and 'ToDGCtor' is reversed relative to8966 // the previous test.8967 auto *ToDGCopyCtor = Import(FromDGCopyCtor, Lang_CXX17);8968 auto *ToDGCtor = Import(FromDGCtor, Lang_CXX17);8969 auto *ToDGOther = Import(FromDGOther, Lang_CXX17);8970 ASSERT_TRUE(ToDGCtor);8971 ASSERT_TRUE(ToDGCopyCtor);8972 ASSERT_TRUE(ToDGOther);8973 8974 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();8975 // Next line: DeclContext is different relative to the previous test.8976 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),8977 ToDGCtor->getTemplatedDecl());8978 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),8979 ToDGCtor->getTemplatedDecl());8980 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),8981 ToDGCtor->getTemplatedDecl());8982 // Next line: DeclContext is different relative to the previous test.8983 EXPECT_EQ(8984 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),8985 ToDGCtor->getTemplatedDecl());8986 EXPECT_EQ(ToDGOther->getDescribedTemplate()8987 ->getTemplateParameters()8988 ->getParam(0)8989 ->getDeclContext(),8990 ToDGOther);8991}8992 8993TEST_P(ASTImporterOptionSpecificTestBase,8994 ImportFieldsFirstForCorrectRecordLayout) {8995 // UnaryOperator(&) triggers RecordLayout computation, which relies on8996 // correctly imported fields.8997 auto Code =8998 R"(8999 class A {9000 int m() {9001 return &((A *)0)->f1 - &((A *)0)->f2;9002 }9003 int f1;9004 int f2;9005 };9006 )";9007 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9008 9009 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(9010 FromTU, cxxMethodDecl(hasName("A::m")));9011 Import(FromF, Lang_CXX11);9012}9013 9014TEST_P(ASTImporterOptionSpecificTestBase,9015 ImportCirularRefFieldsWithoutCorruptedRecordLayoutCache) {9016 // Import sequence: A => A.b => B => B.f() => ... => UnaryOperator(&) => ...9017 //9018 // UnaryOperator(&) should not introduce invalid RecordLayout since 'A' is9019 // still not completely imported.9020 auto Code =9021 R"(9022 class B;9023 class A {9024 B* b;9025 int c;9026 };9027 class B {9028 A *f() { return &((B *)0)->a; }9029 A a;9030 };9031 )";9032 9033 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(9034 getTuDecl(Code, Lang_CXX11), cxxRecordDecl(hasName("A")));9035 FromR = FromR->getDefinition();9036 auto &FromAST = FromR->getASTContext();9037 auto *ToR = Import(FromR, Lang_CXX11);9038 auto &ToAST = ToR->getASTContext();9039 9040 uint64_t SecondFieldOffset = FromAST.getTypeSize(FromAST.VoidPtrTy);9041 9042 EXPECT_TRUE(FromR->isCompleteDefinition());9043 const auto &FromLayout = FromAST.getASTRecordLayout(FromR);9044 EXPECT_TRUE(FromLayout.getFieldOffset(0) == 0);9045 EXPECT_TRUE(FromLayout.getFieldOffset(1) == SecondFieldOffset);9046 9047 EXPECT_TRUE(ToR->isCompleteDefinition());9048 const auto &ToLayout = ToAST.getASTRecordLayout(ToR);9049 EXPECT_TRUE(ToLayout.getFieldOffset(0) == 0);9050 EXPECT_TRUE(ToLayout.getFieldOffset(1) == SecondFieldOffset);9051}9052 9053TEST_P(ASTImporterOptionSpecificTestBase,9054 ImportRecordWithLayoutRequestingExpr) {9055 TranslationUnitDecl *FromTU = getTuDecl(9056 R"(9057 struct A {9058 int idx;9059 static void foo(A x) {9060 (void)&"text"[x.idx];9061 }9062 };9063 )",9064 Lang_CXX11);9065 9066 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9067 FromTU, cxxRecordDecl(hasName("A")));9068 9069 // Test that during import of 'foo' the record layout can be obtained without9070 // crash.9071 auto *ToA = Import(FromA, Lang_CXX11);9072 EXPECT_TRUE(ToA);9073 EXPECT_TRUE(ToA->isCompleteDefinition());9074}9075 9076TEST_P(ASTImporterOptionSpecificTestBase,9077 ImportRecordWithLayoutRequestingExprDifferentRecord) {9078 TranslationUnitDecl *FromTU = getTuDecl(9079 R"(9080 struct B;9081 struct A {9082 int idx;9083 B *b;9084 };9085 struct B {9086 static void foo(A x) {9087 (void)&"text"[x.idx];9088 }9089 };9090 )",9091 Lang_CXX11);9092 9093 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9094 FromTU, cxxRecordDecl(hasName("A")));9095 9096 // Test that during import of 'foo' the record layout (of 'A') can be obtained9097 // without crash. It is not possible to have all of the fields of 'A' imported9098 // at that time (without big code changes).9099 auto *ToA = Import(FromA, Lang_CXX11);9100 EXPECT_TRUE(ToA);9101 EXPECT_TRUE(ToA->isCompleteDefinition());9102}9103 9104TEST_P(ASTImporterOptionSpecificTestBase, ImportInClassInitializerFromField) {9105 // Encounter import of a field when the field already exists but has the9106 // in-class initializer expression not yet set. Such case can occur in the AST9107 // of generated template specializations.9108 // The first code forces to create a template specialization of9109 // `A<int>` but without implicit constructors.9110 // The second ("From") code contains a variable of type `A<int>`, this9111 // results in a template specialization that has constructors and9112 // CXXDefaultInitExpr nodes.9113 Decl *ToTU = getToTuDecl(9114 R"(9115 void f();9116 template<typename> struct A { int X = 1; };9117 struct B { A<int> Y; };9118 )",9119 Lang_CXX11);9120 auto *ToX = FirstDeclMatcher<FieldDecl>().match(9121 ToTU,9122 fieldDecl(hasName("X"), hasParent(classTemplateSpecializationDecl())));9123 ASSERT_TRUE(ToX->hasInClassInitializer());9124 ASSERT_FALSE(ToX->getInClassInitializer());9125 9126 Decl *FromTU = getTuDecl(9127 R"(9128 void f();9129 template<typename> struct A { int X = 1; };9130 struct B { A<int> Y; };9131 //9132 A<int> Z;9133 )",9134 Lang_CXX11, "input1.cc");9135 auto *FromX = FirstDeclMatcher<FieldDecl>().match(9136 FromTU,9137 fieldDecl(hasName("X"), hasParent(classTemplateSpecializationDecl())));9138 9139 auto *ToXImported = Import(FromX, Lang_CXX11);9140 EXPECT_EQ(ToXImported, ToX);9141 EXPECT_TRUE(ToX->getInClassInitializer());9142}9143 9144TEST_P(ASTImporterOptionSpecificTestBase,9145 ImportInClassInitializerFromCXXDefaultInitExpr) {9146 // Encounter AST import of a CXXDefaultInitExpr where the "to-field"9147 // of it exists but has the in-class initializer not set yet.9148 Decl *ToTU = getToTuDecl(9149 R"(9150 namespace N {9151 template<typename> int b;9152 struct X;9153 }9154 template<typename> struct A { N::X *X = nullptr; };9155 struct B { A<int> Y; };9156 )",9157 Lang_CXX14);9158 auto *ToX = FirstDeclMatcher<FieldDecl>().match(9159 ToTU,9160 fieldDecl(hasName("X"), hasParent(classTemplateSpecializationDecl())));9161 ASSERT_TRUE(ToX->hasInClassInitializer());9162 ASSERT_FALSE(ToX->getInClassInitializer());9163 9164 Decl *FromTU = getTuDecl(9165 R"(9166 namespace N {9167 template<typename> int b;9168 struct X;9169 }9170 template<typename> struct A { N::X *X = nullptr; };9171 struct B { A<int> Y; };9172 //9173 void f() {9174 (void)A<int>{};9175 }9176 struct C {9177 C(): attr(new A<int>{}){}9178 A<int> *attr;9179 const int value = N::b<C>;9180 };9181 )",9182 Lang_CXX14, "input1.cc");9183 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(9184 FromTU, functionDecl(hasName("f"), isDefinition()));9185 auto *ToF = Import(FromF, Lang_CXX11);9186 EXPECT_TRUE(ToF);9187 EXPECT_TRUE(ToX->getInClassInitializer());9188}9189 9190TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer) {9191 const char *Code =9192 R"(9193 struct AP_TECS;9194 9195 struct AP_Landing {9196 AP_TECS *TECS_controller;9197 };9198 9199 struct AP_TECS {9200 AP_Landing landing;9201 };9202 9203 class Plane {9204 AP_TECS TECS_controller{landing};9205 AP_Landing landing{&TECS_controller};9206 };9207 )";9208 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9209 9210 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(9211 FromTU, cxxRecordDecl(hasName("Plane")));9212 for (FieldDecl *F : FromR->fields())9213 EXPECT_TRUE(F->getInClassInitializer());9214 auto *ToR = Import(FromR, Lang_CXX11);9215 for (FieldDecl *F : ToR->fields())9216 EXPECT_TRUE(F->getInClassInitializer());9217}9218 9219TEST_P(ASTImporterOptionSpecificTestBase, ImportFieldInitializerWithItself) {9220 const char *Code =9221 R"(9222 class A {9223 int a{a};9224 };9225 )";9226 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9227 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9228 FromTU, cxxRecordDecl(hasName("A")));9229 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());9230 auto *ToA = Import(FromA, Lang_CXX11);9231 EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());9232}9233 9234TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer1) {9235 // FIXME: This is a example of recursive field initialization that is not9236 // supported.9237 // The following import chain occurs (not complete):9238 // import of A => A.a => in-class initializer of A.a => ref_B() => B => B.b9239 // => in-class initializer of B.b => ref_A() => CXXConstructExpr for A =>9240 // CXXDefaultInitExpr for A.a => in-class initializer of A.a9241 // in-class initializer of A.a is created in two different instances in this9242 // case (import of FieldDecl and CXXDefaultInitExpr). Probably not a big9243 // problem because it is an Expr (the second construction can be ignored9244 // instead of assert). But such recursive init code should not occur in9245 // practice.9246 const char *Code =9247 R"(9248 static int ref_A();9249 static int ref_B();9250 struct A {9251 int a = ref_B();9252 };9253 struct B {9254 int b = ref_A();9255 };9256 int ref_B() { B b; return b.b; }9257 int ref_A() { A a; return a.a; }9258 )";9259 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9260 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9261 FromTU, cxxRecordDecl(hasName("A")));9262 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());9263 // auto *ToA = Import(FromA, Lang_CXX11);9264 // EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());9265}9266 9267TEST_P(ASTImporterOptionSpecificTestBase, isNewDecl) {9268 Decl *FromTU = getTuDecl(9269 R"(9270 int bar() {9271 return 0;9272 }9273 void other() {9274 bar();9275 }9276 )",9277 Lang_CXX11);9278 Decl *ToTU = getToTuDecl(9279 R"(9280 int bar() {9281 return 0;9282 }9283 )",9284 Lang_CXX11);9285 auto *FromOther = FirstDeclMatcher<FunctionDecl>().match(9286 FromTU, functionDecl(hasName("other")));9287 ASSERT_TRUE(FromOther);9288 9289 auto *ToOther = Import(FromOther, Lang_CXX11);9290 ASSERT_TRUE(ToOther);9291 9292 auto *ToBar = FirstDeclMatcher<FunctionDecl>().match(9293 ToTU, functionDecl(hasName("bar")));9294 9295 EXPECT_TRUE(SharedStatePtr->isNewDecl(ToOther));9296 EXPECT_FALSE(SharedStatePtr->isNewDecl(ToBar));9297}9298 9299struct ImportInjectedClassNameType : public ASTImporterOptionSpecificTestBase {9300protected:9301 void checkInjType(const ASTContext &Ctx, const CXXRecordDecl *D) {9302 ASSERT_TRUE(D->hasInjectedClassType());9303 const Type *Ty = Ctx.getTagType(ElaboratedTypeKeyword::None,9304 /*Qualifier=*/std::nullopt, D,9305 /*OwnsTag=*/false)9306 .getTypePtr();9307 ASSERT_TRUE(Ty);9308 EXPECT_FALSE(Ty->isCanonicalUnqualified());9309 const auto *InjTy = dyn_cast<InjectedClassNameType>(Ty);9310 EXPECT_TRUE(InjTy);9311 for (const Decl *ReD : D->redecls()) {9312 if (ReD == D)9313 continue;9314 const auto *ReRD = cast<CXXRecordDecl>(ReD);9315 ASSERT_TRUE(ReRD->hasInjectedClassType());9316 const Type *ReTy = Ctx.getTagType(ElaboratedTypeKeyword::None,9317 /*Qualifier=*/std::nullopt, ReRD,9318 /*OwnsTag=*/false)9319 .getTypePtr();9320 ASSERT_TRUE(ReTy);9321 EXPECT_FALSE(ReTy->isCanonicalUnqualified());9322 EXPECT_NE(ReTy, Ty);9323 EXPECT_TRUE(Ctx.hasSameType(ReTy, Ty));9324 }9325 }9326 9327 void testImport(Decl *ToTU, Decl *FromTU, Decl *FromD) {9328 checkInjType(FromTU->getASTContext(), cast<CXXRecordDecl>(FromD));9329 Decl *ToD = Import(FromD, Lang_CXX11);9330 if (auto *ToRD = dyn_cast<CXXRecordDecl>(ToD))9331 checkInjType(ToTU->getASTContext(), ToRD);9332 }9333 9334 const char *ToCodeA =9335 R"(9336 template <class T>9337 struct A;9338 )";9339 const char *ToCodeADef =9340 R"(9341 template <class T>9342 struct A {9343 typedef A T1;9344 };9345 )";9346 const char *ToCodeC =9347 R"(9348 template <class T>9349 struct C;9350 )";9351 const char *ToCodeCDef =9352 R"(9353 template <class T>9354 struct A {9355 typedef A T1;9356 };9357 9358 template <class T1, class T2>9359 struct B {};9360 9361 template<class T>9362 struct C {9363 typedef typename A<T>::T1 T1;9364 typedef B<T1, T> T2;9365 typedef B<T1, C> T3;9366 };9367 )";9368 const char *FromCode =9369 R"(9370 template <class T>9371 struct A;9372 template <class T>9373 struct A {9374 typedef A T1;9375 };9376 template <class T>9377 struct A;9378 9379 template <class T1, class T2>9380 struct B {};9381 9382 template <class T>9383 struct C;9384 template <class T>9385 struct C {9386 typedef typename A<T>::T1 T1;9387 typedef B<T1, T> T2;9388 typedef B<T1, C> T3;9389 };9390 template <class T>9391 struct C;9392 9393 template <class T>9394 struct D {9395 void f(typename C<T>::T3 *);9396 };9397 )";9398};9399 9400TEST_P(ImportInjectedClassNameType, ImportADef) {9401 Decl *ToTU = getToTuDecl(ToCodeA, Lang_CXX11);9402 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9403 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9404 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));9405 testImport(ToTU, FromTU, FromA);9406}9407 9408TEST_P(ImportInjectedClassNameType, ImportAFirst) {9409 Decl *ToTU = getToTuDecl(ToCodeA, Lang_CXX11);9410 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9411 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9412 FromTU, cxxRecordDecl(hasName("A")));9413 testImport(ToTU, FromTU, FromA);9414}9415 9416TEST_P(ImportInjectedClassNameType, ImportALast) {9417 Decl *ToTU = getToTuDecl(ToCodeA, Lang_CXX11);9418 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9419 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(9420 FromTU, cxxRecordDecl(hasName("A")));9421 testImport(ToTU, FromTU, FromA);9422}9423 9424TEST_P(ImportInjectedClassNameType, ImportADefToDef) {9425 Decl *ToTU = getToTuDecl(ToCodeADef, Lang_CXX11);9426 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9427 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9428 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));9429 testImport(ToTU, FromTU, FromA);9430}9431 9432TEST_P(ImportInjectedClassNameType, ImportAFirstToDef) {9433 Decl *ToTU = getToTuDecl(ToCodeADef, Lang_CXX11);9434 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9435 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(9436 FromTU, cxxRecordDecl(hasName("A")));9437 testImport(ToTU, FromTU, FromA);9438}9439 9440TEST_P(ImportInjectedClassNameType, ImportALastToDef) {9441 Decl *ToTU = getToTuDecl(ToCodeADef, Lang_CXX11);9442 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9443 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(9444 FromTU, cxxRecordDecl(hasName("A")));9445 testImport(ToTU, FromTU, FromA);9446}9447 9448TEST_P(ImportInjectedClassNameType, ImportCDef) {9449 Decl *ToTU = getToTuDecl(ToCodeC, Lang_CXX11);9450 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9451 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(9452 FromTU, cxxRecordDecl(hasName("C"), isDefinition()));9453 testImport(ToTU, FromTU, FromC);9454}9455 9456TEST_P(ImportInjectedClassNameType, ImportCLast) {9457 Decl *ToTU = getToTuDecl(ToCodeC, Lang_CXX11);9458 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9459 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(9460 FromTU, cxxRecordDecl(hasName("C")));9461 testImport(ToTU, FromTU, FromC);9462}9463 9464TEST_P(ImportInjectedClassNameType, ImportCDefToDef) {9465 Decl *ToTU = getToTuDecl(ToCodeCDef, Lang_CXX11);9466 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9467 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(9468 FromTU, cxxRecordDecl(hasName("C"), isDefinition()));9469 testImport(ToTU, FromTU, FromC);9470}9471 9472TEST_P(ImportInjectedClassNameType, ImportCLastToDef) {9473 Decl *ToTU = getToTuDecl(ToCodeCDef, Lang_CXX11);9474 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9475 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(9476 FromTU, cxxRecordDecl(hasName("C")));9477 testImport(ToTU, FromTU, FromC);9478}9479 9480TEST_P(ImportInjectedClassNameType, ImportD) {9481 Decl *ToTU = getToTuDecl("", Lang_CXX11);9482 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9483 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(9484 FromTU, cxxRecordDecl(hasName("D"), isDefinition()));9485 testImport(ToTU, FromTU, FromD);9486}9487 9488TEST_P(ImportInjectedClassNameType, ImportDToDef) {9489 Decl *ToTU = getToTuDecl(ToCodeCDef, Lang_CXX11);9490 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);9491 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(9492 FromTU, cxxRecordDecl(hasName("D"), isDefinition()));9493 testImport(ToTU, FromTU, FromD);9494}9495 9496TEST_P(ImportInjectedClassNameType, ImportTypedefType) {9497 Decl *ToTU = getToTuDecl(9498 R"(9499 template <class T>9500 struct A {9501 typedef A A1;9502 void f(A1 *);9503 };9504 )",9505 Lang_CXX11);9506 Decl *FromTU = getTuDecl(9507 R"(9508 template <class T>9509 struct A {9510 typedef A A1;9511 void f(A1 *);9512 };9513 template<class T>9514 void A<T>::f(A::A1 *) {}9515 )",9516 Lang_CXX11);9517 9518 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(9519 FromTU, functionDecl(hasName("f"), isDefinition()));9520 auto *ToF = Import(FromF, Lang_CXX11);9521 EXPECT_TRUE(ToF);9522 ASTContext &ToCtx = ToF->getDeclContext()->getParentASTContext();9523 9524 auto *ToA1 =9525 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("A1")));9526 QualType ToInjTypedef = ToA1->getUnderlyingType().getCanonicalType();9527 QualType ToInjParmVar =9528 ToF->parameters()[0]->getType().getDesugaredType(ToCtx);9529 ToInjParmVar =9530 ToInjParmVar->getAs<PointerType>()->getPointeeType().getCanonicalType();9531 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjTypedef));9532 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjParmVar));9533 EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));9534}9535 9536TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {9537 Decl *From, *To;9538 std::tie(From, To) = getImportedDecl(9539 R"(9540 #define CDECL __attribute__((cdecl))9541 typedef void (CDECL *X)();9542 )",9543 Lang_CXX03, "", Lang_CXX03, "X");9544 9545 auto *FromTy =9546 FirstDeclMatcher<MacroQualifiedType>().match(From, macroQualifiedType());9547 auto *ToTy =9548 FirstDeclMatcher<MacroQualifiedType>().match(To, macroQualifiedType());9549 9550 EXPECT_TRUE(isa<AttributedType>(FromTy->getUnderlyingType()));9551 EXPECT_TRUE(isa<AttributedType>(ToTy->getUnderlyingType()));9552}9553 9554TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {9555 constexpr auto TestCode = R"(9556 template <class T>9557 struct A;9558 template <class T>9559 struct A {};9560 template <template<class> class T = A>9561 struct B {};9562 using C = B<>;9563 )";9564 Decl *ToTU = getToTuDecl(TestCode, Lang_CXX11);9565 Decl *FromTU = getTuDecl(TestCode, Lang_CXX11);9566 9567 auto *ToUsingFirst = FirstDeclMatcher<TypeAliasDecl>().match(9568 ToTU, typeAliasDecl(hasName("C")));9569 9570 auto *FromUsing = FirstDeclMatcher<TypeAliasDecl>().match(9571 FromTU, typeAliasDecl(hasName("C")));9572 auto *ToUsing = Import(FromUsing, Lang_CXX11);9573 EXPECT_TRUE(ToUsing);9574 9575 auto *ToB = FirstDeclMatcher<ClassTemplateDecl>().match(9576 ToTU, classTemplateDecl(hasName("B")));9577 auto *ToB1 = LastDeclMatcher<ClassTemplateDecl>().match(9578 ToTU, classTemplateDecl(hasName("B")));9579 // One template definition of 'B' should exist.9580 EXPECT_EQ(ToB, ToB1);9581 9582 // These declarations are imported separately.9583 EXPECT_NE(ToUsingFirst, ToUsing);9584 9585 auto SpB = ToB->spec_begin();9586 auto SpE = ToB->spec_end();9587 EXPECT_TRUE(SpB != SpE);9588 ClassTemplateSpecializationDecl *Spec1 = *SpB;9589 ++SpB;9590 // The template 'B' should have one specialization (with default argument).9591 EXPECT_TRUE(SpB == SpE);9592 9593 // Even if 'B' has one specialization with the default arguments, the AST9594 // contains after the import two specializations that are linked in the9595 // declaration chain. The 'spec_begin' iteration does not find these because9596 // the template arguments are the same. But the imported type alias has the9597 // link to the second specialization. The template name object in these9598 // specializations must point to the same (and one) instance of definition of9599 // 'B'.9600 auto *Spec2 = cast<ClassTemplateSpecializationDecl>(9601 ToUsing->getUnderlyingType()9602 ->getAs<TemplateSpecializationType>()9603 ->getAsRecordDecl());9604 EXPECT_NE(Spec1, Spec2);9605 EXPECT_TRUE(Spec1->getPreviousDecl() == Spec2 ||9606 Spec2->getPreviousDecl() == Spec1);9607 TemplateDecl *Templ1 =9608 Spec1->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();9609 TemplateDecl *Templ2 =9610 Spec2->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();9611 EXPECT_EQ(Templ1, Templ2);9612}9613 9614TEST_P(ASTImporterOptionSpecificTestBase, VaListC) {9615 Decl *FromTU = getTuDecl(R"(typedef __builtin_va_list va_list;)", Lang_C99);9616 9617 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(9618 FromTU, typedefDecl(hasName("va_list")));9619 ASSERT_TRUE(FromVaList);9620 9621 auto *ToVaList = Import(FromVaList, Lang_C99);9622 ASSERT_TRUE(ToVaList);9623 9624 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(9625 ToAST->getASTContext().getTranslationUnitDecl(),9626 typedefDecl(hasName("__builtin_va_list")));9627 9628 ASSERT_TRUE(ToAST->getASTContext().hasSameType(9629 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));9630}9631 9632TEST_P(ASTImporterOptionSpecificTestBase, VaListCpp) {9633 Decl *FromTU = getTuDecl(R"(typedef __builtin_va_list va_list;)", Lang_CXX03);9634 9635 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(9636 FromTU, typedefDecl(hasName("va_list")));9637 ASSERT_TRUE(FromVaList);9638 9639 auto *ToVaList = Import(FromVaList, Lang_CXX03);9640 ASSERT_TRUE(ToVaList);9641 9642 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(9643 ToAST->getASTContext().getTranslationUnitDecl(),9644 typedefDecl(hasName("__builtin_va_list")));9645 9646 ASSERT_TRUE(ToAST->getASTContext().hasSameType(9647 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));9648}9649 9650TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingTypedefToRecord) {9651 const char *Code =9652 R"(9653 struct S { int i; };9654 typedef struct S T;9655 extern T x;9656 )";9657 Decl *ToTU = getToTuDecl(Code, Lang_C99);9658 Decl *FromTU = getTuDecl(Code, Lang_C99);9659 9660 auto *FromX =9661 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));9662 auto *ToX = Import(FromX, Lang_C99);9663 EXPECT_TRUE(ToX);9664 9665 auto *Typedef1 =9666 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));9667 auto *Typedef2 =9668 LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));9669 EXPECT_EQ(Typedef1, Typedef2);9670}9671 9672TEST_P(ASTImporterOptionSpecificTestBase,9673 ImportExistingTypedefToUnnamedRecord) {9674 const char *Code =9675 R"(9676 typedef const struct { int f; } T;9677 extern T x;9678 )";9679 Decl *ToTU = getToTuDecl(Code, Lang_C99);9680 Decl *FromTU = getTuDecl(Code, Lang_C99);9681 9682 auto *FromX =9683 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));9684 auto *ToX = Import(FromX, Lang_C99);9685 EXPECT_TRUE(ToX);9686 9687 auto *Typedef1 =9688 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));9689 auto *Typedef2 =9690 LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));9691 EXPECT_NE(Typedef1, Typedef2);9692 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),9693 Typedef2->getUnderlyingType().getTypePtr());9694 EXPECT_EQ(ToX->getType()->getAs<TypedefType>()->getDecl(), Typedef2);9695}9696 9697TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) {9698 const char *Code =9699 R"(9700 typedef struct { int f; } T1;9701 typedef struct { int f; } T2;9702 extern T1 x1;9703 extern T2 x2;9704 )";9705 Decl *ToTU = getToTuDecl("", Lang_C99);9706 Decl *FromTU = getTuDecl(Code, Lang_C99);9707 9708 auto *FromX1 =9709 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x1")));9710 auto *FromX2 =9711 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x2")));9712 auto *ToX1 = Import(FromX1, Lang_C99);9713 EXPECT_TRUE(ToX1);9714 auto *ToX2 = Import(FromX2, Lang_C99);9715 EXPECT_TRUE(ToX2);9716 9717 auto *Typedef1 =9718 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T1")));9719 auto *Typedef2 =9720 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T2")));9721 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),9722 Typedef2->getUnderlyingType().getTypePtr());9723}9724 9725TEST_P(ASTImporterOptionSpecificTestBase,9726 ImportExistingTypedefToUnnamedRecordPtr) {9727 const char *Code =9728 R"(9729 typedef const struct { int fff; } * const T;9730 extern T x;9731 )";9732 Decl *ToTU = getToTuDecl(Code, Lang_C99);9733 Decl *FromTU = getTuDecl(Code, Lang_C99);9734 9735 auto *FromX =9736 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));9737 auto *ToX = Import(FromX, Lang_C99);9738 EXPECT_TRUE(ToX);9739 9740 auto *Typedef1 =9741 FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));9742 auto *Typedef2 =9743 LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));9744 // FIXME: These should be imported separately, like in the test above.9745 // Or: In the test above these should be merged too.9746 EXPECT_EQ(Typedef1, Typedef2);9747 9748 auto *FromR = FirstDeclMatcher<RecordDecl>().match(9749 FromTU, recordDecl(hasDescendant(fieldDecl(hasName("fff")))));9750 auto *ToRExisting = FirstDeclMatcher<RecordDecl>().match(9751 ToTU, recordDecl(hasDescendant(fieldDecl(hasName("fff")))));9752 ASSERT_TRUE(FromR);9753 auto *ToRImported = Import(FromR, Lang_C99);9754 // FIXME: If typedefs are not imported separately, do not import ToRImported9755 // separately.9756 EXPECT_NE(ToRExisting, ToRImported);9757}9758 9759TEST_P(ASTImporterOptionSpecificTestBase,9760 ImportTypedefWithDifferentUnderlyingType) {9761 const char *Code =9762 R"(9763 using X1 = int;9764 using Y1 = int;9765 9766 using RPB1 = X1*;9767 typedef RPB1 RPX1;9768 using RPB1 = Y1*; // redeclared9769 typedef RPB1 RPY1;9770 9771 auto X = 0 ? (RPX1){} : (RPY1){};9772 )";9773 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9774 9775 auto *FromX =9776 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("X")));9777 9778 auto *FromXType = FromX->getType()->getAs<TypedefType>();9779 EXPECT_FALSE(FromXType->typeMatchesDecl());9780 9781 auto *ToX = Import(FromX, Lang_CXX11);9782 auto *ToXType = ToX->getType()->getAs<TypedefType>();9783 EXPECT_FALSE(ToXType->typeMatchesDecl());9784}9785 9786TEST_P(ASTImporterOptionSpecificTestBase,9787 ImportTemplateArgumentWithPointerToDifferentInstantiation) {9788 const char *CodeTo =9789 R"(9790 template<class A>9791 A f1() {9792 return A();9793 }9794 template<class A, A (B)()>9795 class X {};9796 9797 X<int, f1<int>> x;9798 )";9799 const char *CodeFrom =9800 R"(9801 template<class A>9802 A f1();9803 template<class A, A (B)()>9804 class X {};9805 9806 X<int, f1<int>> x;9807 )";9808 Decl *ToTU = getToTuDecl(CodeTo, Lang_CXX11);9809 Decl *FromTU = getTuDecl(CodeFrom, Lang_CXX11);9810 9811 auto *ToF1 = FirstDeclMatcher<FunctionDecl>().match(9812 ToTU, functionDecl(hasName("f1"), isInstantiated()));9813 auto *FromF1 = FirstDeclMatcher<FunctionDecl>().match(9814 FromTU, functionDecl(hasName("f1"), isInstantiated()));9815 EXPECT_TRUE(ToF1->isThisDeclarationADefinition());9816 EXPECT_FALSE(FromF1->isThisDeclarationADefinition());9817 9818 auto *ToX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(9819 ToTU, classTemplateSpecializationDecl(hasName("X")));9820 auto *FromX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(9821 FromTU, classTemplateSpecializationDecl(hasName("X")));9822 9823 Decl *ToTArgF = ToX->getTemplateArgs().get(1).getAsDecl();9824 Decl *FromTArgF = FromX->getTemplateArgs().get(1).getAsDecl();9825 EXPECT_EQ(ToTArgF, ToF1);9826 EXPECT_EQ(FromTArgF, FromF1);9827 9828 auto *ToXImported = Import(FromX, Lang_CXX11);9829 // The template argument 1 of 'X' in the "From" code points to a function9830 // that has no definition. The import must ensure that this template argument9831 // is imported in a way that it will point to the existing 'f1' function, not9832 // to the 'f1' that is imported. In this way when specialization of 'X' is9833 // imported it will have the same template arguments as the existing one.9834 EXPECT_EQ(ToXImported, ToX);9835 // FIXME: This matcher causes a crash "Tried to match orphan node".9836 // The code is removed until the problem is fixed.9837 // auto *ToF1Imported =9838 // LastDeclMatcher<FunctionDecl>().match(ToTU,9839 // functionDecl(hasName("f1"),isInstantiated()));9840 // EXPECT_NE(ToF1Imported, ToF1);9841 // EXPECT_EQ(ToF1Imported->getPreviousDecl(), ToF1);9842}9843 9844TEST_P(ASTImporterOptionSpecificTestBase,9845 ImportTypeAliasTemplateAfterSimilarCalledTemplateTypeParm) {9846 const char *Code =9847 R"(9848 struct S;9849 template <typename>9850 using Callable = S;9851 template <typename Callable>9852 int bindingFunctionVTable;9853 )";9854 Decl *FromTU = getTuDecl(Code, Lang_CXX17);9855 9856 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(9857 FromTU, typeAliasTemplateDecl(hasName("Callable")));9858 9859 auto *FromCallableParm = FirstDeclMatcher<TemplateTypeParmDecl>().match(9860 FromTU, templateTypeParmDecl(hasName("Callable")));9861 9862 auto *ToFromCallableParm = Import(FromCallableParm, Lang_CXX17);9863 auto *ToCallable = Import(FromCallable, Lang_CXX17);9864 EXPECT_TRUE(ToFromCallableParm);9865 EXPECT_TRUE(ToCallable);9866}9867 9868TEST_P(ASTImporterOptionSpecificTestBase, ImportConflictTypeAliasTemplate) {9869 const char *ToCode =9870 R"(9871 struct S;9872 template <typename, typename>9873 using Callable = S;9874 )";9875 const char *Code =9876 R"(9877 struct S;9878 template <typename>9879 using Callable = S;9880 )";9881 (void)getToTuDecl(ToCode, Lang_CXX17);9882 Decl *FromTU = getTuDecl(Code, Lang_CXX17);9883 9884 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(9885 FromTU, typeAliasTemplateDecl(hasName("Callable")));9886 9887 auto *ImportedCallable = Import(FromCallable, Lang_CXX17);9888 EXPECT_FALSE(ImportedCallable);9889}9890 9891AST_MATCHER(ClassTemplateSpecializationDecl, hasInstantiatedFromMember) {9892 if (auto Instantiate = Node.getInstantiatedFrom()) {9893 if (auto *FromPartialSpecialization =9894 cast<ClassTemplatePartialSpecializationDecl *>(Instantiate)) {9895 return nullptr != FromPartialSpecialization->getInstantiatedFromMember();9896 }9897 }9898 return false;9899}9900 9901TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) {9902 const char *Code =9903 R"(9904 template <typename> struct B {9905 template <typename, bool = false> union D;9906 template <typename T> union D<T> {};9907 D<int> d;9908 };9909 B<int> b;9910 )";9911 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9912 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(9913 FromTU, classTemplateSpecializationDecl(hasName("D"),9914 hasInstantiatedFromMember()));9915 auto *FromPartialSpecialization =9916 cast<ClassTemplatePartialSpecializationDecl *>(9917 FromD->getInstantiatedFrom());9918 ASSERT_TRUE(FromPartialSpecialization->getInstantiatedFromMember());9919 auto *ImportedPartialSpecialization =9920 Import(FromPartialSpecialization, Lang_CXX11);9921 EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember());9922}9923 9924AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) {9925 for (EnumConstantDecl *D : Node.enumerators())9926 if (D->getName() == ConstName)9927 return true;9928 return false;9929}9930 9931TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnums) {9932 const char *Code =9933 R"(9934 struct A {9935 enum { E1, E2 } x;9936 enum { E3, E4 } y;9937 };9938 )";9939 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9940 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(9941 FromTU, enumDecl(hasEnumConstName("E1")));9942 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);9943 EXPECT_TRUE(ImportedEnumE1);9944 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(9945 FromTU, enumDecl(hasEnumConstName("E3")));9946 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);9947 EXPECT_TRUE(ImportedEnumE3);9948 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);9949}9950 9951TEST_P(ASTImporterOptionSpecificTestBase, ImportFreeStandingAnonymousEnums) {9952 const char *Code =9953 R"(9954 struct A {9955 enum { E1, E2 };9956 enum { E3, E4 };9957 };9958 )";9959 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9960 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(9961 FromTU, enumDecl(hasEnumConstName("E1")));9962 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);9963 EXPECT_TRUE(ImportedEnumE1);9964 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(9965 FromTU, enumDecl(hasEnumConstName("E3")));9966 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);9967 EXPECT_TRUE(ImportedEnumE3);9968 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);9969}9970 9971TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingAnonymousEnums) {9972 const char *ToCode =9973 R"(9974 struct A {9975 enum { E1, E2 } x;9976 enum { E3, E4 } y;9977 };9978 )";9979 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);9980 auto *ToEnumE1 = FirstDeclMatcher<EnumDecl>().match(9981 ToTU, enumDecl(hasEnumConstName("E1")));9982 auto *ToEnumE3 = FirstDeclMatcher<EnumDecl>().match(9983 ToTU, enumDecl(hasEnumConstName("E3")));9984 const char *Code =9985 R"(9986 struct A {9987 enum { E1, E2 } x;9988 enum { E3, E4 } y;9989 };9990 )";9991 Decl *FromTU = getTuDecl(Code, Lang_CXX11);9992 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(9993 FromTU, enumDecl(hasEnumConstName("E1")));9994 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);9995 ASSERT_TRUE(ImportedEnumE1);9996 EXPECT_EQ(ImportedEnumE1, ToEnumE1);9997 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(9998 FromTU, enumDecl(hasEnumConstName("E3")));9999 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);10000 ASSERT_TRUE(ImportedEnumE3);10001 EXPECT_EQ(ImportedEnumE3, ToEnumE3);10002}10003 10004TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingEmptyAnonymousEnums) {10005 const char *ToCode =10006 R"(10007 struct A {10008 enum {};10009 };10010 )";10011 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);10012 auto *ToE1 = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl());10013 const char *Code =10014 R"(10015 struct A {10016 enum {};10017 enum {};10018 };10019 )";10020 Decl *FromTU = getTuDecl(Code, Lang_CXX11);10021 auto *FromE1 = FirstDeclMatcher<EnumDecl>().match(FromTU, enumDecl());10022 auto *ImportedE1 = Import(FromE1, Lang_CXX11);10023 ASSERT_TRUE(ImportedE1);10024 EXPECT_EQ(ImportedE1, ToE1);10025 auto *FromE2 = LastDeclMatcher<EnumDecl>().match(FromTU, enumDecl());10026 ASSERT_NE(FromE1, FromE2);10027 auto *ImportedE2 = Import(FromE2, Lang_CXX11);10028 ASSERT_TRUE(ImportedE2);10029 // FIXME: These should not be equal, or the import should fail.10030 EXPECT_EQ(ImportedE2, ToE1);10031}10032 10033TEST_P(ASTImporterOptionSpecificTestBase, ImportMultipleAnonymousEnumDecls) {10034 Decl *ToTU = getToTuDecl("", Lang_CXX03);10035 Decl *FromTU = getTuDecl(10036 R"(10037 struct foo {10038 enum { A };10039 enum { B };10040 };10041 )",10042 Lang_CXX03);10043 10044 auto EnumConstA = enumConstantDecl(hasName("A"));10045 auto EnumConstB = enumConstantDecl(hasName("B"));10046 10047 auto *FromA = FirstDeclMatcher<EnumConstantDecl>().match(FromTU, EnumConstA);10048 auto *FromB = FirstDeclMatcher<EnumConstantDecl>().match(FromTU, EnumConstB);10049 10050 auto *ToA = Import(FromA, Lang_CXX03);10051 auto *ToB = Import(FromB, Lang_CXX03);10052 10053 ASSERT_TRUE(ToA);10054 ASSERT_TRUE(ToB);10055 10056 auto *ToFooA = FirstDeclMatcher<CXXRecordDecl>().match(10057 ToTU, tagDecl(has(enumDecl(has(EnumConstA)))));10058 auto *ToFooB = FirstDeclMatcher<CXXRecordDecl>().match(10059 ToTU, tagDecl(has(enumDecl(has(EnumConstB)))));10060 ASSERT_EQ(ToFooA, ToFooB);10061 10062 // different EnumDecl10063 auto *ToEnumDeclA =10064 FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(has(EnumConstA)));10065 auto *ToEnumDeclB =10066 FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(has(EnumConstB)));10067 ASSERT_NE(ToEnumDeclA, ToEnumDeclB);10068}10069 10070struct ImportTemplateParmDeclDefaultValue10071 : public ASTImporterOptionSpecificTestBase {10072protected:10073 void checkTemplateParams(RedeclarableTemplateDecl *D,10074 RedeclarableTemplateDecl *InheritedFromD) {10075 auto *NonTypeP =10076 cast<NonTypeTemplateParmDecl>(D->getTemplateParameters()->getParam(0));10077 auto *TypeP =10078 cast<TemplateTypeParmDecl>(D->getTemplateParameters()->getParam(1));10079 auto *TemplateP =10080 cast<TemplateTemplateParmDecl>(D->getTemplateParameters()->getParam(2));10081 if (InheritedFromD) {10082 EXPECT_TRUE(NonTypeP->getDefaultArgStorage().isInherited());10083 EXPECT_TRUE(TypeP->getDefaultArgStorage().isInherited());10084 EXPECT_TRUE(TemplateP->getDefaultArgStorage().isInherited());10085 EXPECT_EQ(NonTypeP->getDefaultArgStorage().getInheritedFrom(),10086 InheritedFromD->getTemplateParameters()->getParam(0));10087 EXPECT_EQ(TypeP->getDefaultArgStorage().getInheritedFrom(),10088 InheritedFromD->getTemplateParameters()->getParam(1));10089 EXPECT_EQ(TemplateP->getDefaultArgStorage().getInheritedFrom(),10090 InheritedFromD->getTemplateParameters()->getParam(2));10091 } else {10092 EXPECT_FALSE(NonTypeP->getDefaultArgStorage().isInherited());10093 EXPECT_FALSE(TypeP->getDefaultArgStorage().isInherited());10094 EXPECT_FALSE(TemplateP->getDefaultArgStorage().isInherited());10095 }10096 }10097 10098 void testImport(RedeclarableTemplateDecl *FromD1,10099 RedeclarableTemplateDecl *FromD2,10100 RedeclarableTemplateDecl *FromD3,10101 RedeclarableTemplateDecl *ToExistingD1) {10102 auto *ToD1 = Import(FromD1, Lang_CXX14);10103 auto *ToD2 = Import(FromD2, Lang_CXX14);10104 auto *ToD3 = Import(FromD3, Lang_CXX14);10105 checkTemplateParams(ToD1, nullptr);10106 checkTemplateParams(ToD2, ToD1);10107 checkTemplateParams(ToD3, ToExistingD1 ? ToExistingD1 : ToD1);10108 }10109 10110 // In these tests a circular dependency is created between the template10111 // parameter default value and the template declaration (with the same10112 // template parameter).10113 template <class TemplateParmDeclT>10114 void10115 testTemplateParmDeclCircularDependency(ClassTemplateDecl *FromD,10116 ClassTemplateDecl *FromDInherited) {10117 auto GetTemplateParm =10118 [](ClassTemplateDecl *D) -> const TemplateParmDeclT * {10119 return dyn_cast<TemplateParmDeclT>(10120 D->getTemplateParameters()->getParam(0));10121 };10122 10123 ASSERT_FALSE(GetTemplateParm(FromD)->getDefaultArgStorage().isInherited());10124 ASSERT_TRUE(10125 GetTemplateParm(FromDInherited)->getDefaultArgStorage().isInherited());10126 10127 auto *ToD = Import(FromD, Lang_CXX14);10128 EXPECT_TRUE(ToD);10129 10130 auto *ToDInherited = Import(FromDInherited, Lang_CXX14);10131 EXPECT_TRUE(ToDInherited);10132 10133 EXPECT_FALSE(GetTemplateParm(ToD)->getDefaultArgStorage().isInherited());10134 EXPECT_TRUE(10135 GetTemplateParm(ToDInherited)->getDefaultArgStorage().isInherited());10136 EXPECT_EQ(GetTemplateParm(ToDInherited)10137 ->getDefaultArgStorage()10138 .getInheritedFrom(),10139 GetTemplateParm(ToD));10140 10141 if (FromD->getPreviousDecl() == FromDInherited) {10142 EXPECT_EQ(ToD->getPreviousDecl(), ToDInherited);10143 } else {10144 EXPECT_EQ(FromD, FromDInherited->getPreviousDecl());10145 // The order is reversed by the import process.10146 EXPECT_EQ(ToD->getPreviousDecl(), ToDInherited);10147 }10148 }10149 10150 const char *CodeFunction =10151 R"(10152 template <class> struct X;10153 10154 template <int A = 2, typename B = int, template<class> class C = X>10155 void test();10156 template <int A, typename B, template<class> class C>10157 void test();10158 template <int A, typename B, template<class> class C>10159 void test() {}10160 )";10161 10162 const char *CodeClass =10163 R"(10164 namespace N {10165 template <class> struct X;10166 10167 template <int A = 2, typename B = int, template<class> class C = X>10168 struct test;10169 template <int A, typename B, template<class> class C>10170 struct test;10171 template <int A, typename B, template<class> class C>10172 struct test {};10173 }10174 )";10175 10176 const char *CodeVar =10177 R"(10178 namespace N {10179 template <class> struct X;10180 10181 template <int A = 2, typename B = int, template<class> class C = X>10182 extern int test;10183 template <int A, typename B, template<class> class C>10184 extern int test;10185 template <int A, typename B, template<class> class C>10186 int test = A;10187 }10188 )";10189};10190 10191TEST_P(ImportTemplateParmDeclDefaultValue, InvisibleInheritedFrom) {10192 const char *ToCode =10193 R"(10194 template <int P = 1>10195 void f() {}10196 )";10197 TranslationUnitDecl *ToTU = getToTuDecl(ToCode, Lang_CXX14);10198 auto *ToFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(10199 ToTU, functionTemplateDecl(hasName("f")));10200 10201 const char *FromCode =10202 R"(10203 template <int P = 1>10204 void f() {}10205 template <int P>10206 void f();10207 )";10208 TranslationUnitDecl *FromTU = getTuDecl(FromCode, Lang_CXX14);10209 auto *FromFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(10210 FromTU, functionTemplateDecl(hasName("f")));10211 auto *FromF = LastDeclMatcher<FunctionTemplateDecl>().match(10212 FromTU, functionTemplateDecl(hasName("f")));10213 10214 auto *ToFDefImported = Import(FromFDef, Lang_CXX14);10215 EXPECT_EQ(ToFDefImported, ToFDef);10216 auto *ToF = Import(FromF, Lang_CXX14);10217 EXPECT_NE(ToF, ToFDef);10218 const auto *Parm = dyn_cast<NonTypeTemplateParmDecl>(10219 ToF->getTemplateParameters()->getParam(0));10220 EXPECT_TRUE(Parm->defaultArgumentWasInherited());10221 // FIXME: This behavior may be confusing:10222 // Default value is not inherited from the existing declaration, instead a new10223 // is created at import that is similar to the existing but not reachable from10224 // the AST.10225 EXPECT_NE(Parm->getDefaultArgStorage().getInheritedFrom(),10226 ToFDef->getTemplateParameters()->getParam(0));10227}10228 10229TEST_P(ImportTemplateParmDeclDefaultValue, DefValImportError) {10230 const char *ToCode =10231 R"(10232 class X {10233 int A;10234 };10235 )";10236 getToTuDecl(ToCode, Lang_CXX14);10237 10238 const char *FromCode =10239 R"(10240 class X;10241 10242 template <typename P = X>10243 void f() {}10244 10245 class X {10246 char A;10247 };10248 )";10249 TranslationUnitDecl *FromTU = getTuDecl(FromCode, Lang_CXX14);10250 auto *FromF = FirstDeclMatcher<FunctionTemplateDecl>().match(10251 FromTU, functionTemplateDecl(hasName("f")));10252 10253 auto *ToFImported = Import(FromF, Lang_CXX14);10254 EXPECT_FALSE(ToFImported);10255}10256 10257TEST_P(ImportTemplateParmDeclDefaultValue, ImportFunctionTemplate) {10258 TranslationUnitDecl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);10259 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(10260 FromTU, functionTemplateDecl(hasName("test") /*, hasBody(stmt())*/));10261 auto *D2 = dyn_cast<FunctionTemplateDecl>(D3->getPreviousDecl());10262 auto *D1 = dyn_cast<FunctionTemplateDecl>(D2->getPreviousDecl());10263 testImport(D1, D2, D3, nullptr);10264}10265 10266TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingFunctionTemplate) {10267 TranslationUnitDecl *ToTU = getToTuDecl(CodeFunction, Lang_CXX14);10268 auto *ToD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(10269 ToTU, functionTemplateDecl(hasName("test")));10270 TranslationUnitDecl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);10271 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(10272 FromTU, functionTemplateDecl(hasName("test")));10273 auto *D2 = dyn_cast<FunctionTemplateDecl>(D3->getPreviousDecl());10274 auto *D1 = dyn_cast<FunctionTemplateDecl>(D2->getPreviousDecl());10275 testImport(D1, D2, D3, ToD1);10276}10277 10278TEST_P(ImportTemplateParmDeclDefaultValue, ImportClassTemplate) {10279 TranslationUnitDecl *FromTU = getTuDecl(CodeClass, Lang_CXX14);10280 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(10281 FromTU, classTemplateDecl(hasName("test")));10282 auto *D2 = dyn_cast<ClassTemplateDecl>(D3->getPreviousDecl());10283 auto *D1 = dyn_cast<ClassTemplateDecl>(D2->getPreviousDecl());10284 testImport(D1, D2, D3, nullptr);10285}10286 10287TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingClassTemplate) {10288 TranslationUnitDecl *ToTU = getToTuDecl(CodeClass, Lang_CXX14);10289 auto *ToD1 = FirstDeclMatcher<ClassTemplateDecl>().match(10290 ToTU, classTemplateDecl(hasName("test")));10291 TranslationUnitDecl *FromTU = getTuDecl(CodeClass, Lang_CXX14);10292 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(10293 FromTU, classTemplateDecl(hasName("test")));10294 auto *D2 = dyn_cast<ClassTemplateDecl>(D3->getPreviousDecl());10295 auto *D1 = dyn_cast<ClassTemplateDecl>(D2->getPreviousDecl());10296 testImport(D1, D2, D3, ToD1);10297}10298 10299TEST_P(ImportTemplateParmDeclDefaultValue, ImportVarTemplate) {10300 TranslationUnitDecl *FromTU = getTuDecl(CodeVar, Lang_CXX14);10301 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(10302 FromTU, varTemplateDecl(hasName("test")));10303 auto *D2 = dyn_cast<VarTemplateDecl>(D3->getPreviousDecl());10304 auto *D1 = dyn_cast<VarTemplateDecl>(D2->getPreviousDecl());10305 testImport(D1, D2, D3, nullptr);10306}10307 10308TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingVarTemplate) {10309 TranslationUnitDecl *ToTU = getToTuDecl(CodeVar, Lang_CXX14);10310 auto *ToD1 = FirstDeclMatcher<VarTemplateDecl>().match(10311 ToTU, varTemplateDecl(hasName("test")));10312 TranslationUnitDecl *FromTU = getTuDecl(CodeVar, Lang_CXX14);10313 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(10314 FromTU, varTemplateDecl(hasName("test")));10315 auto *D2 = dyn_cast<VarTemplateDecl>(D3->getPreviousDecl());10316 auto *D1 = dyn_cast<VarTemplateDecl>(D2->getPreviousDecl());10317 testImport(D1, D2, D3, ToD1);10318}10319 10320TEST_P(ImportTemplateParmDeclDefaultValue,10321 NonTypeTemplateParmDeclCircularDependency) {10322 const char *Code =10323 R"(10324 struct Z;10325 10326 struct Y {10327 Z *z;10328 static const int x = 1;10329 };10330 10331 template <int P1 = Y::x>10332 struct X;10333 10334 template <int P2>10335 struct X {10336 static const int A = 1;10337 };10338 10339 struct Z {10340 template<int P>10341 void f(int A = X<P>::A);10342 };10343 )";10344 10345 Decl *FromTU = getTuDecl(Code, Lang_CXX14);10346 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(10347 FromTU, classTemplateDecl(hasName("X")));10348 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(10349 FromTU, classTemplateDecl(hasName("X")));10350 10351 testTemplateParmDeclCircularDependency<NonTypeTemplateParmDecl>(10352 FromD, FromDInherited);10353}10354 10355TEST_P(ImportTemplateParmDeclDefaultValue,10356 TemplateTypeParmDeclCircularDependency) {10357 const char *Code =10358 R"(10359 struct Z;10360 10361 struct Y {10362 Z *z;10363 };10364 10365 template <typename T1 = Y>10366 struct X;10367 10368 template <typename T2>10369 struct X {10370 static const int A = 1;10371 };10372 10373 struct Z {10374 template<typename T>10375 void f(int A = X<T>::A);10376 };10377 )";10378 10379 Decl *FromTU = getTuDecl(Code, Lang_CXX14);10380 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(10381 FromTU, classTemplateDecl(hasName("X")));10382 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(10383 FromTU, classTemplateDecl(hasName("X")));10384 10385 testTemplateParmDeclCircularDependency<TemplateTypeParmDecl>(FromD,10386 FromDInherited);10387}10388 10389TEST_P(ImportTemplateParmDeclDefaultValue,10390 TemplateTemplateParmDeclCircularDependency) {10391 const char *Code =10392 R"(10393 struct Z;10394 10395 template <int>10396 struct Y {10397 Z *z;10398 };10399 10400 template <template <int> class T1 = Y>10401 struct X;10402 10403 template <template <int> class T2>10404 struct X {10405 static const int A = 1;10406 };10407 10408 struct Z {10409 template <template <int> class T>10410 void f(int A = X<T>::A);10411 };10412 )";10413 10414 Decl *FromTU = getTuDecl(Code, Lang_CXX14);10415 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(10416 FromTU, classTemplateDecl(hasName("X")));10417 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(10418 FromTU, classTemplateDecl(hasName("X")));10419 10420 testTemplateParmDeclCircularDependency<TemplateTemplateParmDecl>(10421 FromD, FromDInherited);10422}10423 10424TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch1) {10425 const char *ToCode =10426 R"(10427 namespace a {10428 }10429 namespace a {10430 struct X { int A; };10431 }10432 )";10433 getToTuDecl(ToCode, Lang_CXX11);10434 const char *Code =10435 R"(10436 namespace a {10437 struct X { char A; };10438 }10439 )";10440 Decl *FromTU = getTuDecl(Code, Lang_CXX11);10441 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(10442 FromTU, cxxRecordDecl(hasName("X")));10443 auto *ImportedX = Import(FromX, Lang_CXX11);10444 EXPECT_FALSE(ImportedX);10445}10446 10447TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch2) {10448 const char *ToCode =10449 R"(10450 namespace a {10451 struct X { int A; };10452 }10453 namespace a {10454 }10455 )";10456 getToTuDecl(ToCode, Lang_CXX11);10457 const char *Code =10458 R"(10459 namespace a {10460 struct X { char A; };10461 }10462 )";10463 Decl *FromTU = getTuDecl(Code, Lang_CXX11);10464 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(10465 FromTU, cxxRecordDecl(hasName("X")));10466 auto *ImportedX = Import(FromX, Lang_CXX11);10467 EXPECT_FALSE(ImportedX);10468}10469 10470TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch1) {10471 const char *ToCode =10472 R"(10473 namespace a {10474 }10475 namespace a {10476 struct X { int A; };10477 }10478 )";10479 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);10480 const char *Code =10481 R"(10482 namespace a {10483 struct X { int A; };10484 }10485 )";10486 Decl *FromTU = getTuDecl(Code, Lang_CXX11);10487 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(10488 FromTU, cxxRecordDecl(hasName("X")));10489 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(10490 ToTU, cxxRecordDecl(hasName("X")));10491 auto *ImportedX = Import(FromX, Lang_CXX11);10492 EXPECT_EQ(ImportedX, ToX);10493}10494 10495TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch2) {10496 const char *ToCode =10497 R"(10498 namespace a {10499 struct X { int A; };10500 }10501 namespace a {10502 }10503 )";10504 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);10505 const char *Code =10506 R"(10507 namespace a {10508 struct X { int A; };10509 }10510 )";10511 Decl *FromTU = getTuDecl(Code, Lang_CXX11);10512 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(10513 FromTU, cxxRecordDecl(hasName("X")));10514 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(10515 ToTU, cxxRecordDecl(hasName("X")));10516 auto *ImportedX = Import(FromX, Lang_CXX11);10517 EXPECT_EQ(ImportedX, ToX);10518}10519 10520TEST_P(ASTImporterLookupTableTest, PrimaryDCChangeAtImport) {10521 const char *ToCode =10522 R"(10523 template <class T>10524 struct X;10525 )";10526 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);10527 auto *ToX = FirstDeclMatcher<ClassTemplateDecl>().match(10528 ToTU, classTemplateDecl(hasName("X")));10529 NamedDecl *ToParm = ToX->getTemplateParameters()->getParam(0);10530 DeclContext *OldPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext();10531 ASSERT_EQ(ToParm->getDeclContext(), ToX->getTemplatedDecl());10532 ASSERT_EQ(SharedStatePtr->getLookupTable()10533 ->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName())10534 .size(),10535 1u);10536 ASSERT_TRUE(SharedStatePtr->getLookupTable()->contains(10537 ToX->getTemplatedDecl(), ToParm));10538 10539 const char *Code =10540 R"(10541 template <class T>10542 struct X;10543 template <class T>10544 struct X {};10545 )";10546 Decl *FromTU = getTuDecl(Code, Lang_CXX11);10547 auto *FromX = LastDeclMatcher<ClassTemplateDecl>().match(10548 FromTU, classTemplateDecl(hasName("X")));10549 10550 auto *ImportedX = Import(FromX, Lang_CXX11);10551 10552 EXPECT_TRUE(ImportedX);10553 EXPECT_EQ(ImportedX->getTemplateParameters()->getParam(0)->getDeclContext(),10554 ImportedX->getTemplatedDecl());10555 10556 // ToX did not change at the import.10557 // Verify that primary context has changed after import of class definition.10558 DeclContext *NewPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext();10559 EXPECT_NE(OldPrimaryDC, NewPrimaryDC);10560 // The lookup table should not be different than it was before.10561 EXPECT_EQ(SharedStatePtr->getLookupTable()10562 ->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName())10563 .size(),10564 1u);10565 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(10566 ToX->getTemplatedDecl(), ToParm));10567}10568 10569TEST_P(ASTImporterOptionSpecificTestBase,10570 ExistingUndeclaredImportDeclaredFriend) {10571 Decl *ToTU = getToTuDecl(10572 R"(10573 template <class A, A>10574 struct foo;10575 10576 template <class A>10577 struct X {10578 template <class A1, A1>10579 friend struct foo;10580 };10581 )",10582 Lang_CXX11);10583 Decl *FromTU = getTuDecl(10584 R"(10585 template <class A, A>10586 struct foo;10587 10588 template <class A>10589 struct X {10590 template <class A1, A1>10591 friend struct foo;10592 };10593 10594 X<int> x;10595 )",10596 Lang_CXX11);10597 10598 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());10599 auto *ToFrD1 = ToFr1->getFriendDecl();10600 10601 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());10602 auto *FromFr2 = LastDeclMatcher<FriendDecl>().match(FromTU, friendDecl());10603 10604 auto *FromFrD1 = FromFr1->getFriendDecl();10605 auto *FromFrD2 = FromFr2->getFriendDecl();10606 10607 auto *Ctx1 = cast<Decl>(FromFrD1->getDeclContext());10608 auto *Ctx2 = cast<Decl>(FromFrD2->getDeclContext());10609 10610 ASSERT_EQ(Ctx1, Ctx2);10611 ASSERT_EQ(ToFrD1->getTemplateDepth(), 1u);10612 ASSERT_EQ(FromFrD2->getTemplateDepth(), 0u);10613 ASSERT_EQ(ToFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);10614 ASSERT_EQ(FromFrD2->getFriendObjectKind(), Decl::FOK_Declared);10615 10616 auto *ToFr2Imp = Import(FromFr2, Lang_CXX11);10617 10618 EXPECT_TRUE(ToFr2Imp);10619}10620 10621TEST_P(ASTImporterOptionSpecificTestBase,10622 ExistingDeclaredImportUndeclaredFriend) {10623 Decl *ToTU = getToTuDecl(10624 R"(10625 template <class A, A>10626 struct foo;10627 10628 template <class A>10629 struct X {10630 template <class A1, A1>10631 friend struct foo;10632 };10633 10634 X<int> x;10635 )",10636 Lang_CXX11);10637 Decl *FromTU = getTuDecl(10638 R"(10639 template <class A, A>10640 struct foo;10641 10642 template <class A>10643 struct X {10644 template <class A1, A1>10645 friend struct foo;10646 };10647 )",10648 Lang_CXX11);10649 10650 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());10651 auto *ToFr2 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());10652 10653 auto *ToFrD1 = ToFr1->getFriendDecl();10654 auto *ToFrD2 = ToFr2->getFriendDecl();10655 10656 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());10657 auto *FromFrD1 = FromFr1->getFriendDecl();10658 10659 auto *Ctx1 = cast<Decl>(ToFrD1->getDeclContext());10660 auto *Ctx2 = cast<Decl>(ToFrD2->getDeclContext());10661 10662 ASSERT_EQ(Ctx1, Ctx2);10663 ASSERT_EQ(FromFrD1->getTemplateDepth(), 1u);10664 ASSERT_EQ(ToFrD2->getTemplateDepth(), 0u);10665 ASSERT_EQ(FromFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);10666 ASSERT_EQ(ToFrD2->getFriendObjectKind(), Decl::FOK_Declared);10667 10668 auto *ToFr1Imp = Import(FromFr1, Lang_CXX11);10669 10670 EXPECT_TRUE(ToFr1Imp);10671 EXPECT_EQ(ToFr1Imp, ToFr1);10672}10673 10674struct ImportAndMergeAnonymousNamespace10675 : public ASTImporterOptionSpecificTestBase {10676protected:10677 void test(const char *ToCode, const char *FromCode) {10678 Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11);10679 Decl *FromTU = getTuDecl(FromCode, Lang_CXX11);10680 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(10681 FromTU, namespaceDecl(isAnonymous()));10682 auto *ToNS = FirstDeclMatcher<NamespaceDecl>().match(10683 ToTU, namespaceDecl(isAnonymous()));10684 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(10685 FromTU, functionDecl(hasName("f")));10686 auto *ImportedF = Import(FromF, Lang_CXX11);10687 EXPECT_TRUE(ImportedF);10688 EXPECT_EQ(ImportedF->getDeclContext(), ToNS);10689 auto *ImportedNS = Import(FromNS, Lang_CXX11);10690 EXPECT_EQ(ImportedNS, ToNS);10691 }10692};10693 10694TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInTU) {10695 const char *ToCode =10696 R"(10697 namespace {10698 }10699 )";10700 const char *FromCode =10701 R"(10702 namespace {10703 void f();10704 }10705 )";10706 test(ToCode, FromCode);10707}10708 10709TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInLinkageSpec) {10710 const char *ToCode =10711 R"(10712 extern "C" {10713 namespace {10714 }10715 }10716 )";10717 const char *FromCode =10718 R"(10719 extern "C" {10720 namespace {10721 void f();10722 }10723 }10724 )";10725 test(ToCode, FromCode);10726}10727 10728TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInNamespace) {10729 const char *ToCode =10730 R"(10731 namespace X {10732 namespace {10733 }10734 }10735 )";10736 const char *FromCode =10737 R"(10738 namespace X {10739 namespace {10740 void f();10741 }10742 }10743 )";10744 test(ToCode, FromCode);10745}10746 10747INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,10748 DefaultTestValuesForRunOptions);10749 10750INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportPath,10751 ::testing::Values(std::vector<std::string>()));10752 10753INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportExpr,10754 DefaultTestValuesForRunOptions);10755 10756INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFixedPointExpr,10757 ExtendWithOptions(DefaultTestArrayForRunOptions,10758 std::vector<std::string>{10759 "-ffixed-point"}));10760 10761INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportBlock,10762 ExtendWithOptions(DefaultTestArrayForRunOptions,10763 std::vector<std::string>{10764 "-fblocks"}));10765 10766INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportType,10767 DefaultTestValuesForRunOptions);10768 10769INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportDecl,10770 DefaultTestValuesForRunOptions);10771 10772INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,10773 DefaultTestValuesForRunOptions);10774 10775INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ErrorHandlingTest,10776 DefaultTestValuesForRunOptions);10777 10778INSTANTIATE_TEST_SUITE_P(ParameterizedTests, RedirectingImporterTest,10779 DefaultTestValuesForRunOptions);10780 10781INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctions,10782 DefaultTestValuesForRunOptions);10783 10784INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAutoFunctions,10785 DefaultTestValuesForRunOptions);10786 10787INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctionTemplates,10788 DefaultTestValuesForRunOptions);10789 10790INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctionTemplates,10791 DefaultTestValuesForRunOptions);10792 10793INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportClasses,10794 DefaultTestValuesForRunOptions);10795 10796INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctions,10797 DefaultTestValuesForRunOptions);10798 10799INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendClasses,10800 DefaultTestValuesForRunOptions);10801 10802INSTANTIATE_TEST_SUITE_P(ParameterizedTests,10803 ImportFunctionTemplateSpecializations,10804 DefaultTestValuesForRunOptions);10805 10806INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportImplicitMethods,10807 DefaultTestValuesForRunOptions);10808 10809INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportVariables,10810 DefaultTestValuesForRunOptions);10811 10812INSTANTIATE_TEST_SUITE_P(ParameterizedTests, LLDBLookupTest,10813 DefaultTestValuesForRunOptions);10814 10815INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportSourceLocations,10816 DefaultTestValuesForRunOptions);10817 10818INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportWithExternalSource,10819 DefaultTestValuesForRunOptions);10820 10821INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAttributes,10822 DefaultTestValuesForRunOptions);10823 10824INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportInjectedClassNameType,10825 DefaultTestValuesForRunOptions);10826 10827INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportMatrixType,10828 DefaultTestValuesForRunOptions);10829 10830INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportTemplateParmDeclDefaultValue,10831 DefaultTestValuesForRunOptions);10832 10833INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAndMergeAnonymousNamespace,10834 DefaultTestValuesForRunOptions);10835 10836// FIXME: Make ImportOpenCLPipe test work.10837// INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportOpenCLPipe,10838// DefaultTestValuesForRunOptions);10839GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImportOpenCLPipe);10840 10841} // end namespace ast_matchers10842} // end namespace clang10843