[PATCH] D38208: Add support for remembering origins to ExternalASTMerger

Sean Callanan via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 25 17:15:30 PDT 2017


Updated the diff.  Unfortunately reviews.llvm.org is down, so I'll try 
updating that page in the morning.

Sean

On 9/25/17 5:04 AM, Bruno Cardoso Lopes via Phabricator wrote:
> bruno added inline comments.
>
>
> ================
> Comment at: lib/AST/ExternalASTMerger.cpp:79
> +      return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
> +    else
> +      return nullptr; // This type of lookup is unsupported
> ----------------
> No need for `else` here.
>
>
> ================
> Comment at: lib/AST/ExternalASTMerger.cpp:173
> +ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
> +  for (const std::unique_ptr<ASTImporter> &I : Importers) {
> +    if (&I->getFromContext() == &OriginContext)
> ----------------
> No need for curly braces here.
>
>
> ================
> Comment at: lib/AST/ExternalASTMerger.cpp:189
> +bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
> +  for (const std::unique_ptr<ASTImporter> &I : Importers) {
> +    if (&I->getFromContext() == &OriginContext)
> ----------------
> No need for curly braces here.
>
>
> ================
> Comment at: lib/AST/ExternalASTMerger.cpp:289
> +      LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
> +  if (!FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC)) {
> +    if (LoggingEnabled())
> ----------------
> You can probably simplify this to something like:
>
>
> ```
> bool RecordOrigin = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
>
> if (RecordOrigin)
>    RecordOriginImpl(ToDC, Origin, Importer);
>    
> if (LoggingEnabled()) {
>    logs() << "(ExternalASTMerger*)" << (void*)this
>           << " decided";
>           
>    if (!RecordOrigin)
>      logs() << " NOT";
>      
>    logs() << " to record origin (DeclContext*)" << (void*)Origin.DC
>           << ", (ASTContext*)" << (void*)&Origin.AST
>           << "\n";
> }
> ```
>
>
> ================
> Comment at: lib/AST/ExternalASTMerger.cpp:380
> +
> +  if (Candidates.empty()) {
> +    return false;
> ----------------
> No need for curly braces here.
>
>
> ================
> Comment at: tools/clang-import-test/clang-import-test.cpp:329
>       CG.GetModule()->print(llvm::outs(), nullptr);
> -  if (CI->getDiagnosticClient().getNumErrors()) {
> +  if (CI.getDiagnosticClient().getNumErrors()) {
>       return llvm::make_error<llvm::StringError>(
> ----------------
> No need for curly braces here
>
>
> Repository:
>    rL LLVM
>
> https://reviews.llvm.org/D38208
>
>
>

-------------- next part --------------
Index: include/clang/AST/ExternalASTMerger.h
===================================================================
--- include/clang/AST/ExternalASTMerger.h	(revision 313996)
+++ include/clang/AST/ExternalASTMerger.h	(working copy)
@@ -1,51 +1,176 @@
 //===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
 //  This file declares the ExternalASTMerger, which vends a combination of ASTs
 //  from several different ASTContext/FileManager pairs
 //
 //===----------------------------------------------------------------------===//
 #ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
 #define LLVM_CLANG_AST_EXTERNALASTMERGER_H
 
 #include "clang/AST/ASTImporter.h"
 #include "clang/AST/ExternalASTSource.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace clang {
 
+/// ExternalASTSource implementation that merges information from several
+/// ASTContexts.
+///
+/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import
+/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
+/// in response to ExternalASTSource API calls.
+///
+/// When lookup occurs in the resulting imported DeclContexts, the original
+/// DeclContexts need to be queried.  Roughly, there are three cases here:
+///
+/// - The DeclContext of origin can be found by simple name lookup.  In this
+///   case, no additional state is required.
+///
+/// - The DeclContext of origin is different from what would be found by name
+///   lookup.  In this case, Origins contains an entry overriding lookup and
+///   specifying the correct pair of DeclContext/ASTContext.
+///
+/// - The DeclContext of origin was determined by another ExterenalASTMerger. 
+///   (This is possible when the source ASTContext for one of the Importers has
+///   its own ExternalASTMerger).  The origin must be properly forwarded in this
+///   case.
+///
+/// ExternalASTMerger's job is to maintain the data structures necessary to
+/// allow this.  The data structures themselves can be extracted (read-only) and
+/// copied for re-use.
 class ExternalASTMerger : public ExternalASTSource {
 public:
-  struct ImporterPair {
-    std::unique_ptr<ASTImporter> Forward;
-    std::unique_ptr<ASTImporter> Reverse;
+  /// A single origin for a DeclContext.  Unlike Decls, DeclContexts do
+  /// not allow their containing ASTContext to be determined in all cases.
+  struct DCOrigin {
+    DeclContext *DC;
+    ASTContext *AST;
   };
 
+  typedef std::map<const DeclContext *, DCOrigin> OriginMap;
+  typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
 private:
-  std::vector<ImporterPair> Importers;
+  /// One importer exists for each source.  
+  ImporterVector Importers;
+  /// Overrides in case name lookup would return nothing or would return
+  /// the wrong thing.
+  OriginMap Origins;
+  /// The installed log stream.
+  llvm::raw_ostream *LogStream;
 
 public:
-  struct ImporterEndpoint {
+  /// The target for an ExternalASTMerger.
+  ///
+  /// ASTImporters require both ASTContext and FileManager to be able to
+  /// import SourceLocations properly.
+  struct ImporterTarget {
     ASTContext &AST;
     FileManager &FM;
   };
-  ExternalASTMerger(const ImporterEndpoint &Target,
-                    llvm::ArrayRef<ImporterEndpoint> Sources);
+  /// A source for an ExternalASTMerger.
+  ///
+  /// ASTImporters require both ASTContext and FileManager to be able to
+  /// import SourceLocations properly.  Additionally, when import occurs for
+  /// a DeclContext whose origin has been overridden, then this
+  /// ExternalASTMerger must be able to determine that.
+  struct ImporterSource {
+    ASTContext &AST;
+    FileManager &FM;
+    const OriginMap &OM;
+  };
 
+private:
+  /// The target for this ExtenralASTMerger.
+  ImporterTarget Target;
+
+public:
+  ExternalASTMerger(const ImporterTarget &Target,
+                    llvm::ArrayRef<ImporterSource> Sources);
+
+  /// Add a set of ASTContexts as possible origins.
+  ///
+  /// Usually the set will be initialized in the constructor, but long-lived
+  /// ExternalASTMergers may neeed to import from new sources (for example,
+  /// newly-parsed source files).
+  ///
+  /// Ensures that Importers does not gain duplicate entries as a result.
+  void AddSources(llvm::ArrayRef<ImporterSource> Sources);
+
+  /// Remove a set of ASTContexts as possible origins.
+  ///
+  /// Sometimes an origin goes away (for example, if a source file gets
+  /// superseded by a newer version). 
+  ///
+  /// The caller is responsible for ensuring that this doesn't leave
+  /// DeclContexts that can't be completed.
+  void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);
+
+  /// Implementation of the ExternalASTSource API.
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
                                       DeclarationName Name) override;
 
+  /// Implementation of the ExternalASTSource API.
   void
   FindExternalLexicalDecls(const DeclContext *DC,
                            llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
                            SmallVectorImpl<Decl *> &Result) override;
+
+  /// Implementation of the ExternalASTSource API.
+  void CompleteType(TagDecl *Tag) override;
+
+  /// Implementation of the ExternalASTSource API.
+  void CompleteType(ObjCInterfaceDecl *Interface) override;
+
+  /// Returns true if DC can be found in any source AST context.
+  bool CanComplete(DeclContext *DC);
+
+  /// Records an origin in Origins only if name lookup would find
+  /// something different or nothing at all.
+  void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
+
+  /// Regardless of any checks, override the Origin for a DeclContext.
+  void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
+
+  /// Get a read-only view of the Origins map, for use in constructing
+  /// an ImporterSource for another ExternalASTMerger.
+  const OriginMap &GetOrigins() { return Origins; }
+
+  /// Returns true if Importers contains an ASTImporter whose source is
+  /// OriginContext.
+  bool HasImporterForOrigin(ASTContext &OriginContext);
+
+  /// Returns a reference to the ASTRImporter from Importers whose origin
+  /// is OriginContext.  This allows manual import of ASTs while preserving the
+  /// OriginMap correctly.
+  ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
+
+  /// Sets the current log stream.
+  void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
+private:
+  /// Records and origin in Origins.
+  void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
+                                  ASTImporter &importer);
+
+  /// Performs an action for every DeclContext that is identified as
+  /// corresponding (either by forced origin or by name lookup) to DC.
+  template <typename CallbackType>
+  void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
+
+public: 
+  /// Log something if there is a logging callback installed.
+  llvm::raw_ostream &logs() { return *LogStream; }
+
+  /// True if the log stream is not llvm::nulls();
+  bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
 };
 
 } // end namespace clang
 
 #endif
Index: lib/AST/ExternalASTMerger.cpp
===================================================================
--- lib/AST/ExternalASTMerger.cpp	(revision 313996)
+++ lib/AST/ExternalASTMerger.cpp	(working copy)
@@ -1,186 +1,402 @@
 //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
 //  This file implements the ExternalASTMerger, which vends a combination of
 //  ASTs from several different ASTContext/FileManager pairs
 //
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExternalASTMerger.h"
 
 using namespace clang;
 
 namespace {
 
 template <typename T> struct Source {
   T t;
   Source(T t) : t(t) {}
   operator T() { return t; }
   template <typename U = T> U &get() { return t; }
   template <typename U = T> const U &get() const { return t; }
   template <typename U> operator Source<U>() { return Source<U>(t); }
 };
 
 typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
 
-class LazyASTImporter : public ASTImporter {
-public:
-  LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
-                  ASTContext &FromContext, FileManager &FromFileManager)
-      : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
-                    /*MinimalImport=*/true) {}
-  Decl *Imported(Decl *From, Decl *To) override {
-    if (auto ToTag = dyn_cast<TagDecl>(To)) {
-      ToTag->setHasExternalLexicalStorage();
-      ToTag->setMustBuildLookupTable();
-    } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
-      ToNamespace->setHasExternalVisibleStorage();
-    } else if (auto ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
-      ToContainer->setHasExternalLexicalStorage();
-      ToContainer->setMustBuildLookupTable();
-    }
-    return ASTImporter::Imported(From, To);
-  }
-};
+/// For the given DC, return the DC that is safe to perform lookups on.  This is
+/// the DC we actually want to work with most of the time.
+const DeclContext *CanonicalizeDC(const DeclContext *DC) {
+  if (isa<LinkageSpecDecl>(DC))
+    return DC->getRedeclContext();
+  return DC;
+}
 
 Source<const DeclContext *>
 LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
                   ASTImporter &ReverseImporter) {
+  DC = CanonicalizeDC(DC);
   if (DC->isTranslationUnit()) {
     return SourceTU;
   }
   Source<const DeclContext *> SourceParentDC =
       LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
   if (!SourceParentDC) {
     // If we couldn't find the parent DC in this TranslationUnit, give up.
     return nullptr;
   }
-  auto ND = cast<NamedDecl>(DC);
+  auto *ND = cast<NamedDecl>(DC);
   DeclarationName Name = ND->getDeclName();
   Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
   DeclContext::lookup_result SearchResult =
       SourceParentDC.get()->lookup(SourceName.get());
   size_t SearchResultSize = SearchResult.size();
-  // Handle multiple candidates once we have a test for it.
-  // This may turn up when we import template specializations correctly.
-  assert(SearchResultSize < 2);
-  if (SearchResultSize == 0) {
-    // couldn't find the name, so we have to give up
+  if (SearchResultSize == 0 || SearchResultSize > 1) {
+    // There are two cases here.  First, we might not find the name.
+    // We might also find multiple copies, in which case we have no
+    // guarantee that the one we wanted is the one we pick.  (E.g.,
+    // if we have two specializations of the same template it is
+    // very hard to determine which is the one you want.)
+    //
+    // The Origins map fixes this problem by allowing the origin to be
+    // explicitly recorded, so we trigger that recording by returning
+    // nothing (rather than a possibly-inaccurate guess) here.
     return nullptr;
   } else {
     NamedDecl *SearchResultDecl = SearchResult[0];
-    return dyn_cast<DeclContext>(SearchResultDecl);
+    if (isa<DeclContext>(SearchResultDecl) &&
+        SearchResultDecl->getKind() == DC->getDeclKind())
+      return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
+    return nullptr; // This type of lookup is unsupported
   }
 }
 
-bool IsForwardDeclaration(Decl *D) {
-  if (auto TD = dyn_cast<TagDecl>(D)) {
-    return !TD->isThisDeclarationADefinition();
-  } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
-    return !FD->isThisDeclarationADefinition();
-  } else if (auto OID = dyn_cast<ObjCInterfaceDecl>(D)) {
-     return OID->isThisDeclarationADefinition();
-  } else {
-    return false;
-  }
-}
+/// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
+///
+/// There are several modifications:
+///
+/// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
+///   others), which instructs Clang to refer to ExternalASTMerger.  Also, it
+///   forces MinimalImport to true, which is necessary to make this work.
+/// - It maintains a reverse importer for use with names.  This allows lookup of
+///   arbitrary names in the source context.
+/// - It updates the ExternalASTMerger's origin map as needed whenever a
+///   it sees a DeclContext.
+class LazyASTImporter : public ASTImporter {
+private:
+  ExternalASTMerger &Parent;
+  ASTImporter Reverse;
+  const ExternalASTMerger::OriginMap &FromOrigins;
 
-template <typename CallbackType>
-void ForEachMatchingDC(
-    const DeclContext *DC,
-    llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
-    CallbackType Callback) {
-  for (const ExternalASTMerger::ImporterPair &IP : Importers) {
-    Source<TranslationUnitDecl *> SourceTU =
-        IP.Forward->getFromContext().getTranslationUnitDecl();
-    if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse))
-      Callback(IP, SourceDC);
+  llvm::raw_ostream &logs() { return Parent.logs(); }
+public:
+  LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
+                  FileManager &ToFileManager, ASTContext &FromContext,
+                  FileManager &FromFileManager,
+                  const ExternalASTMerger::OriginMap &_FromOrigins)
+      : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
+                    /*MinimalImport=*/true),
+        Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext,
+                                 ToFileManager, /*MinimalImport=*/true), FromOrigins(_FromOrigins) {}
+
+  /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
+  /// map is kept up to date.  Also set the appropriate flags.
+  Decl *Imported(Decl *From, Decl *To) override {
+    if (auto *ToDC = dyn_cast<DeclContext>(To)) {
+      const bool LoggingEnabled = Parent.LoggingEnabled();
+      if (LoggingEnabled)
+        logs() << "(ExternalASTMerger*)" << (void*)&Parent
+               << " imported (DeclContext*)" << (void*)ToDC
+               << ", (ASTContext*)" << (void*)&getToContext()
+               << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
+               << ", (ASTContext*)" << (void*)&getFromContext()
+               << "\n";
+      Source<DeclContext *> FromDC(
+          cast<DeclContext>(From)->getPrimaryContext());
+      if (FromOrigins.count(FromDC) &&
+          Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
+        if (LoggingEnabled)
+          logs() << "(ExternalASTMerger*)" << (void*)&Parent
+                 << " forced origin (DeclContext*)"
+                 << (void*)FromOrigins.at(FromDC).DC
+                 << ", (ASTContext*)"
+                 << (void*)FromOrigins.at(FromDC).AST
+                 << "\n";
+        Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
+      } else {
+        if (LoggingEnabled)
+          logs() << "(ExternalASTMerger*)" << (void*)&Parent
+                 << " maybe recording origin (DeclContext*)" << (void*)FromDC
+                 << ", (ASTContext*)" << (void*)&getFromContext()
+                 << "\n";
+        Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
+      }
+    }
+    if (auto *ToTag = dyn_cast<TagDecl>(To)) {
+      ToTag->setHasExternalLexicalStorage();
+      ToTag->setMustBuildLookupTable();
+      assert(Parent.CanComplete(ToTag));
+    } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
+      ToNamespace->setHasExternalVisibleStorage();
+      assert(Parent.CanComplete(ToNamespace));
+    } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
+      ToContainer->setHasExternalLexicalStorage();
+      ToContainer->setMustBuildLookupTable();
+      assert(Parent.CanComplete(ToContainer));
+    }
+    return ASTImporter::Imported(From, To);
   }
-}
+  ASTImporter &GetReverse() { return Reverse; }
+};
 
 bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
+  if (isa<FunctionDecl>(C.first.get()))
+    return false;
   return llvm::any_of(Decls, [&](const Candidate &D) {
     return C.first.get()->getKind() == D.first.get()->getKind();
   });
 }
+
 } // end namespace
 
-ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target,
-                                     llvm::ArrayRef<ImporterEndpoint> Sources) {
-  for (const ImporterEndpoint &S : Sources) {
-    Importers.push_back(
-        {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
-         llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
-                                        /*MinimalImport=*/true)});
-  }
+ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
+  for (const std::unique_ptr<ASTImporter> &I : Importers)
+    if (&I->getFromContext() == &OriginContext)
+      return *I;
+  llvm_unreachable("We should have an importer for this origin!");
 }
 
-bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
-                                                       DeclarationName Name) {
-  llvm::SmallVector<NamedDecl *, 1> Decls;
-  llvm::SmallVector<Candidate, 4> CompleteDecls;
-  llvm::SmallVector<Candidate, 4> ForwardDecls;
+namespace {
+LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
+                                   ASTContext &OriginContext) {
+  return static_cast<LazyASTImporter &>(
+      Merger.ImporterForOrigin(OriginContext));
+}
+}
 
-  auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
-    if (IsForwardDeclaration(C.first.get())) {
-      if (!HasDeclOfSameType(ForwardDecls, C)) {
-        ForwardDecls.push_back(C);
+bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
+  for (const std::unique_ptr<ASTImporter> &I : Importers)
+    if (&I->getFromContext() == &OriginContext)
+      return true;
+  return false;
+}
+
+template <typename CallbackType>
+void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
+                                          CallbackType Callback) {
+  if (Origins.count(DC)) {
+    ExternalASTMerger::DCOrigin Origin = Origins[DC];
+    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
+    Callback(Importer, Importer.GetReverse(), Origin.DC);
+  } else {
+    bool DidCallback = false;
+    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
+      Source<TranslationUnitDecl *> SourceTU =
+          Importer->getFromContext().getTranslationUnitDecl();
+      ASTImporter &Reverse =
+          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
+      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
+        DidCallback = true;
+        if (Callback(*Importer, Reverse, SourceDC))
+          break;
       }
-    } else {
-      CompleteDecls.push_back(C);
     }
-  };
+    if (!DidCallback && LoggingEnabled())
+      logs() << "(ExternalASTMerger*)" << (void*)this
+             << " asserting for (DeclContext*)" << (void*)DC
+             << ", (ASTContext*)" << (void*)&Target.AST
+             << "\n";
+    assert(DidCallback && "Couldn't find a source context matching our DC");
+  }
+}
 
+void ExternalASTMerger::CompleteType(TagDecl *Tag) {
+  assert(Tag->hasExternalLexicalStorage());
+  ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
+                             Source<const DeclContext *> SourceDC) -> bool {
+    auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
+    if (SourceTag->hasExternalLexicalStorage())
+      SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
+    if (!SourceTag->getDefinition())
+      return false;
+    Forward.Imported(SourceTag, Tag);
+    Forward.ImportDefinition(SourceTag);
+    Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
+    return true;
+  });
+}
+
+void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
+  assert(Interface->hasExternalLexicalStorage());
   ForEachMatchingDC(
-      DC, Importers,
-      [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
-        DeclarationName FromName = IP.Reverse->Import(Name);
-        DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
-        for (NamedDecl *FromD : Result) {
-          FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
-        }
+      Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
+                     Source<const DeclContext *> SourceDC) -> bool {
+        auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
+            cast<ObjCInterfaceDecl>(SourceDC.get()));
+        if (SourceInterface->hasExternalLexicalStorage())
+          SourceInterface->getASTContext().getExternalSource()->CompleteType(
+              SourceInterface);
+        if (!SourceInterface->getDefinition())
+          return false;
+        Forward.Imported(SourceInterface, Interface);
+        Forward.ImportDefinition(SourceInterface);
+        return true;
       });
+}
 
-  llvm::ArrayRef<Candidate> DeclsToReport =
-      CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
+bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
+  assert(Interface->hasExternalLexicalStorage() ||
+         Interface->hasExternalVisibleStorage());
+  bool FoundMatchingDC = false;
+  ForEachMatchingDC(Interface,
+                    [&](ASTImporter &Forward, ASTImporter &Reverse,
+                        Source<const DeclContext *> SourceDC) -> bool {
+                      FoundMatchingDC = true;
+                      return true;
+                    });
+  return FoundMatchingDC;
+}
 
-  if (DeclsToReport.empty()) {
-    return false;
+namespace {
+bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
+  if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
+    return true; // There are many cases where Objective-C is ambiguous.
+  if (auto *T1 = dyn_cast<TagDecl>(D1))
+    if (auto *T2 = dyn_cast<TagDecl>(D2))
+      if (T1->getFirstDecl() == T2->getFirstDecl())
+        return true;
+  return D1 == D2 || D1 == CanonicalizeDC(D2);
+}
+}
+
+void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
+                                          DCOrigin Origin) {
+  LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
+  ASTImporter &Reverse = Importer.GetReverse();
+  Source<const DeclContext *> FoundFromDC =
+      LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
+  const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
+  if (DoRecord)
+    RecordOriginImpl(ToDC, Origin, Importer);
+  if (LoggingEnabled())
+    logs() << "(ExternalASTMerger*)" << (void*)this
+             << (DoRecord ? " decided " : " decided NOT")
+             << " to record origin (DeclContext*)" << (void*)Origin.DC
+             << ", (ASTContext*)" << (void*)&Origin.AST
+             << "\n";
+}
+
+void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
+                                          DCOrigin Origin) {
+  RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
+}
+
+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)));
+}
+
+ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
+                                     llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
+  AddSources(Sources);
+}
+
+void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
+  for (const ImporterSource &S : Sources) {
+    assert(&S.AST != &Target.AST);
+    Importers.push_back(llvm::make_unique<LazyASTImporter>(
+        *this, Target.AST, Target.FM, S.AST, S.FM, S.OM));
   }
+}
 
-  Decls.reserve(DeclsToReport.size());
-  for (const Candidate &C : DeclsToReport) {
+void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
+  if (LoggingEnabled())
+    for (const ImporterSource &S : Sources)
+      logs() << "(ExternalASTMerger*)" << (void*)this
+             << " removing source (ASTContext*)" << (void*)&S.AST
+             << "\n";
+  Importers.erase(
+      std::remove_if(Importers.begin(), Importers.end(),
+                     [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
+                       for (const ImporterSource &S : Sources) {
+                         if (&Importer->getFromContext() == &S.AST)
+                           return true;
+                       }
+                       return false;
+                     }),
+      Importers.end());
+  for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
+    std::pair<const DeclContext *, DCOrigin> Origin = *OI;
+    bool Erase = false;
+    for (const ImporterSource &S : Sources) {
+      if (&S.AST == Origin.second.AST) {
+        Erase = true;
+        break;
+      }
+    }
+    if (Erase)
+      OI = Origins.erase(OI);
+    else
+      ++OI;
+  }
+}
+
+bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
+                                                       DeclarationName Name) {
+  llvm::SmallVector<NamedDecl *, 1> Decls;
+  llvm::SmallVector<Candidate, 4> Candidates;
+
+  auto FilterFoundDecl = [&Candidates](const Candidate &C) {
+   if (!HasDeclOfSameType(Candidates, C))
+     Candidates.push_back(C);
+  };
+
+  ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
+                            Source<const DeclContext *> SourceDC) -> bool {
+    DeclarationName FromName = Reverse.Import(Name);
+    DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
+    for (NamedDecl *FromD : Result) {
+      FilterFoundDecl(std::make_pair(FromD, &Forward));
+    }
+    return false;
+  });
+
+  if (Candidates.empty())
+    return false;
+
+  Decls.reserve(Candidates.size());
+  for (const Candidate &C : Candidates) {
     NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
     assert(d);
     Decls.push_back(d);
   }
   SetExternalVisibleDeclsForName(DC, Name, Decls);
   return true;
 }
 
 void ExternalASTMerger::FindExternalLexicalDecls(
     const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
     SmallVectorImpl<Decl *> &Result) {
-  ForEachMatchingDC(
-      DC, Importers,
-      [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
-        for (const Decl *SourceDecl : SourceDC.get()->decls()) {
-          if (IsKindWeWant(SourceDecl->getKind())) {
-            Decl *ImportedDecl =
-                IP.Forward->Import(const_cast<Decl *>(SourceDecl));
-            assert(ImportedDecl->getDeclContext() == DC);
-            (void)ImportedDecl;
-          }
-        }
-      });
+  ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
+                            Source<const DeclContext *> SourceDC) -> bool {
+    for (const Decl *SourceDecl : SourceDC.get()->decls()) {
+      if (IsKindWeWant(SourceDecl->getKind())) {
+        Decl *ImportedDecl = Forward.Import(const_cast<Decl *>(SourceDecl));
+        assert(!ImportedDecl || IsSameDC(ImportedDecl->getDeclContext(), DC));
+        (void)ImportedDecl;
+      }
+    }
+    return false;
+  });
 }
 
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 313996)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -6312,1393 +6312,1397 @@
   switch (Attr.getKind()) {
   default:
     llvm_unreachable("not a calling convention attribute");
   case AttributeList::AT_CDecl:
     return AttributedType::attr_cdecl;
   case AttributeList::AT_FastCall:
     return AttributedType::attr_fastcall;
   case AttributeList::AT_StdCall:
     return AttributedType::attr_stdcall;
   case AttributeList::AT_ThisCall:
     return AttributedType::attr_thiscall;
   case AttributeList::AT_RegCall:
     return AttributedType::attr_regcall;
   case AttributeList::AT_Pascal:
     return AttributedType::attr_pascal;
   case AttributeList::AT_SwiftCall:
     return AttributedType::attr_swiftcall;
   case AttributeList::AT_VectorCall:
     return AttributedType::attr_vectorcall;
   case AttributeList::AT_Pcs: {
     // The attribute may have had a fixit applied where we treated an
     // identifier as a string literal.  The contents of the string are valid,
     // but the form may not be.
     StringRef Str;
     if (Attr.isArgExpr(0))
       Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
     else
       Str = Attr.getArgAsIdent(0)->Ident->getName();
     return llvm::StringSwitch<AttributedType::Kind>(Str)
         .Case("aapcs", AttributedType::attr_pcs)
         .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
   }
   case AttributeList::AT_IntelOclBicc:
     return AttributedType::attr_inteloclbicc;
   case AttributeList::AT_MSABI:
     return AttributedType::attr_ms_abi;
   case AttributeList::AT_SysVABI:
     return AttributedType::attr_sysv_abi;
   case AttributeList::AT_PreserveMost:
     return AttributedType::attr_preserve_most;
   case AttributeList::AT_PreserveAll:
     return AttributedType::attr_preserve_all;
   }
   llvm_unreachable("unexpected attribute kind!");
 }
 
 /// Process an individual function attribute.  Returns true to
 /// indicate that the attribute was handled, false if it wasn't.
 static bool handleFunctionTypeAttr(TypeProcessingState &state,
                                    AttributeList &attr,
                                    QualType &type) {
   Sema &S = state.getSema();
 
   FunctionTypeUnwrapper unwrapped(S, type);
 
   if (attr.getKind() == AttributeList::AT_NoReturn) {
     if (S.CheckNoReturnAttr(attr))
       return true;
 
     // Delay if this is not a function type.
     if (!unwrapped.isFunctionType())
       return false;
 
     // Otherwise we can process right away.
     FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
     type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
     return true;
   }
 
   // ns_returns_retained is not always a type attribute, but if we got
   // here, we're treating it as one right now.
   if (attr.getKind() == AttributeList::AT_NSReturnsRetained) {
     if (attr.getNumArgs()) return true;
 
     // Delay if this is not a function type.
     if (!unwrapped.isFunctionType())
       return false;
 
     // Check whether the return type is reasonable.
     if (S.checkNSReturnsRetainedReturnType(attr.getLoc(),
                                            unwrapped.get()->getReturnType()))
       return true;
 
     // Only actually change the underlying type in ARC builds.
     QualType origType = type;
     if (state.getSema().getLangOpts().ObjCAutoRefCount) {
       FunctionType::ExtInfo EI
         = unwrapped.get()->getExtInfo().withProducesResult(true);
       type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
     }
     type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
                                        origType, type);
     return true;
   }
 
   if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) {
     if (S.CheckNoCallerSavedRegsAttr(attr))
       return true;
 
     // Delay if this is not a function type.
     if (!unwrapped.isFunctionType())
       return false;
 
     FunctionType::ExtInfo EI =
         unwrapped.get()->getExtInfo().withNoCallerSavedRegs(true);
     type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
     return true;
   }
 
   if (attr.getKind() == AttributeList::AT_Regparm) {
     unsigned value;
     if (S.CheckRegparmAttr(attr, value))
       return true;
 
     // Delay if this is not a function type.
     if (!unwrapped.isFunctionType())
       return false;
 
     // Diagnose regparm with fastcall.
     const FunctionType *fn = unwrapped.get();
     CallingConv CC = fn->getCallConv();
     if (CC == CC_X86FastCall) {
       S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
         << FunctionType::getNameForCallConv(CC)
         << "regparm";
       attr.setInvalid();
       return true;
     }
 
     FunctionType::ExtInfo EI =
       unwrapped.get()->getExtInfo().withRegParm(value);
     type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
     return true;
   }
 
   // Delay if the type didn't work out to a function.
   if (!unwrapped.isFunctionType()) return false;
 
   // Otherwise, a calling convention.
   CallingConv CC;
   if (S.CheckCallingConvAttr(attr, CC))
     return true;
 
   const FunctionType *fn = unwrapped.get();
   CallingConv CCOld = fn->getCallConv();
   AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
 
   if (CCOld != CC) {
     // Error out on when there's already an attribute on the type
     // and the CCs don't match.
     const AttributedType *AT = S.getCallingConvAttributedType(type);
     if (AT && AT->getAttrKind() != CCAttrKind) {
       S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
         << FunctionType::getNameForCallConv(CC)
         << FunctionType::getNameForCallConv(CCOld);
       attr.setInvalid();
       return true;
     }
   }
 
   // Diagnose use of variadic functions with calling conventions that
   // don't support them (e.g. because they're callee-cleanup).
   // We delay warning about this on unprototyped function declarations
   // until after redeclaration checking, just in case we pick up a
   // prototype that way.  And apparently we also "delay" warning about
   // unprototyped function types in general, despite not necessarily having
   // much ability to diagnose it later.
   if (!supportsVariadicCall(CC)) {
     const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
     if (FnP && FnP->isVariadic()) {
       unsigned DiagID = diag::err_cconv_varargs;
 
       // stdcall and fastcall are ignored with a warning for GCC and MS
       // compatibility.
       bool IsInvalid = true;
       if (CC == CC_X86StdCall || CC == CC_X86FastCall) {
         DiagID = diag::warn_cconv_varargs;
         IsInvalid = false;
       }
 
       S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC);
       if (IsInvalid) attr.setInvalid();
       return true;
     }
   }
 
   // Also diagnose fastcall with regparm.
   if (CC == CC_X86FastCall && fn->getHasRegParm()) {
     S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
         << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
     attr.setInvalid();
     return true;
   }
 
   // Modify the CC from the wrapped function type, wrap it all back, and then
   // wrap the whole thing in an AttributedType as written.  The modified type
   // might have a different CC if we ignored the attribute.
   QualType Equivalent;
   if (CCOld == CC) {
     Equivalent = type;
   } else {
     auto EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
     Equivalent =
       unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
   }
   type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
   return true;
 }
 
 bool Sema::hasExplicitCallingConv(QualType &T) {
   QualType R = T.IgnoreParens();
   while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
     if (AT->isCallingConv())
       return true;
     R = AT->getModifiedType().IgnoreParens();
   }
   return false;
 }
 
 void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
                                   SourceLocation Loc) {
   FunctionTypeUnwrapper Unwrapped(*this, T);
   const FunctionType *FT = Unwrapped.get();
   bool IsVariadic = (isa<FunctionProtoType>(FT) &&
                      cast<FunctionProtoType>(FT)->isVariadic());
   CallingConv CurCC = FT->getCallConv();
   CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
 
   if (CurCC == ToCC)
     return;
 
   // MS compiler ignores explicit calling convention attributes on structors. We
   // should do the same.
   if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) {
     // Issue a warning on ignored calling convention -- except of __stdcall.
     // Again, this is what MS compiler does.
     if (CurCC != CC_X86StdCall)
       Diag(Loc, diag::warn_cconv_structors)
           << FunctionType::getNameForCallConv(CurCC);
   // Default adjustment.
   } else {
     // Only adjust types with the default convention.  For example, on Windows
     // we should adjust a __cdecl type to __thiscall for instance methods, and a
     // __thiscall type to __cdecl for static methods.
     CallingConv DefaultCC =
         Context.getDefaultCallingConvention(IsVariadic, IsStatic);
 
     if (CurCC != DefaultCC || DefaultCC == ToCC)
       return;
 
     if (hasExplicitCallingConv(T))
       return;
   }
 
   FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
   QualType Wrapped = Unwrapped.wrap(*this, FT);
   T = Context.getAdjustedType(T, Wrapped);
 }
 
 /// HandleVectorSizeAttribute - this attribute is only applicable to integral
 /// and float scalars, although arrays, pointers, and function return values are
 /// allowed in conjunction with this construct. Aggregates with this attribute
 /// are invalid, even if they are of the same size as a corresponding scalar.
 /// The raw attribute should contain precisely 1 argument, the vector size for
 /// the variable, measured in bytes. If curType and rawAttr are well formed,
 /// this routine will return a new vector type.
 static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
                                  Sema &S) {
   // Check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
       << Attr.getName() << 1;
     Attr.setInvalid();
     return;
   }
   Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
   llvm::APSInt vecSize(32);
   if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
       !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
       << Attr.getName() << AANT_ArgumentIntegerConstant
       << sizeExpr->getSourceRange();
     Attr.setInvalid();
     return;
   }
   // The base type must be integer (not Boolean or enumeration) or float, and
   // can't already be a vector.
   if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
       (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
     S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
     Attr.setInvalid();
     return;
   }
   unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
   // vecSize is specified in bytes - convert to bits.
   unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
 
   // the vector size needs to be an integral multiple of the type size.
   if (vectorSize % typeSize) {
     S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
       << sizeExpr->getSourceRange();
     Attr.setInvalid();
     return;
   }
   if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
       << sizeExpr->getSourceRange();
     Attr.setInvalid();
     return;
   }
   if (vectorSize == 0) {
     S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
       << sizeExpr->getSourceRange();
     Attr.setInvalid();
     return;
   }
 
   // Success! Instantiate the vector type, the number of elements is > 0, and
   // not required to be a power of 2, unlike GCC.
   CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
                                     VectorType::GenericVector);
 }
 
 /// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
 /// a type.
 static void HandleExtVectorTypeAttr(QualType &CurType,
                                     const AttributeList &Attr,
                                     Sema &S) {
   // check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
       << Attr.getName() << 1;
     return;
   }
 
   Expr *sizeExpr;
 
   // Special case where the argument is a template id.
   if (Attr.isArgIdent(0)) {
     CXXScopeSpec SS;
     SourceLocation TemplateKWLoc;
     UnqualifiedId id;
     id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
 
     ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
                                           id, false, false);
     if (Size.isInvalid())
       return;
 
     sizeExpr = Size.get();
   } else {
     sizeExpr = Attr.getArgAsExpr(0);
   }
 
   // Create the vector type.
   QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
   if (!T.isNull())
     CurType = T;
 }
 
 static bool isPermittedNeonBaseType(QualType &Ty,
                                     VectorType::VectorKind VecKind, Sema &S) {
   const BuiltinType *BTy = Ty->getAs<BuiltinType>();
   if (!BTy)
     return false;
 
   llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
 
   // Signed poly is mathematically wrong, but has been baked into some ABIs by
   // now.
   bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
                         Triple.getArch() == llvm::Triple::aarch64_be;
   if (VecKind == VectorType::NeonPolyVector) {
     if (IsPolyUnsigned) {
       // AArch64 polynomial vectors are unsigned and support poly64.
       return BTy->getKind() == BuiltinType::UChar ||
              BTy->getKind() == BuiltinType::UShort ||
              BTy->getKind() == BuiltinType::ULong ||
              BTy->getKind() == BuiltinType::ULongLong;
     } else {
       // AArch32 polynomial vector are signed.
       return BTy->getKind() == BuiltinType::SChar ||
              BTy->getKind() == BuiltinType::Short;
     }
   }
 
   // Non-polynomial vector types: the usual suspects are allowed, as well as
   // float64_t on AArch64.
   bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
                  Triple.getArch() == llvm::Triple::aarch64_be;
 
   if (Is64Bit && BTy->getKind() == BuiltinType::Double)
     return true;
 
   return BTy->getKind() == BuiltinType::SChar ||
          BTy->getKind() == BuiltinType::UChar ||
          BTy->getKind() == BuiltinType::Short ||
          BTy->getKind() == BuiltinType::UShort ||
          BTy->getKind() == BuiltinType::Int ||
          BTy->getKind() == BuiltinType::UInt ||
          BTy->getKind() == BuiltinType::Long ||
          BTy->getKind() == BuiltinType::ULong ||
          BTy->getKind() == BuiltinType::LongLong ||
          BTy->getKind() == BuiltinType::ULongLong ||
          BTy->getKind() == BuiltinType::Float ||
          BTy->getKind() == BuiltinType::Half;
 }
 
 /// HandleNeonVectorTypeAttr - The "neon_vector_type" and
 /// "neon_polyvector_type" attributes are used to create vector types that
 /// are mangled according to ARM's ABI.  Otherwise, these types are identical
 /// to those created with the "vector_size" attribute.  Unlike "vector_size"
 /// the argument to these Neon attributes is the number of vector elements,
 /// not the vector size in bytes.  The vector width and element type must
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType& CurType,
                                      const AttributeList &Attr, Sema &S,
                                      VectorType::VectorKind VecKind) {
   // Target must have NEON
   if (!S.Context.getTargetInfo().hasFeature("neon")) {
     S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName();
     Attr.setInvalid();
     return;
   }
   // Check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
       << Attr.getName() << 1;
     Attr.setInvalid();
     return;
   }
   // The number of elements must be an ICE.
   Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
   llvm::APSInt numEltsInt(32);
   if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
       !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
       << Attr.getName() << AANT_ArgumentIntegerConstant
       << numEltsExpr->getSourceRange();
     Attr.setInvalid();
     return;
   }
   // Only certain element types are supported for Neon vectors.
   if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
     Attr.setInvalid();
     return;
   }
 
   // The total size of the vector must be 64 or 128 bits.
   unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
   unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
   unsigned vecSize = typeSize * numElts;
   if (vecSize != 64 && vecSize != 128) {
     S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
     Attr.setInvalid();
     return;
   }
 
   CurType = S.Context.getVectorType(CurType, numElts, VecKind);
 }
 
 /// Handle OpenCL Access Qualifier Attribute.
 static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
                                    Sema &S) {
   // OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
   if (!(CurType->isImageType() || CurType->isPipeType())) {
     S.Diag(Attr.getLoc(), diag::err_opencl_invalid_access_qualifier);
     Attr.setInvalid();
     return;
   }
 
   if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) {
     QualType PointeeTy = TypedefTy->desugar();
     S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
 
     std::string PrevAccessQual;
     switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) {
       #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
     case BuiltinType::Id:                                          \
       PrevAccessQual = #Access;                                    \
       break;
       #include "clang/Basic/OpenCLImageTypes.def"
     default:
       assert(0 && "Unable to find corresponding image type.");
     }
 
     S.Diag(TypedefTy->getDecl()->getLocStart(),
        diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
   } else if (CurType->isPipeType()) {
     if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) {
       QualType ElemType = CurType->getAs<PipeType>()->getElementType();
       CurType = S.Context.getWritePipeType(ElemType);
     }
   }
 }
 
 static void processTypeAttrs(TypeProcessingState &state, QualType &type,
                              TypeAttrLocation TAL, AttributeList *attrs) {
   // Scan through and apply attributes to this type where it makes sense.  Some
   // attributes (such as __address_space__, __vector_size__, etc) apply to the
   // type, but others can be present in the type specifiers even though they
   // apply to the decl.  Here we apply type attributes and ignore the rest.
 
   bool hasOpenCLAddressSpace = false;
   while (attrs) {
     AttributeList &attr = *attrs;
     attrs = attr.getNext(); // reset to the next here due to early loop continue
                             // stmts
 
     // Skip attributes that were marked to be invalid.
     if (attr.isInvalid())
       continue;
 
     if (attr.isCXX11Attribute()) {
       // [[gnu::...]] attributes are treated as declaration attributes, so may
       // not appertain to a DeclaratorChunk, even if we handle them as type
       // attributes.
       if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
         if (TAL == TAL_DeclChunk) {
           state.getSema().Diag(attr.getLoc(),
                                diag::warn_cxx11_gnu_attribute_on_type)
               << attr.getName();
           continue;
         }
       } else if (TAL != TAL_DeclChunk) {
         // Otherwise, only consider type processing for a C++11 attribute if
         // it's actually been applied to a type.
         continue;
       }
     }
 
     // If this is an attribute we can handle, do so now,
     // otherwise, add it to the FnAttrs list for rechaining.
     switch (attr.getKind()) {
     default:
       // A C++11 attribute on a declarator chunk must appertain to a type.
       if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) {
         state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
           << attr.getName();
         attr.setUsedAsTypeAttr();
       }
       break;
 
     case AttributeList::UnknownAttribute:
       if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
         state.getSema().Diag(attr.getLoc(),
                              diag::warn_unknown_attribute_ignored)
           << attr.getName();
       break;
 
     case AttributeList::IgnoredAttribute:
       break;
 
     case AttributeList::AT_MayAlias:
       // FIXME: This attribute needs to actually be handled, but if we ignore
       // it it breaks large amounts of Linux software.
       attr.setUsedAsTypeAttr();
       break;
     case AttributeList::AT_OpenCLPrivateAddressSpace:
     case AttributeList::AT_OpenCLGlobalAddressSpace:
     case AttributeList::AT_OpenCLLocalAddressSpace:
     case AttributeList::AT_OpenCLConstantAddressSpace:
     case AttributeList::AT_OpenCLGenericAddressSpace:
     case AttributeList::AT_AddressSpace:
       HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
       attr.setUsedAsTypeAttr();
       hasOpenCLAddressSpace = true;
       break;
     OBJC_POINTER_TYPE_ATTRS_CASELIST:
       if (!handleObjCPointerTypeAttr(state, attr, type))
         distributeObjCPointerTypeAttr(state, attr, type);
       attr.setUsedAsTypeAttr();
       break;
     case AttributeList::AT_VectorSize:
       HandleVectorSizeAttr(type, attr, state.getSema());
       attr.setUsedAsTypeAttr();
       break;
     case AttributeList::AT_ExtVectorType:
       HandleExtVectorTypeAttr(type, attr, state.getSema());
       attr.setUsedAsTypeAttr();
       break;
     case AttributeList::AT_NeonVectorType:
       HandleNeonVectorTypeAttr(type, attr, state.getSema(),
                                VectorType::NeonVector);
       attr.setUsedAsTypeAttr();
       break;
     case AttributeList::AT_NeonPolyVectorType:
       HandleNeonVectorTypeAttr(type, attr, state.getSema(),
                                VectorType::NeonPolyVector);
       attr.setUsedAsTypeAttr();
       break;
     case AttributeList::AT_OpenCLAccess:
       HandleOpenCLAccessAttr(type, attr, state.getSema());
       attr.setUsedAsTypeAttr();
       break;
 
     MS_TYPE_ATTRS_CASELIST:
       if (!handleMSPointerTypeQualifierAttr(state, attr, type))
         attr.setUsedAsTypeAttr();
       break;
 
 
     NULLABILITY_TYPE_ATTRS_CASELIST:
       // Either add nullability here or try to distribute it.  We
       // don't want to distribute the nullability specifier past any
       // dependent type, because that complicates the user model.
       if (type->canHaveNullability() || type->isDependentType() ||
           type->isArrayType() ||
           !distributeNullabilityTypeAttr(state, type, attr)) {
         unsigned endIndex;
         if (TAL == TAL_DeclChunk)
           endIndex = state.getCurrentChunkIndex();
         else
           endIndex = state.getDeclarator().getNumTypeObjects();
         bool allowOnArrayType =
             state.getDeclarator().isPrototypeContext() &&
             !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
         if (state.getSema().checkNullabilityTypeSpecifier(
               type,
               mapNullabilityAttrKind(attr.getKind()),
               attr.getLoc(),
               attr.isContextSensitiveKeywordAttribute(),
               allowOnArrayType)) {
           attr.setInvalid();
         }
 
         attr.setUsedAsTypeAttr();
       }
       break;
 
     case AttributeList::AT_ObjCKindOf:
       // '__kindof' must be part of the decl-specifiers.
       switch (TAL) {
       case TAL_DeclSpec:
         break;
 
       case TAL_DeclChunk:
       case TAL_DeclName:
         state.getSema().Diag(attr.getLoc(),
                              diag::err_objc_kindof_wrong_position)
           << FixItHint::CreateRemoval(attr.getLoc())
           << FixItHint::CreateInsertion(
                state.getDeclarator().getDeclSpec().getLocStart(), "__kindof ");
         break;
       }
 
       // Apply it regardless.
       if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
         attr.setInvalid();
       attr.setUsedAsTypeAttr();
       break;
 
     FUNCTION_TYPE_ATTRS_CASELIST:
       attr.setUsedAsTypeAttr();
 
       // Never process function type attributes as part of the
       // declaration-specifiers.
       if (TAL == TAL_DeclSpec)
         distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
 
       // Otherwise, handle the possible delays.
       else if (!handleFunctionTypeAttr(state, attr, type))
         distributeFunctionTypeAttr(state, attr, type);
       break;
     }
   }
 
   // If address space is not set, OpenCL 2.0 defines non private default
   // address spaces for some cases:
   // OpenCL 2.0, section 6.5:
   // The address space for a variable at program scope or a static variable
   // inside a function can either be __global or __constant, but defaults to
   // __global if not specified.
   // (...)
   // Pointers that are declared without pointing to a named address space point
   // to the generic address space.
   if (state.getSema().getLangOpts().OpenCLVersion >= 200 &&
       !hasOpenCLAddressSpace && type.getAddressSpace() == 0 &&
       (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) {
     Declarator &D = state.getDeclarator();
     if (state.getCurrentChunkIndex() > 0 &&
         (D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
              DeclaratorChunk::Pointer ||
          D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
              DeclaratorChunk::BlockPointer)) {
       type = state.getSema().Context.getAddrSpaceQualType(
           type, LangAS::opencl_generic);
     } else if (state.getCurrentChunkIndex() == 0 &&
                D.getContext() == Declarator::FileContext &&
                !D.isFunctionDeclarator() && !D.isFunctionDefinition() &&
                D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
                !type->isSamplerT())
       type = state.getSema().Context.getAddrSpaceQualType(
           type, LangAS::opencl_global);
     else if (state.getCurrentChunkIndex() == 0 &&
              D.getContext() == Declarator::BlockContext &&
              D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
       type = state.getSema().Context.getAddrSpaceQualType(
           type, LangAS::opencl_global);
   }
 }
 
 void Sema::completeExprArrayBound(Expr *E) {
   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
     if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
       if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
         SourceLocation PointOfInstantiation = E->getExprLoc();
 
         if (MemberSpecializationInfo *MSInfo =
                 Var->getMemberSpecializationInfo()) {
           // If we don't already have a point of instantiation, this is it.
           if (MSInfo->getPointOfInstantiation().isInvalid()) {
             MSInfo->setPointOfInstantiation(PointOfInstantiation);
 
             // This is a modification of an existing AST node. Notify
             // listeners.
             if (ASTMutationListener *L = getASTMutationListener())
               L->StaticDataMemberInstantiated(Var);
           }
         } else {
           VarTemplateSpecializationDecl *VarSpec =
               cast<VarTemplateSpecializationDecl>(Var);
           if (VarSpec->getPointOfInstantiation().isInvalid())
             VarSpec->setPointOfInstantiation(PointOfInstantiation);
         }
 
         InstantiateVariableDefinition(PointOfInstantiation, Var);
 
         // Update the type to the newly instantiated definition's type both
         // here and within the expression.
         if (VarDecl *Def = Var->getDefinition()) {
           DRE->setDecl(Def);
           QualType T = Def->getType();
           DRE->setType(T);
           // FIXME: Update the type on all intervening expressions.
           E->setType(T);
         }
 
         // We still go on to try to complete the type independently, as it
         // may also require instantiations or diagnostics if it remains
         // incomplete.
       }
     }
   }
 }
 
 /// \brief Ensure that the type of the given expression is complete.
 ///
 /// This routine checks whether the expression \p E has a complete type. If the
 /// expression refers to an instantiable construct, that instantiation is
 /// performed as needed to complete its type. Furthermore
 /// Sema::RequireCompleteType is called for the expression's type (or in the
 /// case of a reference type, the referred-to type).
 ///
 /// \param E The expression whose type is required to be complete.
 /// \param Diagnoser The object that will emit a diagnostic if the type is
 /// incomplete.
 ///
 /// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
 /// otherwise.
 bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser) {
   QualType T = E->getType();
 
   // Incomplete array types may be completed by the initializer attached to
   // their definitions. For static data members of class templates and for
   // variable templates, we need to instantiate the definition to get this
   // initializer and complete the type.
   if (T->isIncompleteArrayType()) {
     completeExprArrayBound(E);
     T = E->getType();
   }
 
   // FIXME: Are there other cases which require instantiating something other
   // than the type to complete the type of an expression?
 
   return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
 }
 
 bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
   BoundTypeDiagnoser<> Diagnoser(DiagID);
   return RequireCompleteExprType(E, Diagnoser);
 }
 
 /// @brief Ensure that the type T is a complete type.
 ///
 /// This routine checks whether the type @p T is complete in any
 /// context where a complete type is required. If @p T is a complete
 /// type, returns false. If @p T is a class template specialization,
 /// this routine then attempts to perform class template
 /// instantiation. If instantiation fails, or if @p T is incomplete
 /// and cannot be completed, issues the diagnostic @p diag (giving it
 /// the type @p T) and returns true.
 ///
 /// @param Loc  The location in the source that the incomplete type
 /// diagnostic should refer to.
 ///
 /// @param T  The type that this routine is examining for completeness.
 ///
 /// @returns @c true if @p T is incomplete and a diagnostic was emitted,
 /// @c false otherwise.
 bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
                                TypeDiagnoser &Diagnoser) {
   if (RequireCompleteTypeImpl(Loc, T, &Diagnoser))
     return true;
   if (const TagType *Tag = T->getAs<TagType>()) {
     if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
       Tag->getDecl()->setCompleteDefinitionRequired();
       Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl());
     }
   }
   return false;
 }
 
 bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
   llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
   if (!Suggested)
     return false;
 
   // FIXME: Add a specific mode for C11 6.2.7/1 in StructuralEquivalenceContext
   // and isolate from other C++ specific checks.
   StructuralEquivalenceContext Ctx(
       D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls,
       false /*StrictTypeSpelling*/, true /*Complain*/,
       true /*ErrorOnTagTypeMismatch*/);
   return Ctx.IsStructurallyEquivalent(D, Suggested);
 }
 
 /// \brief Determine whether there is any declaration of \p D that was ever a
 ///        definition (perhaps before module merging) and is currently visible.
 /// \param D The definition of the entity.
 /// \param Suggested Filled in with the declaration that should be made visible
 ///        in order to provide a definition of this entity.
 /// \param OnlyNeedComplete If \c true, we only need the type to be complete,
 ///        not defined. This only matters for enums with a fixed underlying
 ///        type, since in all other cases, a type is complete if and only if it
 ///        is defined.
 bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
                                 bool OnlyNeedComplete) {
   // Easy case: if we don't have modules, all declarations are visible.
   if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility)
     return true;
 
   // If this definition was instantiated from a template, map back to the
   // pattern from which it was instantiated.
   if (isa<TagDecl>(D) && cast<TagDecl>(D)->isBeingDefined()) {
     // We're in the middle of defining it; this definition should be treated
     // as visible.
     return true;
   } else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
     if (auto *Pattern = RD->getTemplateInstantiationPattern())
       RD = Pattern;
     D = RD->getDefinition();
   } else if (auto *ED = dyn_cast<EnumDecl>(D)) {
     if (auto *Pattern = ED->getTemplateInstantiationPattern())
       ED = Pattern;
     if (OnlyNeedComplete && ED->isFixed()) {
       // If the enum has a fixed underlying type, and we're only looking for a
       // complete type (not a definition), any visible declaration of it will
       // do.
       *Suggested = nullptr;
       for (auto *Redecl : ED->redecls()) {
         if (isVisible(Redecl))
           return true;
         if (Redecl->isThisDeclarationADefinition() ||
             (Redecl->isCanonicalDecl() && !*Suggested))
           *Suggested = Redecl;
       }
       return false;
     }
     D = ED->getDefinition();
   } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
     if (auto *Pattern = FD->getTemplateInstantiationPattern())
       FD = Pattern;
     D = FD->getDefinition();
   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
     if (auto *Pattern = VD->getTemplateInstantiationPattern())
       VD = Pattern;
     D = VD->getDefinition();
   }
   assert(D && "missing definition for pattern of instantiated definition");
 
   *Suggested = D;
   if (isVisible(D))
     return true;
 
   // The external source may have additional definitions of this entity that are
   // visible, so complete the redeclaration chain now and ask again.
   if (auto *Source = Context.getExternalSource()) {
     Source->CompleteRedeclChain(D);
     return isVisible(D);
   }
 
   return false;
 }
 
 /// Locks in the inheritance model for the given class and all of its bases.
 static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
   RD = RD->getMostRecentDecl();
   if (!RD->hasAttr<MSInheritanceAttr>()) {
     MSInheritanceAttr::Spelling IM;
 
     switch (S.MSPointerToMemberRepresentationMethod) {
     case LangOptions::PPTMK_BestCase:
       IM = RD->calculateInheritanceModel();
       break;
     case LangOptions::PPTMK_FullGeneralitySingleInheritance:
       IM = MSInheritanceAttr::Keyword_single_inheritance;
       break;
     case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
       IM = MSInheritanceAttr::Keyword_multiple_inheritance;
       break;
     case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
       IM = MSInheritanceAttr::Keyword_unspecified_inheritance;
       break;
     }
 
     RD->addAttr(MSInheritanceAttr::CreateImplicit(
         S.getASTContext(), IM,
         /*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
             LangOptions::PPTMK_BestCase,
         S.ImplicitMSInheritanceAttrLoc.isValid()
             ? S.ImplicitMSInheritanceAttrLoc
             : RD->getSourceRange()));
     S.Consumer.AssignInheritanceModel(RD);
   }
 }
 
 /// \brief The implementation of RequireCompleteType
 bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
                                    TypeDiagnoser *Diagnoser) {
   // FIXME: Add this assertion to make sure we always get instantiation points.
   //  assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
   // FIXME: Add this assertion to help us flush out problems with
   // checking for dependent types and type-dependent expressions.
   //
   //  assert(!T->isDependentType() &&
   //         "Can't ask whether a dependent type is complete");
 
   // We lock in the inheritance model once somebody has asked us to ensure
   // that a pointer-to-member type is complete.
   if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
     if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
       if (!MPTy->getClass()->isDependentType()) {
         (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
         assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
       }
     }
   }
 
   NamedDecl *Def = nullptr;
   bool Incomplete = T->isIncompleteType(&Def);
 
   // Check that any necessary explicit specializations are visible. For an
   // enum, we just need the declaration, so don't check this.
   if (Def && !isa<EnumDecl>(Def))
     checkSpecializationVisibility(Loc, Def);
 
   // If we have a complete type, we're done.
   if (!Incomplete) {
     // If we know about the definition but it is not visible, complain.
     NamedDecl *SuggestedDef = nullptr;
     if (Def &&
         !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) {
       // If the user is going to see an error here, recover by making the
       // definition visible.
       bool TreatAsComplete = Diagnoser && !isSFINAEContext();
       if (Diagnoser)
         diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
                               /*Recover*/TreatAsComplete);
       return !TreatAsComplete;
     }
 
     return false;
   }
 
   const TagType *Tag = T->getAs<TagType>();
   const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>();
 
   // If there's an unimported definition of this type in a module (for
   // instance, because we forward declared it, then imported the definition),
   // import that definition now.
   //
   // FIXME: What about other cases where an import extends a redeclaration
   // chain for a declaration that can be accessed through a mechanism other
   // than name lookup (eg, referenced in a template, or a variable whose type
   // could be completed by the module)?
   //
   // FIXME: Should we map through to the base array element type before
   // checking for a tag type?
   if (Tag || IFace) {
     NamedDecl *D =
         Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
 
     // Avoid diagnosing invalid decls as incomplete.
     if (D->isInvalidDecl())
       return true;
 
     // Give the external AST source a chance to complete the type.
     if (auto *Source = Context.getExternalSource()) {
-      if (Tag)
-        Source->CompleteType(Tag->getDecl());
-      else
-        Source->CompleteType(IFace->getDecl());
-
+      if (Tag) {
+        TagDecl *TagD = Tag->getDecl();
+        if (TagD->hasExternalLexicalStorage())
+          Source->CompleteType(TagD);
+      } else {
+        ObjCInterfaceDecl *IFaceD = IFace->getDecl();
+        if (IFaceD->hasExternalLexicalStorage())
+          Source->CompleteType(IFace->getDecl());
+      }
       // If the external source completed the type, go through the motions
       // again to ensure we're allowed to use the completed type.
       if (!T->isIncompleteType())
         return RequireCompleteTypeImpl(Loc, T, Diagnoser);
     }
   }
 
   // If we have a class template specialization or a class member of a
   // class template specialization, or an array with known size of such,
   // try to instantiate it.
   QualType MaybeTemplate = T;
   while (const ConstantArrayType *Array
            = Context.getAsConstantArrayType(MaybeTemplate))
     MaybeTemplate = Array->getElementType();
   if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
     bool Instantiated = false;
     bool Diagnosed = false;
     if (ClassTemplateSpecializationDecl *ClassTemplateSpec
           = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
       if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
         Diagnosed = InstantiateClassTemplateSpecialization(
             Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
             /*Complain=*/Diagnoser);
         Instantiated = true;
       }
     } else if (CXXRecordDecl *Rec
                  = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
       CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
       if (!Rec->isBeingDefined() && Pattern) {
         MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
         assert(MSI && "Missing member specialization information?");
         // This record was instantiated from a class within a template.
         if (MSI->getTemplateSpecializationKind() !=
             TSK_ExplicitSpecialization) {
           Diagnosed = InstantiateClass(Loc, Rec, Pattern,
                                        getTemplateInstantiationArgs(Rec),
                                        TSK_ImplicitInstantiation,
                                        /*Complain=*/Diagnoser);
           Instantiated = true;
         }
       }
     }
 
     if (Instantiated) {
       // Instantiate* might have already complained that the template is not
       // defined, if we asked it to.
       if (Diagnoser && Diagnosed)
         return true;
       // If we instantiated a definition, check that it's usable, even if
       // instantiation produced an error, so that repeated calls to this
       // function give consistent answers.
       if (!T->isIncompleteType())
         return RequireCompleteTypeImpl(Loc, T, Diagnoser);
     }
   }
 
   // FIXME: If we didn't instantiate a definition because of an explicit
   // specialization declaration, check that it's visible.
 
   if (!Diagnoser)
     return true;
 
   Diagnoser->diagnose(*this, Loc, T);
 
   // If the type was a forward declaration of a class/struct/union
   // type, produce a note.
   if (Tag && !Tag->getDecl()->isInvalidDecl())
     Diag(Tag->getDecl()->getLocation(),
          Tag->isBeingDefined() ? diag::note_type_being_defined
                                : diag::note_forward_declaration)
       << QualType(Tag, 0);
 
   // If the Objective-C class was a forward declaration, produce a note.
   if (IFace && !IFace->getDecl()->isInvalidDecl())
     Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
 
   // If we have external information that we can use to suggest a fix,
   // produce a note.
   if (ExternalSource)
     ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
 
   return true;
 }
 
 bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
                                unsigned DiagID) {
   BoundTypeDiagnoser<> Diagnoser(DiagID);
   return RequireCompleteType(Loc, T, Diagnoser);
 }
 
 /// \brief Get diagnostic %select index for tag kind for
 /// literal type diagnostic message.
 /// WARNING: Indexes apply to particular diagnostics only!
 ///
 /// \returns diagnostic %select index.
 static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) {
   switch (Tag) {
   case TTK_Struct: return 0;
   case TTK_Interface: return 1;
   case TTK_Class:  return 2;
   default: llvm_unreachable("Invalid tag kind for literal type diagnostic!");
   }
 }
 
 /// @brief Ensure that the type T is a literal type.
 ///
 /// This routine checks whether the type @p T is a literal type. If @p T is an
 /// incomplete type, an attempt is made to complete it. If @p T is a literal
 /// type, or @p AllowIncompleteType is true and @p T is an incomplete type,
 /// returns false. Otherwise, this routine issues the diagnostic @p PD (giving
 /// it the type @p T), along with notes explaining why the type is not a
 /// literal type, and returns true.
 ///
 /// @param Loc  The location in the source that the non-literal type
 /// diagnostic should refer to.
 ///
 /// @param T  The type that this routine is examining for literalness.
 ///
 /// @param Diagnoser Emits a diagnostic if T is not a literal type.
 ///
 /// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
 /// @c false otherwise.
 bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
                               TypeDiagnoser &Diagnoser) {
   assert(!T->isDependentType() && "type should not be dependent");
 
   QualType ElemType = Context.getBaseElementType(T);
   if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) &&
       T->isLiteralType(Context))
     return false;
 
   Diagnoser.diagnose(*this, Loc, T);
 
   if (T->isVariableArrayType())
     return true;
 
   const RecordType *RT = ElemType->getAs<RecordType>();
   if (!RT)
     return true;
 
   const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
 
   // A partially-defined class type can't be a literal type, because a literal
   // class type must have a trivial destructor (which can't be checked until
   // the class definition is complete).
   if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
     return true;
 
   // If the class has virtual base classes, then it's not an aggregate, and
   // cannot have any constexpr constructors or a trivial default constructor,
   // so is non-literal. This is better to diagnose than the resulting absence
   // of constexpr constructors.
   if (RD->getNumVBases()) {
     Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
       << getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
     for (const auto &I : RD->vbases())
       Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here)
           << I.getSourceRange();
   } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
              !RD->hasTrivialDefaultConstructor()) {
     Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
   } else if (RD->hasNonLiteralTypeFieldsOrBases()) {
     for (const auto &I : RD->bases()) {
       if (!I.getType()->isLiteralType(Context)) {
         Diag(I.getLocStart(),
              diag::note_non_literal_base_class)
           << RD << I.getType() << I.getSourceRange();
         return true;
       }
     }
     for (const auto *I : RD->fields()) {
       if (!I->getType()->isLiteralType(Context) ||
           I->getType().isVolatileQualified()) {
         Diag(I->getLocation(), diag::note_non_literal_field)
           << RD << I << I->getType()
           << I->getType().isVolatileQualified();
         return true;
       }
     }
   } else if (!RD->hasTrivialDestructor()) {
     // All fields and bases are of literal types, so have trivial destructors.
     // If this class's destructor is non-trivial it must be user-declared.
     CXXDestructorDecl *Dtor = RD->getDestructor();
     assert(Dtor && "class has literal fields and bases but no dtor?");
     if (!Dtor)
       return true;
 
     Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
          diag::note_non_literal_user_provided_dtor :
          diag::note_non_literal_nontrivial_dtor) << RD;
     if (!Dtor->isUserProvided())
       SpecialMemberIsTrivial(Dtor, CXXDestructor, /*Diagnose*/true);
   }
 
   return true;
 }
 
 bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
   BoundTypeDiagnoser<> Diagnoser(DiagID);
   return RequireLiteralType(Loc, T, Diagnoser);
 }
 
 /// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
 /// and qualified by the nested-name-specifier contained in SS.
 QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
                                  const CXXScopeSpec &SS, QualType T) {
   if (T.isNull())
     return T;
   NestedNameSpecifier *NNS;
   if (SS.isValid())
     NNS = SS.getScopeRep();
   else {
     if (Keyword == ETK_None)
       return T;
     NNS = nullptr;
   }
   return Context.getElaboratedType(Keyword, NNS, T);
 }
 
 QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
   ExprResult ER = CheckPlaceholderExpr(E);
   if (ER.isInvalid()) return QualType();
   E = ER.get();
 
   if (!getLangOpts().CPlusPlus && E->refersToBitField())
     Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
 
   if (!E->isTypeDependent()) {
     QualType T = E->getType();
     if (const TagType *TT = T->getAs<TagType>())
       DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
   }
   return Context.getTypeOfExprType(E);
 }
 
 /// getDecltypeForExpr - Given an expr, will return the decltype for
 /// that expression, according to the rules in C++11
 /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
 static QualType getDecltypeForExpr(Sema &S, Expr *E) {
   if (E->isTypeDependent())
     return S.Context.DependentTy;
 
   // C++11 [dcl.type.simple]p4:
   //   The type denoted by decltype(e) is defined as follows:
   //
   //     - if e is an unparenthesized id-expression or an unparenthesized class
   //       member access (5.2.5), decltype(e) is the type of the entity named
   //       by e. If there is no such entity, or if e names a set of overloaded
   //       functions, the program is ill-formed;
   //
   // We apply the same rules for Objective-C ivar and property references.
   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
     if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
       return VD->getType();
   } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
     if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
       return FD->getType();
   } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
     return IR->getDecl()->getType();
   } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
     if (PR->isExplicitProperty())
       return PR->getExplicitProperty()->getType();
   } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
     return PE->getType();
   }
   
   // C++11 [expr.lambda.prim]p18:
   //   Every occurrence of decltype((x)) where x is a possibly
   //   parenthesized id-expression that names an entity of automatic
   //   storage duration is treated as if x were transformed into an
   //   access to a corresponding data member of the closure type that
   //   would have been declared if x were an odr-use of the denoted
   //   entity.
   using namespace sema;
   if (S.getCurLambda()) {
     if (isa<ParenExpr>(E)) {
       if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
         if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
           QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
           if (!T.isNull())
             return S.Context.getLValueReferenceType(T);
         }
       }
     }
   }
 
 
   // C++11 [dcl.type.simple]p4:
   //   [...]
   QualType T = E->getType();
   switch (E->getValueKind()) {
   //     - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
   //       type of e;
   case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
   //     - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
   //       type of e;
   case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
   //  - otherwise, decltype(e) is the type of e.
   case VK_RValue: break;
   }
 
   return T;
 }
 
 QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
                                  bool AsUnevaluated) {
   ExprResult ER = CheckPlaceholderExpr(E);
   if (ER.isInvalid()) return QualType();
   E = ER.get();
 
   if (AsUnevaluated && CodeSynthesisContexts.empty() &&
       E->HasSideEffects(Context, false)) {
     // The expression operand for decltype is in an unevaluated expression
     // context, so side effects could result in unintended consequences.
     Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
   }
 
   return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
 }
 
 QualType Sema::BuildUnaryTransformType(QualType BaseType,
                                        UnaryTransformType::UTTKind UKind,
                                        SourceLocation Loc) {
   switch (UKind) {
   case UnaryTransformType::EnumUnderlyingType:
     if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
       Diag(Loc, diag::err_only_enums_have_underlying_types);
       return QualType();
     } else {
       QualType Underlying = BaseType;
       if (!BaseType->isDependentType()) {
         // The enum could be incomplete if we're parsing its definition or
         // recovering from an error.
         NamedDecl *FwdDecl = nullptr;
         if (BaseType->isIncompleteType(&FwdDecl)) {
           Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
           Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
           return QualType();
         }
 
         EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
         assert(ED && "EnumType has no EnumDecl");
 
         DiagnoseUseOfDecl(ED, Loc);
 
         Underlying = ED->getIntegerType();
         assert(!Underlying.isNull());
       }
       return Context.getUnaryTransformType(BaseType, Underlying,
                                         UnaryTransformType::EnumUnderlyingType);
     }
   }
   llvm_unreachable("unknown unary transform type");
 }
 
 QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
   if (!T->isDependentType()) {
     // FIXME: It isn't entirely clear whether incomplete atomic types
     // are allowed or not; for simplicity, ban them for the moment.
     if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
       return QualType();
 
     int DisallowedKind = -1;
     if (T->isArrayType())
       DisallowedKind = 1;
     else if (T->isFunctionType())
       DisallowedKind = 2;
     else if (T->isReferenceType())
       DisallowedKind = 3;
     else if (T->isAtomicType())
       DisallowedKind = 4;
     else if (T.hasQualifiers())
       DisallowedKind = 5;
     else if (!T.isTriviallyCopyableType(Context))
       // Some other non-trivially-copyable type (probably a C++ class)
       DisallowedKind = 6;
 
     if (DisallowedKind != -1) {
       Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
       return QualType();
     }
 
     // FIXME: Do we need any handling for ARC here?
   }
 
   // Build the pointer type.
   return Context.getAtomicType(T);
 }
Index: test/Import/extern-c-function/Inputs/F.cpp
===================================================================
--- test/Import/extern-c-function/Inputs/F.cpp	(revision 311017)
+++ test/Import/extern-c-function/Inputs/F.cpp	(working copy)
@@ -1 +1,3 @@
-void f(int arg) { }
+extern "C" {
+  void f(int arg);
+}
Index: test/Import/extern-c-function/test.cpp
===================================================================
--- test/Import/extern-c-function/test.cpp	(revision 311017)
+++ test/Import/extern-c-function/test.cpp	(working copy)
@@ -1,7 +1,4 @@
-// RUN: clang-import-test -import %S/Inputs/F1.c -import %S/Inputs/F2.c -expression %s
+// RUN: clang-import-test -import %S/Inputs/F.cpp -expression %s
 void expr() {
   f(2);
-  f("world");
-  S s;
-  f(s);
-}
+}
\ No newline at end of file
Index: test/Import/forward-declared-objc-class/Inputs/S1.m
===================================================================
--- test/Import/forward-declared-objc-class/Inputs/S1.m	(revision 311468)
+++ test/Import/forward-declared-objc-class/Inputs/S1.m	(working copy)
@@ -1 +1 @@
-struct S;
+ at class MyClass;
\ No newline at end of file
Index: test/Import/forward-declared-objc-class/Inputs/S2.m
===================================================================
--- test/Import/forward-declared-objc-class/Inputs/S2.m	(revision 311468)
+++ test/Import/forward-declared-objc-class/Inputs/S2.m	(working copy)
@@ -1,3 +1,6 @@
-struct S {
-  int a;
+ at interface MyClass {
+  int j;
 };
++(MyClass*)fromInteger:(int)_j;
+-(int)getInteger;
+ at end
\ No newline at end of file
Index: test/Import/forward-declared-objc-class/Inputs/S3.m
===================================================================
--- test/Import/forward-declared-objc-class/Inputs/S3.m	(revision 311468)
+++ test/Import/forward-declared-objc-class/Inputs/S3.m	(working copy)
@@ -1 +1 @@
-struct S;
+ at class MyClass;
\ No newline at end of file
Index: test/Import/forward-declared-objc-class/test.m
===================================================================
--- test/Import/forward-declared-objc-class/test.m	(revision 311468)
+++ test/Import/forward-declared-objc-class/test.m	(working copy)
@@ -1,5 +1,6 @@
-// RUN: clang-import-test -import %S/Inputs/S1.c --import %S/Inputs/S2.c -expression %s
+// RUN: clang-import-test -x objective-c++ -import %S/Inputs/S1.m --import %S/Inputs/S2.m --import %S/Inputs/S3.m -expression %s
 void expr() {
-  struct S MyS;
-  MyS.a = 3;
+  MyClass *c = [MyClass fromInteger:3];
+  const int i = [c getInteger];
+  const int j = c->j;
 }
Index: test/Import/forward-declared-struct/Inputs/S3.c
===================================================================
Index: test/Import/forward-declared-struct/test.c
===================================================================
--- test/Import/forward-declared-struct/test.c	(revision 313996)
+++ test/Import/forward-declared-struct/test.c	(working copy)
@@ -1,5 +1,5 @@
-// RUN: clang-import-test -import %S/Inputs/S1.c --import %S/Inputs/S2.c -expression %s
+// RUN: clang-import-test -import %S/Inputs/S1.c --import %S/Inputs/S2.c --import %S/Inputs/S3.c -expression %s
 void expr() {
   struct S MyS;
   MyS.a = 3;
 }
Index: test/Import/local-struct/test.cpp
===================================================================
--- test/Import/local-struct/test.cpp	(revision 313996)
+++ test/Import/local-struct/test.cpp	(working copy)
@@ -1,8 +1,7 @@
 // RUN: clang-import-test -dump-ir -import %S/Inputs/Callee.cpp -expression %s | FileCheck %s
-// XFAIL: *
 // CHECK: %struct.S = type { i
-// CHECK: %struct.S.0 = type { i1 }
+// CHECK: %struct.S.0 = type { i
 
 void foo() {
   return Bar().bar(3, true);
 }
Index: test/Import/local-struct-use-origins/Inputs/Callee.cpp
===================================================================
Index: test/Import/local-struct-use-origins/test.cpp
===================================================================
--- test/Import/local-struct-use-origins/test.cpp	(revision 310656)
+++ test/Import/local-struct-use-origins/test.cpp	(working copy)
@@ -1,8 +1,7 @@
-// RUN: clang-import-test -dump-ir -import %S/Inputs/Callee.cpp -expression %s | FileCheck %s
-// XFAIL: *
+// RUN: clang-import-test -dump-ir -use-origins -import %S/Inputs/Callee.cpp -expression %s | FileCheck %s
 // CHECK: %struct.S = type { i
-// CHECK: %struct.S.0 = type { i1 }
+// CHECK: %struct.S.0 = type { i
 
 void foo() {
   return Bar().bar(3, true);
 }
Index: test/Import/objc-definitions-in-expression/Inputs/S.m
===================================================================
Index: test/Import/objc-definitions-in-expression/test.m
===================================================================
--- test/Import/objc-definitions-in-expression/test.m	(revision 311468)
+++ test/Import/objc-definitions-in-expression/test.m	(working copy)
@@ -1,5 +1,21 @@
 // RUN: clang-import-test -x objective-c++ -import %S/Inputs/S.m -expression %s
+ at class D;
+
+ at interface B {
+  int x;
+  int y;
+}
+ at end
+
+ at interface D : B {
+  int z;
+}
+-(int)n;
+ at end
+
 void expr() {
   C *c;
   int i = [c m];
+  D *d;
+  int j = [d n] + d->x;
 }
Index: test/Import/struct-and-var/Inputs/S1.cpp
===================================================================
--- test/Import/struct-and-var/Inputs/S1.cpp	(revision 310656)
+++ test/Import/struct-and-var/Inputs/S1.cpp	(working copy)
@@ -1,6 +1 @@
-class T;
-
-class S {
-  T *t;
-  int a;
-};
+int F;
Index: test/Import/struct-and-var/Inputs/S2.cpp
===================================================================
--- test/Import/struct-and-var/Inputs/S2.cpp	(revision 310656)
+++ test/Import/struct-and-var/Inputs/S2.cpp	(working copy)
@@ -1,7 +1,3 @@
-class U {
-  int b;
+struct F {
+  int a;
 };
-
-class T {
-  U u;
-};
Index: test/Import/struct-and-var/test.cpp
===================================================================
--- test/Import/struct-and-var/test.cpp	(revision 310656)
+++ test/Import/struct-and-var/test.cpp	(working copy)
@@ -1,7 +1,5 @@
 // RUN: clang-import-test --import %S/Inputs/S1.cpp --import %S/Inputs/S2.cpp -expression %s
 void expr() {
-  S MyS;
-  T MyT;
-  MyS.a = 3;
-  MyT.u.b = 2;
+  struct F f;
+  int x = f.a;
 }
Index: test/Import/template/Inputs/T.cpp
===================================================================
--- test/Import/template/Inputs/T.cpp	(revision 310656)
+++ test/Import/template/Inputs/T.cpp	(working copy)
@@ -1,14 +1,5 @@
 template <typename T> struct A {
-};
-
-template <> struct A<int> {
   struct B {
-    int f;
+    T f;
   };
 };
-
-template <> struct A<bool> {
-  struct B {
-    int g;
-  };
-};
Index: test/Import/template/test.cpp
===================================================================
--- test/Import/template/test.cpp	(revision 310656)
+++ test/Import/template/test.cpp	(working copy)
@@ -1,7 +1,4 @@
 // RUN: clang-import-test -import %S/Inputs/T.cpp -expression %s
-// XFAIL: *
 void expr() {
-  A<int>::B b1;
-  A<bool>::B b2;
-  b1.f + b2.g;
+  A<int>::B b;
 }
Index: tools/clang-import-test/clang-import-test.cpp
===================================================================
--- tools/clang-import-test/clang-import-test.cpp	(revision 313996)
+++ tools/clang-import-test/clang-import-test.cpp	(working copy)
@@ -1,344 +1,378 @@
 //===-- import-test.cpp - ASTImporter/ExternalASTSource testbed -----------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTImporter.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExternalASTMerger.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/Driver/Types.h"
 #include "clang/Frontend/ASTConsumers.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/MultiplexConsumer.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/ParseAST.h"
 
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Signals.h"
 
 #include <memory>
 #include <string>
 
 using namespace clang;
 
 static llvm::cl::opt<std::string> Expression(
     "expression", llvm::cl::Required,
     llvm::cl::desc("Path to a file containing the expression to parse"));
 
 static llvm::cl::list<std::string>
     Imports("import", llvm::cl::ZeroOrMore,
             llvm::cl::desc("Path to a file containing declarations to import"));
 
 static llvm::cl::opt<bool>
     Direct("direct", llvm::cl::Optional,
-             llvm::cl::desc("Use the parsed declarations without indirection"));
+           llvm::cl::desc("Use the parsed declarations without indirection"));
 
+static llvm::cl::opt<bool>
+    UseOrigins("use-origins", llvm::cl::Optional,
+           llvm::cl::desc("Use DeclContext origin information for more accurate lookups"));  
+
 static llvm::cl::list<std::string>
     ClangArgs("Xcc", llvm::cl::ZeroOrMore,
               llvm::cl::desc("Argument to pass to the CompilerInvocation"),
               llvm::cl::CommaSeparated);
 
 static llvm::cl::opt<std::string>
     Input("x", llvm::cl::Optional,
           llvm::cl::desc("The language to parse (default: c++)"),
           llvm::cl::init("c++"));
 
-static llvm::cl::opt<bool>
-DumpAST("dump-ast", llvm::cl::init(false),
-        llvm::cl::desc("Dump combined AST"));
+static llvm::cl::opt<bool> DumpAST("dump-ast", llvm::cl::init(false),
+                                   llvm::cl::desc("Dump combined AST"));
 
-static llvm::cl::opt<bool>
-DumpIR("dump-ir", llvm::cl::init(false),
-        llvm::cl::desc("Dump IR from final parse"));
+static llvm::cl::opt<bool> DumpIR("dump-ir", llvm::cl::init(false),
+                                  llvm::cl::desc("Dump IR from final parse"));
 
 namespace init_convenience {
 class TestDiagnosticConsumer : public DiagnosticConsumer {
 private:
   std::unique_ptr<TextDiagnosticBuffer> Passthrough;
   const LangOptions *LangOpts = nullptr;
 
 public:
   TestDiagnosticConsumer()
       : Passthrough(llvm::make_unique<TextDiagnosticBuffer>()) {}
 
   virtual void BeginSourceFile(const LangOptions &LangOpts,
                                const Preprocessor *PP = nullptr) override {
     this->LangOpts = &LangOpts;
     return Passthrough->BeginSourceFile(LangOpts, PP);
   }
 
   virtual void EndSourceFile() override {
     this->LangOpts = nullptr;
     Passthrough->EndSourceFile();
   }
 
   virtual bool IncludeInDiagnosticCounts() const override {
     return Passthrough->IncludeInDiagnosticCounts();
   }
 
 private:
   static void PrintSourceForLocation(const SourceLocation &Loc,
                                      SourceManager &SM) {
     const char *LocData = SM.getCharacterData(Loc, /*Invalid=*/nullptr);
     unsigned LocColumn =
         SM.getSpellingColumnNumber(Loc, /*Invalid=*/nullptr) - 1;
     FileID FID = SM.getFileID(Loc);
     llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, Loc, /*Invalid=*/nullptr);
 
     assert(LocData >= Buffer->getBufferStart() &&
            LocData < Buffer->getBufferEnd());
 
     const char *LineBegin = LocData - LocColumn;
 
     assert(LineBegin >= Buffer->getBufferStart());
 
     const char *LineEnd = nullptr;
 
     for (LineEnd = LineBegin; *LineEnd != '\n' && *LineEnd != '\r' &&
                               LineEnd < Buffer->getBufferEnd();
          ++LineEnd)
       ;
 
     llvm::StringRef LineString(LineBegin, LineEnd - LineBegin);
 
     llvm::errs() << LineString << '\n';
     llvm::errs().indent(LocColumn);
     llvm::errs() << '^';
     llvm::errs() << '\n';
   }
 
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                 const Diagnostic &Info) override {
     if (Info.hasSourceManager() && LangOpts) {
       SourceManager &SM = Info.getSourceManager();
 
       if (Info.getLocation().isValid()) {
         Info.getLocation().print(llvm::errs(), SM);
         llvm::errs() << ": ";
       }
 
       SmallString<16> DiagText;
       Info.FormatDiagnostic(DiagText);
       llvm::errs() << DiagText << '\n';
 
       if (Info.getLocation().isValid()) {
         PrintSourceForLocation(Info.getLocation(), SM);
       }
 
       for (const CharSourceRange &Range : Info.getRanges()) {
         bool Invalid = true;
         StringRef Ref = Lexer::getSourceText(Range, SM, *LangOpts, &Invalid);
         if (!Invalid) {
           llvm::errs() << Ref << '\n';
         }
       }
     }
     DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
   }
 };
 
-std::unique_ptr<CompilerInstance>
-BuildCompilerInstance() {
+std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
   auto Ins = llvm::make_unique<CompilerInstance>();
   auto DC = llvm::make_unique<TestDiagnosticConsumer>();
   const bool ShouldOwnClient = true;
   Ins->createDiagnostics(DC.release(), ShouldOwnClient);
 
   auto Inv = llvm::make_unique<CompilerInvocation>();
 
   std::vector<const char *> ClangArgv(ClangArgs.size());
   std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
                  [](const std::string &s) -> const char * { return s.data(); });
   CompilerInvocation::CreateFromArgs(*Inv, ClangArgv.data(),
                                      &ClangArgv.data()[ClangArgv.size()],
                                      Ins->getDiagnostics());
 
   {
     using namespace driver::types;
     ID Id = lookupTypeForTypeSpecifier(Input.c_str());
     assert(Id != TY_INVALID);
     if (isCXX(Id)) {
       Inv->getLangOpts()->CPlusPlus = true;
       Inv->getLangOpts()->CPlusPlus11 = true;
       Inv->getHeaderSearchOpts().UseLibcxx = true;
     }
     if (isObjC(Id)) {
       Inv->getLangOpts()->ObjC1 = 1;
       Inv->getLangOpts()->ObjC2 = 1;
     }
   }
   Inv->getLangOpts()->Bool = true;
   Inv->getLangOpts()->WChar = true;
   Inv->getLangOpts()->Blocks = true;
   Inv->getLangOpts()->DebuggerSupport = true;
   Inv->getLangOpts()->SpellChecking = false;
   Inv->getLangOpts()->ThreadsafeStatics = false;
   Inv->getLangOpts()->AccessControl = false;
   Inv->getLangOpts()->DollarIdents = true;
   Inv->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
   Inv->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
 
   Ins->setInvocation(std::move(Inv));
 
   TargetInfo *TI = TargetInfo::CreateTargetInfo(
       Ins->getDiagnostics(), Ins->getInvocation().TargetOpts);
   Ins->setTarget(TI);
   Ins->getTarget().adjust(Ins->getLangOpts());
   Ins->createFileManager();
   Ins->createSourceManager(Ins->getFileManager());
   Ins->createPreprocessor(TU_Complete);
 
   return Ins;
 }
 
 std::unique_ptr<ASTContext>
 BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) {
   auto AST = llvm::make_unique<ASTContext>(
       CI.getLangOpts(), CI.getSourceManager(),
       CI.getPreprocessor().getIdentifierTable(), ST, BC);
   AST->InitBuiltinTypes(CI.getTarget());
   return AST;
 }
 
 std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI,
                                             llvm::LLVMContext &LLVMCtx) {
   StringRef ModuleName("$__module");
   return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen(
       CI.getDiagnostics(), ModuleName, CI.getHeaderSearchOpts(),
       CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx));
 }
 } // end namespace
 
 namespace {
- 
-void AddExternalSource(
-    CompilerInstance &CI,
-    llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports) {
-  ExternalASTMerger::ImporterEndpoint Target({CI.getASTContext(), CI.getFileManager()});
-  llvm::SmallVector<ExternalASTMerger::ImporterEndpoint, 3> Sources;
-  for (const std::unique_ptr<CompilerInstance> &CI : Imports) {
-    Sources.push_back({CI->getASTContext(), CI->getFileManager()});
+
+/// A container for a CompilerInstance (possibly with an ExternalASTMerger
+/// attached to its ASTContext).
+///
+/// Provides an accessor for the DeclContext origins associated with the
+/// ExternalASTMerger (or an empty list of origins if no ExternalASTMerger is
+/// attached).
+///
+/// This is the main unit of parsed source code maintained by clang-import-test.
+struct CIAndOrigins {
+  using OriginMap = clang::ExternalASTMerger::OriginMap;
+  std::unique_ptr<CompilerInstance> CI;
+
+  ASTContext &getASTContext() { return CI->getASTContext(); }
+  FileManager &getFileManager() { return CI->getFileManager(); }
+  const OriginMap &getOriginMap() {
+    static const OriginMap EmptyOriginMap;
+    if (ExternalASTSource *Source = CI->getASTContext().getExternalSource())
+      return static_cast<ExternalASTMerger *>(Source)->GetOrigins();
+    return EmptyOriginMap;
   }
+  DiagnosticConsumer &getDiagnosticClient() {
+    return CI->getDiagnosticClient();
+  }
+  CompilerInstance &getCompilerInstance() { return *CI; }
+};
+
+void AddExternalSource(CIAndOrigins &CI,
+                       llvm::MutableArrayRef<CIAndOrigins> Imports) {
+  ExternalASTMerger::ImporterTarget Target(
+      {CI.getASTContext(), CI.getFileManager()});
+  llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
+  for (CIAndOrigins &Import : Imports)
+    Sources.push_back(
+        {Import.getASTContext(), Import.getFileManager(), Import.getOriginMap()});
   auto ES = llvm::make_unique<ExternalASTMerger>(Target, Sources);
   CI.getASTContext().setExternalSource(ES.release());
   CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
 }
 
-std::unique_ptr<CompilerInstance> BuildIndirect(std::unique_ptr<CompilerInstance> &CI) {
-  std::unique_ptr<CompilerInstance> IndirectCI =
-      init_convenience::BuildCompilerInstance();
+CIAndOrigins BuildIndirect(CIAndOrigins &CI) {
+  CIAndOrigins IndirectCI{init_convenience::BuildCompilerInstance()};
   auto ST = llvm::make_unique<SelectorTable>();
   auto BC = llvm::make_unique<Builtin::Context>();
-  std::unique_ptr<ASTContext> AST =
-      init_convenience::BuildASTContext(*IndirectCI, *ST, *BC);
-  IndirectCI->setASTContext(AST.release());
-  AddExternalSource(*IndirectCI, CI);
+  std::unique_ptr<ASTContext> AST = init_convenience::BuildASTContext(
+      IndirectCI.getCompilerInstance(), *ST, *BC);
+  IndirectCI.getCompilerInstance().setASTContext(AST.release());
+  AddExternalSource(IndirectCI, CI);
   return IndirectCI;
 }
 
 llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI,
                         ASTConsumer &Consumer) {
   SourceManager &SM = CI.getSourceManager();
   const FileEntry *FE = CI.getFileManager().getFile(Path);
   if (!FE) {
     return llvm::make_error<llvm::StringError>(
         llvm::Twine("Couldn't open ", Path), std::error_code());
   }
   SM.setMainFileID(SM.createFileID(FE, SourceLocation(), SrcMgr::C_User));
   ParseAST(CI.getPreprocessor(), &Consumer, CI.getASTContext());
   return llvm::Error::success();
 }
 
-llvm::Expected<std::unique_ptr<CompilerInstance>>
-Parse(const std::string &Path,
-      llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports,
-      bool ShouldDumpAST, bool ShouldDumpIR) {
-  std::unique_ptr<CompilerInstance> CI =
-      init_convenience::BuildCompilerInstance();
+llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
+                                   llvm::MutableArrayRef<CIAndOrigins> Imports,
+                                   bool ShouldDumpAST, bool ShouldDumpIR) {
+  CIAndOrigins CI{init_convenience::BuildCompilerInstance()};
   auto ST = llvm::make_unique<SelectorTable>();
   auto BC = llvm::make_unique<Builtin::Context>();
   std::unique_ptr<ASTContext> AST =
-      init_convenience::BuildASTContext(*CI, *ST, *BC);
-  CI->setASTContext(AST.release());
+      init_convenience::BuildASTContext(CI.getCompilerInstance(), *ST, *BC);
+  CI.getCompilerInstance().setASTContext(AST.release());
   if (Imports.size())
-    AddExternalSource(*CI, Imports);
+    AddExternalSource(CI, Imports);
 
   std::vector<std::unique_ptr<ASTConsumer>> ASTConsumers;
 
   auto LLVMCtx = llvm::make_unique<llvm::LLVMContext>();
-  ASTConsumers.push_back(init_convenience::BuildCodeGen(*CI, *LLVMCtx));
-  auto &CG = *static_cast<CodeGenerator*>(ASTConsumers.back().get());
+  ASTConsumers.push_back(
+      init_convenience::BuildCodeGen(CI.getCompilerInstance(), *LLVMCtx));
+  auto &CG = *static_cast<CodeGenerator *>(ASTConsumers.back().get());
 
   if (ShouldDumpAST)
     ASTConsumers.push_back(CreateASTDumper("", true, false, false));
 
-  CI->getDiagnosticClient().BeginSourceFile(CI->getLangOpts(),
-                                            &CI->getPreprocessor());
+  CI.getDiagnosticClient().BeginSourceFile(
+      CI.getCompilerInstance().getLangOpts(),
+      &CI.getCompilerInstance().getPreprocessor());
   MultiplexConsumer Consumers(std::move(ASTConsumers));
-  Consumers.Initialize(CI->getASTContext());
+  Consumers.Initialize(CI.getASTContext());
 
-  if (llvm::Error PE = ParseSource(Path, *CI, Consumers)) {
+  if (llvm::Error PE = ParseSource(Path, CI.getCompilerInstance(), Consumers))
     return std::move(PE);
-  }
-  CI->getDiagnosticClient().EndSourceFile();
+  CI.getDiagnosticClient().EndSourceFile();
   if (ShouldDumpIR)
     CG.GetModule()->print(llvm::outs(), nullptr);
-  if (CI->getDiagnosticClient().getNumErrors()) {
+  if (CI.getDiagnosticClient().getNumErrors())
     return llvm::make_error<llvm::StringError>(
         "Errors occured while parsing the expression.", std::error_code());
-  } else {
-    return std::move(CI);
-  }
+  return std::move(CI);
 }
 
+void Forget(CIAndOrigins &CI, llvm::MutableArrayRef<CIAndOrigins> Imports) {
+  llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
+  for (CIAndOrigins &Import : Imports)
+    Sources.push_back(
+        {Import.getASTContext(), Import.getFileManager(), Import.getOriginMap()});
+  ExternalASTSource *Source = CI.CI->getASTContext().getExternalSource();
+  auto *Merger = static_cast<ExternalASTMerger *>(Source);
+  Merger->RemoveSources(Sources);
+}
+
 } // end namespace
 
 int main(int argc, const char **argv) {
   const bool DisableCrashReporting = true;
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0], DisableCrashReporting);
   llvm::cl::ParseCommandLineOptions(argc, argv);
-  std::vector<std::unique_ptr<CompilerInstance>> ImportCIs;
+  std::vector<CIAndOrigins> ImportCIs;
   for (auto I : Imports) {
-    llvm::Expected<std::unique_ptr<CompilerInstance>> ImportCI =
-      Parse(I, {}, false, false);
+    llvm::Expected<CIAndOrigins> ImportCI = Parse(I, {}, false, false);
     if (auto E = ImportCI.takeError()) {
       llvm::errs() << llvm::toString(std::move(E));
       exit(-1);
-    } else {
-      ImportCIs.push_back(std::move(*ImportCI));
     }
+    ImportCIs.push_back(std::move(*ImportCI));
   }
-  std::vector<std::unique_ptr<CompilerInstance>> IndirectCIs;
-  if (!Direct) {
+  std::vector<CIAndOrigins> IndirectCIs;
+  if (!Direct || UseOrigins) {
     for (auto &ImportCI : ImportCIs) {
-      std::unique_ptr<CompilerInstance> IndirectCI = BuildIndirect(ImportCI);
+      CIAndOrigins IndirectCI = BuildIndirect(ImportCI);
       IndirectCIs.push_back(std::move(IndirectCI));
     }
   }
-  llvm::Expected<std::unique_ptr<CompilerInstance>> ExpressionCI =
-      Parse(Expression, Direct ? ImportCIs : IndirectCIs, DumpAST, DumpIR);
+  if (UseOrigins)
+    for (auto &ImportCI : ImportCIs)
+      IndirectCIs.push_back(std::move(ImportCI));
+  llvm::Expected<CIAndOrigins> ExpressionCI =
+      Parse(Expression, (Direct && !UseOrigins) ? ImportCIs : IndirectCIs,
+            DumpAST, DumpIR);
   if (auto E = ExpressionCI.takeError()) {
     llvm::errs() << llvm::toString(std::move(E));
     exit(-1);
-  } else {
-    return 0;
   }
+  Forget(*ExpressionCI, (Direct && !UseOrigins) ? ImportCIs : IndirectCIs);
+  return 0;
 }
-


More information about the cfe-commits mailing list