From 86125ab6a213a0746842254a942fa94539256c1c Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Mon, 18 Feb 2019 11:09:56 +0000 Subject: [PATCH] [ASTImporter] Unify redecl chain tests as type parameterized tests Summary: This patch unifies all those tests which check the correctness of the redecl chains. Previously we had several structurally very similar test cases for each language construct (class, function, variable, function template, ...). We still use value-parameterized tests for the different AST compatibility switches (-fdelayed-template-parsing, -fms-compatibility). Gtest makes it possible to have either value-parameterized or type-parameterized fixtures. However, we cannot have both value- and type-parameterized test fixtures. So we use a value-parameterized test fixture in the gtest sense. We intend to mimic gtest's type-parameters via the type template parameter. We manually instantiate the different tests with the each types. After this patch I am planning to put the "generic redecl chain" related tests into their own separate test file (in another patch). Reviewers: a_sidorin, shafik, a.sidorin Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Differential Revision: https://reviews.llvm.org/D57236 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354259 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/ASTImporterTest.cpp | 1197 ++++++++++++++--------------- 1 file changed, 556 insertions(+), 641 deletions(-) diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 6c929b4d56..30bc9dc73c 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -2008,33 +2008,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) { struct ImportFunctions : ASTImporterOptionSpecificTestBase {}; -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")); @@ -2071,138 +2044,6 @@ TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { 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"( @@ -3875,154 +3716,6 @@ TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) { struct ImportClasses : ASTImporterOptionSpecificTestBase {}; -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"); @@ -4081,169 +3774,572 @@ TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) { EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); } -struct ImportClassTemplates : ASTImporterOptionSpecificTestBase {}; +// 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())); + } +}; -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); +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()); + } +}; - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); +template +struct RedeclChain : ASTImporterOptionSpecificTestBase { + + 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()); + } - 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); + void TypedTest_DefinitionShouldBeImportedAsADefinition() { + Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, getPattern()); + ASSERT_TRUE(FromD->isThisDeclarationADefinition()); - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); + 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(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 : ASTImporterOptionSpecificTestBase {}; @@ -4704,184 +4800,6 @@ TEST_P(ImportFunctionTemplateSpecializations, 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(ASTImporterOptionSpecificTestBase, ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) { { @@ -5496,9 +5414,6 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses, INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, DefaultTestValuesForRunOptions, ); -INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates, - DefaultTestValuesForRunOptions, ); - INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses, DefaultTestValuesForRunOptions, ); -- 2.40.0