summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h7
-rw-r--r--lldb/include/lldb/Symbol/ClangASTImporter.h42
-rw-r--r--lldb/include/lldb/Symbol/CxxModuleHandler.h65
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/TestBasicDeque.py41
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/main.cpp6
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py37
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/main.cpp10
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/TestBasicForwardList.py34
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/main.cpp6
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py31
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/main.cpp10
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/TestBasicList.py41
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/main.cpp6
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py38
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/main.cpp10
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py33
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/main.cpp11
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/TestSharedPtr.py33
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/main.cpp7
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py33
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/main.cpp11
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/TestUniquePtr.py33
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/main.cpp7
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/TestBasicVector.py57
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/main.cpp6
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/TestBoolVector.py34
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/main.cpp6
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py47
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/main.cpp10
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/TestVectorOfVectors.py30
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/main.cpp6
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py33
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/main.cpp12
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/TestWeakPtr.py33
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/main.cpp8
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp4
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp8
-rw-r--r--lldb/source/Symbol/CMakeLists.txt1
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp7
-rw-r--r--lldb/source/Symbol/ClangASTImporter.cpp31
-rw-r--r--lldb/source/Symbol/CxxModuleHandler.cpp278
58 files changed, 1244 insertions, 1 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index 0c76a59f5a9..677359cecf9 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -104,6 +104,9 @@ public:
clang::TargetInfo *getTargetInfo();
+ void setSema(clang::Sema *s);
+ clang::Sema *getSema() { return m_sema; }
+
void Clear();
const char *GetTargetTriple();
@@ -997,6 +1000,10 @@ protected:
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
diff --git a/lldb/include/lldb/Symbol/ClangASTImporter.h b/lldb/include/lldb/Symbol/ClangASTImporter.h
index f374125b39b..422aedd32fb 100644
--- a/lldb/include/lldb/Symbol/ClangASTImporter.h
+++ b/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 @@ private:
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 @@ private:
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;
diff --git a/lldb/include/lldb/Symbol/CxxModuleHandler.h b/lldb/include/lldb/Symbol/CxxModuleHandler.h
new file mode 100644
index 00000000000..f4aef3666ec
--- /dev/null
+++ b/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_
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/TestBasicDeque.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/TestBasicDeque.py
new file mode 100644
index 00000000000..0ede19e8350
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-basic/main.cpp
new file mode 100644
index 00000000000..5bed55674bf
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py
new file mode 100644
index 00000000000..4df280f32d1
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/deque-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..f8fd1fb2dd9
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/TestBasicForwardList.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/TestBasicForwardList.py
new file mode 100644
index 00000000000..5cbc73d34c0
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-basic/main.cpp
new file mode 100644
index 00000000000..4f5e30f0629
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py
new file mode 100644
index 00000000000..6e7be3ec00f
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/forward_list-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..b1ffc4b24cd
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/TestBasicList.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/TestBasicList.py
new file mode 100644
index 00000000000..154c8ed7bd0
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-basic/main.cpp
new file mode 100644
index 00000000000..e54719a02fb
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py
new file mode 100644
index 00000000000..713ec1abb85
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/list-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..3cfb35f8c6b
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py
new file mode 100644
index 00000000000..1e4309f6795
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..73664f1c83a
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/TestSharedPtr.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/TestSharedPtr.py
new file mode 100644
index 00000000000..6f1e7b12d1f
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/shared_ptr/main.cpp
new file mode 100644
index 00000000000..cb81754087f
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py
new file mode 100644
index 00000000000..c321d8022e1
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..73664f1c83a
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/TestUniquePtr.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/TestUniquePtr.py
new file mode 100644
index 00000000000..295ec512327
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/unique_ptr/main.cpp
new file mode 100644
index 00000000000..cb81754087f
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/TestBasicVector.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/TestBasicVector.py
new file mode 100644
index 00000000000..deaf8f0cb75
--- /dev/null
+++ b/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'])
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-basic/main.cpp
new file mode 100644
index 00000000000..edf130d4748
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/TestBoolVector.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/TestBoolVector.py
new file mode 100644
index 00000000000..0ab52695faf
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-bool/main.cpp
new file mode 100644
index 00000000000..9554401cf50
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py
new file mode 100644
index 00000000000..c89265f2cd3
--- /dev/null
+++ b/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'])
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..24c3fec75d2
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/TestVectorOfVectors.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/TestVectorOfVectors.py
new file mode 100644
index 00000000000..2b82e1a039a
--- /dev/null
+++ b/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'])
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/vector-of-vectors/main.cpp
new file mode 100644
index 00000000000..b5ada909e43
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py
new file mode 100644
index 00000000000..0acd54e803c
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr-dbg-info-content/main.cpp
new file mode 100644
index 00000000000..d2c5a6258a5
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/Makefile
new file mode 100644
index 00000000000..01718d86aa7
--- /dev/null
+++ b/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
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/TestWeakPtr.py b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/TestWeakPtr.py
new file mode 100644
index 00000000000..6b8b9ceb7aa
--- /dev/null
+++ b/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'])
+
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/import-std-module/weak_ptr/main.cpp
new file mode 100644
index 00000000000..13479eb9496
--- /dev/null
+++ b/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.
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 8d96dbbef93..e67477440f3 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -761,6 +761,10 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
}
}
+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");
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 09d08d545e2..624c86a5174 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -193,6 +193,8 @@ public:
/// 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;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index d193b9688c4..925ece5e9cb 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -967,8 +967,10 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
*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 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
&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);
diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt
index d212158ceeb..bbfa586b90d 100644
--- a/lldb/source/Symbol/CMakeLists.txt
+++ b/lldb/source/Symbol/CMakeLists.txt
@@ -27,6 +27,7 @@ add_lldb_library(lldbSymbol
LocateSymbolFile.cpp
ObjectFile.cpp
PostfixExpression.cpp
+ CxxModuleHandler.cpp
Symbol.cpp
SymbolContext.cpp
SymbolFile.cpp
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 9a8de48c1c9..a9ccc31df5a 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/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 @@ void ClangASTContext::Clear() {
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();
}
diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp
index d4560e3d981..29c9d0f5469 100644
--- a/lldb/source/Symbol/ClangASTImporter.cpp
+++ b/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 ClangASTImporter::CopyType(clang::ASTContext *dst_ast,
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 @@ clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast,
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 @@ bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
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 @@ bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
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 @@ void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast,
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 @@ void ClangASTImporter::Minion::Imported(clang::Decl *from,
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)
diff --git a/lldb/source/Symbol/CxxModuleHandler.cpp b/lldb/source/Symbol/CxxModuleHandler.cpp
new file mode 100644
index 00000000000..d17b8d360f6
--- /dev/null
+++ b/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);
+}
OpenPOWER on IntegriCloud