martong updated this revision to Diff 152703.
martong added a comment.

- Rebase from master.


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
@@ -95,6 +95,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) {}
 
@@ -1572,18 +1624,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;
 }
@@ -1597,19 +1654,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) {
@@ -1631,13 +1688,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;
 }
 
@@ -1688,11 +1748,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);
     
@@ -1705,7 +1767,7 @@
         cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace);
     }
   }
-  Importer.Imported(D, ToNamespace);
+  Importer.MapImported(D, ToNamespace);
   
   ImportDeclContext(D);
   
@@ -1738,13 +1800,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;
@@ -1775,7 +1840,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);
@@ -1795,27 +1860,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;
@@ -1856,7 +1919,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);
     }
 
@@ -1879,14 +1942,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;
 }
@@ -1904,15 +1970,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)
@@ -1961,7 +2030,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);
@@ -1973,18 +2042,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.
@@ -2016,7 +2088,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of this record.
@@ -2096,7 +2168,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
@@ -2137,15 +2209,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;
@@ -2155,25 +2229,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>(
@@ -2195,22 +2271,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;
@@ -2246,7 +2321,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);
@@ -2265,13 +2340,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;
 }
@@ -2422,7 +2500,7 @@
                                                 FoundFunction->getType())) {
               if (D->doesThisDeclarationHaveABody() &&
                   FoundFunction->hasBody())
-                return Importer.Imported(D, FoundFunction);
+                return Importer.MapImported(D, FoundFunction);
               FoundByLookup = FoundFunction;
               break;
           }
@@ -2499,16 +2577,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()) {
@@ -2525,47 +2602,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) {
@@ -2696,7 +2764,7 @@
 
       if (Importer.IsStructurallyEquivalent(D->getType(),
                                             FoundField->getType())) {
-        Importer.Imported(D, FoundField);
+        Importer.MapImported(D, FoundField);
         return FoundField;
       }
 
@@ -2718,11 +2786,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()) {
@@ -2733,7 +2805,6 @@
       return nullptr;
   }
   ToField->setImplicit(D->isImplicit());
-  Importer.Imported(D, ToField);
   LexicalDC->addDeclInternal(ToField);
   return ToField;
 }
@@ -2761,7 +2832,7 @@
       if (Importer.IsStructurallyEquivalent(D->getType(),
                                             FoundField->getType(),
                                             !Name.isEmpty())) {
-        Importer.Imported(D, FoundField);
+        Importer.MapImported(D, FoundField);
         return FoundField;
       }
 
@@ -2793,16 +2864,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;
 }
@@ -2827,13 +2903,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();
   }
@@ -2861,12 +2937,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);
@@ -2892,7 +2969,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;
       }
 
@@ -2914,14 +2991,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;
 }
@@ -2994,7 +3073,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()) {
@@ -3032,15 +3111,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())
@@ -3079,10 +3160,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) {
@@ -3105,11 +3188,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());
@@ -3142,7 +3228,7 @@
   if (D->isUsed())
     ToParm->setIsUsed();
 
-  return Importer.Imported(D, ToParm);
+  return ToParm;
 }
 
 Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
@@ -3214,7 +3300,7 @@
       }
 
       // FIXME: Any other bits we need to merge?
-      return Importer.Imported(D, FoundMethod);
+      return Importer.MapImported(D, FoundMethod);
     }
   }
 
@@ -3225,11 +3311,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.
@@ -3258,7 +3348,6 @@
   ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
 
   ToMethod->setLexicalDeclContext(LexicalDC);
-  Importer.Imported(D, ToMethod);
   LexicalDC->addDeclInternal(ToMethod);
   return ToMethod;
 }
@@ -3278,16 +3367,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;
 }
@@ -3313,18 +3402,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(
@@ -3351,7 +3441,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.
@@ -3420,7 +3510,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of a protocol.
@@ -3446,15 +3536,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;
@@ -3470,14 +3563,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());
@@ -3487,8 +3580,6 @@
   ToLinkageSpec->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(ToLinkageSpec);
 
-  Importer.Imported(D, ToLinkageSpec);
-
   return ToLinkageSpec;
 }
 
@@ -3506,13 +3597,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)) {
@@ -3555,12 +3649,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)) {
@@ -3598,14 +3695,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;
 }
@@ -3624,12 +3725,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);
@@ -3648,13 +3752,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);
@@ -3786,7 +3893,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of an @interface.
@@ -3814,16 +3921,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(
@@ -3848,13 +3957,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());
@@ -3868,7 +3978,7 @@
     Category->setImplementation(ToImpl);
   }
   
-  Importer.Imported(D, ToImpl);
+  Importer.MapImported(D, ToImpl);
   ImportDeclContext(D);
   return ToImpl;
 }
@@ -3893,28 +4003,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()) ||
@@ -3980,7 +4092,7 @@
       // FIXME: Check property attributes, getters, setters, etc.?
 
       // Consider these properties to be equivalent.
-      Importer.Imported(D, FoundProp);
+      Importer.MapImported(D, FoundProp);
       return FoundProp;
     }
   }
@@ -3991,15 +4103,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);
 
@@ -4053,16 +4165,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
@@ -4095,7 +4208,7 @@
     }
     
     // Merge the existing implementation with the new implementation.
-    Importer.Imported(D, ToImpl);
+    Importer.MapImported(D, ToImpl);
   }
   
   return ToImpl;
@@ -4107,15 +4220,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 *
@@ -4139,13 +4252,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 *
@@ -4157,21 +4273,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
@@ -4197,7 +4315,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of this class template.
@@ -4236,9 +4354,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);
         }
       }
 
@@ -4263,29 +4381,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!
@@ -4305,7 +4419,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   auto *ClassTemplate =
@@ -4341,6 +4455,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.
@@ -4352,7 +4468,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 {
@@ -4376,20 +4492,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());
 
@@ -4399,8 +4517,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)
@@ -4426,7 +4542,6 @@
       LexicalDC->addDeclInternal(D2);
     }
   }
-  Importer.Imported(D, D2);
   if (D->isCompleteDefinition() && ImportDefinition(D, D2))
     return nullptr;
 
@@ -4445,7 +4560,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   // Import the major distinguishing characteristics of this variable template.
@@ -4472,9 +4587,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);
       }
     }
 
@@ -4508,18 +4623,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!
@@ -4539,7 +4655,7 @@
     if (!ImportedDef)
       return nullptr;
 
-    return Importer.Imported(D, ImportedDef);
+    return Importer.MapImported(D, ImportedDef);
   }
 
   auto *VarTemplate = cast_or_null<VarTemplateDecl>(
@@ -4585,7 +4701,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 {
@@ -4617,9 +4733,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));
@@ -4632,9 +4752,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();
@@ -4660,8 +4783,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
@@ -4699,7 +4820,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;
           }
@@ -4718,13 +4839,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;
@@ -6809,22 +6933,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;
 }
 
@@ -7423,17 +7545,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
@@ -314,13 +314,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