<div dir="auto"><div>Hi Nico,<div dir="auto"><br></div><div dir="auto">Yes, I reverted because it broke one of the lldb build bots. </div><div dir="auto">Next time I'll include the reason in the revert commit. </div><div dir="auto"><br></div><div dir="auto">Gábor </div><br><br><div class="gmail_quote"><div dir="ltr">On Mon, 25 Jun 2018, 22:50 Nico Weber, <<a href="mailto:thakis@chromium.org">thakis@chromium.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">When reverting things, please say why in the commit message. (In this case, apparently because it broke the lldb buildbots?)</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jun 25, 2018 at 12:30 PM Gabor Marton via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" rel="noreferrer">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: martong<br>
Date: Mon Jun 25 09:25:30 2018<br>
New Revision: 335491<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=335491&view=rev" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=335491&view=rev</a><br>
Log:<br>
Revert "[ASTImporter] Import the whole redecl chain of functions"<br>
<br>
This reverts commit r335480.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/ASTImporter.h<br>
    cfe/trunk/lib/AST/ASTImporter.cpp<br>
    cfe/trunk/lib/AST/DeclBase.cpp<br>
    cfe/trunk/test/ASTMerge/class/test.cpp<br>
    cfe/trunk/unittests/AST/ASTImporterTest.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/ASTImporter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=335491&r1=335490&r2=335491&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=335491&r1=335490&r2=335491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)<br>
+++ cfe/trunk/include/clang/AST/ASTImporter.h Mon Jun 25 09:25:30 2018<br>
@@ -43,15 +43,6 @@ class TagDecl;<br>
 class TypeSourceInfo;<br>
 class Attr;<br>
<br>
-  // \brief Returns with a list of declarations started from the canonical decl<br>
-  // then followed by subsequent decls in the translation unit.<br>
-  // This gives a canonical list for each entry in the redecl chain.<br>
-  // `Decl::redecls()` gives a list of decls which always start from the<br>
-  // previous decl and the next item is actually the previous item in the order<br>
-  // of source locations.  Thus, `Decl::redecls()` gives different lists for<br>
-  // the different entries in a given redecl chain.<br>
-  llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D);<br>
-<br>
   /// Imports selected nodes from one AST context into another context,<br>
   /// merging AST nodes where appropriate.<br>
   class ASTImporter {<br>
<br>
Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=335491&r1=335490&r2=335491&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=335491&r1=335490&r2=335491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Jun 25 09:25:30 2018<br>
@@ -71,25 +71,6 @@<br>
<br>
 namespace clang {<br>
<br>
-  template <class T><br>
-  SmallVector<Decl*, 2><br>
-  getCanonicalForwardRedeclChain(Redeclarable<T>* D) {<br>
-    SmallVector<Decl*, 2> Redecls;<br>
-    for (auto *R : D->getFirstDecl()->redecls()) {<br>
-      if (R != D->getFirstDecl())<br>
-        Redecls.push_back(R);<br>
-    }<br>
-    Redecls.push_back(D->getFirstDecl());<br>
-    std::reverse(Redecls.begin(), Redecls.end());<br>
-    return Redecls;<br>
-  }<br>
-<br>
-  SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) {<br>
-    // Currently only FunctionDecl is supported<br>
-    auto FD = cast<FunctionDecl>(D);<br>
-    return getCanonicalForwardRedeclChain<FunctionDecl>(FD);<br>
-  }<br>
-<br>
   class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,<br>
                           public DeclVisitor<ASTNodeImporter, Decl *>,<br>
                           public StmtVisitor<ASTNodeImporter, Stmt *> {<br>
@@ -214,12 +195,6 @@ namespace clang {<br>
                                         const InContainerTy &Container,<br>
                                         TemplateArgumentListInfo &Result);<br>
<br>
-    using TemplateArgsTy = SmallVector<TemplateArgument, 8>;<br>
-    using OptionalTemplateArgsTy = Optional<TemplateArgsTy>;<br>
-    std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy><br>
-    ImportFunctionTemplateWithTemplateArgsFromSpecialization(<br>
-        FunctionDecl *FromFD);<br>
-<br>
     bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);<br>
<br>
     bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,<br>
@@ -433,8 +408,6 @@ namespace clang {<br>
<br>
     // Importing overrides.<br>
     void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);<br>
-<br>
-    FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD);<br>
   };<br>
<br>
 template <typename InContainerTy><br>
@@ -464,25 +437,6 @@ bool ASTNodeImporter::ImportTemplateArgu<br>
                                         From.arguments(), Result);<br>
 }<br>
<br>
-std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy><br>
-ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(<br>
-    FunctionDecl *FromFD) {<br>
-  assert(FromFD->getTemplatedKind() ==<br>
-         FunctionDecl::TK_FunctionTemplateSpecialization);<br>
-  auto *FTSInfo = FromFD->getTemplateSpecializationInfo();<br>
-  auto *Template = cast_or_null<FunctionTemplateDecl>(<br>
-      Importer.Import(FTSInfo->getTemplate()));<br>
-<br>
-  // Import template arguments.<br>
-  auto TemplArgs = FTSInfo->TemplateArguments->asArray();<br>
-  TemplateArgsTy ToTemplArgs;<br>
-  if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),<br>
-                              ToTemplArgs)) // Error during import.<br>
-    return std::make_tuple(Template, OptionalTemplateArgsTy());<br>
-<br>
-  return std::make_tuple(Template, ToTemplArgs);<br>
-}<br>
-<br>
 } // namespace clang<br>
<br>
 //----------------------------------------------------------------------------<br>
@@ -2298,17 +2252,23 @@ bool ASTNodeImporter::ImportTemplateInfo<br>
   }<br>
<br>
   case FunctionDecl::TK_FunctionTemplateSpecialization: {<br>
-    FunctionTemplateDecl* Template;<br>
-    OptionalTemplateArgsTy ToTemplArgs;<br>
-    std::tie(Template, ToTemplArgs) =<br>
-        ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);<br>
-    if (!Template || !ToTemplArgs)<br>
+    auto *FTSInfo = FromFD->getTemplateSpecializationInfo();<br>
+    auto *Template = cast_or_null<FunctionTemplateDecl>(<br>
+        Importer.Import(FTSInfo->getTemplate()));<br>
+    if (!Template)<br>
+      return true;<br>
+    TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();<br>
+<br>
+    // Import template arguments.<br>
+    auto TemplArgs = FTSInfo->TemplateArguments->asArray();<br>
+    SmallVector<TemplateArgument, 8> ToTemplArgs;<br>
+    if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),<br>
+                                ToTemplArgs))<br>
       return true;<br>
<br>
     TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy(<br>
-          Importer.getToContext(), *ToTemplArgs);<br>
+          Importer.getToContext(), ToTemplArgs);<br>
<br>
-    auto *FTSInfo = FromFD->getTemplateSpecializationInfo();<br>
     TemplateArgumentListInfo ToTAInfo;<br>
     const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;<br>
     if (FromTAArgsAsWritten)<br>
@@ -2317,7 +2277,6 @@ bool ASTNodeImporter::ImportTemplateInfo<br>
<br>
     SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation());<br>
<br>
-    TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();<br>
     ToFD->setFunctionTemplateSpecialization(<br>
         Template, ToTAList, /* InsertPos= */ nullptr,<br>
         TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI);<br>
@@ -2353,31 +2312,7 @@ bool ASTNodeImporter::ImportTemplateInfo<br>
   llvm_unreachable("All cases should be covered!");<br>
 }<br>
<br>
-FunctionDecl *<br>
-ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) {<br>
-  FunctionTemplateDecl* Template;<br>
-  OptionalTemplateArgsTy ToTemplArgs;<br>
-  std::tie(Template, ToTemplArgs) =<br>
-      ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);<br>
-  if (!Template || !ToTemplArgs)<br>
-    return nullptr;<br>
-<br>
-  void *InsertPos = nullptr;<br>
-  auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos);<br>
-  return FoundSpec;<br>
-}<br>
-<br>
 Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {<br>
-<br>
-  SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D);<br>
-  auto RedeclIt = Redecls.begin();<br>
-  // Import the first part of the decl chain. I.e. import all previous<br>
-  // declarations starting from the canonical decl.<br>
-  for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt)<br>
-    if (!Importer.Import(*RedeclIt))<br>
-      return nullptr;<br>
-  assert(*RedeclIt == D);<br>
-<br>
   // Import the major distinguishing characteristics of this function.<br>
   DeclContext *DC, *LexicalDC;<br>
   DeclarationName Name;<br>
@@ -2388,27 +2323,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl<br>
   if (ToD)<br>
     return ToD;<br>
<br>
-  const FunctionDecl *FoundByLookup = nullptr;<br>
+  const FunctionDecl *FoundWithoutBody = nullptr;<br>
<br>
-  // If this is a function template specialization, then try to find the same<br>
-  // existing specialization in the "to" context. The localUncachedLookup<br>
-  // below will not find any specialization, but would find the primary<br>
-  // template; thus, we have to skip normal lookup in case of specializations.<br>
-  // FIXME handle member function templates (TK_MemberSpecialization) similarly?<br>
-  if (D->getTemplatedKind() ==<br>
-      FunctionDecl::TK_FunctionTemplateSpecialization) {<br>
-    if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) {<br>
-      if (D->doesThisDeclarationHaveABody() &&<br>
-          FoundFunction->hasBody())<br>
-        return Importer.Imported(D, FoundFunction);<br>
-      FoundByLookup = FoundFunction;<br>
-    }<br>
-  }<br>
   // Try to find a function in our own ("to") context with the same name, same<br>
   // type, and in the same context as the function we're importing.<br>
-  else if (!LexicalDC->isFunctionOrMethod()) {<br>
+  if (!LexicalDC->isFunctionOrMethod()) {<br>
     SmallVector<NamedDecl *, 4> ConflictingDecls;<br>
-    unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;<br>
+    unsigned IDNS = Decl::IDNS_Ordinary;<br>
     SmallVector<NamedDecl *, 2> FoundDecls;<br>
     DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);<br>
     for (auto *FoundDecl : FoundDecls) {<br>
@@ -2420,11 +2341,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl<br>
             D->hasExternalFormalLinkage()) {<br>
           if (Importer.IsStructurallyEquivalent(D->getType(), <br>
                                                 FoundFunction->getType())) {<br>
-              if (D->doesThisDeclarationHaveABody() &&<br>
-                  FoundFunction->hasBody())<br>
-                return Importer.Imported(D, FoundFunction);<br>
-              FoundByLookup = FoundFunction;<br>
+            // FIXME: Actually try to merge the body and other attributes.<br>
+            const FunctionDecl *FromBodyDecl = nullptr;<br>
+            D->hasBody(FromBodyDecl);<br>
+            if (D == FromBodyDecl && !FoundFunction->hasBody()) {<br>
+              // This function is needed to merge completely.<br>
+              FoundWithoutBody = FoundFunction;<br>
               break;<br>
+            }<br>
+            return Importer.Imported(D, FoundFunction);<br>
           }<br>
<br>
           // FIXME: Check for overloading more carefully, e.g., by boosting<br>
@@ -2574,9 +2499,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl<br>
   }<br>
   ToFunction->setParams(Parameters);<br>
<br>
-  if (FoundByLookup) {<br>
+  if (FoundWithoutBody) {<br>
     auto *Recent = const_cast<FunctionDecl *>(<br>
-          FoundByLookup->getMostRecentDecl());<br>
+          FoundWithoutBody->getMostRecentDecl());<br>
     ToFunction->setPreviousDecl(Recent);<br>
   }<br>
<br>
@@ -2598,11 +2523,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl<br>
     ToFunction->setType(T);<br>
   }<br>
<br>
-  if (D->doesThisDeclarationHaveABody()) {<br>
-    if (Stmt *FromBody = D->getBody()) {<br>
-      if (Stmt *ToBody = Importer.Import(FromBody)) {<br>
-        ToFunction->setBody(ToBody);<br>
-      }<br>
+  // Import the body, if any.<br>
+  if (Stmt *FromBody = D->getBody()) {<br>
+    if (Stmt *ToBody = Importer.Import(FromBody)) {<br>
+      ToFunction->setBody(ToBody);<br>
     }<br>
   }<br>
<br>
@@ -2612,29 +2536,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl<br>
   if (ImportTemplateInformation(D, ToFunction))<br>
     return nullptr;<br>
<br>
-  bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend);<br>
-<br>
-  // TODO Can we generalize this approach to other AST nodes as well?<br>
-  if (D->getDeclContext()->containsDecl(D))<br>
-    DC->addDeclInternal(ToFunction);<br>
-  if (DC != LexicalDC && D->getLexicalDeclContext()->containsDecl(D))<br>
+  // Add this function to the lexical context.<br>
+  // NOTE: If the function is templated declaration, it should be not added into<br>
+  // LexicalDC. But described template is imported during import of<br>
+  // FunctionTemplateDecl (it happens later). So, we use source declaration<br>
+  // to determine if we should add the result function.<br>
+  if (!D->getDescribedFunctionTemplate())<br>
     LexicalDC->addDeclInternal(ToFunction);<br>
<br>
-  // Friend declaration's lexical context is the befriending class, but the<br>
-  // semantic context is the enclosing scope of the befriending class.<br>
-  // We want the friend functions to be found in the semantic context by lookup.<br>
-  // FIXME should we handle this generically in VisitFriendDecl?<br>
-  // In Other cases when LexicalDC != DC we don't want it to be added,<br>
-  // e.g out-of-class definitions like void B::f() {} .<br>
-  if (LexicalDC != DC && IsFriend) {<br>
-    DC->makeDeclVisibleInContext(ToFunction);<br>
-  }<br>
-<br>
-  // Import the rest of the chain. I.e. import all subsequent declarations.<br>
-  for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt)<br>
-    if (!Importer.Import(*RedeclIt))<br>
-      return nullptr;<br>
-<br>
   if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))<br>
     ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/DeclBase.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=335491&r1=335490&r2=335491&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=335491&r1=335490&r2=335491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/DeclBase.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Jun 25 09:25:30 2018<br>
@@ -1343,8 +1343,6 @@ bool DeclContext::decls_empty() const {<br>
 }<br>
<br>
 bool DeclContext::containsDecl(Decl *D) const {<br>
-  if (hasExternalLexicalStorage())<br>
-    LoadLexicalDeclsFromExternalStorage();<br>
   return (D->getLexicalDeclContext() == this &&<br>
           (D->NextInContextAndBits.getPointer() || D == LastDecl));<br>
 }<br>
<br>
Modified: cfe/trunk/test/ASTMerge/class/test.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/class/test.cpp?rev=335491&r1=335490&r2=335491&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/class/test.cpp?rev=335491&r1=335490&r2=335491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/ASTMerge/class/test.cpp (original)<br>
+++ cfe/trunk/test/ASTMerge/class/test.cpp Mon Jun 25 09:25:30 2018<br>
@@ -13,12 +13,12 @@<br>
 // CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here<br>
 // CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here<br>
<br>
-// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units<br>
-// CHECK: class1.cpp:46:3: note: friend declared here<br>
-// CHECK: class2.cpp:36:8: note: no corresponding friend here<br>
-<br>
 // CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units<br>
 // CHECK: class1.cpp:39:3: note: friend declared here<br>
 // CHECK: class2.cpp:30:8: note: no corresponding friend here<br>
<br>
+// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units<br>
+// CHECK: class1.cpp:46:3: note: friend declared here<br>
+// CHECK: class2.cpp:36:8: note: no corresponding friend here<br>
+<br>
 // CHECK: 4 warnings generated.<br>
<br>
Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=335491&r1=335490&r2=335491&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=335491&r1=335490&r2=335491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)<br>
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Mon Jun 25 09:25:30 2018<br>
@@ -20,7 +20,7 @@<br>
<br>
 #include "DeclMatcher.h"<br>
 #include "Language.h"<br>
-#include "gmock/gmock.h"<br>
+#include "gtest/gtest.h"<br>
 #include "llvm/ADT/StringMap.h"<br>
<br>
 namespace clang {<br>
@@ -428,48 +428,6 @@ struct ImportExpr : TestImportBase {};<br>
 struct ImportType : TestImportBase {};<br>
 struct ImportDecl : TestImportBase {};<br>
<br>
-struct CanonicalRedeclChain : ASTImporterTestBase {};<br>
-<br>
-TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {<br>
-  Decl *FromTU = getTuDecl("void f();", Lang_CXX);<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto Redecls = getCanonicalForwardRedeclChain(D0);<br>
-  ASSERT_EQ(Redecls.size(), 1u);<br>
-  EXPECT_EQ(D0, Redecls[0]);<br>
-}<br>
-<br>
-TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {<br>
-  Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-  auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-  FunctionDecl *D1 = D2->getPreviousDecl();<br>
-<br>
-  auto Redecls = getCanonicalForwardRedeclChain(D0);<br>
-  ASSERT_EQ(Redecls.size(), 3u);<br>
-  EXPECT_EQ(D0, Redecls[0]);<br>
-  EXPECT_EQ(D1, Redecls[1]);<br>
-  EXPECT_EQ(D2, Redecls[2]);<br>
-}<br>
-<br>
-TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {<br>
-  Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-  auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-  FunctionDecl *D1 = D2->getPreviousDecl();<br>
-<br>
-  auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);<br>
-  auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);<br>
-  auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);<br>
-<br>
-  EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));<br>
-  EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));<br>
-}<br>
-<br>
-<br>
 TEST_P(ImportExpr, ImportStringLiteral) {<br>
   MatchVerifier<Decl> Verifier;<br>
   testImport("void declToImport() { \"foo\"; }",<br>
@@ -1715,6 +1673,34 @@ TEST_P(<br>
 struct ImportFunctions : ASTImporterTestBase {};<br>
<br>
 TEST_P(ImportFunctions,<br>
+       PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {<br>
+  Decl *FromTU = getTuDecl("void f();", Lang_CXX);<br>
+  auto Pattern = functionDecl(hasName("f"));<br>
+  FunctionDecl *FromD =<br>
+      FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+<br>
+  Decl *ImportedD = Import(FromD, Lang_CXX);<br>
+  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
+<br>
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
+  EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
+}<br>
+<br>
+TEST_P(ImportFunctions,<br>
+       PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {<br>
+  Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);<br>
+  auto Pattern = functionDecl(hasName("f"));<br>
+  FunctionDecl *FromD = // Prototype<br>
+      FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+<br>
+  Decl *ImportedD = Import(FromD, Lang_CXX);<br>
+  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
+<br>
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
+}<br>
+<br>
+TEST_P(ImportFunctions,<br>
        DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {<br>
   Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);<br>
   auto Pattern = functionDecl(hasName("f"));<br>
@@ -1724,7 +1710,7 @@ TEST_P(ImportFunctions,<br>
   Decl *ImportedD = Import(FromD, Lang_CXX);<br>
   Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
   EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
 }<br>
<br>
@@ -1741,40 +1727,30 @@ TEST_P(ImportFunctions, DefinitionShould<br>
   EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
 }<br>
<br>
-TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {<br>
+TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {<br>
   Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);<br>
   auto Pattern = functionDecl(hasName("f"));<br>
-  auto *From =<br>
-      FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto<br>
+  FunctionDecl *PrototypeFD =<br>
+      FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
<br>
-  Decl *ImportedD = Import(From, Lang_CXX);<br>
+  Decl *ImportedD = Import(PrototypeFD, Lang_CXX);<br>
   Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_TRUE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
 }<br>
<br>
 TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {<br>
   Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);<br>
   auto Pattern = functionDecl(hasName("f"));<br>
-  auto *From =<br>
-      LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def<br>
+  FunctionDecl *DefinitionFD =<br>
+      LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
<br>
-  Decl *ImportedD = Import(From, Lang_CXX);<br>
+  Decl *ImportedD = Import(DefinitionFD, Lang_CXX);<br>
   Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To1);<br>
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_TRUE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
 }<br>
<br>
 TEST_P(ImportFunctions, ImportPrototypes) {<br>
@@ -1783,48 +1759,23 @@ TEST_P(ImportFunctions, ImportPrototypes<br>
   Decl *ImportedD;<br>
   {<br>
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+    FunctionDecl *FromD =<br>
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
<br>
     ImportedD = Import(FromD, Lang_CXX);<br>
   }<br>
+  Decl *ImportedD1;<br>
   {<br>
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    Import(FromD, Lang_CXX);<br>
-  }<br>
-<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_FALSE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
-}<br>
-<br>
-TEST_P(ImportFunctions, ImportDefinitions) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *ImportedD;<br>
-  {<br>
-    Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD = Import(FromD, Lang_CXX);<br>
-  }<br>
-  {<br>
-    Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    Import(FromD, Lang_CXX);<br>
+    FunctionDecl *FromD =<br>
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+    ImportedD1 = Import(FromD, Lang_CXX);<br>
   }<br>
<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
+  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
   EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(To0->doesThisDeclarationHaveABody());<br>
+  EXPECT_EQ(ImportedD, ImportedD1);<br>
+  EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
 }<br>
<br>
 TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {<br>
@@ -1833,24 +1784,23 @@ TEST_P(ImportFunctions, ImportDefinition<br>
   Decl *ImportedD;<br>
   {<br>
     Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+    FunctionDecl *FromD =<br>
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+<br>
     ImportedD = Import(FromD, Lang_CXX);<br>
   }<br>
+  Decl *ImportedD1;<br>
   {<br>
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    Import(FromD, Lang_CXX);<br>
+    FunctionDecl *FromD =<br>
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+    ImportedD1 = Import(FromD, Lang_CXX);<br>
   }<br>
<br>
   Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_FALSE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
+  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
+  EXPECT_EQ(ImportedD, ImportedD1);<br>
+  EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());<br>
 }<br>
<br>
 TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {<br>
@@ -1873,40 +1823,38 @@ TEST_P(ImportFunctions, ImportPrototypeT<br>
   Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
   ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
   FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());<br>
+  EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());<br>
   FunctionDecl *DefinitionD =<br>
       LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
   EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());<br>
   EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);<br>
 }<br>
<br>
-TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {<br>
+TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {<br>
   auto Pattern = functionDecl(hasName("f"));<br>
<br>
   {<br>
     Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+    FunctionDecl *FromD =<br>
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+<br>
     Import(FromD, Lang_CXX);<br>
   }<br>
   {<br>
     Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
+    FunctionDecl *FromD =<br>
+        FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
     Import(FromD, Lang_CXX);<br>
   }<br>
<br>
   Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);<br>
+  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
   FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());<br>
-<br>
+  EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());<br>
   FunctionDecl *DefinitionD =<br>
       LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
   EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());<br>
-<br>
-  EXPECT_TRUE(DefinitionD->getPreviousDecl());<br>
-  EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);<br>
+  EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);<br>
 }<br>
<br>
 TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {<br>
@@ -1946,202 +1894,6 @@ TEST_P(ImportFunctions, VirtualFlagShoul<br>
   EXPECT_TRUE(To->isVirtual());<br>
 }<br>
<br>
-TEST_P(ImportFunctions,<br>
-       ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {<br>
-  Decl *ToTU = getToTuDecl(<br>
-      R"(<br>
-      void f() {}<br>
-      void f();<br>
-      )",<br>
-      Lang_CXX);<br>
-  ASSERT_EQ(1u,<br>
-            DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {<br>
-              return FD->doesThisDeclarationHaveABody();<br>
-            }).match(ToTU, functionDecl()));<br>
-<br>
-  Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");<br>
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());<br>
-<br>
-  Import(FromD, Lang_CXX);<br>
-<br>
-  EXPECT_EQ(1u,<br>
-            DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {<br>
-              return FD->doesThisDeclarationHaveABody();<br>
-            }).match(ToTU, functionDecl()));<br>
-}<br>
-<br>
-struct ImportFriendFunctions : ImportFunctions {};<br>
-<br>
-TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *FromTU = getTuDecl("struct X { friend void f(); };"<br>
-                           "void f();",<br>
-                           Lang_CXX,<br>
-                           "input0.cc");<br>
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());<br>
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);<br>
-}<br>
-<br>
-TEST_P(ImportFriendFunctions,<br>
-       ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *FromTU = getTuDecl("void f();"<br>
-                           "struct X { friend void f(); };",<br>
-                           Lang_CXX, "input0.cc");<br>
-  auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());<br>
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);<br>
-}<br>
-<br>
-TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *FromTU = getTuDecl("struct X { friend void f(){} };"<br>
-                           "void f();",<br>
-                           Lang_CXX,<br>
-                           "input0.cc");<br>
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());<br>
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);<br>
-}<br>
-<br>
-TEST_P(ImportFriendFunctions,<br>
-       ImportFriendFunctionRedeclChainDef_OutOfClassDef) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *FromTU = getTuDecl("struct X { friend void f(); };"<br>
-                           "void f(){}",<br>
-                           Lang_CXX, "input0.cc");<br>
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());<br>
-  auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);<br>
-}<br>
-<br>
-// This test is disabled, because ATM we create a redundant FunctionDecl.  We<br>
-// start the import with the definition of `f` then we continue with the import<br>
-// of the type of `f` which involves `X`. During the import of `X` we start<br>
-// again the import of the definition of `f` and then finally we create the<br>
-// node. But then in the first frame of `VisitFunctionDecl` we create a node<br>
-// again since we do not check if such a node exists yet or not. This is being<br>
-// fixed in a separate patch: <a href="https://reviews.llvm.org/D47632" rel="noreferrer noreferrer" target="_blank">https://reviews.llvm.org/D47632</a><br>
-// FIXME enable this test once the above patch is approved.<br>
-TEST_P(ImportFriendFunctions,<br>
-    DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-        class X;<br>
-        void f(X *x){}<br>
-        class X{<br>
-        friend void f(X *x);<br>
-        };<br>
-      )",<br>
-      Lang_CXX, "input0.cc");<br>
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());<br>
-  auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()<br>
-                                              .match(ToTU, friendDecl())<br>
-                                              ->getFriendDecl());<br>
-  EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);<br>
-  // The parameters must refer the same type<br>
-  EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),<br>
-            (*ImportedD->param_begin())->getOriginalType());<br>
-}<br>
-<br>
-// This test is disabled, because ATM we create a redundant FunctionDecl.  We<br>
-// start the import with the definition of `f` then we continue with the import<br>
-// of the type of `f` which involves `X`. During the import of `X` we start<br>
-// again the import of the definition of `f` and then finally we create the<br>
-// node. But then in the first frame of `VisitFunctionDecl` we create a node<br>
-// again since we do not check if such a node exists yet or not. This is being<br>
-// fixed in a separate patch: <a href="https://reviews.llvm.org/D47632" rel="noreferrer noreferrer" target="_blank">https://reviews.llvm.org/D47632</a><br>
-// FIXME enable this test once the above patch is approved.<br>
-TEST_P(ImportFriendFunctions,<br>
-       DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-        class X;<br>
-        void f(X *x){}<br>
-        class X{<br>
-        friend void f(X *x);<br>
-        };<br>
-      )",<br>
-      Lang_CXX, "input0.cc");<br>
-  auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-  auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());<br>
-  auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(<br>
-      ToTU, functionDecl(unless(hasParent(friendDecl()))));<br>
-<br>
-  EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);<br>
-  // The parameters must refer the same type<br>
-  EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),<br>
-            (*ImportedD->param_begin())->getOriginalType());<br>
-}<br>
-<br>
-TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {<br>
-  auto Pattern = functionDecl(hasName("f"));<br>
-<br>
-  FunctionDecl *ImportedD;<br>
-  {<br>
-    Decl *FromTU =<br>
-        getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  }<br>
-  FunctionDecl *ImportedD1;<br>
-  {<br>
-    Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));<br>
-  }<br>
-<br>
-  Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());<br>
-  EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);<br>
-}<br>
-<br>
 AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,<br>
               InnerMatcher) {<br>
   if (auto *Typedef = Node.getTypedefNameForAnonDecl())<br>
@@ -2272,328 +2024,9 @@ TEST_P(DeclContextTest, removeDeclOfClas<br>
   EXPECT_FALSE(NS->containsDecl(Spec));<br>
 }<br>
<br>
-struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations,<br>
-       TUshouldNotContainFunctionTemplateImplicitInstantiation) {<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-      template<class T><br>
-      int f() { return 0; }<br>
-      void foo() { f<int>(); }<br>
-      )",<br>
-      Lang_CXX, "input0.cc");<br>
-<br>
-  // Check that the function template instantiation is NOT the child of the TU.<br>
-  auto Pattern = translationUnitDecl(<br>
-      unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));<br>
-  ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));<br>
-<br>
-  auto *Foo = FirstDeclMatcher<FunctionDecl>().match(<br>
-      FromTU, functionDecl(hasName("foo")));<br>
-  ASSERT_TRUE(Import(Foo, Lang_CXX));<br>
-<br>
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations,<br>
-       TUshouldNotContainFunctionTemplateExplicitInstantiation) {<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-      template<class T><br>
-      int f() { return 0; }<br>
-      template int f<int>();<br>
-      )",<br>
-      Lang_CXX, "input0.cc");<br>
-<br>
-  // Check that the function template instantiation is NOT the child of the TU.<br>
-  auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());<br>
-  auto Pattern = translationUnitDecl(unless(has(Instantiation)));<br>
-  ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));<br>
-<br>
-  ASSERT_TRUE(<br>
-      Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));<br>
-<br>
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations,<br>
-       TUshouldContainFunctionTemplateSpecialization) {<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-      template<class T><br>
-      int f() { return 0; }<br>
-      template <> int f<int>() { return 4; }<br>
-      )",<br>
-      Lang_CXX, "input0.cc");<br>
-<br>
-  // Check that the function template specialization is the child of the TU.<br>
-  auto Specialization =<br>
-      functionDecl(hasName("f"), isExplicitTemplateSpecialization());<br>
-  auto Pattern = translationUnitDecl(has(Specialization));<br>
-  ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));<br>
-<br>
-  ASSERT_TRUE(<br>
-      Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));<br>
-<br>
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations,<br>
-       FunctionTemplateSpecializationRedeclChain) {<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-      template<class T><br>
-      int f() { return 0; }<br>
-      template <> int f<int>() { return 4; }<br>
-      )",<br>
-      Lang_CXX, "input0.cc");<br>
-<br>
-  auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),<br>
-                           hasParent(translationUnitDecl()));<br>
-  auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);<br>
-  {<br>
-    auto *TU = FromTU;<br>
-    auto *SpecD = FromSpecD;<br>
-    auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(<br>
-        TU, functionTemplateDecl());<br>
-    auto *FirstSpecD = *(TemplateD->spec_begin());<br>
-    ASSERT_EQ(SpecD, FirstSpecD);<br>
-    ASSERT_TRUE(SpecD->getPreviousDecl());<br>
-    ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())<br>
-                     ->doesThisDeclarationHaveABody());<br>
-  }<br>
-<br>
-  ASSERT_TRUE(Import(FromSpecD, Lang_CXX));<br>
-<br>
-  {<br>
-    auto *TU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-    auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);<br>
-    auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(<br>
-        TU, functionTemplateDecl());<br>
-    auto *FirstSpecD = *(TemplateD->spec_begin());<br>
-    EXPECT_EQ(SpecD, FirstSpecD);<br>
-    ASSERT_TRUE(SpecD->getPreviousDecl());<br>
-    EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())<br>
-                     ->doesThisDeclarationHaveABody());<br>
-  }<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations,<br>
-       MatchNumberOfFunctionTemplateSpecializations) {<br>
-<br>
-  Decl *FromTU = getTuDecl(<br>
-      R"(<br>
-      template <typename T> constexpr int f() { return 0; }<br>
-      template <> constexpr int f<int>() { return 4; }<br>
-      void foo() {<br>
-        static_assert(f<char>() == 0, "");<br>
-        static_assert(f<int>() == 4, "");<br>
-      }<br>
-      )",<br>
-      Lang_CXX11, "input0.cc");<br>
-  auto *FromD = FirstDeclMatcher<FunctionDecl>().match(<br>
-      FromTU, functionDecl(hasName("foo")));<br>
-<br>
-  Import(FromD, Lang_CXX11);<br>
-  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();<br>
-  EXPECT_EQ(<br>
-      DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),<br>
-      DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations,<br>
-       ImportPrototypes) {<br>
-  auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());<br>
-  auto Code =<br>
-      R"(<br>
-      // Proto of the primary template.<br>
-      template <class T><br>
-      void f();<br>
-      // Proto of the specialization.<br>
-      template <><br>
-      void f<int>();<br>
-      )";<br>
-<br>
-  Decl *ImportedD;<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");<br>
-    auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-<br>
-    ImportedD = Import(FromD, Lang_CXX);<br>
-  }<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");<br>
-    auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    Import(FromD, Lang_CXX);<br>
-  }<br>
-<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(ImportedD != To1);<br>
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_FALSE(To1->doesThisDeclarationHaveABody());<br>
-  // Check that they are part of the same redecl chain.<br>
-  EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {<br>
-  auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());<br>
-  auto Code =<br>
-      R"(<br>
-      // Proto of the primary template.<br>
-      template <class T><br>
-      void f();<br>
-      // Specialization and definition.<br>
-      template <><br>
-      void f<int>() {}<br>
-      )";<br>
-<br>
-  Decl *ImportedD;<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD = Import(FromD, Lang_CXX);<br>
-  }<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    Import(FromD, Lang_CXX);<br>
-  }<br>
-<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(To0->doesThisDeclarationHaveABody());<br>
-<br>
-  auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(<br>
-      ToTU, functionTemplateDecl());<br>
-  auto *FirstSpecD = *(TemplateD->spec_begin());<br>
-  EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {<br>
-  auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());<br>
-  auto Code =<br>
-      R"(<br>
-      // Proto of the primary template.<br>
-      template <class T><br>
-      void f();<br>
-      // Specialization proto.<br>
-      template <><br>
-      void f<int>();<br>
-      // Specialization proto.<br>
-      template <><br>
-      void f<int>();<br>
-      )";<br>
-<br>
-  Decl *ImportedD;<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD = Import(FromD, Lang_CXX);<br>
-  }<br>
-<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(ImportedD != To1);<br>
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_FALSE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {<br>
-  auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());<br>
-  auto Code =<br>
-      R"(<br>
-      // Proto of the primary template.<br>
-      template <class T><br>
-      void f();<br>
-      // Specialization proto.<br>
-      template <><br>
-      void f<int>();<br>
-      // Specialization definition.<br>
-      template <><br>
-      void f<int>() {}<br>
-      )";<br>
-<br>
-  Decl *ImportedD;<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD = Import(FromD, Lang_CXX);<br>
-  }<br>
-<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(ImportedD != To1);<br>
-  EXPECT_FALSE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_TRUE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
-}<br>
-<br>
-TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {<br>
-  auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());<br>
-  auto Code =<br>
-      R"(<br>
-      // Proto of the primary template.<br>
-      template <class T><br>
-      void f();<br>
-      // Specialization definition.<br>
-      template <><br>
-      void f<int>() {}<br>
-      // Specialization proto.<br>
-      template <><br>
-      void f<int>();<br>
-      )";<br>
-<br>
-  Decl *ImportedD;<br>
-  {<br>
-    Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");<br>
-    auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);<br>
-    ImportedD = Import(FromD, Lang_CXX);<br>
-  }<br>
-<br>
-  Decl *ToTU = ImportedD->getTranslationUnitDecl();<br>
-<br>
-  EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);<br>
-  auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);<br>
-  EXPECT_TRUE(ImportedD == To0);<br>
-  EXPECT_TRUE(ImportedD != To1);<br>
-  EXPECT_TRUE(To0->doesThisDeclarationHaveABody());<br>
-  EXPECT_FALSE(To1->doesThisDeclarationHaveABody());<br>
-  EXPECT_EQ(To1->getPreviousDecl(), To0);<br>
-}<br>
-<br>
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,<br>
                         ::testing::Values(ArgVector()), );<br>
<br>
-INSTANTIATE_TEST_CASE_P(<br>
-    ParameterizedTests, CanonicalRedeclChain,<br>
-    ::testing::Values(ArgVector()),);<br>
-<br>
 auto DefaultTestValuesForRunOptions = ::testing::Values(<br>
     ArgVector(),<br>
     ArgVector{"-fdelayed-template-parsing"},<br>
@@ -2615,12 +2048,5 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTes<br>
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,<br>
                         DefaultTestValuesForRunOptions, );<br>
<br>
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,<br>
-                        DefaultTestValuesForRunOptions, );<br>
-<br>
-INSTANTIATE_TEST_CASE_P(ParameterizedTests,<br>
-                        ImportFunctionTemplateSpecializations,<br>
-                        DefaultTestValuesForRunOptions, );<br>
-<br>
 } // end namespace ast_matchers<br>
 } // end namespace clang<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" rel="noreferrer">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>
</blockquote></div></div></div>