Author: martong Date: Mon Feb 18 03:09:56 2019 New Revision: 354259 URL: http://llvm.org/viewvc/llvm-project?rev=354259&view=rev Log: [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 Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=354259&r1=354258&r2=354259&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Mon Feb 18 03:09:56 2019 @@ -2008,33 +2008,6 @@ TEST_P(ASTImporterOptionSpecificTestBase 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<FunctionDecl>().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); -} - -TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) { - Decl *FromTU = getTuDecl("void f() {}", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = - FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast<FunctionDecl>(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, ImportDefinition 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<FunctionDecl>().match(FromTU, Pattern); - - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().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<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().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<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().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<FunctionDecl>().match(FromTU, Pattern); - - Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); - FunctionDecl *DefinitionD = - LastDeclMatcher<FunctionDecl>().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<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u); - FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); - - FunctionDecl *DefinitionD = - LastDeclMatcher<FunctionDecl>().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, InitAndDefinitio struct ImportClasses : ASTImporterOptionSpecificTestBase {}; -TEST_P(ImportClasses, - PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { - Decl *FromTU = getTuDecl("class X;", Lang_CXX); - auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit())); - auto FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u); - auto ToD = LastDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(FromTU, Pattern); - auto From1 = LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern); - auto To1 = LastDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast<CXXRecordDecl>(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<CXXRecordDecl>().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern); - auto To1 = LastDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(ToTU, Pattern), 1u); - auto To0 = FirstDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(FromTU0, Pattern); - auto FromProto = FirstDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(ToTU, Pattern), 2u); - auto ToDef = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern); - auto ToProto = LastDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(FromTU0, Pattern); - auto FromDef = FirstDeclMatcher<CXXRecordDecl>().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<CXXRecordDecl>().match(ToTU, Pattern), 2u); - auto ToProto = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern); - auto ToDef = LastDeclMatcher<CXXRecordDecl>().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<RecordDecl>().match(ToTU, Pattern); - auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern); - - Decl *ImportedDef = Import(FromDef, Lang_C); - - EXPECT_NE(ImportedDef, ToProto); - EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u); - auto ToDef = LastDeclMatcher<RecordDecl>().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, ImportNestedProtot 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<Decl> getPattern() { + return functionDecl(hasName("X"), unless(isImplicit())); + } +}; -TEST_P(ImportClassTemplates, - PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { - Decl *FromTU = getTuDecl("template <class T> class X;", Lang_CXX); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern); +struct Class { + using DeclTy = CXXRecordDecl; + static constexpr auto *Prototype = "class X;"; + static constexpr auto *Definition = "class X {};"; + BindableMatcher<Decl> 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<Decl> getPattern() { + return varDecl(hasName("X")); + } +}; - EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u); - auto ToD = LastDeclMatcher<ClassTemplateDecl>().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 <class T> void X();"; + static constexpr auto *Definition = + R"( + template <class T> void X() {}; + // Explicit instantiation is a must because of -fdelayed-template-parsing: + template void X<int>(); + )"; + BindableMatcher<Decl> getPattern() { + return functionTemplateDecl(hasName("X"), unless(isImplicit())); + } +}; -TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) { - Decl *FromTU = getTuDecl( - "template <class T> class X; template <class T> class X;", Lang_CXX); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern); - auto From1 = LastDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern); - auto To1 = LastDeclMatcher<ClassTemplateDecl>().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 T> class X;"; + static constexpr auto *Definition = "template <class T> class X {};"; + BindableMatcher<Decl> getPattern() { + return classTemplateDecl(hasName("X"), unless(isImplicit())); + } +}; + +struct FunctionTemplateSpec { + using DeclTy = FunctionDecl; + static constexpr auto *Prototype = + R"( + // Proto of the primary template. + template <class T> + void X(); + // Proto of the specialization. + template <> + void X<int>(); + )"; + static constexpr auto *Definition = + R"( + // Proto of the primary template. + template <class T> + void X(); + // Specialization and definition. + template <> + void X<int>() {} + )"; + BindableMatcher<Decl> getPattern() { + return functionDecl(hasName("X"), isExplicitTemplateSpecialization()); + } +}; -TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) { - Decl *FromTU = getTuDecl("template <class T> class X {};", Lang_CXX); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern); +template <typename TypeParam> +struct RedeclChain : ASTImporterOptionSpecificTestBase { - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); + using DeclTy = typename TypeParam::DeclTy; + std::string getPrototype() { return TypeParam::Prototype; } + std::string getDefinition() { return TypeParam::Definition; } + BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); } + + void + TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() { + Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX); + auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + ASSERT_FALSE(FromD->isThisDeclarationADefinition()); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u); + auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern()); + EXPECT_TRUE(ImportedD == ToD); + EXPECT_FALSE(ToD->isThisDeclarationADefinition()); + if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) + EXPECT_TRUE(ToT->getTemplatedDecl()); + } + + void TypedTest_DefinitionShouldBeImportedAsADefinition() { + Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX); + auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + ASSERT_TRUE(FromD->isThisDeclarationADefinition()); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u); + auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern()); + EXPECT_TRUE(ToD->isThisDeclarationADefinition()); + if (auto *ToT = dyn_cast<TemplateDecl>(ToD)) + EXPECT_TRUE(ToT->getTemplatedDecl()); + } - EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u); - auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern); - ASSERT_TRUE(ToD->getTemplatedDecl()); - EXPECT_TRUE(ToD->isThisDeclarationADefinition()); -} - -TEST_P(ImportClassTemplates, - ImportPrototypeFromDifferentTUAfterImportedPrototype) { - Decl *FromTU0 = - getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern); - - Decl *Imported0 = Import(From0, Lang_CXX); - Decl *Imported1 = Import(From1, Lang_CXX); - Decl *ToTU = Imported0->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u); - auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern); - auto To1 = LastDeclMatcher<ClassTemplateDecl>().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()); -} + void TypedTest_ImportPrototypeAfterImportedPrototype() { + Decl *FromTU = getTuDecl( + getPrototype() + getPrototype(), Lang_CXX); + auto *From0 = + FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + auto *From1 = LastDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + auto *To1 = LastDeclMatcher<DeclTy>().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<TemplateDecl>(To0)) { + auto *ToT1 = cast<TemplateDecl>(To1); + ASSERT_TRUE(ToT0->getTemplatedDecl()); + ASSERT_TRUE(ToT1->getTemplatedDecl()); + EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(), + ToT0->getTemplatedDecl()); + } + } -TEST_P(ImportClassTemplates, ImportDefinitions) { - Decl *FromTU0 = - getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern); - auto From1 = FirstDeclMatcher<ClassTemplateDecl>().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<ClassTemplateDecl>().match(ToTU, Pattern), 1u); - auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern); - EXPECT_TRUE(Imported0 == To0); - ASSERT_TRUE(To0->getTemplatedDecl()); - EXPECT_TRUE(To0->isThisDeclarationADefinition()); -} - -TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) { - Decl *FromTU0 = - getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern); - auto FromProto = - FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern); + void TypedTest_ImportDefinitionAfterImportedPrototype() { + Decl *FromTU = getTuDecl( + getPrototype() + getDefinition(), Lang_CXX); + auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + auto *FromDef = LastDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + auto *ToDef = LastDeclMatcher<DeclTy>().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<TemplateDecl>(ToProto)) { + auto *ToDefT = cast<TemplateDecl>(ToDef); + ASSERT_TRUE(ToProtoT->getTemplatedDecl()); + ASSERT_TRUE(ToDefT->getTemplatedDecl()); + EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(), + ToProtoT->getTemplatedDecl()); + } + } - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); + void TypedTest_ImportPrototypeAfterImportedDefinition() { + Decl *FromTU = getTuDecl( + getDefinition() + getPrototype(), Lang_CXX); + auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + auto *FromProto = LastDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + auto *ToProto = LastDeclMatcher<DeclTy>().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<TemplateDecl>(ToDef)) { + auto *ToProtoT = cast<TemplateDecl>(ToProto); + ASSERT_TRUE(ToDefT->getTemplatedDecl()); + ASSERT_TRUE(ToProtoT->getTemplatedDecl()); + EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(), + ToDefT->getTemplatedDecl()); + } + } - EXPECT_NE(ImportedDef, ImportedProto); - EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u); - auto ToDef = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern); - auto ToProto = LastDeclMatcher<ClassTemplateDecl>().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 T> class X;", Lang_CXX, "input0.cc"); - Decl *FromTU1 = - getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc"); - auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit())); - auto FromProto = - FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern); - auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern); + void TypedTest_ImportPrototypes() { + Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc"); + Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc"); + auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern()); + auto *From1 = FirstDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + auto *To1 = LastDeclMatcher<DeclTy>().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<TemplateDecl>(To0)) { + auto *ToT1 = cast<TemplateDecl>(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<FunctionDecl>(From0)) { + auto *To0F = cast<FunctionDecl>(To0); + if (From0F->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) { + auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().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<DeclTy>().match(FromTU0, getPattern()); + auto *From1 = FirstDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 1u); + auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + EXPECT_TRUE(Imported0 == To0); + EXPECT_TRUE(To0->isThisDeclarationADefinition()); + if (auto *ToT0 = dyn_cast<TemplateDecl>(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<DeclTy>().match(FromTUDef, getPattern()); + auto *FromProto = + FirstDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + auto *ToProto = LastDeclMatcher<DeclTy>().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<TemplateDecl>(ToDef)) { + auto *ToProtoT = cast<TemplateDecl>(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<DeclTy>().match(FromTUProto, getPattern()); + auto *FromDef = FirstDeclMatcher<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + auto *ToDef = LastDeclMatcher<DeclTy>().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<TemplateDecl>(ToDef)) { + auto *ToProtoT = cast<TemplateDecl>(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<DeclTy>().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<DeclTy>().match(ToTU, getPattern()), 2u); + EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition()); + } + + void TypedTest_ImportPrototypeThenProtoAndDefinition() { + { + Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + Import(FromD, Lang_CXX); + } + { + Decl *FromTU = + getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern()); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + + ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u); + DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern()); + EXPECT_FALSE(ProtoD->isThisDeclarationADefinition()); + + DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().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<TypeParam>; \ + 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, ); - Decl *ImportedProto = Import(FromProto, Lang_CXX); - Decl *ImportedDef = Import(FromDef, Lang_CXX); - Decl *ToTU = ImportedDef->getTranslationUnitDecl(); - EXPECT_NE(ImportedDef, ImportedProto); - EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u); - auto ToProto = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern); - auto ToDef = LastDeclMatcher<ClassTemplateDecl>().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(ImportFunctionTemplateSpecializat DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f")))); } -TEST_P(ImportFunctionTemplateSpecializations, - ImportPrototypes) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template <class T> - void f(); - // Proto of the specialization. - template <> - void f<int>(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().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 <class T> - void f(); - // Specialization and definition. - template <> - void f<int>() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - - auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().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 <class T> - void f(); - // Specialization proto. - template <> - void f<int>(); - // Specialization proto. - template <> - void f<int>(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().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 <class T> - void f(); - // Specialization proto. - template <> - void f<int>(); - // Specialization definition. - template <> - void f<int>() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().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 <class T> - void f(); - // Specialization definition. - template <> - void f<int>() {} - // Specialization proto. - template <> - void f<int>(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().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(ParameterizedTes INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, DefaultTestValuesForRunOptions, ); -INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates, - DefaultTestValuesForRunOptions, ); - INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses, DefaultTestValuesForRunOptions, ); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits