Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -73,6 +73,11 @@ }; +auto DefaultTestValuesForRunOptions = ::testing::Values( + ArgVector(), ArgVector{"-fdelayed-template-parsing"}, + ArgVector{"-fms-compatibility"}, + ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"}); + // Base class for those tests which use the family of `testImport` functions. class TestImportBase : public ParameterizedTestsFixture { @@ -1976,33 +1981,6 @@ struct ImportFunctions : ASTImporterTestBase {}; -TEST_P(ImportFunctions, - DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) { - Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = // Definition - LastDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); -} - -TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) { - Decl *FromTU = getTuDecl("void f() {}", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); -} - TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); @@ -2039,138 +2017,6 @@ EXPECT_EQ(To1->getPreviousDecl(), To0); } -TEST_P(ImportFunctions, ImportPrototypes) { - auto Pattern = functionDecl(hasName("f")); - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctions, ImportDefinitions) { - auto Pattern = functionDecl(hasName("f")); - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); -} - -TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { - auto Pattern = functionDecl(hasName("f")); - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { - auto Pattern = functionDecl(hasName("f")); - - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - - Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); - FunctionDecl *DefinitionD = - LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); - EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); -} - -TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) { - auto Pattern = functionDecl(hasName("f")); - - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 3u); - FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); - - FunctionDecl *DefinitionD = - LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); - - EXPECT_TRUE(DefinitionD->getPreviousDecl()); - EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody()); - EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); -} - TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { auto Code = R"( @@ -3371,154 +3217,6 @@ struct ImportClasses : ASTImporterTestBase {}; -TEST_P(ImportClasses, - PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { - Decl *FromTU = getTuDecl("class X;", Lang_CXX); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto FromD = FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto ToD = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == ToD); - EXPECT_FALSE(ToD->isThisDeclarationADefinition()); -} - -TEST_P(ImportClasses, ImportPrototypeAfterImportedPrototype) { - Decl *FromTU = getTuDecl("class X; class X;", Lang_CXX); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher().match(FromTU, Pattern); - auto From1 = LastDeclMatcher().match(FromTU, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - EXPECT_TRUE(Imported1 == To1); - EXPECT_FALSE(To0->isThisDeclarationADefinition()); - EXPECT_FALSE(To1->isThisDeclarationADefinition()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportClasses, DefinitionShouldBeImportedAsADefinition) { - Decl *FromTU = getTuDecl("class X {};", Lang_CXX); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->isThisDeclarationADefinition()); -} - -TEST_P(ImportClasses, ImportPrototypeFromDifferentTUAfterImportedPrototype) { - Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc"); - Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc"); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - EXPECT_TRUE(Imported1 == To1); - EXPECT_FALSE(To0->isThisDeclarationADefinition()); - EXPECT_FALSE(To1->isThisDeclarationADefinition()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportClasses, ImportDefinitions) { - Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc"); - Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc"); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(Imported0, Imported1); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto To0 = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - EXPECT_TRUE(To0->isThisDeclarationADefinition()); -} - -TEST_P(ImportClasses, ImportDefinitionThenPrototype) { - Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc"); - Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc"); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto FromDef = FirstDeclMatcher().match(FromTU0, Pattern); - auto FromProto = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); - - EXPECT_NE(ImportedDef, ImportedProto); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto ToDef = FirstDeclMatcher().match(ToTU, Pattern); - auto ToProto = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedDef == ToDef); - EXPECT_TRUE(ImportedProto == ToProto); - EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); - EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); - EXPECT_EQ(ToProto->getPreviousDecl(), ToDef); -} - -TEST_P(ImportClasses, ImportPrototypeThenDefinition) { - Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc"); - Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc"); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto FromProto = FirstDeclMatcher().match(FromTU0, Pattern); - auto FromDef = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); - - EXPECT_NE(ImportedDef, ImportedProto); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto ToProto = FirstDeclMatcher().match(ToTU, Pattern); - auto ToDef = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedDef == ToDef); - EXPECT_TRUE(ImportedProto == ToProto); - EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); - EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); - EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); -} - -TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInToContext) { - Decl *ToTU = getToTuDecl("struct X;", Lang_C); - Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc"); - auto Pattern = recordDecl(hasName("X"), unless(isImplicit())); - auto ToProto = FirstDeclMatcher().match(ToTU, Pattern); - auto FromDef = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *ImportedDef = Import(FromDef, Lang_C); - - EXPECT_NE(ImportedDef, ToProto); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto ToDef = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedDef == ToDef); - EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); - EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); - EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); -} - TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) { Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C); Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc"); @@ -3577,169 +3275,572 @@ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); } -struct ImportClassTemplates : ASTImporterTestBase {}; +// FIXME put these structs and the tests rely on them into their own separate +// test file! +struct Function { + using DeclTy = FunctionDecl; + static constexpr auto *Prototype = "void X();"; + static constexpr auto *Definition = "void X() {}"; + BindableMatcher getPattern() { + return functionDecl(hasName("X"), unless(isImplicit())); + } +}; -TEST_P(ImportClassTemplates, - PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { - Decl *FromTU = getTuDecl("template class X;", Lang_CXX); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto FromD = FirstDeclMatcher().match(FromTU, Pattern); +struct Class { + using DeclTy = CXXRecordDecl; + static constexpr auto *Prototype = "class X;"; + static constexpr auto *Definition = "class X {};"; + BindableMatcher getPattern() { + return cxxRecordDecl(hasName("X"), unless(isImplicit())); + } +}; - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); +struct Variable { + using DeclTy = VarDecl; + static constexpr auto *Prototype = "extern int X;"; + static constexpr auto *Definition = "int X;"; + BindableMatcher getPattern() { + return varDecl(hasName("X")); + } +}; - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto ToD = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == ToD); - ASSERT_TRUE(ToD->getTemplatedDecl()); - EXPECT_FALSE(ToD->isThisDeclarationADefinition()); -} +struct FunctionTemplate { + using DeclTy = FunctionTemplateDecl; + static constexpr auto *Prototype = "template void X();"; + static constexpr auto *Definition = + R"( + template void X() {}; + // Explicit instantiation is a must because of -fdelayed-template-parsing: + template void X(); + )"; + BindableMatcher getPattern() { + return functionTemplateDecl(hasName("X"), unless(isImplicit())); + } +}; -TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) { - Decl *FromTU = getTuDecl( - "template class X; template class X;", Lang_CXX); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher().match(FromTU, Pattern); - auto From1 = LastDeclMatcher().match(FromTU, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - EXPECT_TRUE(Imported1 == To1); - ASSERT_TRUE(To0->getTemplatedDecl()); - ASSERT_TRUE(To1->getTemplatedDecl()); - EXPECT_FALSE(To0->isThisDeclarationADefinition()); - EXPECT_FALSE(To1->isThisDeclarationADefinition()); - EXPECT_EQ(To1->getPreviousDecl(), To0); - EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(), - To0->getTemplatedDecl()); -} +struct ClassTemplate { + using DeclTy = ClassTemplateDecl; + static constexpr auto *Prototype = "template class X;"; + static constexpr auto *Definition = "template class X {};"; + BindableMatcher getPattern() { + return classTemplateDecl(hasName("X"), unless(isImplicit())); + } +}; + +struct FunctionTemplateSpec { + using DeclTy = FunctionDecl; + static constexpr auto *Prototype = + R"( + // Proto of the primary template. + template + void X(); + // Proto of the specialization. + template <> + void X(); + )"; + static constexpr auto *Definition = + R"( + // Proto of the primary template. + template + void X(); + // Specialization and definition. + template <> + void X() {} + )"; + BindableMatcher getPattern() { + return functionDecl(hasName("X"), isExplicitTemplateSpecialization()); + } +}; -TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) { - Decl *FromTU = getTuDecl("template class X {};", Lang_CXX); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); +template +struct RedeclChain : ASTImporterTestBase { + + using DeclTy = typename TypeParam::DeclTy; + std::string getPrototype() { return TypeParam::Prototype; } + std::string getDefinition() { return TypeParam::Definition; } + BindableMatcher getPattern() const { return TypeParam().getPattern(); } + + void + TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() { + Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, getPattern()); + ASSERT_FALSE(FromD->isThisDeclarationADefinition()); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 1u); + auto *ToD = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(ImportedD == ToD); + EXPECT_FALSE(ToD->isThisDeclarationADefinition()); + if (auto *ToT = dyn_cast(ToD)) + EXPECT_TRUE(ToT->getTemplatedDecl()); + } - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); + void TypedTest_DefinitionShouldBeImportedAsADefinition() { + Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, getPattern()); + ASSERT_TRUE(FromD->isThisDeclarationADefinition()); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto ToD = LastDeclMatcher().match(ToTU, Pattern); - ASSERT_TRUE(ToD->getTemplatedDecl()); - EXPECT_TRUE(ToD->isThisDeclarationADefinition()); -} - -TEST_P(ImportClassTemplates, - ImportPrototypeFromDifferentTUAfterImportedPrototype) { - Decl *FromTU0 = - getTuDecl("template class X;", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template class X;", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - EXPECT_TRUE(Imported1 == To1); - ASSERT_TRUE(To0->getTemplatedDecl()); - ASSERT_TRUE(To1->getTemplatedDecl()); - EXPECT_FALSE(To0->isThisDeclarationADefinition()); - EXPECT_FALSE(To1->isThisDeclarationADefinition()); - EXPECT_EQ(To1->getPreviousDecl(), To0); - EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(), - To0->getTemplatedDecl()); -} - -TEST_P(ImportClassTemplates, ImportDefinitions) { - Decl *FromTU0 = - getTuDecl("template class X {};", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template class X {};", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(Imported0, Imported1); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto To0 = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - ASSERT_TRUE(To0->getTemplatedDecl()); - EXPECT_TRUE(To0->isThisDeclarationADefinition()); -} - -TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) { - Decl *FromTU0 = - getTuDecl("template class X {};", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template class X;", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto FromDef = FirstDeclMatcher().match(FromTU0, Pattern); - auto FromProto = - FirstDeclMatcher().match(FromTU1, Pattern); + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 1u); + auto *ToD = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(ToD->isThisDeclarationADefinition()); + if (auto *ToT = dyn_cast(ToD)) + EXPECT_TRUE(ToT->getTemplatedDecl()); + } + + void TypedTest_ImportPrototypeAfterImportedPrototype() { + Decl *FromTU = getTuDecl( + getPrototype() + getPrototype(), Lang_CXX); + auto *From0 = + FirstDeclMatcher().match(FromTU, getPattern()); + auto *From1 = LastDeclMatcher().match(FromTU, getPattern()); + ASSERT_FALSE(From0->isThisDeclarationADefinition()); + ASSERT_FALSE(From1->isThisDeclarationADefinition()); + + Decl *Imported0 = Import(From0, Lang_CXX); + Decl *Imported1 = Import(From1, Lang_CXX); + Decl *ToTU = Imported0->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, getPattern()); + auto *To1 = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(Imported0 == To0); + EXPECT_TRUE(Imported1 == To1); + EXPECT_FALSE(To0->isThisDeclarationADefinition()); + EXPECT_FALSE(To1->isThisDeclarationADefinition()); + EXPECT_EQ(To1->getPreviousDecl(), To0); + if (auto *ToT0 = dyn_cast(To0)) { + auto *ToT1 = cast(To1); + ASSERT_TRUE(ToT0->getTemplatedDecl()); + ASSERT_TRUE(ToT1->getTemplatedDecl()); + EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(), + ToT0->getTemplatedDecl()); + } + } + + void TypedTest_ImportDefinitionAfterImportedPrototype() { + Decl *FromTU = getTuDecl( + getPrototype() + getDefinition(), Lang_CXX); + auto *FromProto = FirstDeclMatcher().match(FromTU, getPattern()); + auto *FromDef = LastDeclMatcher().match(FromTU, getPattern()); + ASSERT_FALSE(FromProto->isThisDeclarationADefinition()); + ASSERT_TRUE(FromDef->isThisDeclarationADefinition()); + + Decl *ImportedProto = Import(FromProto, Lang_CXX); + Decl *ImportedDef = Import(FromDef, Lang_CXX); + Decl *ToTU = ImportedProto->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + auto *ToProto = FirstDeclMatcher().match(ToTU, getPattern()); + auto *ToDef = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(ImportedProto == ToProto); + EXPECT_TRUE(ImportedDef == ToDef); + EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); + EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); + EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); + if (auto *ToProtoT = dyn_cast(ToProto)) { + auto *ToDefT = cast(ToDef); + ASSERT_TRUE(ToProtoT->getTemplatedDecl()); + ASSERT_TRUE(ToDefT->getTemplatedDecl()); + EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(), + ToProtoT->getTemplatedDecl()); + } + } + + void TypedTest_ImportPrototypeAfterImportedDefinition() { + Decl *FromTU = getTuDecl( + getDefinition() + getPrototype(), Lang_CXX); + auto *FromDef = FirstDeclMatcher().match(FromTU, getPattern()); + auto *FromProto = LastDeclMatcher().match(FromTU, getPattern()); + ASSERT_TRUE(FromDef->isThisDeclarationADefinition()); + ASSERT_FALSE(FromProto->isThisDeclarationADefinition()); + + Decl *ImportedDef = Import(FromDef, Lang_CXX); + Decl *ImportedProto = Import(FromProto, Lang_CXX); + Decl *ToTU = ImportedDef->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + auto *ToDef = FirstDeclMatcher().match(ToTU, getPattern()); + auto *ToProto = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(ImportedDef == ToDef); + EXPECT_TRUE(ImportedProto == ToProto); + EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); + EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); + EXPECT_EQ(ToProto->getPreviousDecl(), ToDef); + if (auto *ToDefT = dyn_cast(ToDef)) { + auto *ToProtoT = cast(ToProto); + ASSERT_TRUE(ToDefT->getTemplatedDecl()); + ASSERT_TRUE(ToProtoT->getTemplatedDecl()); + EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(), + ToDefT->getTemplatedDecl()); + } + } + + void TypedTest_ImportPrototypes() { + Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc"); + Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc"); + auto *From0 = FirstDeclMatcher().match(FromTU0, getPattern()); + auto *From1 = FirstDeclMatcher().match(FromTU1, getPattern()); + ASSERT_FALSE(From0->isThisDeclarationADefinition()); + ASSERT_FALSE(From1->isThisDeclarationADefinition()); + + Decl *Imported0 = Import(From0, Lang_CXX); + Decl *Imported1 = Import(From1, Lang_CXX); + Decl *ToTU = Imported0->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, getPattern()); + auto *To1 = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(Imported0 == To0); + EXPECT_TRUE(Imported1 == To1); + EXPECT_FALSE(To0->isThisDeclarationADefinition()); + EXPECT_FALSE(To1->isThisDeclarationADefinition()); + EXPECT_EQ(To1->getPreviousDecl(), To0); + if (auto *ToT0 = dyn_cast(To0)) { + auto *ToT1 = cast(To1); + ASSERT_TRUE(ToT0->getTemplatedDecl()); + ASSERT_TRUE(ToT1->getTemplatedDecl()); + EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(), + ToT0->getTemplatedDecl()); + } + // Extra check for specializations. + // FIXME Add this check to other tests too (possibly factor out into a + // function), when they start to pass. + if (auto *From0F = dyn_cast(From0)) { + auto *To0F = cast(To0); + if (From0F->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) { + auto *TemplateD = FirstDeclMatcher().match( + ToTU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0F->getCanonicalDecl()); + } + } + } + + void TypedTest_ImportDefinitions() { + Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc"); + Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc"); + auto *From0 = FirstDeclMatcher().match(FromTU0, getPattern()); + auto *From1 = FirstDeclMatcher().match(FromTU1, getPattern()); + ASSERT_TRUE(From0->isThisDeclarationADefinition()); + ASSERT_TRUE(From1->isThisDeclarationADefinition()); + + Decl *Imported0 = Import(From0, Lang_CXX); + Decl *Imported1 = Import(From1, Lang_CXX); + Decl *ToTU = Imported0->getTranslationUnitDecl(); + + EXPECT_EQ(Imported0, Imported1); + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 1u); + auto *To0 = FirstDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(Imported0 == To0); + EXPECT_TRUE(To0->isThisDeclarationADefinition()); + if (auto *ToT0 = dyn_cast(To0)) + EXPECT_TRUE(ToT0->getTemplatedDecl()); + } + + void TypedTest_ImportDefinitionThenPrototype() { + Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc"); + Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc"); + auto *FromDef = FirstDeclMatcher().match(FromTUDef, getPattern()); + auto *FromProto = + FirstDeclMatcher().match(FromTUProto, getPattern()); + ASSERT_TRUE(FromDef->isThisDeclarationADefinition()); + ASSERT_FALSE(FromProto->isThisDeclarationADefinition()); + + Decl *ImportedDef = Import(FromDef, Lang_CXX); + Decl *ImportedProto = Import(FromProto, Lang_CXX); + Decl *ToTU = ImportedDef->getTranslationUnitDecl(); + + EXPECT_NE(ImportedDef, ImportedProto); + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + auto *ToDef = FirstDeclMatcher().match(ToTU, getPattern()); + auto *ToProto = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(ImportedDef == ToDef); + EXPECT_TRUE(ImportedProto == ToProto); + EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); + EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); + EXPECT_EQ(ToProto->getPreviousDecl(), ToDef); + if (auto *ToDefT = dyn_cast(ToDef)) { + auto *ToProtoT = cast(ToProto); + ASSERT_TRUE(ToDefT->getTemplatedDecl()); + ASSERT_TRUE(ToProtoT->getTemplatedDecl()); + EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(), + ToDefT->getTemplatedDecl()); + } + } + + void TypedTest_ImportPrototypeThenDefinition() { + Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc"); + Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc"); + auto *FromProto = + FirstDeclMatcher().match(FromTUProto, getPattern()); + auto *FromDef = FirstDeclMatcher().match(FromTUDef, getPattern()); + ASSERT_TRUE(FromDef->isThisDeclarationADefinition()); + ASSERT_FALSE(FromProto->isThisDeclarationADefinition()); + + Decl *ImportedProto = Import(FromProto, Lang_CXX); + Decl *ImportedDef = Import(FromDef, Lang_CXX); + Decl *ToTU = ImportedDef->getTranslationUnitDecl(); + + EXPECT_NE(ImportedDef, ImportedProto); + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + auto *ToProto = FirstDeclMatcher().match(ToTU, getPattern()); + auto *ToDef = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(ImportedDef == ToDef); + EXPECT_TRUE(ImportedProto == ToProto); + EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); + EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); + EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); + if (auto *ToDefT = dyn_cast(ToDef)) { + auto *ToProtoT = cast(ToProto); + ASSERT_TRUE(ToDefT->getTemplatedDecl()); + ASSERT_TRUE(ToProtoT->getTemplatedDecl()); + EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(), + ToProtoT->getTemplatedDecl()); + } + } + + void TypedTest_WholeRedeclChainIsImportedAtOnce() { + Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX); + auto *FromD = // Definition + LastDeclMatcher().match(FromTU, getPattern()); + ASSERT_TRUE(FromD->isThisDeclarationADefinition()); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + // The whole redecl chain is imported at once. + EXPECT_EQ(DeclCounter().match(ToTU, getPattern()), 2u); + EXPECT_TRUE(cast(ImportedD)->isThisDeclarationADefinition()); + } + + void TypedTest_ImportPrototypeThenProtoAndDefinition() { + { + Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, getPattern()); + Import(FromD, Lang_CXX); + } + { + Decl *FromTU = + getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, getPattern()); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + + ASSERT_EQ(DeclCounter().match(ToTU, getPattern()), 3u); + DeclTy *ProtoD = FirstDeclMatcher().match(ToTU, getPattern()); + EXPECT_FALSE(ProtoD->isThisDeclarationADefinition()); + + DeclTy *DefinitionD = LastDeclMatcher().match(ToTU, getPattern()); + EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition()); + + EXPECT_TRUE(DefinitionD->getPreviousDecl()); + EXPECT_FALSE( + DefinitionD->getPreviousDecl()->isThisDeclarationADefinition()); + EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); + } +}; + +#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \ + NamePrefix, TestCase) \ + using BaseTemplate##TypeParam = BaseTemplate; \ + TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \ + TypedTest_##TestCase(); \ + } + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, Function, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, Class, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, Variable, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, FunctionTemplate, DISABLED_, + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, ClassTemplate, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, FunctionTemplateSpec, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, FunctionTemplate, DISABLED_, + DefinitionShouldBeImportedAsADefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, FunctionTemplateSpec, , + DefinitionShouldBeImportedAsADefinition); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportPrototypeAfterImportedPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , + ImportPrototypeAfterImportedPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportPrototypeAfterImportedPrototype); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + ImportPrototypeAfterImportedPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , + ImportPrototypeAfterImportedPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , + ImportPrototypeAfterImportedPrototype); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportDefinitionAfterImportedPrototype); +// FIXME This does not pass, possible error with Class import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, DISABLED_, + ImportDefinitionAfterImportedPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportDefinitionAfterImportedPrototype); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + ImportDefinitionAfterImportedPrototype); +// FIXME This does not pass, possible error with ClassTemplate import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, DISABLED_, + ImportDefinitionAfterImportedPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , + ImportDefinitionAfterImportedPrototype); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportPrototypeAfterImportedDefinition); +// FIXME This does not pass, possible error with Class import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, DISABLED_, + ImportPrototypeAfterImportedDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportPrototypeAfterImportedDefinition); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + ImportPrototypeAfterImportedDefinition); +// FIXME This does not pass, possible error with ClassTemplate import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, DISABLED_, + ImportPrototypeAfterImportedDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , + ImportPrototypeAfterImportedDefinition); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportPrototypes); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportPrototypes); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, ImportPrototypes); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , + ImportPrototypes); +// FIXME This does not pass, possible error with Spec import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, + DISABLED_, ImportPrototypes); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportDefinitions); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , + ImportDefinitions); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportDefinitions); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, ImportDefinitions); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , + ImportDefinitions); +// FIXME This does not pass, possible error with Spec import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, + DISABLED_, ImportDefinitions); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportDefinitionThenPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , + ImportDefinitionThenPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportDefinitionThenPrototype); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + ImportDefinitionThenPrototype); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , + ImportDefinitionThenPrototype); +// FIXME This does not pass, possible error with Spec import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, + DISABLED_, + ImportDefinitionThenPrototype); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportPrototypeThenDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , + ImportPrototypeThenDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportPrototypeThenDefinition); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + ImportPrototypeThenDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , + ImportPrototypeThenDefinition); +// FIXME This does not pass, possible error with Spec import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, + DISABLED_, + ImportPrototypeThenDefinition); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + WholeRedeclChainIsImportedAtOnce); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + WholeRedeclChainIsImportedAtOnce); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + WholeRedeclChainIsImportedAtOnce); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , + WholeRedeclChainIsImportedAtOnce); + +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , + ImportPrototypeThenProtoAndDefinition); +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , + ImportPrototypeThenProtoAndDefinition); +// FIXME Enable this test, once we import function templates chains correctly. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, + DISABLED_, + ImportPrototypeThenProtoAndDefinition); +// FIXME This does not pass, possible error with Spec import. +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, + DISABLED_, + ImportPrototypeThenProtoAndDefinition); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate, + DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec, + DefaultTestValuesForRunOptions, ); - EXPECT_NE(ImportedDef, ImportedProto); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto ToDef = FirstDeclMatcher().match(ToTU, Pattern); - auto ToProto = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedDef == ToDef); - EXPECT_TRUE(ImportedProto == ToProto); - ASSERT_TRUE(ToDef->getTemplatedDecl()); - ASSERT_TRUE(ToProto->getTemplatedDecl()); - EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); - EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); - EXPECT_EQ(ToProto->getPreviousDecl(), ToDef); - EXPECT_EQ(ToProto->getTemplatedDecl()->getPreviousDecl(), - ToDef->getTemplatedDecl()); -} - -TEST_P(ImportClassTemplates, ImportPrototypeThenDefinition) { - Decl *FromTU0 = - getTuDecl("template class X;", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template class X {};", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto FromProto = - FirstDeclMatcher().match(FromTU0, Pattern); - auto FromDef = FirstDeclMatcher().match(FromTU1, Pattern); - - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); - EXPECT_NE(ImportedDef, ImportedProto); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto ToProto = FirstDeclMatcher().match(ToTU, Pattern); - auto ToDef = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedDef == ToDef); - EXPECT_TRUE(ImportedProto == ToProto); - ASSERT_TRUE(ToProto->getTemplatedDecl()); - ASSERT_TRUE(ToDef->getTemplatedDecl()); - EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); - EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); - EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); - EXPECT_EQ(ToDef->getTemplatedDecl()->getPreviousDecl(), - ToProto->getTemplatedDecl()); -} struct ImportFriendClasses : ASTImporterTestBase {}; @@ -4199,184 +4300,6 @@ DeclCounter().match(ToTU, functionDecl(hasName("f")))); } -TEST_P(ImportFunctionTemplateSpecializations, - ImportPrototypes) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Proto of the specialization. - template <> - void f(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = LastDeclMatcher().match(FromTU, Pattern); - - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = LastDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - // Check that they are part of the same redecl chain. - EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl()); -} - -TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization and definition. - template <> - void f() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - - auto *TemplateD = FirstDeclMatcher().match( - ToTU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl()); -} - -TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization proto. - template <> - void f(); - // Specialization proto. - template <> - void f(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization proto. - template <> - void f(); - // Specialization definition. - template <> - void f() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization definition. - template <> - void f() {} - // Specialization proto. - template <> - void f(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - TEST_P(ASTImporterTestBase, ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) { { @@ -4865,12 +4788,6 @@ ParameterizedTests, CanonicalRedeclChain, ::testing::Values(ArgVector()),); -auto DefaultTestValuesForRunOptions = ::testing::Values( - ArgVector(), - ArgVector{"-fdelayed-template-parsing"}, - ArgVector{"-fms-compatibility"}, - ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"}); - INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions, ); @@ -4895,9 +4812,6 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, DefaultTestValuesForRunOptions, ); -INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates, - DefaultTestValuesForRunOptions, ); - INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses, DefaultTestValuesForRunOptions, );