teemperor updated this revision to Diff 196962.
teemperor edited the summary of this revision.
teemperor added a comment.

- Renamed to CxxModuleHandler as I want to reuse most of code later for decl 
importing from generic modules.
- Moved declaration construction into it's own templated method similar to the 
way the ASTImporter is handling decl construction.
- Make sure we register all created decls with the ASTImporter to prevent 
triggering the new assert in ASTImporter::Import_New(Decl *d).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59537/new/

https://reviews.llvm.org/D59537

Files:
  lldb/include/lldb/Symbol/ClangASTContext.h
  lldb/include/lldb/Symbol/ClangASTImporter.h
  lldb/include/lldb/Symbol/CxxModuleHandler.h
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/TestBasicDeque.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/TestBasicForwardList.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/TestBasicList.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/TestSharedPtr.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/TestUniquePtr.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/TestBasicVector.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/TestBoolVector.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/TestVectorOfVectors.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/main.cpp
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/Makefile
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/TestWeakPtr.py
  
lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/main.cpp
  lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
  lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
  lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
  lldb/source/Symbol/CMakeLists.txt
  lldb/source/Symbol/ClangASTContext.cpp
  lldb/source/Symbol/ClangASTImporter.cpp
  lldb/source/Symbol/CxxModuleHandler.cpp

Index: lldb/source/Symbol/CxxModuleHandler.cpp
===================================================================
--- /dev/null
+++ lldb/source/Symbol/CxxModuleHandler.cpp
@@ -0,0 +1,278 @@
+//===-- CxxModuleHandler.cpp ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/CxxModuleHandler.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/Support/Error.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target)
+    : m_importer(&importer),
+      m_sema(ClangASTContext::GetASTContext(target)->getSema()) {
+
+  std::initializer_list<const char *> supported_names = {
+      // containers
+      "vector",
+      "list",
+      "forward_list",
+      "deque",
+      // pointers
+      "shared_ptr",
+      "unique_ptr",
+      "weak_ptr",
+      // utility
+      "allocator",
+  };
+  m_supported_templates.insert(supported_names.begin(), supported_names.end());
+}
+
+/// Builds a list of scopes that point into the given context.
+///
+/// \param sema The sema that will be using the scopes.
+/// \param ctxt The context that the scope should look into.
+/// \param result A list of scopes. The scopes need to be freed by the caller
+///               (except the TUScope which is owned by the sema).
+static void makeScopes(Sema &sema, DeclContext *ctxt,
+                       std::vector<Scope *> &result) {
+  // FIXME: The result should be a list of unique_ptrs, but the TUScope makes
+  // this currently impossible as it's owned by the Sema.
+
+  if (auto parent = ctxt->getParent()) {
+    makeScopes(sema, parent, result);
+
+    Scope *scope =
+        new Scope(result.back(), Scope::DeclScope, sema.getDiagnostics());
+    scope->setEntity(ctxt);
+    result.push_back(scope);
+  } else
+    result.push_back(sema.TUScope);
+}
+
+/// Uses the Sema to look up the given name in the given DeclContext.
+static std::unique_ptr<LookupResult>
+emulateLookupInCtxt(Sema &sema, llvm::StringRef name, DeclContext *ctxt) {
+  IdentifierInfo &ident = sema.getASTContext().Idents.get(name);
+
+  std::unique_ptr<LookupResult> lookup_result;
+  lookup_result.reset(new LookupResult(sema, DeclarationName(&ident),
+                                       SourceLocation(),
+                                       Sema::LookupOrdinaryName));
+
+  // Usually during parsing we already encountered the scopes we would use. But
+  // here don't have these scopes so we have to emulate the behavior of the
+  // Sema during parsing.
+  std::vector<Scope *> scopes;
+  makeScopes(sema, ctxt, scopes);
+
+  // Now actually perform the lookup with the sema.
+  sema.LookupName(*lookup_result, scopes.back());
+
+  // Delete all the allocated scopes beside the translation unit scope (which
+  // has depth 0).
+  for (Scope *s : scopes)
+    if (s->getDepth() != 0)
+      delete s;
+
+  return lookup_result;
+}
+
+/// Error class for handling problems when finding a certain DeclContext.
+struct MissingDeclContext : public llvm::ErrorInfo<MissingDeclContext> {
+
+  static char ID;
+
+  MissingDeclContext(DeclContext *context, std::string error)
+      : m_context(context), m_error(error) {}
+
+  DeclContext *m_context;
+  std::string m_error;
+
+  void log(llvm::raw_ostream &OS) const override {
+    OS << llvm::formatv("error when reconstructing context of kind {0}:{1}",
+                        m_context->getDeclKindName(), m_error);
+  }
+
+  std::error_code convertToErrorCode() const override {
+    return llvm::inconvertibleErrorCode();
+  }
+};
+
+char MissingDeclContext::ID = 0;
+
+/// Given a foreign decl context, this function finds the equivalent local
+/// decl context in the ASTContext of the given Sema. Potentially deserializes
+/// decls from the 'std' module if necessary.
+static llvm::Expected<DeclContext *>
+getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt) {
+
+  // Inline namespaces don't matter for lookups, so let's skip them.
+  while (foreign_ctxt && foreign_ctxt->isInlineNamespace())
+    foreign_ctxt = foreign_ctxt->getParent();
+
+  // If the foreign context is the TU, we just return the local TU.
+  if (foreign_ctxt->isTranslationUnit())
+    return sema.getASTContext().getTranslationUnitDecl();
+
+  // Recursively find/build the parent DeclContext.
+  llvm::Expected<DeclContext *> parent =
+      getEqualLocalDeclContext(sema, foreign_ctxt->getParent());
+  if (!parent)
+    return parent;
+
+  // We currently only support building namespaces.
+  if (foreign_ctxt->isNamespace()) {
+    NamedDecl *ns = llvm::dyn_cast<NamedDecl>(foreign_ctxt);
+    llvm::StringRef ns_name = ns->getName();
+
+    auto lookup_result = emulateLookupInCtxt(sema, ns_name, *parent);
+    for (NamedDecl *named_decl : *lookup_result) {
+      if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl))
+        return DC->getPrimaryContext();
+    }
+    return llvm::make_error<MissingDeclContext>(
+        foreign_ctxt,
+        "Couldn't find namespace " + ns->getQualifiedNameAsString());
+  }
+
+  return llvm::make_error<MissingDeclContext>(foreign_ctxt, "Unknown context ");
+}
+
+/// Returns true iff tryInstantiateStdTemplate supports instantiating a template
+/// with the given template arguments.
+static bool templateArgsAreSupported(ArrayRef<TemplateArgument> a) {
+  for (const TemplateArgument &arg : a) {
+    switch (arg.getKind()) {
+    case TemplateArgument::Type:
+    case TemplateArgument::Integral:
+      break;
+    default:
+      // TemplateArgument kind hasn't been handled yet.
+      return false;
+    }
+  }
+  return true;
+}
+
+/// Constructor function for Clang declarations. Ensures that the created
+/// declaration is registered with the ASTImporter.
+template <typename T, typename... Args>
+T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) {
+  T *to_d = T::Create(std::forward<Args>(args)...);
+  importer.RegisterImportedDecl(from_d, to_d);
+  return to_d;
+}
+
+llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) {
+  // If we don't have a template to instiantiate, then there is nothing to do.
+  auto td = dyn_cast<ClassTemplateSpecializationDecl>(d);
+  if (!td)
+    return {};
+
+  // We only care about templates in the std namespace.
+  if (!td->getDeclContext()->isStdNamespace())
+    return {};
+
+  // We have a whitelist of supported template names.
+  if (m_supported_templates.find(td->getName()) == m_supported_templates.end())
+    return {};
+
+  // Early check if we even support instantiating this template. We do this
+  // before we import anything into the target AST.
+  auto &foreign_args = td->getTemplateInstantiationArgs();
+  if (!templateArgsAreSupported(foreign_args.asArray()))
+    return {};
+
+  // Find the local DeclContext that corresponds to the DeclContext of our
+  // decl we want to import.
+  auto to_context = getEqualLocalDeclContext(*m_sema, td->getDeclContext());
+  if (!to_context)
+    return {};
+
+  // Look up the template in our local context.
+  std::unique_ptr<LookupResult> lookup =
+      emulateLookupInCtxt(*m_sema, td->getName(), *to_context);
+
+  ClassTemplateDecl *new_class_template = nullptr;
+  for (auto LD : *lookup) {
+    if ((new_class_template = dyn_cast<ClassTemplateDecl>(LD)))
+      break;
+  }
+  if (!new_class_template)
+    return {};
+
+  // Import the foreign template arguments.
+  llvm::SmallVector<TemplateArgument, 4> imported_args;
+
+  // If this logic is changed, also update templateArgsAreSupported.
+  for (const TemplateArgument &arg : foreign_args.asArray()) {
+    switch (arg.getKind()) {
+    case TemplateArgument::Type: {
+      llvm::Expected<QualType> type = m_importer->Import_New(arg.getAsType());
+      if (!type) {
+        llvm::consumeError(type.takeError());
+        return {};
+      }
+      imported_args.push_back(TemplateArgument(*type));
+      break;
+    }
+    case TemplateArgument::Integral: {
+      llvm::APSInt integral = arg.getAsIntegral();
+      llvm::Expected<QualType> type =
+          m_importer->Import_New(arg.getIntegralType());
+      if (!type) {
+        llvm::consumeError(type.takeError());
+        return {};
+      }
+      imported_args.push_back(
+          TemplateArgument(d->getASTContext(), integral, *type));
+      break;
+    }
+    default:
+      assert(false && "templateArgsAreSupported not updated?");
+    }
+  }
+
+  // Find the class template specialization declaration that
+  // corresponds to these arguments.
+  void *InsertPos = nullptr;
+  ClassTemplateSpecializationDecl *result =
+      new_class_template->findSpecialization(imported_args, InsertPos);
+
+  if (result) {
+    // We found an existing specialization in the module that fits our arguments
+    // so we can treat it as the result and register it with the ASTImporter.
+    m_importer->RegisterImportedDecl(d, result);
+    return result;
+  }
+
+  // Instantiate the template.
+  result = createDecl<ClassTemplateSpecializationDecl>(
+      *m_importer, d, m_sema->getASTContext(),
+      new_class_template->getTemplatedDecl()->getTagKind(),
+      new_class_template->getDeclContext(),
+      new_class_template->getTemplatedDecl()->getLocation(),
+      new_class_template->getLocation(), new_class_template, imported_args,
+      nullptr);
+
+  new_class_template->AddSpecialization(result, InsertPos);
+  if (new_class_template->isOutOfLine())
+    result->setLexicalDeclContext(
+        new_class_template->getLexicalDeclContext());
+  return result;
+}
+
+llvm::Optional<Decl *> CxxModuleHandler::Import(Decl *d) {
+  if (!isValid())
+    return {};
+
+  return tryInstantiateStdTemplate(d);
+}
Index: lldb/source/Symbol/ClangASTImporter.cpp
===================================================================
--- lldb/source/Symbol/ClangASTImporter.cpp
+++ lldb/source/Symbol/ClangASTImporter.cpp
@@ -16,6 +16,8 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <memory>
@@ -58,6 +60,8 @@
                                            clang::QualType type) {
   MinionSP minion_sp(GetMinion(dst_ast, src_ast));
 
+  Minion::CxxModuleScope std_scope(*minion_sp, dst_ast);
+
   if (minion_sp)
     return minion_sp->Import(type);
 
@@ -99,6 +103,8 @@
 
   minion_sp = GetMinion(dst_ast, src_ast);
 
+  Minion::CxxModuleScope std_scope(*minion_sp, dst_ast);
+
   if (minion_sp) {
     clang::Decl *result = minion_sp->Import(decl);
 
@@ -557,6 +563,7 @@
 
   MinionSP minion_sp(GetMinion(&decl->getASTContext(), decl_origin.ctx));
 
+  Minion::CxxModuleScope std_scope(*minion_sp, &decl->getASTContext());
   if (minion_sp)
     minion_sp->ImportDefinitionTo(decl, decl_origin.decl);
 
@@ -624,6 +631,8 @@
 
     MinionSP minion_sp(GetMinion(&tag_decl->getASTContext(), decl_origin.ctx));
 
+    Minion::CxxModuleScope std_scope(*minion_sp, &tag_decl->getASTContext());
+
     TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
 
     for (Decl *origin_child_decl : origin_tag_decl->decls()) {
@@ -816,6 +825,23 @@
 
 ClangASTImporter::MapCompleter::~MapCompleter() { return; }
 
+llvm::Expected<Decl *> ClangASTImporter::Minion::ImportImpl(Decl *From) {
+  if (m_std_handler) {
+    llvm::Optional<Decl *> D = m_std_handler->Import(From);
+    if (D) {
+      // Make sure we don't use this decl later to map it back to it's original
+      // decl. The decl the CxxModuleHandler created has nothing to do with
+      // the one from debug info, and linking those two would just cause the
+      // ASTImporter to try 'updating' the module decl with the minimal one from
+      // the debug info.
+      m_decls_to_ignore.insert(*D);
+      return *D;
+    }
+  }
+
+  return ASTImporter::ImportImpl(From);
+}
+
 void ClangASTImporter::Minion::InitDeportWorkQueues(
     std::set<clang::NamedDecl *> *decls_to_deport,
     std::set<clang::NamedDecl *> *decls_already_deported) {
@@ -943,6 +969,11 @@
 
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
 
+  // Some decls shouldn't be tracked here because they were not created by
+  // copying 'from' to 'to'. Just exit early for those.
+  if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end())
+    return clang::ASTImporter::Imported(from, to);
+
   lldb::user_id_t user_id = LLDB_INVALID_UID;
   ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
   if (metadata)
Index: lldb/source/Symbol/ClangASTContext.cpp
===================================================================
--- lldb/source/Symbol/ClangASTContext.cpp
+++ lldb/source/Symbol/ClangASTContext.cpp
@@ -52,6 +52,7 @@
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Frontend/FrontendOptions.h"
 #include "clang/Frontend/LangStandard.h"
+#include "clang/Sema/Sema.h"
 
 #ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
 #undef NDEBUG
@@ -792,6 +793,12 @@
   m_pointer_byte_size = 0;
 }
 
+void ClangASTContext::setSema(Sema *s) {
+  // Ensure that the new sema actually belongs to our ASTContext.
+  assert(s == nullptr || &s->getASTContext() == m_ast_up.get());
+  m_sema = s;
+}
+
 const char *ClangASTContext::GetTargetTriple() {
   return m_target_triple.c_str();
 }
Index: lldb/source/Symbol/CMakeLists.txt
===================================================================
--- lldb/source/Symbol/CMakeLists.txt
+++ lldb/source/Symbol/CMakeLists.txt
@@ -27,6 +27,7 @@
   LocateSymbolFile.cpp
   ObjectFile.cpp
   PostfixExpression.cpp
+  CxxModuleHandler.cpp
   Symbol.cpp
   SymbolContext.cpp
   SymbolFile.cpp
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -967,8 +967,10 @@
                                *Consumer, TU_Complete, completion_consumer));
   m_compiler->setASTConsumer(std::move(Consumer));
 
-  if (ast_context.getLangOpts().Modules)
+  if (ast_context.getLangOpts().Modules) {
     m_compiler->createModuleManager();
+    m_ast_context->setSema(&m_compiler->getSema());
+  }
 
   ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
   if (decl_map) {
@@ -1005,6 +1007,10 @@
         &m_compiler->getSema());
     ParseAST(m_compiler->getSema(), false, false);
   }
+
+  // Make sure we have no pointer to the Sema we are about to destroy.
+  if (ast_context.getLangOpts().Modules)
+    m_ast_context->setSema(nullptr);
   // Destroy the Sema. This is necessary because we want to emulate the
   // original behavior of ParseAST (which also destroys the Sema after parsing).
   m_compiler->setSema(nullptr);
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -193,6 +193,8 @@
   ///     The NameSearchContext to use when filing results.
   virtual void FindExternalVisibleDecls(NameSearchContext &context);
 
+  clang::Sema *getSema();
+
   void SetImportInProgress(bool import_in_progress) {
     m_import_in_progress = import_in_progress;
   }
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -761,6 +761,10 @@
   }
 }
 
+clang::Sema *ClangASTSource::getSema() {
+  return ClangASTContext::GetASTContext(m_ast_context)->getSema();
+}
+
 bool ClangASTSource::IgnoreName(const ConstString name,
                                 bool ignore_all_dollar_names) {
   static const ConstString id_name("id");
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/main.cpp
@@ -0,0 +1,8 @@
+#include <memory>
+
+int main(int argc, char **argv) {
+  std::shared_ptr<int> s(new int);
+  *s = 3;
+  std::weak_ptr<int> w = s;
+  return *s; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/TestWeakPtr.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/TestWeakPtr.py
@@ -0,0 +1,33 @@
+"""
+Test basic std::weak_ptr functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestSharedPtr(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (int)*w.lock()", substrs=['(int) $0 = 3'])
+        self.expect("expr (int)(*w.lock() = 5)", substrs=['(int) $1 = 5'])
+        self.expect("expr (int)*w.lock()", substrs=['(int) $2 = 5'])
+        self.expect("expr w.use_count()", substrs=['(long) $3 = 1'])
+        self.expect("expr w.reset()")
+        self.expect("expr w.use_count()", substrs=['(long) $4 = 0'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/main.cpp
@@ -0,0 +1,12 @@
+#include <memory>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::shared_ptr<Foo> s(new Foo);
+  s->a = 3;
+  std::weak_ptr<Foo> w = s;
+  return s->a; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py
@@ -0,0 +1,33 @@
+"""
+Test std::weak_ptr functionality with a decl from debug info as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDbgInfoContentWeakPtr(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (int)w.lock()->a", substrs=['(int) $0 = 3'])
+        self.expect("expr (int)(w.lock()->a = 5)", substrs=['(int) $1 = 5'])
+        self.expect("expr (int)w.lock()->a", substrs=['(int) $2 = 5'])
+        self.expect("expr w.use_count()", substrs=['(long) $3 = 1'])
+        self.expect("expr w.reset()")
+        self.expect("expr w.use_count()", substrs=['(long) $4 = 0'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/main.cpp
@@ -0,0 +1,6 @@
+#include <vector>
+
+int main(int argc, char **argv) {
+  std::vector<std::vector<int> > a = {{1, 2, 3}, {3, 2, 1}};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/TestVectorOfVectors.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/TestVectorOfVectors.py
@@ -0,0 +1,30 @@
+"""
+Test std::vector functionality when it's contents are vectors.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestVectorOfVectors(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 2'])
+        self.expect("expr (int)a.front().front()", substrs=['(int) $1 = 1'])
+        self.expect("expr (int)a[1][1]", substrs=['(int) $2 = 2'])
+        self.expect("expr (int)a.back().at(0)", substrs=['(int) $3 = 3'])
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/main.cpp
@@ -0,0 +1,10 @@
+#include <vector>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::vector<Foo> a = {{3}, {1}, {2}};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py
@@ -0,0 +1,47 @@
+"""
+Test basic std::vector functionality but with a declaration from
+the debug info (the Foo struct) as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDbgInfoContentVector(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3'])
+        self.expect("expr (int)a[1].a", substrs=['(int) $2 = 1'])
+        self.expect("expr (int)a.back().a", substrs=['(int) $3 = 2'])
+
+        self.expect("expr std::reverse(a.begin(), a.end())")
+        self.expect("expr (int)a.front().a", substrs=['(int) $4 = 2'])
+
+        self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2'])
+        self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3'])
+
+        self.expect("expr a.pop_back()")
+        self.expect("expr (int)a.back().a", substrs=['(int) $7 = 1'])
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $8 = 2'])
+
+        self.expect("expr (int)a.at(0).a", substrs=['(int) $9 = 2'])
+
+        self.expect("expr a.push_back({4})")
+        self.expect("expr (int)a.back().a", substrs=['(int) $10 = 4'])
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $11 = 3'])
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/main.cpp
@@ -0,0 +1,6 @@
+#include <vector>
+
+int main(int argc, char **argv) {
+  std::vector<bool> a = {0, 1, 0, 1};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/TestBoolVector.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/TestBoolVector.py
@@ -0,0 +1,34 @@
+"""
+Test basic std::vector<bool> functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestBoolVector(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 4'])
+        self.expect("expr (bool)a.front()", substrs=['(bool) $1 = false'])
+        self.expect("expr (bool)a[1]", substrs=['(bool) $2 = true'])
+        self.expect("expr (bool)a.back()", substrs=['(bool) $3 = true'])
+
+        self.expect("expr (bool)(*a.begin())", substrs=['(bool) $4 = false'])
+        self.expect("expr (bool)(*a.rbegin())", substrs=['(bool) $5 = true'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/main.cpp
@@ -0,0 +1,6 @@
+#include <vector>
+
+int main(int argc, char **argv) {
+  std::vector<int> a = {3, 1, 2};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/TestBasicVector.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/TestBasicVector.py
@@ -0,0 +1,57 @@
+"""
+Test basic std::vector functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestBasicVector(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front()", substrs=['(int) $1 = 3'])
+        self.expect("expr (int)a[1]", substrs=['(int) $2 = 1'])
+        self.expect("expr (int)a.back()", substrs=['(int) $3 = 2'])
+
+        self.expect("expr std::sort(a.begin(), a.end())")
+        self.expect("expr (int)a.front()", substrs=['(int) $4 = 1'])
+        self.expect("expr (int)a[1]", substrs=['(int) $5 = 2'])
+        self.expect("expr (int)a.back()", substrs=['(int) $6 = 3'])
+
+        self.expect("expr std::reverse(a.begin(), a.end())")
+        self.expect("expr (int)a.front()", substrs=['(int) $7 = 3'])
+        self.expect("expr (int)a[1]", substrs=['(int) $8 = 2'])
+        self.expect("expr (int)a.back()", substrs=['(int) $9 = 1'])
+
+        self.expect("expr (int)(*a.begin())", substrs=['(int) $10 = 3'])
+        self.expect("expr (int)(*a.rbegin())", substrs=['(int) $11 = 1'])
+
+        self.expect("expr a.pop_back()")
+        self.expect("expr (int)a.back()", substrs=['(int) $12 = 2'])
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $13 = 2'])
+
+        self.expect("expr (int)a.at(0)", substrs=['(int) $14 = 3'])
+
+        self.expect("expr a.push_back(4)")
+        self.expect("expr (int)a.back()", substrs=['(int) $15 = 4'])
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $16 = 3'])
+
+        self.expect("expr a.emplace_back(5)")
+        self.expect("expr (int)a.back()", substrs=['(int) $17 = 5'])
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $18 = 4'])
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/main.cpp
@@ -0,0 +1,7 @@
+#include <memory>
+
+int main(int argc, char **argv) {
+  std::shared_ptr<int> s(new int);
+  *s = 3;
+  return *s; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/TestUniquePtr.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/TestUniquePtr.py
@@ -0,0 +1,33 @@
+"""
+Test basic std::unique_ptr functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestUniquePtr(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (int)*s", substrs=['(int) $0 = 3'])
+        self.expect("expr (int)(*s = 5)", substrs=['(int) $1 = 5'])
+        self.expect("expr (int)*s", substrs=['(int) $2 = 5'])
+        self.expect("expr (bool)s", substrs=['(bool) $3 = true'])
+        self.expect("expr s.reset()")
+        self.expect("expr (bool)s", substrs=['(bool) $4 = false'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/main.cpp
@@ -0,0 +1,11 @@
+#include <memory>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::shared_ptr<Foo> s(new Foo);
+  s->a = 3;
+  return s->a; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py
@@ -0,0 +1,33 @@
+"""
+Test std::unique_ptr functionality with a decl from debug info as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestUniquePtrDbgInfoContent(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (int)s->a", substrs=['(int) $0 = 3'])
+        self.expect("expr (int)(s->a = 5)", substrs=['(int) $1 = 5'])
+        self.expect("expr (int)s->a", substrs=['(int) $2 = 5'])
+        self.expect("expr (bool)s", substrs=['(bool) $3 = true'])
+        self.expect("expr s.reset()")
+        self.expect("expr (bool)s", substrs=['(bool) $4 = false'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/main.cpp
@@ -0,0 +1,7 @@
+#include <memory>
+
+int main(int argc, char **argv) {
+  std::shared_ptr<int> s(new int);
+  *s = 3;
+  return *s; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/TestSharedPtr.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/TestSharedPtr.py
@@ -0,0 +1,33 @@
+"""
+Test basic std::shared_ptr functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestSharedPtr(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (int)*s", substrs=['(int) $0 = 3'])
+        self.expect("expr (int)(*s = 5)", substrs=['(int) $1 = 5'])
+        self.expect("expr (int)*s", substrs=['(int) $2 = 5'])
+        self.expect("expr (bool)s", substrs=['(bool) $3 = true'])
+        self.expect("expr s.reset()")
+        self.expect("expr (bool)s", substrs=['(bool) $4 = false'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/main.cpp
@@ -0,0 +1,11 @@
+#include <memory>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::shared_ptr<Foo> s(new Foo);
+  s->a = 3;
+  return s->a; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py
@@ -0,0 +1,33 @@
+"""
+Test std::shared_ptr functionality with a class from debug info as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestSharedPtr(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (int)s->a", substrs=['(int) $0 = 3'])
+        self.expect("expr (int)(s->a = 5)", substrs=['(int) $1 = 5'])
+        self.expect("expr (int)s->a", substrs=['(int) $2 = 5'])
+        self.expect("expr (bool)s", substrs=['(bool) $3 = true'])
+        self.expect("expr s.reset()")
+        self.expect("expr (bool)s", substrs=['(bool) $4 = false'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/main.cpp
@@ -0,0 +1,10 @@
+#include <list>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::list<Foo> a = {{3}, {1}, {2}};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py
@@ -0,0 +1,38 @@
+"""
+Test basic std::list functionality but with a declaration from
+the debug info (the Foo struct) as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDbgInfoContentList(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3'])
+        self.expect("expr (int)a.back().a", substrs=['(int) $2 = 2'])
+
+        self.expect("expr std::reverse(a.begin(), a.end())")
+        self.expect("expr (int)a.front().a", substrs=['(int) $3 = 2'])
+        self.expect("expr (int)a.back().a", substrs=['(int) $4 = 3'])
+
+        self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2'])
+        self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/main.cpp
@@ -0,0 +1,6 @@
+#include <list>
+
+int main(int argc, char **argv) {
+  std::list<int> a = {3, 1, 2};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/TestBasicList.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/TestBasicList.py
@@ -0,0 +1,41 @@
+"""
+Test basic std::list functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestBasicList(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front()", substrs=['(int) $1 = 3'])
+        self.expect("expr (int)a.back()", substrs=['(int) $2 = 2'])
+
+        self.expect("expr a.sort()")
+        self.expect("expr (int)a.front()", substrs=['(int) $3 = 1'])
+        self.expect("expr (int)a.back()", substrs=['(int) $4 = 3'])
+
+        self.expect("expr std::reverse(a.begin(), a.end())")
+        self.expect("expr (int)a.front()", substrs=['(int) $5 = 3'])
+        self.expect("expr (int)a.back()", substrs=['(int) $6 = 1'])
+
+        self.expect("expr (int)(*a.begin())", substrs=['(int) $7 = 3'])
+        self.expect("expr (int)(*a.rbegin())", substrs=['(int) $8 = 1'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/main.cpp
@@ -0,0 +1,10 @@
+#include <forward_list>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::forward_list<Foo> a = {{3}, {1}, {2}};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py
@@ -0,0 +1,31 @@
+"""
+Test std::forward_list functionality with a decl from debug info as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDbgInfoContentForwardList(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)std::distance(a.begin(), a.end())", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front()->a", substrs=['(int) $1 = 3'])
+
+        self.expect("expr (int)(a.begin()->a)", substrs=['(int) $2 = 3'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/main.cpp
@@ -0,0 +1,6 @@
+#include <forward_list>
+
+int main(int argc, char **argv) {
+  std::forward_list<int> a = {3, 1, 2};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/TestBasicForwardList.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/TestBasicForwardList.py
@@ -0,0 +1,34 @@
+"""
+Test basic std::forward_list functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestBasicList(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)std::distance(a.begin(), a.end())", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front()", substrs=['(int) $1 = 3'])
+
+        self.expect("expr a.sort()")
+        self.expect("expr (int)a.front()", substrs=['(int) $2 = 1'])
+
+        self.expect("expr (int)(*a.begin())", substrs=['(int) $3 = 1'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/main.cpp
@@ -0,0 +1,10 @@
+#include <deque>
+
+struct Foo {
+  int a;
+};
+
+int main(int argc, char **argv) {
+  std::deque<Foo> a = {{3}, {1}, {2}};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py
@@ -0,0 +1,37 @@
+"""
+Test std::deque functionality with a decl from dbg info as content.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDbgInfoContentDeque(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front()->a", substrs=['(int) $1 = 3'])
+        self.expect("expr (int)a.back()->a", substrs=['(int) $2 = 2'])
+
+        self.expect("expr std::reverse(a.begin(), a.end())")
+        self.expect("expr (int)a.front()->a", substrs=['(int) $3 = 2'])
+        self.expect("expr (int)a.back()->a", substrs=['(int) $4 = 3'])
+
+        self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2'])
+        self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/main.cpp
@@ -0,0 +1,6 @@
+#include <deque>
+
+int main(int argc, char **argv) {
+  std::deque<int> a = {3, 1, 2};
+  return 0; // Set break point at this line.
+}
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/TestBasicDeque.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/TestBasicDeque.py
@@ -0,0 +1,41 @@
+"""
+Test basic std::list functionality.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestBasicDeque(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    # FIXME: This should work on more setups, so remove these
+    # skipIf's in the future.
+    @add_test_categories(["libc++"])
+    @skipIf(compiler=no_match("clang"))
+    @skipIf(oslist=no_match(["linux"]))
+    @skipIf(debug_info=no_match(["dwarf"]))
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+        self.runCmd("settings set target.import-std-module true")
+
+        self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3'])
+        self.expect("expr (int)a.front()", substrs=['(int) $1 = 3'])
+        self.expect("expr (int)a.back()", substrs=['(int) $2 = 2'])
+
+        self.expect("expr std::sort(a.begin(), a.end())")
+        self.expect("expr (int)a.front()", substrs=['(int) $3 = 1'])
+        self.expect("expr (int)a.back()", substrs=['(int) $4 = 3'])
+
+        self.expect("expr std::reverse(a.begin(), a.end())")
+        self.expect("expr (int)a.front()", substrs=['(int) $5 = 3'])
+        self.expect("expr (int)a.back()", substrs=['(int) $6 = 1'])
+
+        self.expect("expr (int)(*a.begin())", substrs=['(int) $7 = 3'])
+        self.expect("expr (int)(*a.rbegin())", substrs=['(int) $8 = 1'])
+
Index: lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+USE_LIBCPP := 1
+CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS)
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
Index: lldb/include/lldb/Symbol/CxxModuleHandler.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Symbol/CxxModuleHandler.h
@@ -0,0 +1,65 @@
+//===-- CxxModuleHandler.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CxxModuleHandler_h_
+#define liblldb_CxxModuleHandler_h_
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace lldb_private {
+
+/// Handles importing decls into an ASTContext with an attached C++ module.
+///
+/// This class searches a C++ module (which must be attached to the target
+/// ASTContext) for an equivalent decl to the one that should be imported.
+/// If the decl that is found in the module is a suitable replacement
+/// for the decl that should be imported, the module decl will be treated as
+/// the result of the import process.
+///
+/// If the Decl that should be imported is a template specialization
+/// that doesn't exist yet in the target ASTContext (e.g. `std::vector<int>`),
+/// then this class tries to create the template specialization in the target
+/// ASTContext. This is only possible if the CxxModuleHandler can determine
+/// that instantiating this template is safe to do, e.g. because the target
+/// decl is a container class from the STL.
+class CxxModuleHandler {
+  /// The ASTImporter that should be used to import any Decls which aren't
+  /// directly handled by this class itself.
+  clang::ASTImporter *m_importer = nullptr;
+
+  /// The Sema instance of the target ASTContext.
+  clang::Sema *m_sema = nullptr;
+
+  /// List of template names this class currently supports. These are the
+  /// template names inside the 'std' namespace such as 'vector' or 'list'.
+  llvm::StringSet<> m_supported_templates;
+
+  /// Tries to manually instantiate the given foreign template in the target
+  /// context (designated by m_sema).
+  llvm::Optional<clang::Decl *> tryInstantiateStdTemplate(clang::Decl *d);
+
+public:
+  CxxModuleHandler() = default;
+  CxxModuleHandler(clang::ASTImporter &importer, clang::ASTContext *target);
+
+  /// Attempts to import the given decl into the target ASTContext by
+  /// deserializing it from the 'std' module. This function returns a Decl if a
+  /// Decl has been deserialized from the 'std' module. Otherwise this function
+  /// returns nothing.
+  llvm::Optional<clang::Decl *> Import(clang::Decl *d);
+
+  /// Returns true iff this instance is capable of importing any declarations
+  /// in the target ASTContext.
+  bool isValid() const { return m_sema != nullptr; }
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CxxModuleHandler_h_
Index: lldb/include/lldb/Symbol/ClangASTImporter.h
===================================================================
--- lldb/include/lldb/Symbol/ClangASTImporter.h
+++ lldb/include/lldb/Symbol/ClangASTImporter.h
@@ -23,6 +23,7 @@
 
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/CxxModuleHandler.h"
 #include "lldb/lldb-types.h"
 
 #include "llvm/ADT/DenseMap.h"
@@ -243,6 +244,41 @@
           m_decls_to_deport(nullptr), m_decls_already_deported(nullptr),
           m_master(master), m_source_ctx(source_ctx) {}
 
+    /// Scope guard that attaches a CxxModuleHandler to a Minion and deattaches
+    /// it at the end of the scope. Supports being used multiple times on the
+    /// same Minion instance in nested scopes.
+    class CxxModuleScope {
+      /// The handler we attach to the Minion.
+      CxxModuleHandler m_handler;
+      /// The Minion we are supposed to attach the handler to.
+      Minion &m_minion;
+      /// True iff we attached the handler to the Minion.
+      bool m_valid = false;
+
+    public:
+      CxxModuleScope(Minion &minion, clang::ASTContext *dst_ctx)
+          : m_minion(minion) {
+        // If the minion doesn't have a CxxModuleHandler yet, create one
+        // and attach it.
+        if (!minion.m_std_handler) {
+          m_handler = CxxModuleHandler(minion, dst_ctx);
+          m_valid = true;
+          minion.m_std_handler = &m_handler;
+        }
+      }
+      ~CxxModuleScope() {
+        if (m_valid) {
+          // Make sure no one messed with the handler we placed.
+          assert(m_minion.m_std_handler == &m_handler);
+          m_minion.m_std_handler = nullptr;
+        }
+      }
+    };
+
+  protected:
+    llvm::Expected<clang::Decl *> ImportImpl(clang::Decl *From) override;
+
+  public:
     // A call to "InitDeportWorkQueues" puts the minion into deport mode.
     // In deport mode, every copied Decl that could require completion is
     // recorded and placed into the decls_to_deport set.
@@ -266,10 +302,16 @@
 
     clang::Decl *GetOriginalDecl(clang::Decl *To) override;
 
+    /// Decls we should ignore when mapping decls back to their original
+    /// ASTContext. Used by the CxxModuleHandler to mark declarations that
+    /// were created from the 'std' C++ module to prevent that the Importer
+    /// tries to sync them with the broken equivalent in the debug info AST.
+    std::set<clang::Decl *> m_decls_to_ignore;
     std::set<clang::NamedDecl *> *m_decls_to_deport;
     std::set<clang::NamedDecl *> *m_decls_already_deported;
     ClangASTImporter &m_master;
     clang::ASTContext *m_source_ctx;
+    CxxModuleHandler *m_std_handler = nullptr;
   };
 
   typedef std::shared_ptr<Minion> MinionSP;
Index: lldb/include/lldb/Symbol/ClangASTContext.h
===================================================================
--- lldb/include/lldb/Symbol/ClangASTContext.h
+++ lldb/include/lldb/Symbol/ClangASTContext.h
@@ -104,6 +104,9 @@
 
   clang::TargetInfo *getTargetInfo();
 
+  void setSema(clang::Sema *s);
+  clang::Sema *getSema() { return m_sema; }
+
   void Clear();
 
   const char *GetTargetTriple();
@@ -997,6 +1000,10 @@
     uint32_t                                        m_pointer_byte_size;
     bool                                            m_ast_owned;
     bool                                            m_can_evaluate_expressions;
+    // The sema associated that is currently used to build this ASTContext.
+    // May be null if we are already done parsing this ASTContext or the
+    // ASTContext wasn't created by parsing source code.
+    clang::Sema *                                   m_sema = nullptr;
   // clang-format on
 private:
   // For ClangASTContext only
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to