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