martong created this revision.
martong added reviewers: a.sidorin, balazske, xazax.hun, r.stahl.
Herald added subscribers: cfe-commits, dkrupp, rnkovacs.

Generalize the creation of Decl nodes during Import.  With this patch we do the
same things after and before a new AST node is created (::Create) The import
logic should be really simple, we create the node, then we mark that as
imported, then we recursively import the parts for that node and then set them
on that node.  However, the AST is actually a graph, so we have to handle
circles.  If we mark something as imported (`MapImported()`) then we return with
the corresponding `To` decl whenever we want to import that node again, this way
circles are handled.  In order to make this algorithm work we must ensure
things, which are handled in the generic CreateDecl<> template:

- There are no `Import()` calls in between any node creation (::Create)

and the `MapImported()` call.

- Before actually creating an AST node (::Create), we must check if

the Node had been imported already, if yes then return with that one.
One very important case for this is connected to templates: we may
start an import both from the templated decl of a template and from
the template itself.

Now, the virtual `Imported` function is called in `ASTImporter::Impor(Decl *)`,
but only once, when the `Decl` is imported.  One point of this refactor is to
separate responsibilities. The original `Imported()` had 3 responsibilities:

- notify subclasses when an import happened
- register the decl into `ImportedDecls`
- initialise the Decl (set attributes, etc)

Now all of these are in separate functions:

- `Imported`
- `MapImported`
- `InitializeImportedDecl`

I tried to check all the clients, I executed tests for `ExternalASTMerger.cpp`
and some unittests for lldb.


Repository:
  rC Clang

https://reviews.llvm.org/D47632

Files:
  include/clang/AST/ASTImporter.h
  include/clang/AST/DeclBase.h
  lib/AST/ASTImporter.cpp
  lib/AST/ExternalASTMerger.cpp

Index: lib/AST/ExternalASTMerger.cpp
===================================================================
--- lib/AST/ExternalASTMerger.cpp
+++ lib/AST/ExternalASTMerger.cpp
@@ -154,7 +154,7 @@
       ToContainer->setMustBuildLookupTable();
       assert(Parent.CanComplete(ToContainer));
     }
-    return ASTImporter::Imported(From, To);
+    return To;
   }
   ASTImporter &GetReverse() { return Reverse; }
 };
@@ -229,7 +229,7 @@
       SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
     if (!SourceTag->getDefinition())
       return false;
-    Forward.Imported(SourceTag, Tag);
+    Forward.MapImported(SourceTag, Tag);
     Forward.ImportDefinition(SourceTag);
     Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
     return true;
@@ -248,7 +248,7 @@
               SourceInterface);
         if (!SourceInterface->getDefinition())
           return false;
-        Forward.Imported(SourceInterface, Interface);
+        Forward.MapImported(SourceInterface, Interface);
         Forward.ImportDefinition(SourceInterface);
         return true;
       });
@@ -304,7 +304,7 @@
 void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
                                          ASTImporter &Importer) {
   Origins[ToDC] = Origin;
-  Importer.ASTImporter::Imported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
+  Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
 }
 
 ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -76,6 +76,58 @@
                           public StmtVisitor<ASTNodeImporter, Stmt *> {
     ASTImporter &Importer;
 
+    // Wrapper for an overload set.
+    template <typename ToDeclT> struct CallOverloadedCreateFun {
+      template <typename... Args>
+      auto operator()(Args &&... args)
+          -> decltype(ToDeclT::Create(std::forward<Args>(args)...)) {
+        return ToDeclT::Create(std::forward<Args>(args)...);
+      }
+    };
+
+    // Always use this function to create a Decl during import. There are
+    // certain tasks which must be done after the Decl was created, e.g. we
+    // must immediately register that as an imported Decl.
+    // Returns a pair consisting of a pointer to the new or the already imported
+    // Decl and a bool value set to true if the `FromD` had been imported
+    // before.
+    template <typename ToDeclT, typename FromDeclT, typename... Args>
+    std::pair<ToDeclT *, bool> CreateDecl(FromDeclT *FromD, Args &&... args) {
+      // There may be several overloads of ToDeclT::Create. We must make sure
+      // to call the one which would be chosen by the arguments, thus we use a
+      // wrapper for the overload set.
+      CallOverloadedCreateFun<ToDeclT> OC;
+      return CreateDecl(OC, FromD, std::forward<Args>(args)...);
+    }
+    // Use this overload directly only if a special create function must be
+    // used, e.g. CXXRecordDecl::CreateLambda .
+    template <typename CreateFunT, typename FromDeclT, typename... Args>
+    auto CreateDecl(CreateFunT CreateFun, FromDeclT *FromD, Args &&... args)
+        -> std::pair<decltype(CreateFun(std::forward<Args>(args)...)), bool> {
+      using ToDeclT = typename std::remove_pointer<decltype(
+          CreateFun(std::forward<Args>(args)...))>::type;
+      ToDeclT *AlreadyImported =
+          cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD));
+      if (AlreadyImported) {
+        return std::make_pair(AlreadyImported, /*AlreadyImported=*/true);
+      }
+      ToDeclT *ToD = CreateFun(std::forward<Args>(args)...);
+      InitializeImportedDecl(FromD, ToD);
+      return std::make_pair(ToD, /*AlreadyImported=*/false);
+    }
+
+    void InitializeImportedDecl(Decl *FromD, Decl *ToD) {
+      Importer.MapImported(FromD, ToD);
+      ToD->IdentifierNamespace = FromD->IdentifierNamespace;
+      if (FromD->hasAttrs())
+        for (const Attr *FromAttr : FromD->getAttrs())
+          ToD->addAttr(Importer.Import(FromAttr));
+      if (FromD->isUsed())
+        ToD->setIsUsed();
+      if (FromD->isImplicit())
+        ToD->setImplicit();
+    }
+
   public:
     explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}
 
@@ -1526,18 +1578,23 @@
   // Import the location of this declaration.
   SourceLocation Loc = Importer.Import(D->getLocation());
 
-  EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc);
+  bool AlreadyImported;
+  EmptyDecl *ToD;
+  std::tie(ToD, AlreadyImported) =
+      CreateDecl<EmptyDecl>(D, Importer.getToContext(), DC, Loc);
+  if (AlreadyImported)
+    return ToD;
+
   ToD->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToD);
   LexicalDC->addDeclInternal(ToD);
   return ToD;
 }
 
 Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
   TranslationUnitDecl *ToD = 
     Importer.getToContext().getTranslationUnitDecl();
     
-  Importer.Imported(D, ToD);
+  Importer.MapImported(D, ToD);
     
   return ToD;
 }
@@ -1551,19 +1608,19 @@
   if (!DC)
     return nullptr;
 
-  AccessSpecDecl *accessSpecDecl
-    = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(),
-                             DC, Loc, ColonLoc);
-
-  if (!accessSpecDecl)
-    return nullptr;
+  bool AlreadyImported;
+  AccessSpecDecl *ToD;
+  std::tie(ToD, AlreadyImported) = CreateDecl<AccessSpecDecl>(
+      D, Importer.getToContext(), D->getAccess(), DC, Loc, ColonLoc);
+  if (AlreadyImported)
+    return ToD;
 
   // Lexical DeclContext and Semantic DeclContext
   // is always the same for the accessSpec.
-  accessSpecDecl->setLexicalDeclContext(DC);
-  DC->addDeclInternal(accessSpecDecl);
+  ToD->setLexicalDeclContext(DC);
+  DC->addDeclInternal(ToD);
 
-  return accessSpecDecl;
+  return ToD;
 }
 
 Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
@@ -1585,13 +1642,16 @@
   if (!ToMsg && FromMsg)
     return nullptr;
 
-  StaticAssertDecl *ToD = StaticAssertDecl::Create(
-        Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
-        Importer.Import(D->getRParenLoc()), D->isFailed());
+  bool AlreadyImported;
+  StaticAssertDecl *ToD;
+  std::tie(ToD, AlreadyImported) = CreateDecl<StaticAssertDecl>(
+      D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
+      Importer.Import(D->getRParenLoc()), D->isFailed());
+  if (AlreadyImported)
+    return ToD;
 
   ToD->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToD);
-  Importer.Imported(D, ToD);
   return ToD;
 }
 
@@ -1642,11 +1702,13 @@
   // Create the "to" namespace, if needed.
   NamespaceDecl *ToNamespace = MergeWithNamespace;
   if (!ToNamespace) {
-    ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC,
-                                        D->isInline(),
-                                        Importer.Import(D->getLocStart()),
-                                        Loc, Name.getAsIdentifierInfo(),
-                                        /*PrevDecl=*/nullptr);
+    bool AlreadyImported;
+    std::tie(ToNamespace, AlreadyImported) = CreateDecl<NamespaceDecl>(
+        D, Importer.getToContext(), DC, D->isInline(),
+        Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(),
+        /*PrevDecl=*/nullptr);
+    if (AlreadyImported)
+      return ToNamespace;
     ToNamespace->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDeclInternal(ToNamespace);
     
@@ -1659,7 +1721,7 @@
         cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace);
     }
   }
-  Importer.Imported(D, ToNamespace);
+  Importer.MapImported(D, ToNamespace);
   
   ImportDeclContext(D);
   
@@ -1692,13 +1754,16 @@
   if (D->getQualifierLoc() && !ToQLoc)
     return nullptr;
 
-  NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create(
-        Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()),
-        Importer.Import(D->getAliasLoc()), ToII, ToQLoc,
-        Importer.Import(D->getTargetNameLoc()), TargetDecl);
+  bool AlreadyImported;
+  NamespaceAliasDecl *ToD;
+  std::tie(ToD, AlreadyImported) = CreateDecl<NamespaceAliasDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()),
+      Importer.Import(D->getAliasLoc()), ToII, ToQLoc,
+      Importer.Import(D->getTargetNameLoc()), TargetDecl);
+  if (AlreadyImported)
+    return ToD;
 
   ToD->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToD);
   LexicalDC->addDeclInternal(ToD);
 
   return ToD;
@@ -1729,7 +1794,7 @@
       if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
         if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(),
                                             FoundTypedef->getUnderlyingType()))
-          return Importer.Imported(D, FoundTypedef);
+          return Importer.MapImported(D, FoundTypedef);
       }
 
       ConflictingDecls.push_back(FoundDecl);
@@ -1749,27 +1814,25 @@
   if (T.isNull())
     return nullptr;
 
-  // Some nodes (like anonymous tags referred by typedefs) are allowed to
-  // import their enclosing typedef directly. Check if this is the case.
-  if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D))
-    return AlreadyImported;
-
   // Create the new typedef node.
   TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
   SourceLocation StartL = Importer.Import(D->getLocStart());
+
+  bool AlreadyImported;
   TypedefNameDecl *ToTypedef;
   if (IsAlias)
-    ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, StartL, Loc,
-                                      Name.getAsIdentifierInfo(), TInfo);
+    std::tie(ToTypedef, AlreadyImported) =
+        CreateDecl<TypeAliasDecl>(D, Importer.getToContext(), DC, StartL, Loc,
+                                  Name.getAsIdentifierInfo(), TInfo);
   else
-    ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC,
-                                    StartL, Loc,
-                                    Name.getAsIdentifierInfo(),
-                                    TInfo);
+    std::tie(ToTypedef, AlreadyImported) =
+        CreateDecl<TypedefDecl>(D, Importer.getToContext(), DC, StartL, Loc,
+                                Name.getAsIdentifierInfo(), TInfo);
+  if (AlreadyImported)
+    return ToTypedef;
 
   ToTypedef->setAccess(D->getAccess());
   ToTypedef->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToTypedef);
 
   // Templated declarations should not appear in DeclContext.
   TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr;
@@ -1810,7 +1873,7 @@
       if (!FoundDecl->isInIdentifierNamespace(IDNS))
         continue;
       if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl))
-          return Importer.Imported(D, FoundAlias);
+          return Importer.MapImported(D, FoundAlias);
       ConflictingDecls.push_back(FoundDecl);
     }
 
@@ -1833,14 +1896,17 @@
   if (!TemplDecl)
     return nullptr;
 
-  TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create(
-        Importer.getToContext(), DC, Loc, Name, Params, TemplDecl);
+  bool AlreadyImported;
+  TypeAliasTemplateDecl *ToAlias;
+  std::tie(ToAlias, AlreadyImported) = CreateDecl<TypeAliasTemplateDecl>(
+      D, Importer.getToContext(), DC, Loc, Name, Params, TemplDecl);
+  if (AlreadyImported)
+    return ToAlias;
 
   TemplDecl->setDescribedAliasTemplate(ToAlias);
 
   ToAlias->setAccess(D->getAccess());
   ToAlias->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToAlias);
   LexicalDC->addDeclInternal(ToAlias);
   return ToAlias;
 }
@@ -1858,15 +1924,18 @@
 
   assert(LexicalDC->isFunctionOrMethod());
 
-  LabelDecl *ToLabel = D->isGnuLocal()
-      ? LabelDecl::Create(Importer.getToContext(),
-                          DC, Importer.Import(D->getLocation()),
-                          Name.getAsIdentifierInfo(),
-                          Importer.Import(D->getLocStart()))
-      : LabelDecl::Create(Importer.getToContext(),
-                          DC, Importer.Import(D->getLocation()),
-                          Name.getAsIdentifierInfo());
-  Importer.Imported(D, ToLabel);
+  bool AlreadyImported;
+  LabelDecl *ToLabel;
+  std::tie(ToLabel, AlreadyImported) =
+      D->isGnuLocal() ? CreateDecl<LabelDecl>(D, Importer.getToContext(), DC,
+                                              Importer.Import(D->getLocation()),
+                                              Name.getAsIdentifierInfo(),
+                                              Importer.Import(D->getLocStart()))
+                      : CreateDecl<LabelDecl>(D, Importer.getToContext(), DC,
+                                              Importer.Import(D->getLocation()),
+                                              Name.getAsIdentifierInfo());
+  if (AlreadyImported)
+    return ToLabel;
 
   auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt()));
   if (!Label)
@@ -1915,7 +1984,7 @@
       
       if (auto *FoundEnum = dyn_cast<EnumDecl>(Found)) {
         if (IsStructuralMatch(D, FoundEnum))
-          return Importer.Imported(D, FoundEnum);
+          return Importer.MapImported(D, FoundEnum);
       }
       
       ConflictingDecls.push_back(FoundDecl);
@@ -1927,18 +1996,21 @@
                                          ConflictingDecls.size());
     }
   }
-  
+
   // Create the enum declaration.
-  EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC,
-                                  Importer.Import(D->getLocStart()),
-                                  Loc, Name.getAsIdentifierInfo(), nullptr,
-                                  D->isScoped(), D->isScopedUsingClassTag(),
-                                  D->isFixed());
+  bool AlreadyImported;
+  EnumDecl *D2;
+  std::tie(D2, AlreadyImported) = CreateDecl<EnumDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()), Loc,
+      Name.getAsIdentifierInfo(), nullptr, D->isScoped(),
+      D->isScopedUsingClassTag(), D->isFixed());
+  if (AlreadyImported)
+    return D2;
+
   // Import the qualifier, if any.
   D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
   D2->setAccess(D->getAccess());
   D2->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, D2);
   LexicalDC->addDeclInternal(D2);
 
   // Import the integer type.
@@ -1970,7 +2042,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of this record.
@@ -2050,7 +2122,7 @@
             // unit only had a forward declaration anyway; call it the same
             // function.
             // FIXME: For C++, we should also merge methods here.
-            return Importer.Imported(D, FoundDef);
+            return Importer.MapImported(D, FoundDef);
           }
         } else if (!D->isCompleteDefinition()) {
           // We have a forward declaration of this type, so adopt that forward
@@ -2091,15 +2163,17 @@
   RecordDecl *D2 = AdoptDecl;
   SourceLocation StartLoc = Importer.Import(D->getLocStart());
   if (!D2) {
+    bool AlreadyImported;
     CXXRecordDecl *D2CXX = nullptr;
     if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
       if (DCXX->isLambda()) {
         TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo());
-        D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(),
-                                            DC, TInfo, Loc,
-                                            DCXX->isDependentLambda(),
-                                            DCXX->isGenericLambda(),
-                                            DCXX->getLambdaCaptureDefault());
+        std::tie(D2CXX, AlreadyImported) = CreateDecl(
+            CXXRecordDecl::CreateLambda, D, Importer.getToContext(), DC, TInfo,
+            Loc, DCXX->isDependentLambda(), DCXX->isGenericLambda(),
+            DCXX->getLambdaCaptureDefault());
+        if (AlreadyImported)
+          return D2CXX;
         Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl());
         if (DCXX->getLambdaContextDecl() && !CDecl)
           return nullptr;
@@ -2109,25 +2183,27 @@
         // Sema::ActOnStartCXXMemberDeclarations
         CXXRecordDecl *const PrevDecl = nullptr;
         const bool DelayTypeCreation = true;
-        D2CXX = CXXRecordDecl::Create(
-            Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,
+        std::tie(D2CXX, AlreadyImported) = CreateDecl<CXXRecordDecl>(
+            D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,
             Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation);
+        if (AlreadyImported)
+          return D2CXX;
         Importer.getToContext().getTypeDeclType(
             D2CXX, dyn_cast<CXXRecordDecl>(DC));
       } else {
-        D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
-                                      D->getTagKind(),
-                                      DC, StartLoc, Loc,
-                                      Name.getAsIdentifierInfo());
+        std::tie(D2CXX, AlreadyImported) = CreateDecl<CXXRecordDecl>(
+            D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,
+            Name.getAsIdentifierInfo(), cast_or_null<CXXRecordDecl>(PrevDecl));
+        if (AlreadyImported)
+          return D2CXX;
       }
+
       D2 = D2CXX;
       D2->setAccess(D->getAccess());
       D2->setLexicalDeclContext(LexicalDC);
       if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit())
         LexicalDC->addDeclInternal(D2);
 
-      Importer.Imported(D, D2);
-
       if (ClassTemplateDecl *FromDescribed =
           DCXX->getDescribedClassTemplate()) {
         auto *ToDescribed = cast_or_null<ClassTemplateDecl>(
@@ -2149,22 +2225,21 @@
               Importer.Import(MemberInfo->getPointOfInstantiation()));
       }
     } else {
-      D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
-                              DC, StartLoc, Loc, Name.getAsIdentifierInfo());
+      std::tie(D2, AlreadyImported) = CreateDecl<RecordDecl>(
+          D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,
+          Name.getAsIdentifierInfo(), PrevDecl);
+      if (AlreadyImported)
+        return D2;
       D2->setLexicalDeclContext(LexicalDC);
       LexicalDC->addDeclInternal(D2);
     }
-    
+
     D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
     if (D->isAnonymousStructOrUnion())
       D2->setAnonymousStructOrUnion(true);
-    if (PrevDecl) {
-      // FIXME: do this for all Redeclarables, not just RecordDecls.
-      D2->setPreviousDecl(PrevDecl);
-    }
   }
-  
-  Importer.Imported(D, D2);
+
+  Importer.MapImported(D, D2);
 
   if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default))
     return nullptr;
@@ -2200,7 +2275,7 @@
 
       if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) {
         if (IsStructuralMatch(D, FoundEnumConstant))
-          return Importer.Imported(D, FoundEnumConstant);
+          return Importer.MapImported(D, FoundEnumConstant);
       }
 
       ConflictingDecls.push_back(FoundDecl);
@@ -2219,13 +2294,16 @@
   if (D->getInitExpr() && !Init)
     return nullptr;
 
-  EnumConstantDecl *ToEnumerator
-    = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc, 
-                               Name.getAsIdentifierInfo(), T, 
-                               Init, D->getInitVal());
+  bool AlreadyImported;
+  EnumConstantDecl *ToEnumerator;
+  std::tie(ToEnumerator, AlreadyImported) = CreateDecl<EnumConstantDecl>(
+      D, Importer.getToContext(), cast<EnumDecl>(DC), Loc,
+      Name.getAsIdentifierInfo(), T, Init, D->getInitVal());
+  if (AlreadyImported)
+    return ToEnumerator;
+
   ToEnumerator->setAccess(D->getAccess());
   ToEnumerator->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToEnumerator);
   LexicalDC->addDeclInternal(ToEnumerator);
   return ToEnumerator;
 }
@@ -2349,7 +2427,7 @@
               FoundWithoutBody = FoundFunction;
               break;
             }
-            return Importer.Imported(D, FoundFunction);
+            return Importer.MapImported(D, FoundFunction);
           }
 
           // FIXME: Check for overloading more carefully, e.g., by boosting
@@ -2424,16 +2502,15 @@
 
   // Create the imported function.
   FunctionDecl *ToFunction = nullptr;
+  bool AlreadyImported;
   SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart());
   if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
-    ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
-                                            cast<CXXRecordDecl>(DC),
-                                            InnerLocStart,
-                                            NameInfo, T, TInfo,
-                                            FromConstructor->isExplicit(),
-                                            D->isInlineSpecified(), 
-                                            D->isImplicit(),
-                                            D->isConstexpr());
+    std::tie(ToFunction, AlreadyImported) = CreateDecl<CXXConstructorDecl>(
+        D, Importer.getToContext(), cast<CXXRecordDecl>(DC), InnerLocStart,
+        NameInfo, T, TInfo, FromConstructor->isExplicit(),
+        D->isInlineSpecified(), D->isImplicit(), D->isConstexpr());
+    if (AlreadyImported)
+      return ToFunction;
     if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
       SmallVector<CXXCtorInitializer *, 4> CtorInitializers;
       for (auto *I : FromConstructor->inits()) {
@@ -2450,47 +2527,38 @@
       ToCtor->setNumCtorInitializers(NumInitializers);
     }
   } else if (isa<CXXDestructorDecl>(D)) {
-    ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
-                                           cast<CXXRecordDecl>(DC),
-                                           InnerLocStart,
-                                           NameInfo, T, TInfo,
-                                           D->isInlineSpecified(),
-                                           D->isImplicit());
-  } else if (auto *FromConversion = dyn_cast<CXXConversionDecl>(D)) {
-    ToFunction = CXXConversionDecl::Create(Importer.getToContext(), 
-                                           cast<CXXRecordDecl>(DC),
-                                           InnerLocStart,
-                                           NameInfo, T, TInfo,
-                                           D->isInlineSpecified(),
-                                           FromConversion->isExplicit(),
-                                           D->isConstexpr(),
-                                           Importer.Import(D->getLocEnd()));
+    std::tie(ToFunction, AlreadyImported) = CreateDecl<CXXDestructorDecl>(
+        D, Importer.getToContext(), cast<CXXRecordDecl>(DC), InnerLocStart,
+        NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit());
+  } else if (CXXConversionDecl *FromConversion =
+                 dyn_cast<CXXConversionDecl>(D)) {
+    std::tie(ToFunction, AlreadyImported) = CreateDecl<CXXConversionDecl>(
+        D, Importer.getToContext(), cast<CXXRecordDecl>(DC), InnerLocStart,
+        NameInfo, T, TInfo, D->isInlineSpecified(),
+        FromConversion->isExplicit(), D->isConstexpr(),
+        Importer.Import(D->getLocEnd()));
   } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
-    ToFunction = CXXMethodDecl::Create(Importer.getToContext(), 
-                                       cast<CXXRecordDecl>(DC),
-                                       InnerLocStart,
-                                       NameInfo, T, TInfo,
-                                       Method->getStorageClass(),
-                                       Method->isInlineSpecified(),
-                                       D->isConstexpr(),
-                                       Importer.Import(D->getLocEnd()));
+    std::tie(ToFunction, AlreadyImported) = CreateDecl<CXXMethodDecl>(
+        D, Importer.getToContext(), cast<CXXRecordDecl>(DC), InnerLocStart,
+        NameInfo, T, TInfo, Method->getStorageClass(),
+        Method->isInlineSpecified(), D->isConstexpr(),
+        Importer.Import(D->getLocEnd()));
   } else {
-    ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
-                                      InnerLocStart,
-                                      NameInfo, T, TInfo, D->getStorageClass(),
-                                      D->isInlineSpecified(),
-                                      D->hasWrittenPrototype(),
-                                      D->isConstexpr());
+    std::tie(ToFunction, AlreadyImported) = CreateDecl<FunctionDecl>(
+        D, Importer.getToContext(), DC, InnerLocStart, NameInfo, T, TInfo,
+        D->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(),
+        D->isConstexpr());
   }
+  if (AlreadyImported)
+    return ToFunction;
 
   // Import the qualifier, if any.
   ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
   ToFunction->setAccess(D->getAccess());
   ToFunction->setLexicalDeclContext(LexicalDC);
   ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
   ToFunction->setTrivial(D->isTrivial());
   ToFunction->setPure(D->isPure());
-  Importer.Imported(D, ToFunction);
 
   // Set the parameters.
   for (auto *Param : Parameters) {
@@ -2605,7 +2673,7 @@
 
       if (Importer.IsStructurallyEquivalent(D->getType(),
                                             FoundField->getType())) {
-        Importer.Imported(D, FoundField);
+        Importer.MapImported(D, FoundField);
         return FoundField;
       }
 
@@ -2627,11 +2695,15 @@
   if (!BitWidth && D->getBitWidth())
     return nullptr;
 
-  FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
-                                         Importer.Import(D->getInnerLocStart()),
-                                         Loc, Name.getAsIdentifierInfo(),
-                                         T, TInfo, BitWidth, D->isMutable(),
-                                         D->getInClassInitStyle());
+  bool AlreadyImported;
+  FieldDecl *ToField;
+  std::tie(ToField, AlreadyImported) = CreateDecl<FieldDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()),
+      Loc, Name.getAsIdentifierInfo(), T, TInfo, BitWidth, D->isMutable(),
+      D->getInClassInitStyle());
+  if (AlreadyImported)
+    return ToField;
+
   ToField->setAccess(D->getAccess());
   ToField->setLexicalDeclContext(LexicalDC);
   if (Expr *FromInitializer = D->getInClassInitializer()) {
@@ -2642,7 +2714,6 @@
       return nullptr;
   }
   ToField->setImplicit(D->isImplicit());
-  Importer.Imported(D, ToField);
   LexicalDC->addDeclInternal(ToField);
   return ToField;
 }
@@ -2670,7 +2741,7 @@
       if (Importer.IsStructurallyEquivalent(D->getType(),
                                             FoundField->getType(),
                                             !Name.isEmpty())) {
-        Importer.Imported(D, FoundField);
+        Importer.MapImported(D, FoundField);
         return FoundField;
       }
 
@@ -2702,16 +2773,21 @@
     NamedChain[i++] = cast<NamedDecl>(D);
   }
 
-  IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create(
-      Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T,
-      {NamedChain, D->getChainingSize()});
+  llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()};
+  bool AlreadyImported;
+  IndirectFieldDecl *ToIndirectField;
+  std::tie(ToIndirectField, AlreadyImported) = CreateDecl<IndirectFieldDecl>(
+      D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, CH);
+  if (AlreadyImported) {
+    // FIXME here we leak `NamedChain` which is allocated before
+    return ToIndirectField;
+  }
 
   for (const auto *A : D->attrs())
     ToIndirectField->addAttr(Importer.Import(A));
 
   ToIndirectField->setAccess(D->getAccess());
   ToIndirectField->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToIndirectField);
   LexicalDC->addDeclInternal(ToIndirectField);
   return ToIndirectField;
 }
@@ -2736,13 +2812,13 @@
     if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
       if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
                                            ImportedFriend->getFriendDecl()))
-        return Importer.Imported(D, ImportedFriend);
+        return Importer.MapImported(D, ImportedFriend);
 
     } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
       if (Importer.IsStructurallyEquivalent(
             D->getFriendType()->getType(),
             ImportedFriend->getFriendType()->getType(), true))
-        return Importer.Imported(D, ImportedFriend);
+        return Importer.MapImported(D, ImportedFriend);
     }
     ImportedFriend = ImportedFriend->getNextFriend();
   }
@@ -2770,12 +2846,13 @@
     ToTPLists[I] = List;
   }
 
-  FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC,
-                                       Importer.Import(D->getLocation()),
-                                       ToFU, Importer.Import(D->getFriendLoc()),
-                                       ToTPLists);
-
-  Importer.Imported(D, FrD);
+  bool AlreadyImported;
+  FriendDecl *FrD;
+  std::tie(FrD, AlreadyImported) = CreateDecl<FriendDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getLocation()), ToFU,
+      Importer.Import(D->getFriendLoc()), ToTPLists);
+  if (AlreadyImported)
+    return FrD;
 
   FrD->setAccess(D->getAccess());
   FrD->setLexicalDeclContext(LexicalDC);
@@ -2801,7 +2878,7 @@
     if (auto *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) {
       if (Importer.IsStructurallyEquivalent(D->getType(),
                                             FoundIvar->getType())) {
-        Importer.Imported(D, FoundIvar);
+        Importer.MapImported(D, FoundIvar);
         return FoundIvar;
       }
 
@@ -2823,14 +2900,16 @@
   if (!BitWidth && D->getBitWidth())
     return nullptr;
 
-  ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(),
-                                              cast<ObjCContainerDecl>(DC),
-                                       Importer.Import(D->getInnerLocStart()),
-                                              Loc, Name.getAsIdentifierInfo(),
-                                              T, TInfo, D->getAccessControl(),
-                                              BitWidth, D->getSynthesize());
+  bool AlreadyImported;
+  ObjCIvarDecl *ToIvar;
+  std::tie(ToIvar, AlreadyImported) = CreateDecl<ObjCIvarDecl>(
+      D, Importer.getToContext(), cast<ObjCContainerDecl>(DC),
+      Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(),
+      T, TInfo, D->getAccessControl(), BitWidth, D->getSynthesize());
+  if (AlreadyImported)
+    return ToIvar;
+
   ToIvar->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToIvar);
   LexicalDC->addDeclInternal(ToIvar);
   return ToIvar;
 }
@@ -2903,7 +2982,7 @@
     if (MergeWithVar) {
       // An equivalent variable with external linkage has been found. Link 
       // the two declarations, then merge them.
-      Importer.Imported(D, MergeWithVar);
+      Importer.MapImported(D, MergeWithVar);
       
       if (VarDecl *DDef = D->getDefinition()) {
         if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) {
@@ -2941,15 +3020,17 @@
 
   // Create the imported variable.
   TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
-  VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC,
-                                   Importer.Import(D->getInnerLocStart()),
-                                   Loc, Name.getAsIdentifierInfo(),
-                                   T, TInfo,
-                                   D->getStorageClass());
+  bool AlreadyImported;
+  VarDecl *ToVar;
+  std::tie(ToVar, AlreadyImported) = CreateDecl<VarDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()),
+      Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass());
+  if (AlreadyImported)
+    return ToVar;
+
   ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
   ToVar->setAccess(D->getAccess());
   ToVar->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToVar);
 
   // Templated declarations should never appear in the enclosing DeclContext.
   if (!D->getDescribedVarTemplate())
@@ -2988,10 +3069,12 @@
     return nullptr;
 
   // Create the imported parameter.
-  auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc,
-                                           Name.getAsIdentifierInfo(), T,
-                                           D->getParameterKind());
-  return Importer.Imported(D, ToParm);
+  bool AlreadyImported;
+  ImplicitParamDecl *ToParm;
+  std::tie(ToParm, AlreadyImported) = CreateDecl<ImplicitParamDecl>(
+      D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T,
+      D->getParameterKind());
+  return ToParm;
 }
 
 Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
@@ -3014,11 +3097,14 @@
 
   // Create the imported parameter.
   TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
-  ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC,
-                                     Importer.Import(D->getInnerLocStart()),
-                                            Loc, Name.getAsIdentifierInfo(),
-                                            T, TInfo, D->getStorageClass(),
-                                            /*DefaultArg*/ nullptr);
+  bool AlreadyImported;
+  ParmVarDecl *ToParm;
+  std::tie(ToParm, AlreadyImported) = CreateDecl<ParmVarDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()),
+      Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(),
+      /*DefaultArg*/ nullptr);
+  if (AlreadyImported)
+    return ToParm;
 
   // Set the default argument.
   ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
@@ -3051,7 +3137,7 @@
   if (D->isUsed())
     ToParm->setIsUsed();
 
-  return Importer.Imported(D, ToParm);
+  return ToParm;
 }
 
 Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
@@ -3123,7 +3209,7 @@
       }
 
       // FIXME: Any other bits we need to merge?
-      return Importer.Imported(D, FoundMethod);
+      return Importer.MapImported(D, FoundMethod);
     }
   }
 
@@ -3134,11 +3220,15 @@
 
   TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo());
 
-  ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create(
-      Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()),
+  bool AlreadyImported;
+  ObjCMethodDecl *ToMethod;
+  std::tie(ToMethod, AlreadyImported) = CreateDecl<ObjCMethodDecl>(
+      D, Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()),
       Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(),
       D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
       D->getImplementationControl(), D->hasRelatedResultType());
+  if (AlreadyImported)
+    return ToMethod;
 
   // FIXME: When we decide to merge method definitions, we'll need to
   // deal with implicit parameters.
@@ -3167,7 +3257,6 @@
   ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
 
   ToMethod->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToMethod);
   LexicalDC->addDeclInternal(ToMethod);
   return ToMethod;
 }
@@ -3187,16 +3276,16 @@
   if (!BoundInfo)
     return nullptr;
 
-  ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create(
-                                Importer.getToContext(), DC,
-                                D->getVariance(),
-                                Importer.Import(D->getVarianceLoc()),
-                                D->getIndex(),
-                                Importer.Import(D->getLocation()),
-                                Name.getAsIdentifierInfo(),
-                                Importer.Import(D->getColonLoc()),
-                                BoundInfo);
-  Importer.Imported(D, Result);
+  bool AlreadyImported;
+  ObjCTypeParamDecl *Result;
+  std::tie(Result, AlreadyImported) = CreateDecl<ObjCTypeParamDecl>(
+      D, Importer.getToContext(), DC, D->getVariance(),
+      Importer.Import(D->getVarianceLoc()), D->getIndex(),
+      Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(),
+      Importer.Import(D->getColonLoc()), BoundInfo);
+  if (AlreadyImported)
+    return Result;
+
   Result->setLexicalDeclContext(LexicalDC);
   return Result;
 }
@@ -3222,18 +3311,19 @@
     = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
   ObjCCategoryDecl *ToCategory = MergeWithCategory;
   if (!ToCategory) {
-    ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC,
-                                          Importer.Import(D->getAtStartLoc()),
-                                          Loc, 
-                                       Importer.Import(D->getCategoryNameLoc()), 
-                                          Name.getAsIdentifierInfo(),
-                                          ToInterface,
-                                          /*TypeParamList=*/nullptr,
-                                       Importer.Import(D->getIvarLBraceLoc()),
-                                       Importer.Import(D->getIvarRBraceLoc()));
+
+    bool AlreadyImported;
+    std::tie(ToCategory, AlreadyImported) = CreateDecl<ObjCCategoryDecl>(
+        D, Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()),
+        Loc, Importer.Import(D->getCategoryNameLoc()),
+        Name.getAsIdentifierInfo(), ToInterface,
+        /*TypeParamList=*/nullptr, Importer.Import(D->getIvarLBraceLoc()),
+        Importer.Import(D->getIvarRBraceLoc()));
+    if (AlreadyImported)
+      return ToCategory;
+
     ToCategory->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDeclInternal(ToCategory);
-    Importer.Imported(D, ToCategory);
     // Import the type parameter list after calling Imported, to avoid
     // loops when bringing in their DeclContext.
     ToCategory->setTypeParamList(ImportObjCTypeParamList(
@@ -3260,7 +3350,7 @@
     ToCategory->setProtocolList(Protocols.data(), Protocols.size(),
                                 ProtocolLocs.data(), Importer.getToContext());
   } else {
-    Importer.Imported(D, ToCategory);
+    Importer.MapImported(D, ToCategory);
   }
   
   // Import all of the members of this category.
@@ -3329,7 +3419,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of a protocol.
@@ -3355,15 +3445,18 @@
   
   ObjCProtocolDecl *ToProto = MergeWithProtocol;
   if (!ToProto) {
-    ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
-                                       Name.getAsIdentifierInfo(), Loc,
-                                       Importer.Import(D->getAtStartLoc()),
-                                       /*PrevDecl=*/nullptr);
+    bool AlreadyImported;
+    std::tie(ToProto, AlreadyImported) = CreateDecl<ObjCProtocolDecl>(
+        D, Importer.getToContext(), DC, Name.getAsIdentifierInfo(), Loc,
+        Importer.Import(D->getAtStartLoc()),
+        /*PrevDecl=*/nullptr);
+    if (AlreadyImported)
+      return ToProto;
     ToProto->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDeclInternal(ToProto);
   }
-    
-  Importer.Imported(D, ToProto);
+
+  Importer.MapImported(D, ToProto);
 
   if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto))
     return nullptr;
@@ -3379,14 +3472,14 @@
   SourceLocation LangLoc = Importer.Import(D->getLocation());
 
   bool HasBraces = D->hasBraces();
- 
-  LinkageSpecDecl *ToLinkageSpec =
-    LinkageSpecDecl::Create(Importer.getToContext(),
-                            DC,
-                            ExternLoc,
-                            LangLoc,
-                            D->getLanguage(),
-                            HasBraces);
+
+  bool AlreadyImported;
+  LinkageSpecDecl *ToLinkageSpec;
+  std::tie(ToLinkageSpec, AlreadyImported) =
+      CreateDecl<LinkageSpecDecl>(D, Importer.getToContext(), DC, ExternLoc,
+                                  LangLoc, D->getLanguage(), HasBraces);
+  if (AlreadyImported)
+    return ToLinkageSpec;
 
   if (HasBraces) {
     SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc());
@@ -3396,8 +3489,6 @@
   ToLinkageSpec->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToLinkageSpec);
 
-  Importer.Imported(D, ToLinkageSpec);
-
   return ToLinkageSpec;
 }
 
@@ -3415,13 +3506,16 @@
                                Importer.Import(D->getNameInfo().getLoc()));
   ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
 
-  UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC,
-                                         Importer.Import(D->getUsingLoc()),
-                                         Importer.Import(D->getQualifierLoc()),
-                                         NameInfo, D->hasTypename());
+  bool AlreadyImported;
+  UsingDecl *ToUsing;
+  std::tie(ToUsing, AlreadyImported) = CreateDecl<UsingDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+      Importer.Import(D->getQualifierLoc()), NameInfo, D->hasTypename());
+  if (AlreadyImported)
+    return ToUsing;
+
   ToUsing->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToUsing);
-  Importer.Imported(D, ToUsing);
 
   if (NamedDecl *FromPattern =
       Importer.getFromContext().getInstantiatedFromUsingDecl(D)) {
@@ -3464,12 +3558,15 @@
   if (!ToTarget)
     return nullptr;
 
-  UsingShadowDecl *ToShadow = UsingShadowDecl::Create(
-        Importer.getToContext(), DC, Loc, ToUsing, ToTarget);
+  bool AlreadyImported;
+  UsingShadowDecl *ToShadow;
+  std::tie(ToShadow, AlreadyImported) = CreateDecl<UsingShadowDecl>(
+      D, Importer.getToContext(), DC, Loc, ToUsing, ToTarget);
+  if (AlreadyImported)
+    return ToShadow;
 
   ToShadow->setLexicalDeclContext(LexicalDC);
   ToShadow->setAccess(D->getAccess());
-  Importer.Imported(D, ToShadow);
 
   if (UsingShadowDecl *FromPattern =
       Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) {
@@ -3507,14 +3604,18 @@
   if (!ToNominated)
     return nullptr;
 
-  UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create(
-        Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
-        Importer.Import(D->getNamespaceKeyLocation()),
-        Importer.Import(D->getQualifierLoc()),
-        Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor);
+  bool AlreadyImported;
+  UsingDirectiveDecl *ToUsingDir;
+  std::tie(ToUsingDir, AlreadyImported) = CreateDecl<UsingDirectiveDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+      Importer.Import(D->getNamespaceKeyLocation()),
+      Importer.Import(D->getQualifierLoc()),
+      Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor);
+  if (AlreadyImported)
+    return ToUsingDir;
+
   ToUsingDir->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToUsingDir);
-  Importer.Imported(D, ToUsingDir);
 
   return ToUsingDir;
 }
@@ -3533,12 +3634,15 @@
   DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc()));
   ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
 
-  UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create(
-        Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
-        Importer.Import(D->getQualifierLoc()), NameInfo,
-        Importer.Import(D->getEllipsisLoc()));
+  bool AlreadyImported;
+  UnresolvedUsingValueDecl *ToUsingValue;
+  std::tie(ToUsingValue, AlreadyImported) = CreateDecl<UnresolvedUsingValueDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+      Importer.Import(D->getQualifierLoc()), NameInfo,
+      Importer.Import(D->getEllipsisLoc()));
+  if (AlreadyImported)
+    return ToUsingValue;
 
-  Importer.Imported(D, ToUsingValue);
   ToUsingValue->setAccess(D->getAccess());
   ToUsingValue->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToUsingValue);
@@ -3557,13 +3661,16 @@
   if (ToD)
     return ToD;
 
-  UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create(
-        Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
-        Importer.Import(D->getTypenameLoc()),
-        Importer.Import(D->getQualifierLoc()), Loc, Name,
-        Importer.Import(D->getEllipsisLoc()));
+  bool AlreadyImported;
+  UnresolvedUsingTypenameDecl *ToUsing;
+  std::tie(ToUsing, AlreadyImported) = CreateDecl<UnresolvedUsingTypenameDecl>(
+      D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()),
+      Importer.Import(D->getTypenameLoc()),
+      Importer.Import(D->getQualifierLoc()), Loc, Name,
+      Importer.Import(D->getEllipsisLoc()));
+  if (AlreadyImported)
+    return ToUsing;
 
-  Importer.Imported(D, ToUsing);
   ToUsing->setAccess(D->getAccess());
   ToUsing->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToUsing);
@@ -3695,7 +3802,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of an @interface.
@@ -3723,16 +3830,18 @@
   // Create an interface declaration, if one does not already exist.
   ObjCInterfaceDecl *ToIface = MergeWithIface;
   if (!ToIface) {
-    ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
-                                        Importer.Import(D->getAtStartLoc()),
-                                        Name.getAsIdentifierInfo(),
-                                        /*TypeParamList=*/nullptr,
-                                        /*PrevDecl=*/nullptr, Loc,
-                                        D->isImplicitInterfaceDecl());
+    bool AlreadyImported;
+    std::tie(ToIface, AlreadyImported) = CreateDecl<ObjCInterfaceDecl>(
+        D, Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()),
+        Name.getAsIdentifierInfo(),
+        /*TypeParamList=*/nullptr,
+        /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl());
+    if (AlreadyImported)
+      return ToIface;
     ToIface->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDeclInternal(ToIface);
   }
-  Importer.Imported(D, ToIface);
+  Importer.MapImported(D, ToIface);
   // Import the type parameter list after calling Imported, to avoid
   // loops when bringing in their DeclContext.
   ToIface->setTypeParamList(ImportObjCTypeParamList(
@@ -3757,13 +3866,14 @@
       return nullptr;
 
     SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc());
-    ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC,
-                                          Importer.Import(D->getIdentifier()),
-                                          Category->getClassInterface(),
-                                          Importer.Import(D->getLocation()),
-                                          Importer.Import(D->getAtStartLoc()),
-                                          CategoryNameLoc);
-    
+    bool AlreadyImported;
+    std::tie(ToImpl, AlreadyImported) = CreateDecl<ObjCCategoryImplDecl>(
+        D, Importer.getToContext(), DC, Importer.Import(D->getIdentifier()),
+        Category->getClassInterface(), Importer.Import(D->getLocation()),
+        Importer.Import(D->getAtStartLoc()), CategoryNameLoc);
+    if (AlreadyImported)
+      return ToImpl;
+
     DeclContext *LexicalDC = DC;
     if (D->getDeclContext() != D->getLexicalDeclContext()) {
       LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
@@ -3777,7 +3887,7 @@
     Category->setImplementation(ToImpl);
   }
   
-  Importer.Imported(D, ToImpl);
+  Importer.MapImported(D, ToImpl);
   ImportDeclContext(D);
   return ToImpl;
 }
@@ -3802,28 +3912,30 @@
   if (!Impl) {
     // We haven't imported an implementation yet. Create a new @implementation
     // now.
-    Impl = ObjCImplementationDecl::Create(Importer.getToContext(),
-                                  Importer.ImportContext(D->getDeclContext()),
-                                          Iface, Super,
-                                          Importer.Import(D->getLocation()),
-                                          Importer.Import(D->getAtStartLoc()),
-                                          Importer.Import(D->getSuperClassLoc()),
-                                          Importer.Import(D->getIvarLBraceLoc()),
-                                          Importer.Import(D->getIvarRBraceLoc()));
-    
+    bool AlreadyImported;
+    std::tie(Impl, AlreadyImported) = CreateDecl<ObjCImplementationDecl>(
+        D, Importer.getToContext(), Importer.ImportContext(D->getDeclContext()),
+        Iface, Super, Importer.Import(D->getLocation()),
+        Importer.Import(D->getAtStartLoc()),
+        Importer.Import(D->getSuperClassLoc()),
+        Importer.Import(D->getIvarLBraceLoc()),
+        Importer.Import(D->getIvarRBraceLoc()));
+    if (AlreadyImported)
+      return Impl;
+
     if (D->getDeclContext() != D->getLexicalDeclContext()) {
       DeclContext *LexicalDC
         = Importer.ImportContext(D->getLexicalDeclContext());
       if (!LexicalDC)
         return nullptr;
       Impl->setLexicalDeclContext(LexicalDC);
     }
-    
+
     // Associate the implementation with the class it implements.
     Iface->setImplementation(Impl);
-    Importer.Imported(D, Iface->getImplementation());
+    Importer.MapImported(D, Iface->getImplementation());
   } else {
-    Importer.Imported(D, Iface->getImplementation());
+    Importer.MapImported(D, Iface->getImplementation());
 
     // Verify that the existing @implementation has the same superclass.
     if ((Super && !Impl->getSuperClass()) ||
@@ -3889,7 +4001,7 @@
       // FIXME: Check property attributes, getters, setters, etc.?
 
       // Consider these properties to be equivalent.
-      Importer.Imported(D, FoundProp);
+      Importer.MapImported(D, FoundProp);
       return FoundProp;
     }
   }
@@ -3900,15 +4012,15 @@
     return nullptr;
 
   // Create the new property.
-  ObjCPropertyDecl *ToProperty
-    = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc,
-                               Name.getAsIdentifierInfo(), 
-                               Importer.Import(D->getAtLoc()),
-                               Importer.Import(D->getLParenLoc()),
-                               Importer.Import(D->getType()),
-                               TSI,
-                               D->getPropertyImplementation());
-  Importer.Imported(D, ToProperty);
+  bool AlreadyImported;
+  ObjCPropertyDecl *ToProperty;
+  std::tie(ToProperty, AlreadyImported) = CreateDecl<ObjCPropertyDecl>(
+      D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(),
+      Importer.Import(D->getAtLoc()), Importer.Import(D->getLParenLoc()),
+      Importer.Import(D->getType()), TSI, D->getPropertyImplementation());
+  if (AlreadyImported)
+    return ToProperty;
+
   ToProperty->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToProperty);
 
@@ -3962,16 +4074,17 @@
   ObjCPropertyImplDecl *ToImpl
     = InImpl->FindPropertyImplDecl(Property->getIdentifier(),
                                    Property->getQueryKind());
-  if (!ToImpl) {    
-    ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC,
-                                          Importer.Import(D->getLocStart()),
-                                          Importer.Import(D->getLocation()),
-                                          Property,
-                                          D->getPropertyImplementation(),
-                                          Ivar, 
-                                  Importer.Import(D->getPropertyIvarDeclLoc()));
+  if (!ToImpl) {
+    bool AlreadyImported;
+    std::tie(ToImpl, AlreadyImported) = CreateDecl<ObjCPropertyImplDecl>(
+        D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()),
+        Importer.Import(D->getLocation()), Property,
+        D->getPropertyImplementation(), Ivar,
+        Importer.Import(D->getPropertyIvarDeclLoc()));
+    if (AlreadyImported)
+      return ToImpl;
+
     ToImpl->setLexicalDeclContext(LexicalDC);
-    Importer.Imported(D, ToImpl);
     LexicalDC->addDeclInternal(ToImpl);
   } else {
     // Check that we have the same kind of property implementation (@synthesize
@@ -4004,7 +4117,7 @@
     }
     
     // Merge the existing implementation with the new implementation.
-    Importer.Imported(D, ToImpl);
+    Importer.MapImported(D, ToImpl);
   }
   
   return ToImpl;
@@ -4016,15 +4129,15 @@
   // is created.
   
   // FIXME: Import default argument.
-  return TemplateTypeParmDecl::Create(Importer.getToContext(),
-                              Importer.getToContext().getTranslationUnitDecl(),
-                                      Importer.Import(D->getLocStart()),
-                                      Importer.Import(D->getLocation()),
-                                      D->getDepth(),
-                                      D->getIndex(), 
-                                      Importer.Import(D->getIdentifier()),
-                                      D->wasDeclaredWithTypename(),
-                                      D->isParameterPack());
+  bool AlreadyImported;
+  TemplateTypeParmDecl *ToD;
+  std::tie(ToD, AlreadyImported) = CreateDecl<TemplateTypeParmDecl>(
+      D, Importer.getToContext(),
+      Importer.getToContext().getTranslationUnitDecl(),
+      Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()),
+      D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()),
+      D->wasDeclaredWithTypename(), D->isParameterPack());
+  return ToD;
 }
 
 Decl *
@@ -4048,13 +4161,16 @@
     return nullptr;
 
   // FIXME: Import default argument.
-  
-  return NonTypeTemplateParmDecl::Create(Importer.getToContext(),
-                               Importer.getToContext().getTranslationUnitDecl(),
-                                         Importer.Import(D->getInnerLocStart()),
-                                         Loc, D->getDepth(), D->getPosition(),
-                                         Name.getAsIdentifierInfo(),
-                                         T, D->isParameterPack(), TInfo);
+
+  bool AlreadyImported;
+  NonTypeTemplateParmDecl *ToD;
+  std::tie(ToD, AlreadyImported) = CreateDecl<NonTypeTemplateParmDecl>(
+      D, Importer.getToContext(),
+      Importer.getToContext().getTranslationUnitDecl(),
+      Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(),
+      D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(),
+      TInfo);
+  return ToD;
 }
 
 Decl *
@@ -4066,21 +4182,23 @@
 
   // Import the location of this declaration.
   SourceLocation Loc = Importer.Import(D->getLocation());
-  
+
   // Import template parameters.
   TemplateParameterList *TemplateParams
     = ImportTemplateParameterList(D->getTemplateParameters());
   if (!TemplateParams)
     return nullptr;
 
   // FIXME: Import default argument.
-  
-  return TemplateTemplateParmDecl::Create(Importer.getToContext(), 
-                              Importer.getToContext().getTranslationUnitDecl(), 
-                                          Loc, D->getDepth(), D->getPosition(),
-                                          D->isParameterPack(),
-                                          Name.getAsIdentifierInfo(), 
-                                          TemplateParams);
+
+  bool AlreadyImported;
+  TemplateTemplateParmDecl *ToD;
+  std::tie(ToD, AlreadyImported) = CreateDecl<TemplateTemplateParmDecl>(
+      D, Importer.getToContext(),
+      Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(),
+      D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(),
+      TemplateParams);
+  return ToD;
 }
 
 // Returns the definition for a (forward) declaration of a ClassTemplateDecl, if
@@ -4106,7 +4224,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of this class template.
@@ -4145,9 +4263,9 @@
         if (IsStructuralMatch(D, FoundTemplate)) {
           // The class templates structurally match; call it the same template.
 
-          Importer.Imported(D->getTemplatedDecl(),
-                            FoundTemplate->getTemplatedDecl());
-          return Importer.Imported(D, FoundTemplate);
+          Importer.MapImported(D->getTemplatedDecl(),
+                               FoundTemplate->getTemplatedDecl());
+          return Importer.MapImported(D, FoundTemplate);
         }
       }
 
@@ -4172,29 +4290,25 @@
   if (!ToTemplated)
     return nullptr;
 
-  // Resolve possible cyclic import.
-  if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D))
-    return AlreadyImported;
-
   // Create the class template declaration itself.
   TemplateParameterList *TemplateParams =
       ImportTemplateParameterList(D->getTemplateParameters());
   if (!TemplateParams)
     return nullptr;
 
-  ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, 
-                                                    Loc, Name, TemplateParams, 
-                                                    ToTemplated);
+  bool AlreadyImported;
+  ClassTemplateDecl *D2;
+  std::tie(D2, AlreadyImported) = CreateDecl<ClassTemplateDecl>(
+      D, Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated);
+  if (AlreadyImported)
+    return D2;
+
   ToTemplated->setDescribedClassTemplate(D2);
   
   D2->setAccess(D->getAccess());
   D2->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(D2);
   
-  // Note the relationship between the class templates.
-  Importer.Imported(D, D2);
-  Importer.Imported(FromTemplated, ToTemplated);
-
   if (FromTemplated->isCompleteDefinition() &&
       !ToTemplated->isCompleteDefinition()) {
     // FIXME: Import definition!
@@ -4214,7 +4328,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   auto *ClassTemplate =
@@ -4250,6 +4364,8 @@
   void *InsertPos = nullptr;
   ClassTemplateSpecializationDecl *D2
     = ClassTemplate->findSpecialization(TemplateArgs, InsertPos);
+  Optional<bool> AlreadyImported; // Using optional to make sure that all paths
+                                  // initialize it.
   if (D2) {
     // We already have a class template specialization with these template
     // arguments.
@@ -4261,7 +4377,7 @@
         // The record types structurally match, or the "from" translation
         // unit only had a forward declaration anyway; call it the same
         // function.
-        return Importer.Imported(D, FoundDef);
+        return Importer.MapImported(D, FoundDef);
       }
     }
   } else {
@@ -4285,20 +4401,22 @@
       if (!ToTPList && PartialSpec->getTemplateParameters())
         return nullptr;
 
-      D2 = ClassTemplatePartialSpecializationDecl::Create(
-            Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc,
-            ToTPList, ClassTemplate,
-            llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
-            ToTAInfo, CanonInjType, nullptr);
+      std::tie(D2, AlreadyImported) =
+          CreateDecl<ClassTemplatePartialSpecializationDecl>(
+              D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc,
+              ToTPList, ClassTemplate,
+              llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
+              ToTAInfo, CanonInjType, nullptr);
 
     } else {
-      D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(),
-                                                   D->getTagKind(), DC,
-                                                   StartLoc, IdLoc,
-                                                   ClassTemplate,
-                                                   TemplateArgs,
-                                                   /*PrevDecl=*/nullptr);
+      std::tie(D2, AlreadyImported) =
+          CreateDecl<ClassTemplateSpecializationDecl>(
+              D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc,
+              ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr);
     }
+    assert(AlreadyImported.hasValue());
+    if (*AlreadyImported)
+      return D2;
 
     D2->setSpecializationKind(D->getSpecializationKind());
 
@@ -4308,8 +4426,6 @@
     // Import the qualifier, if any.
     D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
 
-    Importer.Imported(D, D2);
-
     if (auto *TSI = D->getTypeAsWritten()) {
       TypeSourceInfo *TInfo = Importer.Import(TSI);
       if (!TInfo)
@@ -4335,7 +4451,6 @@
       LexicalDC->addDeclInternal(D2);
     }
   }
-  Importer.Imported(D, D2);
   if (D->isCompleteDefinition() && ImportDefinition(D, D2))
     return nullptr;
 
@@ -4354,7 +4469,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of this variable template.
@@ -4381,9 +4496,9 @@
     if (auto *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
       if (IsStructuralMatch(D, FoundTemplate)) {
         // The variable templates structurally match; call it the same template.
-        Importer.Imported(D->getTemplatedDecl(),
-                          FoundTemplate->getTemplatedDecl());
-        return Importer.Imported(D, FoundTemplate);
+        Importer.MapImported(D->getTemplatedDecl(),
+                             FoundTemplate->getTemplatedDecl());
+        return Importer.MapImported(D, FoundTemplate);
       }
     }
 
@@ -4417,18 +4532,19 @@
   if (!TemplateParams)
     return nullptr;
 
-  VarTemplateDecl *ToVarTD = VarTemplateDecl::Create(
-      Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated);
+  bool AlreadyImported;
+  VarTemplateDecl *ToVarTD;
+  std::tie(ToVarTD, AlreadyImported) = CreateDecl<VarTemplateDecl>(
+      D, Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated);
+  if (AlreadyImported)
+    return ToVarTD;
+
   ToTemplated->setDescribedVarTemplate(ToVarTD);
 
   ToVarTD->setAccess(D->getAccess());
   ToVarTD->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToVarTD);
 
-  // Note the relationship between the variable templates.
-  Importer.Imported(D, ToVarTD);
-  Importer.Imported(DTemplated, ToTemplated);
-
   if (DTemplated->isThisDeclarationADefinition() &&
       !ToTemplated->isThisDeclarationADefinition()) {
     // FIXME: Import definition!
@@ -4448,7 +4564,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   auto *VarTemplate = cast_or_null<VarTemplateDecl>(
@@ -4494,7 +4610,7 @@
         // The record types structurally match, or the "from" translation
         // unit only had a forward declaration anyway; call it the same
         // variable.
-        return Importer.Imported(D, FoundDef);
+        return Importer.MapImported(D, FoundDef);
       }
     }
   } else {
@@ -4526,9 +4642,13 @@
       if (!ToTPList)
         return nullptr;
 
-      auto *ToPartial = PartVarSpecDecl::Create(
-          Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList, VarTemplate,
-          T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos);
+      bool AlreadyImported;
+      PartVarSpecDecl *ToPartial;
+      std::tie(ToPartial, AlreadyImported) = CreateDecl<PartVarSpecDecl>(
+          D, Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList,
+          VarTemplate, T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos);
+      if (AlreadyImported)
+        return ToPartial;
 
       auto *FromInst = FromPartial->getInstantiatedFromMember();
       auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst));
@@ -4541,9 +4661,12 @@
 
       D2 = ToPartial;
     } else { // Full specialization
-      D2 = VarTemplateSpecializationDecl::Create(
-          Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
-          D->getStorageClass(), TemplateArgs);
+      bool AlreadyImported;
+      std::tie(D2, AlreadyImported) = CreateDecl<VarTemplateSpecializationDecl>(
+          D, Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T,
+          TInfo, D->getStorageClass(), TemplateArgs);
+      if (AlreadyImported)
+        return D2;
     }
 
     SourceLocation POI = D->getPointOfInstantiation();
@@ -4569,8 +4692,6 @@
     D2->setAccess(D->getAccess());
   }
 
-  Importer.Imported(D, D2);
-
   // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if
   // declaration has initializer. Should this be fixed in the AST?.. Anyway,
   // we have to check the declaration for initializer - otherwise, it won't be
@@ -4608,7 +4729,7 @@
         if (FoundFunction->hasExternalFormalLinkage() &&
             D->hasExternalFormalLinkage()) {
           if (IsStructuralMatch(D, FoundFunction)) {
-            Importer.Imported(D, FoundFunction);
+            Importer.MapImported(D, FoundFunction);
             // FIXME: Actually try to merge the body and other attributes.
             return FoundFunction;
           }
@@ -4627,13 +4748,16 @@
   if (!TemplatedFD)
     return nullptr;
 
-  FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create(
-      Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD);
+  bool AlreadyImported;
+  FunctionTemplateDecl *ToFunc;
+  std::tie(ToFunc, AlreadyImported) = CreateDecl<FunctionTemplateDecl>(
+      D, Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD);
+  if (AlreadyImported)
+    return ToFunc;
 
   TemplatedFD->setDescribedFunctionTemplate(ToFunc);
   ToFunc->setAccess(D->getAccess());
   ToFunc->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToFunc);
 
   LexicalDC->addDeclInternal(ToFunc);
   return ToFunc;
@@ -6718,22 +6842,20 @@
 
   ASTNodeImporter Importer(*this);
 
-  // Check whether we've already imported this declaration.  
-  llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
-  if (Pos != ImportedDecls.end()) {
-    Decl *ToD = Pos->second;
-    Importer.ImportDefinitionIfNeeded(FromD, ToD);
+  // Check whether we've already imported this declaration.
+  Decl *ToD = GetAlreadyImportedOrNull(FromD);
+  if (ToD) {
     return ToD;
   }
-  
-  // Import the type
-  Decl *ToD = Importer.Visit(FromD);
+
+  // Import the type.
+  ToD = Importer.Visit(FromD);
   if (!ToD)
     return nullptr;
 
-  // Record the imported declaration.
-  ImportedDecls[FromD] = ToD;
-  ToD->IdentifierNamespace = FromD->IdentifierNamespace;
+  // Notify subclasses.
+  Imported(FromD, ToD);
+
   return ToD;
 }
 
@@ -7332,17 +7454,12 @@
   }
 }
 
-Decl *ASTImporter::Imported(Decl *From, Decl *To) {
-  if (From->hasAttrs()) {
-    for (const auto *FromAttr : From->getAttrs())
-      To->addAttr(Import(FromAttr));
-  }
-  if (From->isUsed()) {
-    To->setIsUsed();
-  }
-  if (From->isImplicit()) {
-    To->setImplicit();
-  }
+Decl *ASTImporter::MapImported(Decl *From, Decl *To) {
+  llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(From);
+  assert((Pos == ImportedDecls.end() || Pos->second == To) &&
+      "Try to import an already imported Decl");
+  if (Pos != ImportedDecls.end())
+    return Pos->second;
   ImportedDecls[From] = To;
   return To;
 }
Index: include/clang/AST/DeclBase.h
===================================================================
--- include/clang/AST/DeclBase.h
+++ include/clang/AST/DeclBase.h
@@ -309,7 +309,7 @@
 protected:
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
-  friend class ASTImporter;
+  friend class ASTNodeImporter;
   friend class ASTReader;
   friend class CXXClassMemberWrapper;
   friend class LinkageComputer;
Index: include/clang/AST/ASTImporter.h
===================================================================
--- include/clang/AST/ASTImporter.h
+++ include/clang/AST/ASTImporter.h
@@ -305,13 +305,13 @@
     /// \param D A declaration in the "to" context.
     virtual void CompleteDecl(Decl* D);
     
-    /// Note that we have imported the "from" declaration by mapping it
-    /// to the (potentially-newly-created) "to" declaration.
-    ///
     /// Subclasses can override this function to observe all of the \c From ->
     /// \c To declaration mappings as they are imported.
-    virtual Decl *Imported(Decl *From, Decl *To);
-      
+    virtual Decl *Imported(Decl *From, Decl *To) { return To; }
+
+    /// Store and assign the imported declaration to its counterpart.
+    Decl *MapImported(Decl *From, Decl *To);
+
     /// Called by StructuralEquivalenceContext.  If a RecordDecl is
     /// being compared to another RecordDecl as part of import, completing the
     /// other RecordDecl may trigger importation of the first RecordDecl. This
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to