[Expression parser] Setting to enable use of ExternalASTMerger

This setting can be enabled like this at the target level:

(lldb) settings set target.experimental.use-modern-type-lookup true

This causes several new behaviors in the Clang expression parser:

- It completely disables use of ClangASTImporter.  None are created
  at all, and all users of it are now conditionalized on its
  presence.

- It instead constructs a per-expression ExternalASTMerger, which
  exists inside Clang and contains much of the type completion
  logic that hitherto lived in ExternalASTSource,
  ClangExpressionDeclMap, and ClangASTImporter.

- The expression parser uses this Merger as a backend for copying
  and completing types.

- It also constructs a persistent ExternalASTMerger which is
  connected to the Target's persistent AST context.

This is a major chunk of LLDB functionality moved into Clang.  It
can be tested in two ways:

1. For an individual debug session, enable the setting before
   running a target.

2. For the testsuite, change the option to be default-true.  This
   is done in Target.cpp's g_experimental_properties.  The
   testsuite is not yet clean with this, so I have not committed
   that switch.

I have filed a Bugzilla for extending the testsuite to allow
custom settings for all tests:
  https://bugs.llvm.org/show_bug.cgi?id=34771

I have also filed a Bugzilla for fixing the remaining testsuite
failures with this setting enabled:
  https://bugs.llvm.org/show_bug.cgi?id=34772

llvm-svn: 314458
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index eefe130..d102fb4 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -48,8 +48,10 @@
 #include "lldb/lldb-private.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclarationName.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 
 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
 
@@ -178,6 +180,134 @@
   return ret;
 }
 
+namespace {
+/// This class walks an AST and ensures that all DeclContexts defined inside the
+/// current source file are properly complete.
+///
+/// This is used to ensure that persistent types defined in the current source
+/// file migrate completely to the persistent AST context before they are
+/// reused.  If that didn't happen, it would be impoossible to complete them
+/// because their origin would be gone.
+///
+/// The stragtegy used by this class is to check the SourceLocation (to be
+/// specific, the FileID) and see if it's the FileID for the current expression.
+/// Alternate strategies could include checking whether an ExternalASTMerger,
+/// set up to not have the current context as a source, can find an original for
+/// the type.
+class Completer : public clang::RecursiveASTVisitor<Completer> {
+private:
+  clang::ASTImporter &m_exporter;             /// Used to import Decl contents
+  clang::FileID m_file;                       /// The file that's going away
+  llvm::DenseSet<clang::Decl *> m_completed;  /// Visited Decls, to avoid cycles
+
+  bool ImportAndCheckCompletable(clang::Decl *decl) {
+    (void)m_exporter.Import(decl);
+    if (m_completed.count(decl))
+      return false;
+    if (!llvm::isa<DeclContext>(decl))
+      return false;
+    const clang::SourceLocation loc = decl->getLocation();
+    if (!loc.isValid())
+      return false;
+    const clang::FileID file =
+        m_exporter.getFromContext().getSourceManager().getFileID(loc);
+    if (file != m_file)
+      return false;
+    // We are assuming the Decl was parsed in this very expression, so it should
+    // not have external storage.
+    lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage());
+    return true;
+  }
+
+  void Complete(clang::Decl *decl) {
+    m_completed.insert(decl);
+    auto *decl_context = llvm::cast<DeclContext>(decl);
+    (void)m_exporter.Import(decl);
+    m_exporter.CompleteDecl(decl);
+    for (Decl *child : decl_context->decls())
+      if (ImportAndCheckCompletable(child))
+        Complete(child);
+  }
+
+  void MaybeComplete(clang::Decl *decl) {
+    if (ImportAndCheckCompletable(decl))
+      Complete(decl);
+  }
+
+public:
+  Completer(clang::ASTImporter &exporter, clang::FileID file)
+      : m_exporter(exporter), m_file(file) {}
+  
+  // Implements the RecursiveASTVisitor's core API.  It is called on each Decl
+  // that the RecursiveASTVisitor encounters, and returns true if the traversal
+  // should continue.
+  bool VisitDecl(clang::Decl *decl) {
+    MaybeComplete(decl);
+    return true;
+  }
+};
+}
+
+static void CompleteAllDeclContexts(clang::ASTImporter &exporter,
+                                    clang::FileID file,
+                                    clang::QualType root) {
+  clang::QualType canonical_type = root.getCanonicalType();
+  if (clang::TagDecl *tag_decl = canonical_type->getAsTagDecl()) {
+    Completer(exporter, file).TraverseDecl(tag_decl);
+  } else if (auto interface_type = llvm::dyn_cast<ObjCInterfaceType>(
+                 canonical_type.getTypePtr())) {
+    Completer(exporter, file).TraverseDecl(interface_type->getDecl());
+  } else {
+    Completer(exporter, file).TraverseType(canonical_type);
+  }
+}
+
+static clang::QualType ExportAllDeclaredTypes(
+    clang::ExternalASTMerger &merger,
+    clang::ASTContext &source, clang::FileManager &source_file_manager,
+    const clang::ExternalASTMerger::OriginMap &source_origin_map,
+    clang::FileID file, clang::QualType root) {
+  clang::ExternalASTMerger::ImporterSource importer_source =
+      { source, source_file_manager, source_origin_map };
+  merger.AddSources(importer_source);
+  clang::ASTImporter &exporter = merger.ImporterForOrigin(source);
+  CompleteAllDeclContexts(exporter, file, root);
+  clang::QualType ret = exporter.Import(root);
+  merger.RemoveSources(importer_source);
+  return ret;
+}
+
+TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target,
+                                                ClangASTContext &source,
+                                                TypeFromParser parser_type) {
+  assert (&target == m_target->GetScratchClangASTContext());
+  assert ((TypeSystem*)&source == parser_type.GetTypeSystem());
+  assert (source.getASTContext() == m_ast_context);
+  
+  if (m_ast_importer_sp) {
+    return TypeFromUser(m_ast_importer_sp->DeportType(
+                            target.getASTContext(), source.getASTContext(),
+                            parser_type.GetOpaqueQualType()),
+                        &target);
+  } else if (m_merger_up) {
+    clang::FileID source_file =
+        source.getASTContext()->getSourceManager().getFileID(
+            source.getASTContext()->getTranslationUnitDecl()->getLocation());
+    auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>(
+        m_target->GetScratchClangASTContext());
+    clang::QualType exported_type = ExportAllDeclaredTypes(
+        scratch_ast_context->GetMergerUnchecked(),
+        *source.getASTContext(), *source.getFileManager(),
+        m_merger_up->GetOrigins(),
+        source_file,
+        clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType()));
+    return TypeFromUser(exported_type.getAsOpaquePtr(), &target);
+  } else {
+    lldbassert(!"No mechanism for deporting a type!");
+    return TypeFromUser();
+  }
+}
+
 bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
                                                    const ConstString &name,
                                                    TypeFromParser parser_type,
@@ -198,12 +328,8 @@
     if (target == nullptr)
       return false;
 
-    ClangASTContext *context(target->GetScratchClangASTContext());
-
-    TypeFromUser user_type(m_ast_importer_sp->DeportType(
-                               context->getASTContext(), ast->getASTContext(),
-                               parser_type.GetOpaqueQualType()),
-                           context);
+    TypeFromUser user_type =
+        DeportType(*target->GetScratchClangASTContext(), *ast, parser_type);
 
     uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(
         user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err);
@@ -240,10 +366,7 @@
 
   ClangASTContext *context(target->GetScratchClangASTContext());
 
-  TypeFromUser user_type(m_ast_importer_sp->DeportType(
-                             context->getASTContext(), ast->getASTContext(),
-                             parser_type.GetOpaqueQualType()),
-                         context);
+  TypeFromUser user_type = DeportType(*context, *ast, parser_type);
 
   if (!user_type.GetOpaqueQualType()) {
     if (log)
@@ -688,16 +811,18 @@
     }
 
     ClangASTImporter::NamespaceMapSP namespace_map =
-        m_ast_importer_sp->GetNamespaceMap(namespace_context);
+        m_ast_importer_sp
+            ? m_ast_importer_sp->GetNamespaceMap(namespace_context)
+            : ClangASTImporter::NamespaceMapSP();
+
+    if (!namespace_map)
+      return;
 
     if (log && log->GetVerbose())
       log->Printf("  CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
                   current_id, static_cast<void *>(namespace_map.get()),
                   (int)namespace_map->size());
-
-    if (!namespace_map)
-      return;
-
+    
     for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(),
                                                   e = namespace_map->end();
          i != e; ++i) {
@@ -775,8 +900,7 @@
       if (!persistent_decl)
         break;
 
-      Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl(
-          m_ast_context, scratch_ast_context, persistent_decl);
+      Decl *parser_persistent_decl = CopyDecl(persistent_decl);
 
       if (!parser_persistent_decl)
         break;
@@ -1320,8 +1444,7 @@
         for (clang::NamedDecl *decl : decls_from_modules) {
           if (llvm::isa<clang::FunctionDecl>(decl)) {
             clang::NamedDecl *copied_decl =
-                llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl(
-                    m_ast_context, &decl->getASTContext(), decl));
+                llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
             if (copied_decl) {
               context.AddNamedDecl(copied_decl);
               context.m_found.function_with_type_info = true;
@@ -1363,9 +1486,7 @@
                           current_id, name.GetCString());
             }
 
-            clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
-                m_ast_context, &decl_from_modules->getASTContext(),
-                decl_from_modules);
+            clang::Decl *copied_decl = CopyDecl(decl_from_modules);
             clang::FunctionDecl *copied_function_decl =
                 copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl)
                             : nullptr;
@@ -1392,9 +1513,7 @@
                           current_id, name.GetCString());
             }
 
-            clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
-                m_ast_context, &decl_from_modules->getASTContext(),
-                decl_from_modules);
+            clang::Decl *copied_decl = CopyDecl(decl_from_modules);
             clang::VarDecl *copied_var_decl =
                 copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl)
                             : nullptr;
@@ -1753,7 +1872,9 @@
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
   Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
 
-  ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext();
+  ClangASTContextForExpressions *scratch_ast_context =
+      static_cast<ClangASTContextForExpressions*>(
+          target->GetScratchClangASTContext());
 
   for (size_t index = 0, num_entities = m_found_entities.GetSize();
        index < num_entities; ++index) {
@@ -1784,9 +1905,20 @@
           var_type.getAsOpaquePtr(),
           ClangASTContext::GetASTContext(&var_decl->getASTContext()));
 
-      lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(
-          scratch_ast_context->getASTContext(), &var_decl->getASTContext(),
-          var_type.getAsOpaquePtr());
+      lldb::opaque_compiler_type_t copied_type = 0;
+      if (m_ast_importer_sp) {
+        copied_type = m_ast_importer_sp->CopyType(
+            scratch_ast_context->getASTContext(), &var_decl->getASTContext(),
+            var_type.getAsOpaquePtr());
+      } else if (HasMerger()) {
+        copied_type = CopyTypeWithMerger(
+            var_decl->getASTContext(),
+            scratch_ast_context->GetMergerUnchecked(),
+            var_type).getAsOpaquePtr();
+      } else {
+        lldbassert(!"No mechanism to copy a resolved unknown type!");
+        return false;
+      }
 
       if (!copied_type) {
         if (log)
@@ -1896,9 +2028,7 @@
               src_function_decl->getTemplateSpecializationInfo()->getTemplate();
           clang::FunctionTemplateDecl *copied_function_template =
               llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(
-                 m_ast_importer_sp->CopyDecl(m_ast_context,
-                                             src_ast->getASTContext(),
-                                             function_template));
+                  CopyDecl(function_template));
           if (copied_function_template) {
             if (log) {
               ASTDumper ast_dumper((clang::Decl *)copied_function_template);
@@ -1919,9 +2049,7 @@
         } else if (src_function_decl) {
           if (clang::FunctionDecl *copied_function_decl =
                   llvm::dyn_cast_or_null<clang::FunctionDecl>(
-                      m_ast_importer_sp->CopyDecl(m_ast_context,
-                                                  src_ast->getASTContext(),
-                                                  src_function_decl))) {
+                       CopyDecl(src_function_decl))) {
             if (log) {
               ASTDumper ast_dumper((clang::Decl *)copied_function_decl);