teemperor created this revision.
teemperor added reviewers: aprantl, shafik, jingham.
teemperor added a project: C++ modules in LLDB.
Herald added subscribers: lldb-commits, jdoerfert, abidh, mgrang, mgorny.
Herald added a reviewer: martong.
Herald added a reviewer: serge-sans-paille.
Herald added a project: LLDB.
teemperor added a parent revision: D59485: [ASTImporter] Allow adding a import 
strategy to the ASTImporter.
Herald added a subscriber: rnkovacs.

This patch is a follow-up for D58125 <https://reviews.llvm.org/D58125>. It 
implements the manual instantiation and merging of 'std' templates like
`std::vector` and `std::shared_ptr` with information from the debug info AST. 
This (finally) allows using these classes
in the expression evaluator like every other class (i.e. things like 
`vec.size()` and shared_ptr debugging now works, yay!).

The main logic is the `StdModuleHandler` which intercept the ASTImporter import 
process and replaces any `std` decls
by decls from the C++ module. The decls from the C++ module are "imported" by 
just deserializing them directly in
the expression evaluation context. This is mostly because we don't want to rely 
on the ASTImporter to correctly import
these declarations.

This patch doesn't contain the automatic desugaring for result variables. This 
means that if you call for example
`size` of `std::vector` you maybe get some very verbose typedef'd type as the 
variable type, e.g.
`std::vector<int, std::allocator<int>>::value_type`.

This is not only unreadable, it also means that our ASTImporter has to import 
all these types and associated
decls into the persisent variable context. This currently usually leads to some 
assertion getting triggered
in Clang when the ASTImporter either makes a mistake during importing or our 
debug info AST is inconsitent.
The current workaround I use in the tests is to just cast the result to it's 
actual type (e.g. `size_t` or `int`) to prevent
the ASTImporter from having to handle all these complicated decls.

The automatic desugaring will be a future patch because I'm not happy yet with 
the current code for that and because
I anticipate that this will be a controversial patch.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D59537

Files:
  lldb/include/lldb/Symbol/ClangASTContext.h
  lldb/include/lldb/Symbol/ClangASTImporter.h
  lldb/include/lldb/Symbol/StdModuleHandler.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/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/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/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/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/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/StdModuleHandler.cpp

Index: lldb/source/Symbol/StdModuleHandler.cpp
===================================================================
--- /dev/null
+++ lldb/source/Symbol/StdModuleHandler.cpp
@@ -0,0 +1,275 @@
+//===-- StdModuleHandler.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/StdModuleHandler.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/Support/Error.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+StdModuleHandler::StdModuleHandler(ASTImporter &importer, Listener *listener,
+                                   ASTContext *target)
+    : m_importer(importer), m_listener(listener),
+      m_sema(ClangASTContext::GetASTContext(target)->getSema()) {
+  if (m_sema && m_importer.getStrategy() == nullptr)
+    m_importer.setStrategy(this);
+
+  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());
+}
+
+StdModuleHandler::~StdModuleHandler() {
+  // Remove this from the ASTImporter (unless someone else has subscribed,
+  // which can happen if we have nested calls that attach StdModuleHandlers).
+  if (m_sema && m_importer.getStrategy() == this)
+    m_importer.setStrategy(nullptr);
+}
+
+/// 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 its 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;
+}
+
+llvm::Optional<Decl *> StdModuleHandler::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: {
+      QualType our_type = m_importer.Import(arg.getAsType());
+      imported_args.push_back(TemplateArgument(our_type));
+      break;
+    }
+    case TemplateArgument::Integral: {
+      llvm::APSInt integral = arg.getAsIntegral();
+      QualType our_type = m_importer.Import(arg.getIntegralType());
+      imported_args.push_back(
+          TemplateArgument(d->getASTContext(), integral, our_type));
+      break;
+    }
+    default:
+      assert(false && "templateArgsAreSupported not updated?");
+    }
+  }
+
+  // Find the class template specialization declaration that
+  // corresponds to these arguments.
+  void *InsertPos = nullptr;
+  ClassTemplateSpecializationDecl *found_decl =
+      new_class_template->findSpecialization(imported_args, InsertPos);
+  if (!found_decl) {
+    // Instantiate the template.
+    found_decl = ClassTemplateSpecializationDecl::Create(
+        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(found_decl, InsertPos);
+    if (new_class_template->isOutOfLine())
+      found_decl->setLexicalDeclContext(
+          new_class_template->getLexicalDeclContext());
+  }
+
+  if (found_decl)
+    return found_decl;
+
+  return {};
+}
+
+llvm::Optional<Decl *> StdModuleHandler::Import(ASTImporter &importer,
+                                                Decl *d) {
+  if (!isValid())
+    return {};
+
+  llvm::Optional<Decl *> result = tryInstantiateStdTemplate(d);
+
+  // Inform the listener if we have one that we imported a decl from the 'std'
+  // module.
+  if (m_listener && result)
+    m_listener->importedDeclFromStdModule(*result);
+
+  return result;
+}
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));
 
+  StdModuleHandler spec(*minion_sp, minion_sp.get(), dst_ast);
+
   if (minion_sp)
     return minion_sp->Import(type);
 
@@ -99,6 +103,8 @@
 
   minion_sp = GetMinion(dst_ast, src_ast);
 
+  StdModuleHandler spec(*minion_sp, minion_sp.get(), 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));
 
+  StdModuleHandler spec(*minion_sp, minion_sp.get(), &decl->getASTContext());
   if (minion_sp)
     minion_sp->ImportDefinitionTo(decl, decl_origin.decl);
 
@@ -624,6 +631,9 @@
 
     MinionSP minion_sp(GetMinion(&tag_decl->getASTContext(), decl_origin.ctx));
 
+    StdModuleHandler spec(*minion_sp, minion_sp.get(),
+                          &tag_decl->getASTContext());
+
     TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
 
     for (Decl *origin_child_decl : origin_tag_decl->decls()) {
@@ -943,6 +953,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)
@@ -1114,3 +1129,10 @@
 
   return const_cast<clang::Decl *>(iter->second.decl);
 }
+
+void ClangASTImporter::Minion::importedDeclFromStdModule(Decl *d) {
+  // The StdModuleHandler is letting us know that it created this decl. Keep
+  // track of that decl for when we try to map it back to an ASTContext in
+  // Minion::Imported.
+  m_decls_to_ignore.insert(d);
+}
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
@@ -794,6 +795,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
@@ -26,6 +26,7 @@
   LineTable.cpp
   LocateSymbolFile.cpp
   ObjectFile.cpp
+  StdModuleHandler.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
@@ -970,8 +970,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) {
@@ -1008,6 +1010,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
@@ -217,6 +217,8 @@
   //------------------------------------------------------------------
   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
@@ -763,6 +763,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/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/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/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-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-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/StdModuleHandler.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Symbol/StdModuleHandler.h
@@ -0,0 +1,67 @@
+//===-- StdModuleHandler.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_StdModuleHandler_h_
+#define liblldb_StdModuleHandler_h_
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace lldb_private {
+
+/// Handles importing declarations that are also in the 'std' C++ module.
+///
+/// In general this class expects that the target ASTContext of our import
+/// process is setup to use C++ modules and has the 'std' module attached.
+class StdModuleHandler : public clang::ImportStrategy {
+  clang::ASTImporter &m_importer;
+
+public:
+  struct Listener {
+    virtual ~Listener() = default;
+    /// Called for every decl that has been imported from the 'std' module
+    /// instead of being imported by the ASTImporter from the debug info AST.
+    virtual void importedDeclFromStdModule(clang::Decl *d) = 0;
+  };
+
+private:
+  /// The listener we should notify when we deserialize decls from the 'std'
+  /// module.
+  Listener *m_listener = nullptr;
+
+  clang::Sema *m_sema;
+  /// 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;
+
+  bool isValid() const { return m_sema != nullptr; }
+
+  /// Tries to manually instantiate the given foreign declaration in the target
+  /// context (designated by m_sema).
+  llvm::Optional<clang::Decl *> tryInstantiateStdTemplate(clang::Decl *d);
+
+public:
+  StdModuleHandler(clang::ASTImporter &importer, Listener *listener,
+                   clang::ASTContext *target);
+  ~StdModuleHandler() override;
+
+  /// 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. Implements the ImportStrategy interface, so it will be
+  /// called from the ASTImporter.
+  llvm::Optional<clang::Decl *> Import(clang::ASTImporter &importer,
+                                       clang::Decl *d) override;
+
+  void setListener(Listener *l) { m_listener = l; }
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_StdModuleHandler_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/StdModuleHandler.h"
 #include "lldb/lldb-types.h"
 
 #include "llvm/ADT/DenseMap.h"
@@ -234,7 +235,7 @@
 
   typedef std::map<const clang::Decl *, DeclOrigin> OriginMap;
 
-  class Minion : public clang::ASTImporter {
+  class Minion : public clang::ASTImporter, public StdModuleHandler::Listener {
   public:
     Minion(ClangASTImporter &master, clang::ASTContext *target_ctx,
            clang::ASTContext *source_ctx)
@@ -266,6 +267,13 @@
 
     clang::Decl *GetOriginalDecl(clang::Decl *To) override;
 
+    void importedDeclFromStdModule(clang::Decl *d) override;
+
+    /// Decls we should ignore when mapping decls back to their original
+    /// ASTContext. Used by the StdModuleHandler 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;
Index: lldb/include/lldb/Symbol/ClangASTContext.h
===================================================================
--- lldb/include/lldb/Symbol/ClangASTContext.h
+++ lldb/include/lldb/Symbol/ClangASTContext.h
@@ -110,6 +110,9 @@
 
   clang::TargetInfo *getTargetInfo();
 
+  void setSema(clang::Sema *s);
+  clang::Sema *getSema() { return m_sema; }
+
   void Clear();
 
   const char *GetTargetTriple();
@@ -1053,6 +1056,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:
   //------------------------------------------------------------------
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to