r335491 - Revert "[ASTImporter] Import the whole redecl chain of functions"

Gabor Marton via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 25 09:25:30 PDT 2018


Author: martong
Date: Mon Jun 25 09:25:30 2018
New Revision: 335491

URL: http://llvm.org/viewvc/llvm-project?rev=335491&view=rev
Log:
Revert "[ASTImporter] Import the whole redecl chain of functions"

This reverts commit r335480.

Modified:
    cfe/trunk/include/clang/AST/ASTImporter.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/test/ASTMerge/class/test.cpp
    cfe/trunk/unittests/AST/ASTImporterTest.cpp

Modified: cfe/trunk/include/clang/AST/ASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=335491&r1=335490&r2=335491&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)
+++ cfe/trunk/include/clang/AST/ASTImporter.h Mon Jun 25 09:25:30 2018
@@ -43,15 +43,6 @@ class TagDecl;
 class TypeSourceInfo;
 class Attr;
 
-  // \brief Returns with a list of declarations started from the canonical decl
-  // then followed by subsequent decls in the translation unit.
-  // This gives a canonical list for each entry in the redecl chain.
-  // `Decl::redecls()` gives a list of decls which always start from the
-  // previous decl and the next item is actually the previous item in the order
-  // of source locations.  Thus, `Decl::redecls()` gives different lists for
-  // the different entries in a given redecl chain.
-  llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D);
-
   /// Imports selected nodes from one AST context into another context,
   /// merging AST nodes where appropriate.
   class ASTImporter {

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=335491&r1=335490&r2=335491&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Jun 25 09:25:30 2018
@@ -71,25 +71,6 @@
 
 namespace clang {
 
-  template <class T>
-  SmallVector<Decl*, 2>
-  getCanonicalForwardRedeclChain(Redeclarable<T>* D) {
-    SmallVector<Decl*, 2> Redecls;
-    for (auto *R : D->getFirstDecl()->redecls()) {
-      if (R != D->getFirstDecl())
-        Redecls.push_back(R);
-    }
-    Redecls.push_back(D->getFirstDecl());
-    std::reverse(Redecls.begin(), Redecls.end());
-    return Redecls;
-  }
-
-  SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) {
-    // Currently only FunctionDecl is supported
-    auto FD = cast<FunctionDecl>(D);
-    return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
-  }
-
   class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
                           public DeclVisitor<ASTNodeImporter, Decl *>,
                           public StmtVisitor<ASTNodeImporter, Stmt *> {
@@ -214,12 +195,6 @@ namespace clang {
                                         const InContainerTy &Container,
                                         TemplateArgumentListInfo &Result);
 
-    using TemplateArgsTy = SmallVector<TemplateArgument, 8>;
-    using OptionalTemplateArgsTy = Optional<TemplateArgsTy>;
-    std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy>
-    ImportFunctionTemplateWithTemplateArgsFromSpecialization(
-        FunctionDecl *FromFD);
-
     bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
 
     bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
@@ -433,8 +408,6 @@ namespace clang {
 
     // Importing overrides.
     void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);
-
-    FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD);
   };
 
 template <typename InContainerTy>
@@ -464,25 +437,6 @@ bool ASTNodeImporter::ImportTemplateArgu
                                         From.arguments(), Result);
 }
 
-std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy>
-ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
-    FunctionDecl *FromFD) {
-  assert(FromFD->getTemplatedKind() ==
-         FunctionDecl::TK_FunctionTemplateSpecialization);
-  auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
-  auto *Template = cast_or_null<FunctionTemplateDecl>(
-      Importer.Import(FTSInfo->getTemplate()));
-
-  // Import template arguments.
-  auto TemplArgs = FTSInfo->TemplateArguments->asArray();
-  TemplateArgsTy ToTemplArgs;
-  if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),
-                              ToTemplArgs)) // Error during import.
-    return std::make_tuple(Template, OptionalTemplateArgsTy());
-
-  return std::make_tuple(Template, ToTemplArgs);
-}
-
 } // namespace clang
 
 //----------------------------------------------------------------------------
@@ -2298,17 +2252,23 @@ bool ASTNodeImporter::ImportTemplateInfo
   }
 
   case FunctionDecl::TK_FunctionTemplateSpecialization: {
-    FunctionTemplateDecl* Template;
-    OptionalTemplateArgsTy ToTemplArgs;
-    std::tie(Template, ToTemplArgs) =
-        ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
-    if (!Template || !ToTemplArgs)
+    auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
+    auto *Template = cast_or_null<FunctionTemplateDecl>(
+        Importer.Import(FTSInfo->getTemplate()));
+    if (!Template)
+      return true;
+    TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();
+
+    // Import template arguments.
+    auto TemplArgs = FTSInfo->TemplateArguments->asArray();
+    SmallVector<TemplateArgument, 8> ToTemplArgs;
+    if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),
+                                ToTemplArgs))
       return true;
 
     TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy(
-          Importer.getToContext(), *ToTemplArgs);
+          Importer.getToContext(), ToTemplArgs);
 
-    auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
     TemplateArgumentListInfo ToTAInfo;
     const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;
     if (FromTAArgsAsWritten)
@@ -2317,7 +2277,6 @@ bool ASTNodeImporter::ImportTemplateInfo
 
     SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation());
 
-    TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();
     ToFD->setFunctionTemplateSpecialization(
         Template, ToTAList, /* InsertPos= */ nullptr,
         TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI);
@@ -2353,31 +2312,7 @@ bool ASTNodeImporter::ImportTemplateInfo
   llvm_unreachable("All cases should be covered!");
 }
 
-FunctionDecl *
-ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) {
-  FunctionTemplateDecl* Template;
-  OptionalTemplateArgsTy ToTemplArgs;
-  std::tie(Template, ToTemplArgs) =
-      ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
-  if (!Template || !ToTemplArgs)
-    return nullptr;
-
-  void *InsertPos = nullptr;
-  auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos);
-  return FoundSpec;
-}
-
 Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
-
-  SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D);
-  auto RedeclIt = Redecls.begin();
-  // Import the first part of the decl chain. I.e. import all previous
-  // declarations starting from the canonical decl.
-  for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt)
-    if (!Importer.Import(*RedeclIt))
-      return nullptr;
-  assert(*RedeclIt == D);
-
   // Import the major distinguishing characteristics of this function.
   DeclContext *DC, *LexicalDC;
   DeclarationName Name;
@@ -2388,27 +2323,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl
   if (ToD)
     return ToD;
 
-  const FunctionDecl *FoundByLookup = nullptr;
+  const FunctionDecl *FoundWithoutBody = nullptr;
 
-  // If this is a function template specialization, then try to find the same
-  // existing specialization in the "to" context. The localUncachedLookup
-  // below will not find any specialization, but would find the primary
-  // template; thus, we have to skip normal lookup in case of specializations.
-  // FIXME handle member function templates (TK_MemberSpecialization) similarly?
-  if (D->getTemplatedKind() ==
-      FunctionDecl::TK_FunctionTemplateSpecialization) {
-    if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) {
-      if (D->doesThisDeclarationHaveABody() &&
-          FoundFunction->hasBody())
-        return Importer.Imported(D, FoundFunction);
-      FoundByLookup = FoundFunction;
-    }
-  }
   // Try to find a function in our own ("to") context with the same name, same
   // type, and in the same context as the function we're importing.
-  else if (!LexicalDC->isFunctionOrMethod()) {
+  if (!LexicalDC->isFunctionOrMethod()) {
     SmallVector<NamedDecl *, 4> ConflictingDecls;
-    unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;
+    unsigned IDNS = Decl::IDNS_Ordinary;
     SmallVector<NamedDecl *, 2> FoundDecls;
     DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
     for (auto *FoundDecl : FoundDecls) {
@@ -2420,11 +2341,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl
             D->hasExternalFormalLinkage()) {
           if (Importer.IsStructurallyEquivalent(D->getType(), 
                                                 FoundFunction->getType())) {
-              if (D->doesThisDeclarationHaveABody() &&
-                  FoundFunction->hasBody())
-                return Importer.Imported(D, FoundFunction);
-              FoundByLookup = FoundFunction;
+            // FIXME: Actually try to merge the body and other attributes.
+            const FunctionDecl *FromBodyDecl = nullptr;
+            D->hasBody(FromBodyDecl);
+            if (D == FromBodyDecl && !FoundFunction->hasBody()) {
+              // This function is needed to merge completely.
+              FoundWithoutBody = FoundFunction;
               break;
+            }
+            return Importer.Imported(D, FoundFunction);
           }
 
           // FIXME: Check for overloading more carefully, e.g., by boosting
@@ -2574,9 +2499,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl
   }
   ToFunction->setParams(Parameters);
 
-  if (FoundByLookup) {
+  if (FoundWithoutBody) {
     auto *Recent = const_cast<FunctionDecl *>(
-          FoundByLookup->getMostRecentDecl());
+          FoundWithoutBody->getMostRecentDecl());
     ToFunction->setPreviousDecl(Recent);
   }
 
@@ -2598,11 +2523,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl
     ToFunction->setType(T);
   }
 
-  if (D->doesThisDeclarationHaveABody()) {
-    if (Stmt *FromBody = D->getBody()) {
-      if (Stmt *ToBody = Importer.Import(FromBody)) {
-        ToFunction->setBody(ToBody);
-      }
+  // Import the body, if any.
+  if (Stmt *FromBody = D->getBody()) {
+    if (Stmt *ToBody = Importer.Import(FromBody)) {
+      ToFunction->setBody(ToBody);
     }
   }
 
@@ -2612,29 +2536,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl
   if (ImportTemplateInformation(D, ToFunction))
     return nullptr;
 
-  bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend);
-
-  // TODO Can we generalize this approach to other AST nodes as well?
-  if (D->getDeclContext()->containsDecl(D))
-    DC->addDeclInternal(ToFunction);
-  if (DC != LexicalDC && D->getLexicalDeclContext()->containsDecl(D))
+  // Add this function to the lexical context.
+  // NOTE: If the function is templated declaration, it should be not added into
+  // LexicalDC. But described template is imported during import of
+  // FunctionTemplateDecl (it happens later). So, we use source declaration
+  // to determine if we should add the result function.
+  if (!D->getDescribedFunctionTemplate())
     LexicalDC->addDeclInternal(ToFunction);
 
-  // Friend declaration's lexical context is the befriending class, but the
-  // semantic context is the enclosing scope of the befriending class.
-  // We want the friend functions to be found in the semantic context by lookup.
-  // FIXME should we handle this generically in VisitFriendDecl?
-  // In Other cases when LexicalDC != DC we don't want it to be added,
-  // e.g out-of-class definitions like void B::f() {} .
-  if (LexicalDC != DC && IsFriend) {
-    DC->makeDeclVisibleInContext(ToFunction);
-  }
-
-  // Import the rest of the chain. I.e. import all subsequent declarations.
-  for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt)
-    if (!Importer.Import(*RedeclIt))
-      return nullptr;
-
   if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
     ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);
 

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=335491&r1=335490&r2=335491&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Jun 25 09:25:30 2018
@@ -1343,8 +1343,6 @@ bool DeclContext::decls_empty() const {
 }
 
 bool DeclContext::containsDecl(Decl *D) const {
-  if (hasExternalLexicalStorage())
-    LoadLexicalDeclsFromExternalStorage();
   return (D->getLexicalDeclContext() == this &&
           (D->NextInContextAndBits.getPointer() || D == LastDecl));
 }

Modified: cfe/trunk/test/ASTMerge/class/test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/class/test.cpp?rev=335491&r1=335490&r2=335491&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/class/test.cpp (original)
+++ cfe/trunk/test/ASTMerge/class/test.cpp Mon Jun 25 09:25:30 2018
@@ -13,12 +13,12 @@
 // CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here
 // CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here
 
-// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units
-// CHECK: class1.cpp:46:3: note: friend declared here
-// CHECK: class2.cpp:36:8: note: no corresponding friend here
-
 // CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units
 // CHECK: class1.cpp:39:3: note: friend declared here
 // CHECK: class2.cpp:30:8: note: no corresponding friend here
 
+// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units
+// CHECK: class1.cpp:46:3: note: friend declared here
+// CHECK: class2.cpp:36:8: note: no corresponding friend here
+
 // CHECK: 4 warnings generated.

Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=335491&r1=335490&r2=335491&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Mon Jun 25 09:25:30 2018
@@ -20,7 +20,7 @@
 
 #include "DeclMatcher.h"
 #include "Language.h"
-#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "llvm/ADT/StringMap.h"
 
 namespace clang {
@@ -428,48 +428,6 @@ struct ImportExpr : TestImportBase {};
 struct ImportType : TestImportBase {};
 struct ImportDecl : TestImportBase {};
 
-struct CanonicalRedeclChain : ASTImporterTestBase {};
-
-TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
-  Decl *FromTU = getTuDecl("void f();", Lang_CXX);
-  auto Pattern = functionDecl(hasName("f"));
-  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto Redecls = getCanonicalForwardRedeclChain(D0);
-  ASSERT_EQ(Redecls.size(), 1u);
-  EXPECT_EQ(D0, Redecls[0]);
-}
-
-TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
-  Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
-  auto Pattern = functionDecl(hasName("f"));
-  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-  auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-  FunctionDecl *D1 = D2->getPreviousDecl();
-
-  auto Redecls = getCanonicalForwardRedeclChain(D0);
-  ASSERT_EQ(Redecls.size(), 3u);
-  EXPECT_EQ(D0, Redecls[0]);
-  EXPECT_EQ(D1, Redecls[1]);
-  EXPECT_EQ(D2, Redecls[2]);
-}
-
-TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
-  Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
-  auto Pattern = functionDecl(hasName("f"));
-  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-  auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-  FunctionDecl *D1 = D2->getPreviousDecl();
-
-  auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
-  auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
-  auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
-
-  EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
-  EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
-}
-
-
 TEST_P(ImportExpr, ImportStringLiteral) {
   MatchVerifier<Decl> Verifier;
   testImport("void declToImport() { \"foo\"; }",
@@ -1715,6 +1673,34 @@ TEST_P(
 struct ImportFunctions : ASTImporterTestBase {};
 
 TEST_P(ImportFunctions,
+       PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
+  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,
+       PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {
+  Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
+  auto Pattern = functionDecl(hasName("f"));
+  FunctionDecl *FromD = // Prototype
+      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,
        DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
   Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
   auto Pattern = functionDecl(hasName("f"));
@@ -1724,7 +1710,7 @@ TEST_P(ImportFunctions,
   Decl *ImportedD = Import(FromD, Lang_CXX);
   Decl *ToTU = ImportedD->getTranslationUnitDecl();
 
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
   EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
 }
 
@@ -1741,40 +1727,30 @@ TEST_P(ImportFunctions, DefinitionShould
   EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
 }
 
-TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
+TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {
   Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
   auto Pattern = functionDecl(hasName("f"));
-  auto *From =
-      FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
+  FunctionDecl *PrototypeFD =
+      FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
 
-  Decl *ImportedD = Import(From, Lang_CXX);
+  Decl *ImportedD = Import(PrototypeFD, 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_TRUE(To1->doesThisDeclarationHaveABody());
-  EXPECT_EQ(To1->getPreviousDecl(), To0);
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
 }
 
 TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
   Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
   auto Pattern = functionDecl(hasName("f"));
-  auto *From =
-      LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
+  FunctionDecl *DefinitionFD =
+      LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
 
-  Decl *ImportedD = Import(From, Lang_CXX);
+  Decl *ImportedD = Import(DefinitionFD, 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 == To1);
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
-  EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
-  EXPECT_EQ(To1->getPreviousDecl(), To0);
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
 }
 
 TEST_P(ImportFunctions, ImportPrototypes) {
@@ -1783,48 +1759,23 @@ TEST_P(ImportFunctions, ImportPrototypes
   Decl *ImportedD;
   {
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+    FunctionDecl *FromD =
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
 
     ImportedD = Import(FromD, Lang_CXX);
   }
+  Decl *ImportedD1;
   {
     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);
+    FunctionDecl *FromD =
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+    ImportedD1 = Import(FromD, Lang_CXX);
   }
 
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();
-
+  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
   EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_TRUE(ImportedD == To0);
-  EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
+  EXPECT_EQ(ImportedD, ImportedD1);
+  EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
 }
 
 TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
@@ -1833,24 +1784,23 @@ TEST_P(ImportFunctions, ImportDefinition
   Decl *ImportedD;
   {
     Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+    FunctionDecl *FromD =
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+
     ImportedD = Import(FromD, Lang_CXX);
   }
+  Decl *ImportedD1;
   {
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-    Import(FromD, Lang_CXX);
+    FunctionDecl *FromD =
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+    ImportedD1 = 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);
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+  EXPECT_EQ(ImportedD, ImportedD1);
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
 }
 
 TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
@@ -1873,40 +1823,38 @@ TEST_P(ImportFunctions, ImportPrototypeT
   Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
   ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
   FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
+  EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
   FunctionDecl *DefinitionD =
       LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
   EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
   EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
 }
 
-TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
+TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {
   auto Pattern = functionDecl(hasName("f"));
 
   {
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+    FunctionDecl *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);
+    FunctionDecl *FromD =
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
     Import(FromD, Lang_CXX);
   }
 
   Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
+  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
   FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
-
+  EXPECT_TRUE(!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);
+  EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
 }
 
 TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
@@ -1946,202 +1894,6 @@ TEST_P(ImportFunctions, VirtualFlagShoul
   EXPECT_TRUE(To->isVirtual());
 }
 
-TEST_P(ImportFunctions,
-       ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
-  Decl *ToTU = getToTuDecl(
-      R"(
-      void f() {}
-      void f();
-      )",
-      Lang_CXX);
-  ASSERT_EQ(1u,
-            DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
-              return FD->doesThisDeclarationHaveABody();
-            }).match(ToTU, functionDecl()));
-
-  Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
-
-  Import(FromD, Lang_CXX);
-
-  EXPECT_EQ(1u,
-            DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
-              return FD->doesThisDeclarationHaveABody();
-            }).match(ToTU, functionDecl()));
-}
-
-struct ImportFriendFunctions : ImportFunctions {};
-
-TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  Decl *FromTU = getTuDecl("struct X { friend void f(); };"
-                           "void f();",
-                           Lang_CXX,
-                           "input0.cc");
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions,
-       ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  Decl *FromTU = getTuDecl("void f();"
-                           "struct X { friend void f(); };",
-                           Lang_CXX, "input0.cc");
-  auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
-                           "void f();",
-                           Lang_CXX,
-                           "input0.cc");
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-TEST_P(ImportFriendFunctions,
-       ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  Decl *FromTU = getTuDecl("struct X { friend void f(); };"
-                           "void f(){}",
-                           Lang_CXX, "input0.cc");
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
-  EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
-}
-
-// This test is disabled, because ATM we create a redundant FunctionDecl.  We
-// start the import with the definition of `f` then we continue with the import
-// of the type of `f` which involves `X`. During the import of `X` we start
-// again the import of the definition of `f` and then finally we create the
-// node. But then in the first frame of `VisitFunctionDecl` we create a node
-// again since we do not check if such a node exists yet or not. This is being
-// fixed in a separate patch: https://reviews.llvm.org/D47632
-// FIXME enable this test once the above patch is approved.
-TEST_P(ImportFriendFunctions,
-    DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  Decl *FromTU = getTuDecl(
-      R"(
-        class X;
-        void f(X *x){}
-        class X{
-        friend void f(X *x);
-        };
-      )",
-      Lang_CXX, "input0.cc");
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
-  auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
-                                              .match(ToTU, friendDecl())
-                                              ->getFriendDecl());
-  EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
-  EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
-  // The parameters must refer the same type
-  EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
-            (*ImportedD->param_begin())->getOriginalType());
-}
-
-// This test is disabled, because ATM we create a redundant FunctionDecl.  We
-// start the import with the definition of `f` then we continue with the import
-// of the type of `f` which involves `X`. During the import of `X` we start
-// again the import of the definition of `f` and then finally we create the
-// node. But then in the first frame of `VisitFunctionDecl` we create a node
-// again since we do not check if such a node exists yet or not. This is being
-// fixed in a separate patch: https://reviews.llvm.org/D47632
-// FIXME enable this test once the above patch is approved.
-TEST_P(ImportFriendFunctions,
-       DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  Decl *FromTU = getTuDecl(
-      R"(
-        class X;
-        void f(X *x){}
-        class X{
-        friend void f(X *x);
-        };
-      )",
-      Lang_CXX, "input0.cc");
-  auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
-  auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
-      ToTU, functionDecl(unless(hasParent(friendDecl()))));
-
-  EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
-  EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
-  // The parameters must refer the same type
-  EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
-            (*ImportedD->param_begin())->getOriginalType());
-}
-
-TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
-  auto Pattern = functionDecl(hasName("f"));
-
-  FunctionDecl *ImportedD;
-  {
-    Decl *FromTU =
-        getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-    ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  }
-  FunctionDecl *ImportedD1;
-  {
-    Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
-    ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
-  }
-
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
-  EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
-  EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
-  EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
-}
-
 AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
               InnerMatcher) {
   if (auto *Typedef = Node.getTypedefNameForAnonDecl())
@@ -2272,328 +2024,9 @@ TEST_P(DeclContextTest, removeDeclOfClas
   EXPECT_FALSE(NS->containsDecl(Spec));
 }
 
-struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
-
-TEST_P(ImportFunctionTemplateSpecializations,
-       TUshouldNotContainFunctionTemplateImplicitInstantiation) {
-
-  Decl *FromTU = getTuDecl(
-      R"(
-      template<class T>
-      int f() { return 0; }
-      void foo() { f<int>(); }
-      )",
-      Lang_CXX, "input0.cc");
-
-  // Check that the function template instantiation is NOT the child of the TU.
-  auto Pattern = translationUnitDecl(
-      unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
-  ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
-
-  auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
-      FromTU, functionDecl(hasName("foo")));
-  ASSERT_TRUE(Import(Foo, Lang_CXX));
-
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
-       TUshouldNotContainFunctionTemplateExplicitInstantiation) {
-
-  Decl *FromTU = getTuDecl(
-      R"(
-      template<class T>
-      int f() { return 0; }
-      template int f<int>();
-      )",
-      Lang_CXX, "input0.cc");
-
-  // Check that the function template instantiation is NOT the child of the TU.
-  auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
-  auto Pattern = translationUnitDecl(unless(has(Instantiation)));
-  ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
-
-  ASSERT_TRUE(
-      Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
-
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
-       TUshouldContainFunctionTemplateSpecialization) {
-
-  Decl *FromTU = getTuDecl(
-      R"(
-      template<class T>
-      int f() { return 0; }
-      template <> int f<int>() { return 4; }
-      )",
-      Lang_CXX, "input0.cc");
-
-  // Check that the function template specialization is the child of the TU.
-  auto Specialization =
-      functionDecl(hasName("f"), isExplicitTemplateSpecialization());
-  auto Pattern = translationUnitDecl(has(Specialization));
-  ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
-
-  ASSERT_TRUE(
-      Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
-
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
-       FunctionTemplateSpecializationRedeclChain) {
-
-  Decl *FromTU = getTuDecl(
-      R"(
-      template<class T>
-      int f() { return 0; }
-      template <> int f<int>() { return 4; }
-      )",
-      Lang_CXX, "input0.cc");
-
-  auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
-                           hasParent(translationUnitDecl()));
-  auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
-  {
-    auto *TU = FromTU;
-    auto *SpecD = FromSpecD;
-    auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
-        TU, functionTemplateDecl());
-    auto *FirstSpecD = *(TemplateD->spec_begin());
-    ASSERT_EQ(SpecD, FirstSpecD);
-    ASSERT_TRUE(SpecD->getPreviousDecl());
-    ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
-                     ->doesThisDeclarationHaveABody());
-  }
-
-  ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
-
-  {
-    auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
-    auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
-    auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
-        TU, functionTemplateDecl());
-    auto *FirstSpecD = *(TemplateD->spec_begin());
-    EXPECT_EQ(SpecD, FirstSpecD);
-    ASSERT_TRUE(SpecD->getPreviousDecl());
-    EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
-                     ->doesThisDeclarationHaveABody());
-  }
-}
-
-TEST_P(ImportFunctionTemplateSpecializations,
-       MatchNumberOfFunctionTemplateSpecializations) {
-
-  Decl *FromTU = getTuDecl(
-      R"(
-      template <typename T> constexpr int f() { return 0; }
-      template <> constexpr int f<int>() { return 4; }
-      void foo() {
-        static_assert(f<char>() == 0, "");
-        static_assert(f<int>() == 4, "");
-      }
-      )",
-      Lang_CXX11, "input0.cc");
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
-      FromTU, functionDecl(hasName("foo")));
-
-  Import(FromD, Lang_CXX11);
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
-  EXPECT_EQ(
-      DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
-      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);
-}
-
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
                         ::testing::Values(ArgVector()), );
 
-INSTANTIATE_TEST_CASE_P(
-    ParameterizedTests, CanonicalRedeclChain,
-    ::testing::Values(ArgVector()),);
-
 auto DefaultTestValuesForRunOptions = ::testing::Values(
     ArgVector(),
     ArgVector{"-fdelayed-template-parsing"},
@@ -2615,12 +2048,5 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTes
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
                         DefaultTestValuesForRunOptions, );
 
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
-                        DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests,
-                        ImportFunctionTemplateSpecializations,
-                        DefaultTestValuesForRunOptions, );
-
 } // end namespace ast_matchers
 } // end namespace clang




More information about the cfe-commits mailing list