[ASTImporter] Unify redecl chain tests as type parameterized tests

Summary:
This patch unifies all those tests which check the correctness of the
redecl chains. Previously we had several structurally very similar test
cases for each language construct (class, function, variable, function
template, ...).

We still use value-parameterized tests for the different AST
compatibility switches (-fdelayed-template-parsing, -fms-compatibility).
Gtest makes it possible to have either value-parameterized or
type-parameterized fixtures. However, we cannot have both value- and
type-parameterized test fixtures. So we use a value-parameterized test
fixture in the gtest sense. We intend to mimic gtest's type-parameters
via the type template parameter. We manually instantiate the different
tests with the each types.

After this patch I am planning to put the "generic redecl chain" related
tests into their own separate test file (in another patch).

Reviewers: a_sidorin, shafik, a.sidorin

Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits

Differential Revision: https://reviews.llvm.org/D57236

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354259 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index 6c929b4..30bc9dc 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -2008,33 +2008,6 @@
 
 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 @@
   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 @@
 
 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 @@
   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);
+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()));
+  }
+};
 
-  Decl *Imported0 = Import(From0, Lang_CXX);
-  Decl *Imported1 = Import(From1, Lang_CXX);
-  Decl *ToTU = Imported0->getTranslationUnitDecl();
+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());
+  }
+};
 
-  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());
-}
+template <typename TypeParam>
+struct RedeclChain : ASTImporterOptionSpecificTestBase {
 
-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);
+  using DeclTy = typename TypeParam::DeclTy;
+  std::string getPrototype() { return TypeParam::Prototype; }
+  std::string getDefinition() { return TypeParam::Definition; }
+  BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
 
-  Decl *ImportedD = Import(FromD, Lang_CXX);
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();
+  void
+  TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
+    Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
+    auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+    ASSERT_FALSE(FromD->isThisDeclarationADefinition());
 
-  EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
-  auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
-  ASSERT_TRUE(ToD->getTemplatedDecl());
-  EXPECT_TRUE(ToD->isThisDeclarationADefinition());
-}
+    Decl *ImportedD = Import(FromD, Lang_CXX);
+    Decl *ToTU = ImportedD->getTranslationUnitDecl();
 
-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);
+    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());
+  }
 
-  Decl *Imported0 = Import(From0, Lang_CXX);
-  Decl *Imported1 = Import(From1, Lang_CXX);
-  Decl *ToTU = Imported0->getTranslationUnitDecl();
+  void TypedTest_DefinitionShouldBeImportedAsADefinition() {
+    Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
+    auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+    ASSERT_TRUE(FromD->isThisDeclarationADefinition());
 
-  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());
-}
+    Decl *ImportedD = Import(FromD, Lang_CXX);
+    Decl *ToTU = ImportedD->getTranslationUnitDecl();
 
-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);
+    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());
+  }
 
-  Decl *Imported0 = Import(From0, Lang_CXX);
-  Decl *Imported1 = Import(From1, Lang_CXX);
-  Decl *ToTU = Imported0->getTranslationUnitDecl();
+  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());
 
-  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());
-}
+    Decl *Imported0 = Import(From0, Lang_CXX);
+    Decl *Imported1 = Import(From1, Lang_CXX);
+    Decl *ToTU = Imported0->getTranslationUnitDecl();
 
-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);
+    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());
+    }
+  }
 
-  Decl *ImportedDef = Import(FromDef, Lang_CXX);
-  Decl *ImportedProto = Import(FromProto, Lang_CXX);
-  Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+  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());
 
-  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());
-}
+    Decl *ImportedProto = Import(FromProto, Lang_CXX);
+    Decl *ImportedDef = Import(FromDef, Lang_CXX);
+    Decl *ToTU = ImportedProto->getTranslationUnitDecl();
 
-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);
+    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 *ImportedProto = Import(FromProto, Lang_CXX);
-  Decl *ImportedDef = Import(FromDef, 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());
 
-  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());
-}
+    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());
+    }
+  }
+
+  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, );
+
+
 
 struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
 
@@ -4704,184 +4800,6 @@
       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(ParameterizedTests, ImportFriendFunctions,
                         DefaultTestValuesForRunOptions, );
 
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates,
-                        DefaultTestValuesForRunOptions, );
-
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
                         DefaultTestValuesForRunOptions, );