diff options
7 files changed, 88 insertions, 4 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/Makefile new file mode 100644 index 00000000000..533ff707023 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/Makefile @@ -0,0 +1,9 @@ +# We don't have any standard include directories, so we can't +# parse the test_common.h header we usually inject as it includes +# system headers. +NO_TEST_COMMON_H := 1 + +CXXFLAGS_EXTRAS = -I $(SRCDIR)/root/usr/include/c++/v1/ -I $(SRCDIR)/root/usr/include/ -nostdinc -nostdinc++ -DENABLE_STD_CONTENT=1 +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/TestEmptyStdModule.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/TestEmptyStdModule.py new file mode 100644 index 00000000000..94af997298f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/TestEmptyStdModule.py @@ -0,0 +1,35 @@ +""" +Test that LLDB doesn't crash if the std module we load is empty. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import os + +class ImportStdModule(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(compiler=no_match("clang")) + def test(self): + self.build() + + sysroot = os.path.join(os.getcwd(), "root") + + # Set the sysroot. + self.runCmd("platform select --sysroot '" + sysroot + "' host", CURRENT_EXECUTABLE_SET) + + 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.runCmd("log enable lldb expr") + + # Use the typedef that is only defined in our 'empty' module. If this fails, then LLDB + # somehow figured out the correct define for the header and compiled the right + # standard module that actually contains the std::vector template. + self.expect("expr MissingContent var = 3; var", substrs=['$0 = 3']) + # Try to access our mock std::vector. This should fail but not crash LLDB as the + # std::vector template should be missing from the std module. + self.expect("expr (size_t)v.size()", substrs=["Couldn't lookup symbols"], error=True) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/main.cpp new file mode 100644 index 00000000000..b01fe1a7853 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/main.cpp @@ -0,0 +1,8 @@ +#include <algorithm> + +int main(int argc, char **argv) { + // Makes sure we have the mock libc headers in the debug information. + libc_struct s; + std::vector<int> v; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/c++/v1/algorithm b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/c++/v1/algorithm new file mode 100644 index 00000000000..a77c3d86739 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/c++/v1/algorithm @@ -0,0 +1,22 @@ +// This is only defined when building, but LLDB is missing this flag when loading the standard +// library module so the actual contents of the module are missing. +#ifdef ENABLE_STD_CONTENT + +#include "libc_header.h" + +namespace std { + inline namespace __1 { + // Pretend to be a std::vector template we need to instantiate + // in LLDB. + template<typename T> + struct vector { T i; int size() { return 2; } }; + } +} +#else +// Unused typedef we can use to check that we actually loaded +// an empty module. Will be missing if LLDB somehow can get the +// ENABLE_STD_CONTENT define right and break this test silently +// (as with the define the module isn't empty anymore and this +// test always succeeds). +typedef int MissingContent; +#endif // ENABLE_STD_CONTENT diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/c++/v1/module.modulemap b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/c++/v1/module.modulemap new file mode 100644 index 00000000000..0eb48492a65 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/c++/v1/module.modulemap @@ -0,0 +1,3 @@ +module std { + module "algorithm" { header "algorithm" export * } +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/libc_header.h b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/libc_header.h new file mode 100644 index 00000000000..47525c9db34 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/empty-module/root/usr/include/libc_header.h @@ -0,0 +1 @@ +struct libc_struct {}; diff --git a/lldb/source/Symbol/CxxModuleHandler.cpp b/lldb/source/Symbol/CxxModuleHandler.cpp index 68a2aab80bd..19e80e5036b 100644 --- a/lldb/source/Symbol/CxxModuleHandler.cpp +++ b/lldb/source/Symbol/CxxModuleHandler.cpp @@ -175,6 +175,8 @@ T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) { } llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); + // If we don't have a template to instiantiate, then there is nothing to do. auto td = dyn_cast<ClassTemplateSpecializationDecl>(d); if (!td) @@ -196,9 +198,15 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { // 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) + llvm::Expected<DeclContext *> to_context = + getEqualLocalDeclContext(*m_sema, td->getDeclContext()); + if (!to_context) { + LLDB_LOG_ERROR(log, to_context.takeError(), + "Got error while searching equal local DeclContext for decl " + "'{1}':\n{0}", + td->getName()); return {}; + } // Look up the template in our local context. std::unique_ptr<LookupResult> lookup = @@ -215,8 +223,6 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { // Import the foreign template arguments. llvm::SmallVector<TemplateArgument, 4> imported_args; - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - // If this logic is changed, also update templateArgsAreSupported. for (const TemplateArgument &arg : foreign_args.asArray()) { switch (arg.getKind()) { |