Index: lldb/trunk/include/lldb/Symbol/CompileUnit.h =================================================================== --- lldb/trunk/include/lldb/Symbol/CompileUnit.h +++ lldb/trunk/include/lldb/Symbol/CompileUnit.h @@ -225,6 +225,14 @@ DebugMacros *GetDebugMacros(); + /// Apply a lambda to each external lldb::Module referenced by this + /// compilation unit. Recursively also descends into the referenced external + /// modules of any encountered compilation unit. + /// + /// \param[in] lambda + /// The lambda that should be applied to every module. + void ForEachExternalModule(llvm::function_ref f); + /// Get the compile unit's support file list. /// /// The support file list is used by the line table, and any objects that Index: lldb/trunk/include/lldb/Symbol/SymbolFile.h =================================================================== --- lldb/trunk/include/lldb/Symbol/SymbolFile.h +++ lldb/trunk/include/lldb/Symbol/SymbolFile.h @@ -122,6 +122,9 @@ virtual size_t ParseFunctions(CompileUnit &comp_unit) = 0; virtual bool ParseLineTable(CompileUnit &comp_unit) = 0; virtual bool ParseDebugMacros(CompileUnit &comp_unit) = 0; + virtual void + ForEachExternalModule(CompileUnit &comp_unit, + llvm::function_ref f) {} virtual bool ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) = 0; virtual size_t ParseTypes(CompileUnit &comp_unit) = 0; Index: lldb/trunk/include/lldb/Target/Platform.h =================================================================== --- lldb/trunk/include/lldb/Target/Platform.h +++ lldb/trunk/include/lldb/Target/Platform.h @@ -257,19 +257,6 @@ virtual bool SetRemoteWorkingDirectory(const FileSpec &working_dir); - /// Retrieve the system include directories on this platform for the - /// given language. - /// - /// \param[in] lang - /// The language for which the include directories should be queried. - /// - /// \param[out] directories - /// The include directories for this system. - virtual std::vector - GetSystemIncludeDirectories(lldb::LanguageType lang) { - return {}; - } - virtual UserIDResolver &GetUserIDResolver() = 0; /// Locate a file for a platform. Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/TestImportStdModule.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/TestImportStdModule.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/TestImportStdModule.py @@ -11,12 +11,8 @@ 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() @@ -34,12 +30,8 @@ self.expect("expr char char_a = 'b'; char char_b = 'a'; std::swap(char_a, char_b); char_a", substrs=["(char) $3 = 'a'"]) - # 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_non_cpp_language(self): self.build() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py @@ -16,12 +16,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/TestBasicDeque.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/TestBasicDeque.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/TestBasicDeque.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/TestBasicForwardList.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/TestBasicForwardList.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/TestBasicForwardList.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/TestBasicList.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/TestBasicList.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/TestBasicList.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py @@ -11,12 +11,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/TestMissingStdModule.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/TestMissingStdModule.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/TestMissingStdModule.py @@ -17,12 +17,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/TestQueue.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/TestQueue.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/TestQueue.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/TestSharedPtr.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/TestSharedPtr.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/TestSharedPtr.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/TestStack.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/TestStack.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/TestStack.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/Makefile @@ -3,7 +3,6 @@ # system headers. NO_TEST_COMMON_H := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXXFLAGS += -I $(SRCDIR)/root/usr/include/c++/include/ -I $(SRCDIR)/root/usr/include/ -nostdinc -nostdinc++ -nostdlib++ CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/TestStdModuleSysroot.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/TestStdModuleSysroot.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/TestStdModuleSysroot.py @@ -11,11 +11,7 @@ mydir = TestBase.compute_mydir(__file__) - # FIXME: This should work on more setups, so remove these - # skipIf's in the future. @skipIf(compiler=no_match("clang")) - @skipIf(oslist=no_match(["linux"])) - @skipIf(debug_info=no_match(["dwarf"])) def test(self): self.build() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/TestUniquePtr.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/TestUniquePtr.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/TestUniquePtr.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/TestBasicVector.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/TestBasicVector.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/TestBasicVector.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/TestBoolVector.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/TestBoolVector.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/TestBoolVector.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py @@ -11,12 +11,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectors.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectors.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectors.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/Makefile @@ -1,4 +1,3 @@ USE_LIBCPP := 1 -CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) CXX_SOURCES := main.cpp include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/TestWeakPtr.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/TestWeakPtr.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/TestWeakPtr.py @@ -10,12 +10,8 @@ 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() Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/CMakeLists.txt @@ -19,6 +19,7 @@ ClangPersistentVariables.cpp ClangUserExpression.cpp ClangUtilityFunction.cpp + CppModuleConfiguration.cpp IRForTarget.cpp IRDynamicChecks.cpp Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -241,38 +241,23 @@ search_opts.ModuleCachePath = module_cache.str(); LLDB_LOG(log, "Using module cache path: {0}", module_cache.c_str()); - FileSpec clang_resource_dir = GetClangResourceDir(); - std::string resource_dir = clang_resource_dir.GetPath(); - if (FileSystem::Instance().IsDirectory(resource_dir)) { - search_opts.ResourceDir = resource_dir; - std::string resource_include = resource_dir + "/include"; - search_opts.AddPath(resource_include, frontend::System, false, true); - - LLDB_LOG(log, "Added resource include dir: {0}", resource_include); - } + search_opts.ResourceDir = GetClangResourceDir().GetPath(); search_opts.ImplicitModuleMaps = true; - - std::vector system_include_directories = - target_sp->GetPlatform()->GetSystemIncludeDirectories( - lldb::eLanguageTypeC_plus_plus); - - for (const std::string &include_dir : system_include_directories) { - search_opts.AddPath(include_dir, frontend::System, false, true); - - LLDB_LOG(log, "Added system include dir: {0}", include_dir); - } } //===----------------------------------------------------------------------===// // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// -ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, - bool generate_debug_info, std::vector include_directories, std::string filename) +ClangExpressionParser::ClangExpressionParser( + ExecutionContextScope *exe_scope, Expression &expr, + bool generate_debug_info, std::vector include_directories, + std::string filename) : ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(), m_pp_callbacks(nullptr), - m_include_directories(std::move(include_directories)), m_filename(std::move(filename)) { + m_include_directories(std::move(include_directories)), + m_filename(std::move(filename)) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // We can't compile expressions without a target. So if the exe_scope is Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -179,7 +179,6 @@ lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) override; - std::vector GetModulesToImport(ExecutionContext &exe_ctx); void CreateSourceCode(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, std::vector modules_to_import, Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -25,6 +25,7 @@ #include "ClangExpressionParser.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" +#include "CppModuleConfiguration.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" @@ -433,48 +434,59 @@ } } -std::vector -ClangUserExpression::GetModulesToImport(ExecutionContext &exe_ctx) { +/// Utility method that puts a message into the expression log and +/// returns an invalid module configuration. +static CppModuleConfiguration LogConfigError(const std::string &msg) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + LLDB_LOG(log, "[C++ module config] {0}", msg); + return CppModuleConfiguration(); +} - if (!SupportsCxxModuleImport(Language())) - return {}; +CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, + ExecutionContext &exe_ctx) { + // Don't do anything if this is not a C++ module configuration. + if (!SupportsCxxModuleImport(language)) + return LogConfigError("Language doesn't support C++ modules"); Target *target = exe_ctx.GetTargetPtr(); - if (!target || !target->GetEnableImportStdModule()) - return {}; + if (!target) + return LogConfigError("No target"); + + if (!target->GetEnableImportStdModule()) + return LogConfigError("Importing std module not enabled in settings"); StackFrame *frame = exe_ctx.GetFramePtr(); if (!frame) - return {}; + return LogConfigError("No frame"); Block *block = frame->GetFrameBlock(); if (!block) - return {}; + return LogConfigError("No block"); SymbolContext sc; block->CalculateSymbolContext(&sc); if (!sc.comp_unit) - return {}; + return LogConfigError("Couldn't calculate symbol context"); - if (log) { - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) { - LLDB_LOG(log, "Found module in compile unit: {0:$[.]} - include dir: {1}", - llvm::make_range(m.path.begin(), m.path.end()), m.search_path); + // Build a list of files we need to analyze to build the configuration. + FileSpecList files; + for (const FileSpec &f : sc.comp_unit->GetSupportFiles()) + files.AppendIfUnique(f); + // We also need to look at external modules in the case of -gmodules as they + // contain the support files for libc++ and the C library. + sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) { + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) { + const FileSpecList &support_files = + module->GetCompileUnitAtIndex(i)->GetSupportFiles(); + for (const FileSpec &f : support_files) { + files.AppendIfUnique(f); + } } - } - - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) - m_include_directories.emplace_back(m.search_path.GetCString()); - - // Check if we imported 'std' or any of its submodules. - // We currently don't support importing any other modules in the expression - // parser. - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) - if (!m.path.empty() && m.path.front() == "std") - return {"std"}; - - return {}; + }); + // Try to create a configuration from the files. If there is no valid + // configuration possible with the files, this just returns an invalid + // configuration. + return CppModuleConfiguration(files); } bool ClangUserExpression::PrepareForParsing( @@ -502,14 +514,21 @@ SetupDeclVendor(exe_ctx, m_target); - std::vector used_modules = GetModulesToImport(exe_ctx); - m_imported_cpp_modules = !used_modules.empty(); + CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx); + llvm::ArrayRef imported_modules = + module_config.GetImportedModules(); + m_imported_cpp_modules = !imported_modules.empty(); + m_include_directories = module_config.GetIncludeDirs(); LLDB_LOG(log, "List of imported modules in expression: {0}", - llvm::make_range(used_modules.begin(), used_modules.end())); + llvm::make_range(imported_modules.begin(), imported_modules.end())); + LLDB_LOG(log, "List of include directories gathered for modules: {0}", + llvm::make_range(m_include_directories.begin(), + m_include_directories.end())); UpdateLanguageForExpr(); - CreateSourceCode(diagnostic_manager, exe_ctx, used_modules, for_completion); + CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules, + for_completion); return true; } Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -0,0 +1,84 @@ +//===-- CppModuleConfiguration.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_CppModuleConfiguration_h_ +#define liblldb_CppModuleConfiguration_h_ + +#include +#include + +namespace lldb_private { + +/// A Clang configuration when importing C++ modules. +/// +/// Includes a list of include paths that should be used when importing +/// and a list of modules that can be imported. Currently only used when +/// importing the 'std' module and its dependencies. +class CppModuleConfiguration { + /// Utility class for a path that can only be set once. + class SetOncePath { + std::string m_path; + bool m_valid = false; + /// True iff this path hasn't been set yet. + bool m_first = true; + + public: + /// Try setting the path. Returns true if the path was set and false if + /// the path was already set. + LLVM_NODISCARD bool TrySet(llvm::StringRef path); + /// Return the path if there is one. + std::string Get() const { + assert(m_valid && "Called Get() on an invalid SetOncePath?"); + return m_path; + } + /// Returns true iff this path was set exactly once so far. + bool Valid() const { return m_valid; } + }; + + /// If valid, the include path used for the std module. + SetOncePath m_std_inc; + /// If valid, the include path to the C library (e.g. /usr/include). + SetOncePath m_c_inc; + /// The Clang resource include path for this configuration. + std::string m_resource_inc; + + std::vector m_include_dirs; + std::vector m_imported_modules; + + /// Analyze a given source file to build the current configuration. + /// Returns false iff there was a fatal error that makes analyzing any + /// further files pointless as the configuration is now invalid. + bool analyzeFile(const FileSpec &f); + +public: + /// Creates a configuraiton by analyzing the given list of used source files. + /// + /// Currently only looks at the used paths and doesn't actually access the + /// files on the disk. + explicit CppModuleConfiguration(const FileSpecList &support_files); + /// Creates an empty and invalid configuration. + CppModuleConfiguration() {} + + /// Returns true iff this is a valid configuration that can be used to + /// load and compile modules. + bool hasValidConfig(); + + /// Returns a list of include directories that should be used when using this + /// configuration (e.g. {"/usr/include", "/usr/include/c++/v1"}). + llvm::ArrayRef GetIncludeDirs() const { return m_include_dirs; } + + /// Returns a list of (top level) modules that should be imported when using + /// this configuration (e.g. {"std"}). + llvm::ArrayRef GetImportedModules() const { + return m_imported_modules; + } +}; + +} // namespace lldb_private + +#endif Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -0,0 +1,82 @@ +//===-- CppModuleConfiguration.cpp ----------------------------------------===// +// +// 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 "CppModuleConfiguration.h" + +#include "ClangHost.h" +#include "lldb/Host/FileSystem.h" + +using namespace lldb_private; + +bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) { + // Setting for the first time always works. + if (m_first) { + m_path = path.str(); + m_valid = true; + m_first = false; + return true; + } + // Changing the path to the same value is fine. + if (m_path == path) + return true; + + // Changing the path after it was already set is not allowed. + m_valid = false; + return false; +} + +bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { + llvm::SmallString<256> dir_buffer = f.GetDirectory().GetStringRef(); + // Convert to posix style so that we can use '/'. + llvm::sys::path::native(dir_buffer, llvm::sys::path::Style::posix); + llvm::StringRef posix_dir(dir_buffer); + + // Check for /c++/vX/ that is used by libc++. + static llvm::Regex libcpp_regex(R"regex(/c[+][+]/v[0-9]/)regex"); + if (libcpp_regex.match(f.GetPath())) { + // Strip away libc++'s /experimental directory if there is one. + posix_dir.consume_back("/experimental"); + return m_std_inc.TrySet(posix_dir); + } + + // Check for /usr/include. On Linux this might be /usr/include/bits, so + // we should remove that '/bits' suffix to get the actual include directory. + if (posix_dir.endswith("/usr/include/bits")) + posix_dir.consume_back("/bits"); + if (posix_dir.endswith("/usr/include")) + return m_c_inc.TrySet(posix_dir); + + // File wasn't interesting, continue analyzing. + return true; +} + +bool CppModuleConfiguration::hasValidConfig() { + // We all these include directories to have a valid usable configuration. + return m_c_inc.Valid() && m_std_inc.Valid(); +} + +CppModuleConfiguration::CppModuleConfiguration( + const FileSpecList &support_files) { + // Analyze all files we were given to build the configuration. + bool error = !std::all_of(support_files.begin(), support_files.end(), + std::bind(&CppModuleConfiguration::analyzeFile, + this, std::placeholders::_1)); + // If we have a valid configuration at this point, set the + // include directories and module list that should be used. + if (!error && hasValidConfig()) { + // Calculate the resource directory for LLDB. + llvm::SmallString<256> resource_dir; + llvm::sys::path::append(resource_dir, GetClangResourceDir().GetPath(), + "include"); + m_resource_inc = resource_dir.str(); + + // This order matches the way Clang orders these directories. + m_include_dirs = {m_std_inc.Get(), m_resource_inc, m_c_inc.Get()}; + m_imported_modules = {"std"}; + } +} Index: lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h =================================================================== --- lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h +++ lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h @@ -48,9 +48,6 @@ bool CanDebugProcess() override; - std::vector - GetSystemIncludeDirectories(lldb::LanguageType lang) override; - lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, Status &error) override; Index: lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -260,25 +260,6 @@ } } -std::vector -PlatformLinux::GetSystemIncludeDirectories(lldb::LanguageType lang) { - std::string sys_root = GetSDKRootDirectory().AsCString(""); - switch (lang) { - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC89: - case lldb::eLanguageTypeC99: - case lldb::eLanguageTypeC11: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeC_plus_plus_03: - case lldb::eLanguageTypeC_plus_plus_11: - case lldb::eLanguageTypeC_plus_plus_14: - case lldb::eLanguageTypeObjC_plus_plus: - return {sys_root + "/usr/include/"}; - default: - return {}; - } -} - // For local debugging, Linux will override the debug logic to use llgs-launch // rather than lldb-launch, llgs-attach. This differs from current lldb- // launch, debugserver-attach approach on MacOSX. Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -105,6 +105,10 @@ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -845,6 +845,18 @@ return functions_added; } +void SymbolFileDWARF::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref f) { + UpdateExternalModuleListIfNeeded(); + + for (auto &p : m_external_type_modules) { + ModuleSP module = p.second; + f(module); + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) + module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f); + } +} + bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { if (!comp_unit.GetLineTable()) Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -53,6 +53,10 @@ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -652,6 +652,14 @@ return false; } +void SymbolFileDWARFDebugMap::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref f) { + std::lock_guard guard(GetModuleMutex()); + SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); + if (oso_dwarf) + oso_dwarf->ForEachExternalModule(comp_unit, f); +} + bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { std::lock_guard guard(GetModuleMutex()); Index: lldb/trunk/source/Symbol/CompileUnit.cpp =================================================================== --- lldb/trunk/source/Symbol/CompileUnit.cpp +++ lldb/trunk/source/Symbol/CompileUnit.cpp @@ -353,6 +353,11 @@ return m_imported_modules; } +void CompileUnit::ForEachExternalModule(llvm::function_ref f) { + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) + symfile->ForEachExternalModule(*this, f); +} + const FileSpecList &CompileUnit::GetSupportFiles() { if (m_support_files.GetSize() == 0) { if (m_flags.IsClear(flagsParsedSupportFiles)) { Index: lldb/trunk/unittests/Expression/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/Expression/CMakeLists.txt +++ lldb/trunk/unittests/Expression/CMakeLists.txt @@ -2,6 +2,7 @@ ClangParserTest.cpp DiagnosticManagerTest.cpp DWARFExpressionTest.cpp + CppModuleConfigurationTest.cpp LINK_LIBS lldbCore Index: lldb/trunk/unittests/Expression/CppModuleConfigurationTest.cpp =================================================================== --- lldb/trunk/unittests/Expression/CppModuleConfigurationTest.cpp +++ lldb/trunk/unittests/Expression/CppModuleConfigurationTest.cpp @@ -0,0 +1,168 @@ +//===-- CppModuleConfigurationTest.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 "Plugins/ExpressionParser/Clang/CppModuleConfiguration.h" +#include "Plugins/ExpressionParser/Clang/ClangHost.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +namespace { +struct CppModuleConfigurationTest : public testing::Test { + static void SetUpTestCase() { + // Getting the resource directory uses those subsystems, so we should + // initialize them. + FileSystem::Initialize(); + HostInfo::Initialize(); + } + static void TearDownTestCase() { + HostInfo::Terminate(); + FileSystem::Terminate(); + } +}; +} // namespace + +/// Returns the Clang resource include directory. +static std::string ResourceInc() { + llvm::SmallString<256> resource_dir; + llvm::sys::path::append(resource_dir, GetClangResourceDir().GetPath(), + "include"); + return resource_dir.str().str(); +} + +/// Utility function turningn a list of paths into a FileSpecList. +static FileSpecList makeFiles(llvm::ArrayRef paths) { + FileSpecList result; + for (const std::string &path : paths) + result.Append(FileSpec(path)); + return result; +} + +TEST_F(CppModuleConfigurationTest, Linux) { + // Test the average Linux configuration. + std::string libcpp = "/usr/include/c++/v1"; + std::string usr = "/usr/include"; + CppModuleConfiguration config( + makeFiles({usr + "/bits/types.h", libcpp + "/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre(libcpp, ResourceInc(), usr)); +} + +TEST_F(CppModuleConfigurationTest, Sysroot) { + // Test that having a sysroot for the whole system works fine. + std::string libcpp = "/home/user/sysroot/usr/include/c++/v1"; + std::string usr = "/home/user/sysroot/usr/include"; + CppModuleConfiguration config( + makeFiles({usr + "/bits/types.h", libcpp + "/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre(libcpp, ResourceInc(), usr)); +} + +TEST_F(CppModuleConfigurationTest, LinuxLocalLibCpp) { + // Test that a locally build libc++ is detected. + std::string libcpp = "/home/user/llvm-build/include/c++/v1"; + std::string usr = "/usr/include"; + CppModuleConfiguration config( + makeFiles({usr + "/bits/types.h", libcpp + "/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre(libcpp, ResourceInc(), usr)); +} + +TEST_F(CppModuleConfigurationTest, UnrelatedLibrary) { + // Test that having an unrelated library in /usr/include doesn't break. + std::string libcpp = "/home/user/llvm-build/include/c++/v1"; + std::string usr = "/usr/include"; + CppModuleConfiguration config(makeFiles( + {usr + "/bits/types.h", libcpp + "/vector", usr + "/boost/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre(libcpp, ResourceInc(), usr)); +} + +TEST_F(CppModuleConfigurationTest, Xcode) { + // Test detection of libc++ coming from Xcode with generic platform names. + std::string p = "/Applications/Xcode.app/Contents/Developer/"; + std::string libcpp = p + "Toolchains/B.xctoolchain/usr/include/c++/v1"; + std::string usr = + p + "Platforms/A.platform/Developer/SDKs/OSVers.sdk/usr/include"; + CppModuleConfiguration config( + makeFiles({libcpp + "/unordered_map", usr + "/stdio.h"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre(libcpp, ResourceInc(), usr)); +} + +TEST_F(CppModuleConfigurationTest, LibCppV2) { + // Test that a "v2" of libc++ is still correctly detected. + CppModuleConfiguration config( + makeFiles({"/usr/include/bits/types.h", "/usr/include/c++/v2/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre("/usr/include/c++/v2", ResourceInc(), + "/usr/include")); +} + +TEST_F(CppModuleConfigurationTest, UnknownLibCppFile) { + // Test that having some unknown file in the libc++ path doesn't break + // anything. + CppModuleConfiguration config(makeFiles( + {"/usr/include/bits/types.h", "/usr/include/c++/v1/non_existing_file"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre("/usr/include/c++/v1", ResourceInc(), + "/usr/include")); +} + +TEST_F(CppModuleConfigurationTest, MissingUsrInclude) { + // Test that we don't load 'std' if we can't find the C standard library. + CppModuleConfiguration config(makeFiles({"/usr/include/c++/v1/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); + EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); +} + +TEST_F(CppModuleConfigurationTest, MissingLibCpp) { + // Test that we don't load 'std' if we don't have a libc++. + CppModuleConfiguration config(makeFiles({"/usr/include/bits/types.h"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); + EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); +} + +TEST_F(CppModuleConfigurationTest, IgnoreLibStdCpp) { + // Test that we don't do anything bad when we encounter libstdc++ paths. + CppModuleConfiguration config(makeFiles( + {"/usr/include/bits/types.h", "/usr/include/c++/8.0.1/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); + EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); +} + +TEST_F(CppModuleConfigurationTest, AmbiguousCLib) { + // Test that we don't do anything when we are not sure where the + // right C standard library is. + CppModuleConfiguration config( + makeFiles({"/usr/include/bits/types.h", "/usr/include/c++/v1/vector", + "/sysroot/usr/include/bits/types.h"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); + EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); +} + +TEST_F(CppModuleConfigurationTest, AmbiguousLibCpp) { + // Test that we don't do anything when we are not sure where the + // right libc++ is. + CppModuleConfiguration config( + makeFiles({"/usr/include/bits/types.h", "/usr/include/c++/v1/vector", + "/usr/include/c++/v2/vector"})); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); + EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); +}