r354259 - [ASTImporter] Unify redecl chain tests as type parameterized tests

Gabor Marton via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 18 03:09:57 PST 2019


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, );
 




More information about the cfe-commits mailing list