summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2015-04-20 16:31:29 +0000
committerSean Callanan <scallanan@apple.com>2015-04-20 16:31:29 +0000
commitf0c5aeb69011197d1ef1bbed7ba363d52e95c5d8 (patch)
treea9ad4361dfe9cdc044504cafed3af7dc215ff5c7
parent2cc2b63f533cfbda9753711cdf3414f6c26cbe6a (diff)
downloadbcm5719-llvm-f0c5aeb69011197d1ef1bbed7ba363d52e95c5d8.tar.gz
bcm5719-llvm-f0c5aeb69011197d1ef1bbed7ba363d52e95c5d8.zip
This patch implements several improvements to the
module-loading support for the expression parser. - It adds support for auto-loading modules referred to by a compile unit. These references are currently in the form of empty translation units. This functionality is gated by the setting target.auto-import-clang-modules (boolean) = false - It improves and corrects support for loading macros from modules, currently by textually pasting all #defines into the user's expression. The improvements center around including only those modules that are relevant to the current context - hand-loaded modules and the modules that are imported from the current compile unit. - It adds an "opt-in" mechanism for all of this functionality. Modules have to be explicitly imported (via @import) or auto-loaded (by enabling the above setting) to enable any of this functionality. It also adds support to the compile unit and symbol file code to deal with empty translation units that indicate module imports, and plumbs this through to the CompileUnit interface. Finally, it makes the following changes to the test suite: - It adds a testcase that verifies that modules are automatically loaded when the appropriate setting is enabled (lang/objc/modules-auto-import); and - It modifies lanb/objc/modules-incomplete to test the case where a module #undefs something that is #defined in another module. <rdar://problem/20299554> llvm-svn: 235313
-rw-r--r--lldb/include/lldb/Expression/ClangModulesDeclVendor.h72
-rw-r--r--lldb/include/lldb/Expression/ClangPersistentVariables.h16
-rw-r--r--lldb/include/lldb/Symbol/CompileUnit.h25
-rw-r--r--lldb/include/lldb/Symbol/SymbolFile.h1
-rw-r--r--lldb/include/lldb/Symbol/SymbolVendor.h4
-rw-r--r--lldb/include/lldb/Target/Target.h3
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp37
-rw-r--r--lldb/source/Expression/ClangModulesDeclVendor.cpp245
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp30
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp25
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp79
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h15
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp25
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h1
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h3
-rw-r--r--lldb/source/Symbol/CompileUnit.cpp17
-rw-r--r--lldb/source/Symbol/SymbolVendor.cpp15
-rw-r--r--lldb/source/Target/Target.cpp9
-rw-r--r--lldb/test/functionalities/data-formatter/typedef_array/Makefile4
-rw-r--r--lldb/test/lang/objc/modules-auto-import/Makefile6
-rw-r--r--lldb/test/lang/objc/modules-auto-import/TestModulesAutoImport.py78
-rw-r--r--lldb/test/lang/objc/modules-auto-import/main.m7
-rw-r--r--lldb/test/lang/objc/modules-incomplete/TestIncompleteModules.py6
-rw-r--r--lldb/test/lang/objc/modules-incomplete/myModule.h2
25 files changed, 676 insertions, 55 deletions
diff --git a/lldb/include/lldb/Expression/ClangModulesDeclVendor.h b/lldb/include/lldb/Expression/ClangModulesDeclVendor.h
index 5bc383db1b8..a8297c8fa33 100644
--- a/lldb/include/lldb/Expression/ClangModulesDeclVendor.h
+++ b/lldb/include/lldb/Expression/ClangModulesDeclVendor.h
@@ -15,6 +15,7 @@
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Target/Platform.h"
+#include <set>
#include <vector>
namespace lldb_private
@@ -34,6 +35,10 @@ public:
static ClangModulesDeclVendor *
Create(Target &target);
+ typedef std::vector<ConstString> ModulePath;
+ typedef uintptr_t ModuleID;
+ typedef std::vector<ModuleID> ModuleVector;
+
//------------------------------------------------------------------
/// Add a module to the list of modules to search.
///
@@ -41,6 +46,10 @@ public:
/// The path to the exact module to be loaded. E.g., if the desired
/// module is std.io, then this should be { "std", "io" }.
///
+ /// @param[in] exported_modules
+ /// If non-NULL, a pointer to a vector to populate with the ID of every
+ /// module that is re-exported by the specified module.
+ ///
/// @param[in] error_stream
/// A stream to populate with the output of the Clang parser when
/// it tries to load the module.
@@ -51,18 +60,69 @@ public:
/// load, then this will always return false for this ModuleImporter.
//------------------------------------------------------------------
virtual bool
- AddModule(std::vector<llvm::StringRef> &path, Stream &error_stream) = 0;
+ AddModule(ModulePath &path,
+ ModuleVector *exported_modules,
+ Stream &error_stream) = 0;
//------------------------------------------------------------------
- /// Enumerate all the macros that are currently visible.
+ /// Add all modules referred to in a given compilation unit to the list
+ /// of modules to search.
+ ///
+ /// @param[in] cu
+ /// The compilation unit to scan for imported modules.
+ ///
+ /// @param[in] exported_modules
+ /// A vector to populate with the ID of each module loaded (directly
+ /// and via re-exports) in this way.
+ ///
+ /// @param[in] error_stream
+ /// A stream to populate with the output of the Clang parser when
+ /// it tries to load the modules.
+ ///
+ /// @return
+ /// True if all modules referred to by the compilation unit could be
+ /// loaded; false if one could not be loaded. If the compiler
+ /// encountered a fatal error during a previous module
+ /// load, then this will always return false for this ModuleImporter.
+ //------------------------------------------------------------------
+ virtual bool
+ AddModulesForCompileUnit(CompileUnit &cu,
+ ModuleVector &exported_modules,
+ Stream &error_stream) = 0;
+
+ //------------------------------------------------------------------
+ /// Enumerate all the macros that are defined by a given set of modules
+ /// that are already imported.
+ ///
+ /// @param[in] modules
+ /// The unique IDs for all modules to query. Later modules have higher
+ /// priority, just as if you @imported them in that order. This matters
+ /// if module A #defines a macro and module B #undefs it.
///
/// @param[in] handler
- /// A function that receives the text of each #define macro.
- /// If handler returns true, this function returns immediately,
- /// without calling handler again.
+ /// A function to call with the text of each #define (including the
+ /// #define directive). #undef directives are not included; we simply
+ /// elide any corresponding #define. If this function returns true,
+ /// we stop the iteration immediately.
//------------------------------------------------------------------
virtual void
- ForEachMacro(std::function<bool (const std::string &)> handler) = 0;
+ ForEachMacro(const ModuleVector &modules,
+ std::function<bool (const std::string &)> handler) = 0;
+
+ //------------------------------------------------------------------
+ /// Query whether Clang supports modules for a particular language.
+ /// LLDB uses this to decide whether to try to find the modules loaded
+ /// by a gaiven compile unit.
+ ///
+ /// @param[in] language
+ /// The language to query for.
+ ///
+ /// @return
+ /// True if Clang has modules for the given language.
+ //------------------------------------------------------------------
+ static bool
+ LanguageSupportsClangModules (lldb::LanguageType language);
+
};
}
diff --git a/lldb/include/lldb/Expression/ClangPersistentVariables.h b/lldb/include/lldb/Expression/ClangPersistentVariables.h
index 6d9dae95473..247f87fae41 100644
--- a/lldb/include/lldb/Expression/ClangPersistentVariables.h
+++ b/lldb/include/lldb/Expression/ClangPersistentVariables.h
@@ -11,6 +11,8 @@
#define liblldb_ClangPersistentVariables_h_
#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangModulesDeclVendor.h"
+
#include "llvm/ADT/DenseMap.h"
namespace lldb_private
@@ -63,11 +65,25 @@ public:
clang::TypeDecl *
GetPersistentType (const ConstString &name);
+ void
+ AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module)
+ {
+ m_hand_loaded_clang_modules.push_back(module);
+ }
+
+ const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules()
+ {
+ return m_hand_loaded_clang_modules;
+ }
+
private:
uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
typedef llvm::DenseMap<const char *, clang::TypeDecl *> PersistentTypeMap;
PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user.
+
+ ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest-
+ ///< priority source for macros.
};
}
diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index f9238ebba18..e0c069352bf 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -256,6 +256,18 @@ public:
//------------------------------------------------------------------
FileSpecList&
GetSupportFiles ();
+
+ //------------------------------------------------------------------
+ /// Get the compile unit's imported module list.
+ ///
+ /// This reports all the imports that the compile unit made,
+ /// including the current module.
+ ///
+ /// @return
+ /// A list of imported module names.
+ //------------------------------------------------------------------
+ const std::vector<ConstString> &
+ GetImportedModules ();
//------------------------------------------------------------------
/// Get the SymbolFile plug-in user data.
@@ -400,6 +412,8 @@ protected:
Flags m_flags; ///< Compile unit flags that help with partial parsing.
std::vector<lldb::FunctionSP> m_functions; ///< The sparsely populated list of shared pointers to functions
///< that gets populated as functions get partially parsed.
+ std::vector<ConstString> m_imported_modules; ///< All modules, including the current module, imported by this
+ ///< compile unit.
FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations.
std::unique_ptr<LineTable> m_line_table_ap; ///< Line table that will get parsed on demand.
lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand.
@@ -407,11 +421,12 @@ protected:
private:
enum
{
- flagsParsedAllFunctions = (1u << 0), ///< Have we already parsed all our functions
- flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics?
- flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit?
- flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already?
- flagsParsedLanguage = (1u << 4) ///< Have we parsed the line table already?
+ flagsParsedAllFunctions = (1u << 0), ///< Have we already parsed all our functions
+ flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics?
+ flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit?
+ flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already?
+ flagsParsedLanguage = (1u << 4), ///< Have we parsed the line table already?
+ flagsParsedImportedModules = (1u << 5) ///< Have we parsed the imported modules already?
};
DISALLOW_COPY_AND_ASSIGN (CompileUnit);
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h
index 6df3d49fc46..0efe034235d 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -124,6 +124,7 @@ public:
virtual size_t ParseCompileUnitFunctions (const SymbolContext& sc) = 0;
virtual bool ParseCompileUnitLineTable (const SymbolContext& sc) = 0;
virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) = 0;
+ virtual bool ParseImportedModules (const SymbolContext &sc, std::vector<ConstString> &imported_modules) = 0;
virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0;
virtual size_t ParseTypes (const SymbolContext& sc) = 0;
virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0;
diff --git a/lldb/include/lldb/Symbol/SymbolVendor.h b/lldb/include/lldb/Symbol/SymbolVendor.h
index cddf2165635..248918af283 100644
--- a/lldb/include/lldb/Symbol/SymbolVendor.h
+++ b/lldb/include/lldb/Symbol/SymbolVendor.h
@@ -66,6 +66,10 @@ public:
virtual bool
ParseCompileUnitSupportFiles (const SymbolContext& sc,
FileSpecList& support_files);
+
+ virtual bool
+ ParseImportedModules (const SymbolContext &sc,
+ std::vector<ConstString> &imported_modules);
virtual size_t
ParseFunctionBlocks (const SymbolContext& sc);
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 43038642548..872a8ec0dbb 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -128,6 +128,9 @@ public:
GetClangModuleSearchPaths ();
bool
+ GetEnableAutoImportClangModules () const;
+
+ bool
GetEnableSyntheticValue () const;
uint32_t
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index c7d84e61813..57e620bf2d9 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -24,6 +24,7 @@
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangModulesDeclVendor.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/IRInterpreter.h"
@@ -96,12 +97,15 @@ std::string GetBuiltinIncludePath(const char *Argv0) {
class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks
{
- ClangModulesDeclVendor &m_decl_vendor;
- StreamString m_error_stream;
- bool m_has_errors = false;
+ ClangModulesDeclVendor &m_decl_vendor;
+ ClangPersistentVariables &m_persistent_vars;
+ StreamString m_error_stream;
+ bool m_has_errors = false;
public:
- LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor) :
- m_decl_vendor(decl_vendor)
+ LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor,
+ ClangPersistentVariables &persistent_vars) :
+ m_decl_vendor(decl_vendor),
+ m_persistent_vars(persistent_vars)
{
}
@@ -109,19 +113,26 @@ public:
ModuleIdPath path,
const clang::Module * /*null*/)
{
- std::vector<llvm::StringRef> string_path;
+ std::vector<ConstString> string_path;
for (const std::pair<IdentifierInfo *, SourceLocation> &component : path)
{
- string_path.push_back(component.first->getName());
+ string_path.push_back(ConstString(component.first->getName()));
}
StreamString error_stream;
- if (!m_decl_vendor.AddModule(string_path, m_error_stream))
+ ClangModulesDeclVendor::ModuleVector exported_modules;
+
+ if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream))
{
m_has_errors = true;
}
+
+ for (ClangModulesDeclVendor::ModuleID module : exported_modules)
+ {
+ m_persistent_vars.AddHandLoadedClangModule(module);
+ }
}
bool hasErrors()
@@ -298,7 +309,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor())
{
- std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor));
+ std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, target_sp->GetPersistentVariables()));
m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get());
m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
}
@@ -309,10 +320,10 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
m_builtin_context.reset(new Builtin::Context());
std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
- m_compiler->getSourceManager(),
- m_compiler->getPreprocessor().getIdentifierTable(),
- *m_selector_table.get(),
- *m_builtin_context.get()));
+ m_compiler->getSourceManager(),
+ m_compiler->getPreprocessor().getIdentifierTable(),
+ *m_selector_table.get(),
+ *m_builtin_context.get()));
ast_context->InitBuiltinTypes(m_compiler->getTarget());
diff --git a/lldb/source/Expression/ClangModulesDeclVendor.cpp b/lldb/source/Expression/ClangModulesDeclVendor.cpp
index efa50b19748..b4dd73b6e2f 100644
--- a/lldb/source/Expression/ClangModulesDeclVendor.cpp
+++ b/lldb/source/Expression/ClangModulesDeclVendor.cpp
@@ -16,6 +16,7 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/Target.h"
#include "clang/Basic/TargetInfo.h"
@@ -61,9 +62,15 @@ namespace {
std::unique_ptr<clang::Parser> &&parser);
virtual bool
- AddModule(std::vector<llvm::StringRef> &path,
+ AddModule(ModulePath &path,
+ ModuleVector *exported_modules,
Stream &error_stream) override;
+ virtual bool
+ AddModulesForCompileUnit(CompileUnit &cu,
+ ModuleVector &exported_modules,
+ Stream &error_stream) override;
+
virtual uint32_t
FindDecls (const ConstString &name,
bool append,
@@ -71,19 +78,36 @@ namespace {
std::vector <clang::NamedDecl*> &decls) override;
virtual void
- ForEachMacro(std::function<bool (const std::string &)> handler) override;
+ ForEachMacro(const ModuleVector &modules,
+ std::function<bool (const std::string &)> handler) override;
~ClangModulesDeclVendorImpl();
private:
+ void
+ ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
+ clang::Module *module);
+
+ void
+ ReportModuleExports (ModuleVector &exports,
+ clang::Module *module);
+
clang::ModuleLoadResult
DoGetModule(clang::ModuleIdPath path, bool make_visible);
+ bool m_enabled = false;
+
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation;
std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
std::unique_ptr<clang::Parser> m_parser;
size_t m_source_location_index = 0; // used to give name components fake SourceLocations
+
+ typedef std::vector<ConstString> ImportedModule;
+ typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
+ typedef std::set<ModuleID> ImportedModuleSet;
+ ImportedModuleMap m_imported_modules;
+ ImportedModuleSet m_user_imported_modules;
};
}
@@ -156,12 +180,47 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<
m_diagnostics_engine(diagnostics_engine),
m_compiler_invocation(compiler_invocation),
m_compiler_instance(std::move(compiler_instance)),
- m_parser(std::move(parser))
+ m_parser(std::move(parser)),
+ m_imported_modules()
{
}
+void
+ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
+ clang::Module *module)
+{
+ if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
+ return;
+
+ exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
+
+ llvm::SmallVector<clang::Module*, 2> sub_exports;
+
+ module->getExportedModules(sub_exports);
+
+ for (clang::Module *module : sub_exports)
+ {
+ ReportModuleExportsHelper(exports, module);
+ }
+}
+
+void
+ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports,
+ clang::Module *module)
+{
+ std::set<ClangModulesDeclVendor::ModuleID> exports_set;
+
+ ReportModuleExportsHelper(exports_set, module);
+
+ for (ModuleID module : exports_set)
+ {
+ exports.push_back(module);
+ }
+}
+
bool
-ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
+ClangModulesDeclVendorImpl::AddModule(ModulePath &path,
+ ModuleVector *exported_modules,
Stream &error_stream)
{
// Fail early.
@@ -172,9 +231,31 @@ ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
return false;
}
- if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0]))
+ // Check if we've already imported this module.
+
+ std::vector<ConstString> imported_module;
+
+ for (ConstString path_component : path)
{
- error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].str().c_str());
+ imported_module.push_back(path_component);
+ }
+
+ {
+ ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
+
+ if (mi != m_imported_modules.end())
+ {
+ if (exported_modules)
+ {
+ ReportModuleExports(*exported_modules, mi->second);
+ }
+ return true;
+ }
+ }
+
+ if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef()))
+ {
+ error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString());
return false;
}
@@ -183,9 +264,9 @@ ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
{
clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager();
- for (llvm::StringRef &component : path)
+ for (ConstString path_component : path)
{
- clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(component),
+ clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()),
source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++)));
}
}
@@ -199,7 +280,7 @@ ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
if (!top_level_module)
{
diagnostic_consumer->DumpDiagnostics(error_stream);
- error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].str().c_str());
+ error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString());
return false;
}
@@ -207,7 +288,7 @@ ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
for (size_t ci = 1; ci < path.size(); ++ci)
{
- llvm::StringRef &component = path[ci];
+ llvm::StringRef component = path[ci].GetStringRef();
submodule = submodule->findSubmodule(component.str());
if (!submodule)
{
@@ -219,7 +300,66 @@ ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
clang::Module *requested_module = DoGetModule(clang_path, true);
- return (requested_module != nullptr);
+ if (requested_module != nullptr)
+ {
+ if (exported_modules)
+ {
+ ReportModuleExports(*exported_modules, requested_module);
+ }
+
+ m_imported_modules[imported_module] = requested_module;
+
+ m_enabled = true;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language)
+{
+ switch (language)
+ {
+ default:
+ return false;
+ // C++ and friends to be added
+ case lldb::LanguageType::eLanguageTypeC:
+ case lldb::LanguageType::eLanguageTypeC11:
+ case lldb::LanguageType::eLanguageTypeC89:
+ case lldb::LanguageType::eLanguageTypeC99:
+ case lldb::LanguageType::eLanguageTypeObjC:
+ return true;
+ }
+}
+
+bool
+ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu,
+ ClangModulesDeclVendor::ModuleVector &exported_modules,
+ Stream &error_stream)
+{
+ if (LanguageSupportsClangModules(cu.GetLanguage()))
+ {
+ std::vector<ConstString> imported_modules = cu.GetImportedModules();
+
+ for (ConstString imported_module : imported_modules)
+ {
+ std::vector<ConstString> path;
+
+ path.push_back(imported_module);
+
+ if (!AddModule(path, &exported_modules, error_stream))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return true;
}
// ClangImporter::lookupValue
@@ -230,6 +370,11 @@ ClangModulesDeclVendorImpl::FindDecls (const ConstString &name,
uint32_t max_matches,
std::vector <clang::NamedDecl*> &decls)
{
+ if (!m_enabled)
+ {
+ return 0;
+ }
+
if (!append)
decls.clear();
@@ -257,14 +402,90 @@ ClangModulesDeclVendorImpl::FindDecls (const ConstString &name,
}
void
-ClangModulesDeclVendorImpl::ForEachMacro(std::function<bool (const std::string &)> handler)
+ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules,
+ std::function<bool (const std::string &)> handler)
{
+ if (!m_enabled)
+ {
+ return;
+ }
+
+ typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
+ ModulePriorityMap module_priorities;
+
+ ssize_t priority = 0;
+
+ for (ModuleID module : modules)
+ {
+ module_priorities[module] = priority++;
+ }
+
+ if (m_compiler_instance->getPreprocessor().getExternalSource())
+ {
+ m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros();
+ }
for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(),
me = m_compiler_instance->getPreprocessor().macro_end();
mi != me;
++mi)
{
+ const clang::IdentifierInfo *ii = nullptr;
+
+ {
+ if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup())
+ {
+ lookup->get(mi->first->getName());
+ }
+ if (!ii)
+ {
+ ii = mi->first;
+ }
+ }
+
+ ssize_t found_priority = -1;
+ clang::MacroInfo *info = nullptr;
+
+ for (clang::MacroDirective *directive = m_compiler_instance->getPreprocessor().getMacroDirectiveHistory(ii);
+ directive != nullptr;
+ directive = directive->getPrevious())
+ {
+ unsigned module_id = directive->getOwningModuleID();
+
+ if (!module_id)
+ continue;
+
+ clang::Module *module = m_compiler_instance->getModuleManager()->getModule(module_id);
+
+ {
+ ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module));
+
+ if (pi != module_priorities.end() && pi->second > found_priority)
+ {
+ info = directive->getMacroInfo();
+ found_priority = pi->second;
+ }
+ }
+
+ clang::Module *top_level_module = module->getTopLevelModule();
+
+ if (top_level_module != module)
+ {
+ ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module));
+
+ if ((pi != module_priorities.end()) && pi->second > found_priority)
+ {
+ info = directive->getMacroInfo();
+ found_priority = pi->second;
+ }
+ }
+ }
+
+ if (!info)
+ {
+ continue;
+ }
+
if (mi->second->getKind() == clang::MacroDirective::MD_Define)
{
std::string macro_expansion = "#define ";
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 08ee437b164..ba284311180 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -458,7 +458,35 @@ ClangUserExpression::Parse (Stream &error_stream,
if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
{
- decl_vendor->ForEachMacro([log, &prefix] (const std::string &expansion) -> bool {
+ const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = m_target->GetPersistentVariables().GetHandLoadedClangModules();
+ ClangModulesDeclVendor::ModuleVector modules_for_macros;
+
+ for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
+ {
+ modules_for_macros.push_back(module);
+ }
+
+ if (m_target->GetEnableAutoImportClangModules())
+ {
+ if (StackFrame *frame = exe_ctx.GetFramePtr())
+ {
+ if (Block *block = frame->GetFrameBlock())
+ {
+ SymbolContext sc;
+
+ block->CalculateSymbolContext(&sc);
+
+ if (sc.comp_unit)
+ {
+ StreamString error_stream;
+
+ decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
+ }
+ }
+ }
+ }
+
+ decl_vendor->ForEachMacro(modules_for_macros, [log, &prefix] (const std::string &expansion) -> bool {
prefix.append(expansion);
prefix.append("\n");
return false;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index ef1b037000c..545476c7168 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -446,6 +446,31 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
}
}
+ if (debug_aranges->IsEmpty())
+ {
+ // We got nothing from the functions, maybe we have a line tables only
+ // situation. Check the line tables and build the arange table from this.
+ SymbolContext sc;
+ sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
+ if (sc.comp_unit)
+ {
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table)
+ {
+ LineTable::FileAddressRanges file_ranges;
+ const bool append = true;
+ const size_t num_ranges = line_table->GetContiguousFileAddressRanges (file_ranges, append);
+ for (uint32_t idx=0; idx<num_ranges; ++idx)
+ {
+ const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
+ debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
+ printf ("0x%8.8x: [0x%16.16llx - 0x%16.16llx)\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
+ }
+ }
+ }
+ }
+
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed
if (clear_dies)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 28bfcb9cae9..19faac42e1d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -27,6 +27,8 @@
#include "llvm/Support/Casting.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Scalar.h"
@@ -36,6 +38,8 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
+#include "lldb/Expression/ClangModulesDeclVendor.h"
+
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
@@ -515,6 +519,7 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_indexed (false),
m_is_external_ast_source (false),
m_using_apple_tables (false),
+ m_fetched_external_modules (false),
m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate),
m_ranges(),
m_unique_ast_type_map ()
@@ -1263,6 +1268,25 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec
return false;
}
+bool
+SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules)
+{
+ assert (sc.comp_unit);
+ DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ if (dwarf_cu)
+ {
+ if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))
+ {
+ UpdateExternalModuleListIfNeeded();
+ for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules)
+ {
+ imported_modules.push_back(external_type_module.second.m_name);
+ }
+ }
+ }
+ return false;
+}
+
struct ParseDWARFLineTableCallbackInfo
{
LineTable* line_table;
@@ -2845,7 +2869,60 @@ SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn
return false;
}
-
+void
+SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
+{
+ if (m_fetched_external_modules)
+ return;
+ m_fetched_external_modules = true;
+
+ DWARFDebugInfo * debug_info = DebugInfo();
+ debug_info->GetNumCompileUnits();
+
+ const uint32_t num_compile_units = GetNumCompileUnits();
+ for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ {
+ DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+
+ const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly();
+ if (die && die->HasChildren() == false)
+ {
+ const uint64_t name_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_name, UINT64_MAX);
+ const uint64_t dwo_path_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_GNU_dwo_name, UINT64_MAX);
+
+ if (name_strp != UINT64_MAX)
+ {
+ if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end())
+ {
+ const char *name = get_debug_str_data().PeekCStr(name_strp);
+ const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp);
+ if (name || dwo_path)
+ {
+ ModuleSP module_sp;
+ if (dwo_path)
+ {
+ ModuleSpec dwo_module_spec;
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
+ dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
+ //printf ("Loading dwo = '%s'\n", dwo_path);
+ Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
+ }
+
+ if (dwo_path_strp != LLDB_INVALID_UID)
+ {
+ m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp };
+ }
+ else
+ {
+ // This hack should be removed promptly once clang emits both.
+ m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp };
+ }
+ }
+ }
+ }
+ }
+ }
+}
SymbolFileDWARF::GlobalVariableMap &
SymbolFileDWARF::GetGlobalAranges()
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 1bf5c0d8212..2f0b3f05b15 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -103,6 +103,7 @@ public:
virtual size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
virtual bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
virtual bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files);
+ virtual bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules);
virtual size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
virtual size_t ParseTypes (const lldb_private::SymbolContext& sc);
virtual size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc);
@@ -547,6 +548,13 @@ protected:
FixupAddress (lldb_private::Address &addr);
typedef std::set<lldb_private::Type *> TypeSet;
+
+ typedef struct {
+ lldb_private::ConstString m_name;
+ lldb::ModuleSP m_module_sp;
+ } ClangModuleInfo;
+
+ typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap;
void
GetTypes (DWARFCompileUnit* dwarf_cu,
@@ -560,6 +568,9 @@ protected:
GlobalVariableMap &
GetGlobalAranges();
+
+ void
+ UpdateExternalModuleListIfNeeded();
lldb::ModuleWP m_debug_map_module_wp;
SymbolFileDWARFDebugMap * m_debug_map_symfile;
@@ -589,6 +600,7 @@ protected:
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
+ ExternalTypeModuleMap m_external_type_modules;
NameToDIE m_function_basename_index; // All concrete functions
NameToDIE m_function_fullname_index; // All concrete functions
NameToDIE m_function_method_index; // All inlined functions
@@ -599,7 +611,8 @@ protected:
NameToDIE m_namespace_index; // All type DIE offsets
bool m_indexed:1,
m_is_external_ast_source:1,
- m_using_apple_tables:1;
+ m_using_apple_tables:1,
+ m_fetched_external_modules:1;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
std::unique_ptr<DWARFDebugRanges> m_ranges;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 3087bde65d5..d5d60aed03e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -227,18 +227,11 @@ public:
if (exe_objfile && exe_sym_vendor)
{
- if (oso_symfile->GetNumCompileUnits() == 1)
- {
- oso_symfile->SetDebugMapModule(exe_module_sp);
- // Set the ID of the symbol file DWARF to the index of the OSO
- // shifted left by 32 bits to provide a unique prefix for any
- // UserID's that get created in the symbol file.
- oso_symfile->SetID (((uint64_t)m_cu_idx + 1ull) << 32ull);
- }
- else
- {
- oso_symfile->SetID (UINT64_MAX);
- }
+ oso_symfile->SetDebugMapModule(exe_module_sp);
+ // Set the ID of the symbol file DWARF to the index of the OSO
+ // shifted left by 32 bits to provide a unique prefix for any
+ // UserID's that get created in the symbol file.
+ oso_symfile->SetID (((uint64_t)m_cu_idx + 1ull) << 32ull);
}
return symbol_vendor;
}
@@ -743,6 +736,14 @@ SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc,
return false;
}
+bool
+SymbolFileDWARFDebugMap::ParseImportedModules (const SymbolContext &sc, std::vector<ConstString> &imported_modules)
+{
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+ if (oso_dwarf)
+ return oso_dwarf->ParseImportedModules(sc, imported_modules);
+ return false;
+}
size_t
SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 2a6e989fde9..78ec761a7b2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -70,6 +70,7 @@ public:
virtual size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
virtual bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
virtual bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
+ virtual bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) override;
virtual size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
virtual size_t ParseTypes (const lldb_private::SymbolContext& sc);
virtual size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc);
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 8e85d482528..8eb3e3a09c8 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -266,6 +266,12 @@ SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpe
return false;
}
+bool
+SymbolFileSymtab::ParseImportedModules (const SymbolContext &sc, std::vector<ConstString> &imported_modules)
+{
+ return false;
+}
+
size_t
SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
{
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
index 914efe6eb3c..d606419a0d9 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -65,6 +65,9 @@ public:
virtual bool
ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
+
+ virtual bool
+ ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules);
virtual size_t
ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 6483258ee67..d8e95ce7271 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -436,6 +436,23 @@ CompileUnit::SetVariableList(VariableListSP &variables)
m_variables = variables;
}
+const std::vector<ConstString> &
+CompileUnit::GetImportedModules ()
+{
+ if (m_imported_modules.empty() &&
+ m_flags.IsClear(flagsParsedImportedModules))
+ {
+ m_flags.Set(flagsParsedImportedModules);
+ if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor())
+ {
+ SymbolContext sc;
+ CalculateSymbolContext(&sc);
+ symbol_vendor->ParseImportedModules(sc, m_imported_modules);
+ }
+ }
+ return m_imported_modules;
+}
+
FileSpecList&
CompileUnit::GetSupportFiles ()
{
diff --git a/lldb/source/Symbol/SymbolVendor.cpp b/lldb/source/Symbol/SymbolVendor.cpp
index 6445efbb3cb..6ec9f3861ec 100644
--- a/lldb/source/Symbol/SymbolVendor.cpp
+++ b/lldb/source/Symbol/SymbolVendor.cpp
@@ -198,6 +198,21 @@ SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecLis
return false;
}
+bool
+SymbolVendor::ParseImportedModules (const SymbolContext &sc,
+ std::vector<ConstString> &imported_modules)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseImportedModules(sc, imported_modules);
+ }
+ return false;
+
+}
+
size_t
SymbolVendor::ParseFunctionBlocks (const SymbolContext &sc)
{
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 400cf47bf05..6042a8f9267 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2927,6 +2927,7 @@ g_properties[] =
{ "exec-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "Executable search paths to use when locating executable files whose paths don't match the local file system." },
{ "debug-file-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "List of directories to be searched when locating debug symbol files." },
{ "clang-module-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "List of directories to be searched when locating modules for Clang." },
+ { "auto-import-clang-modules" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Automatically load Clang modules referred to by the program." },
{ "max-children-count" , OptionValue::eTypeSInt64 , false, 256 , NULL, NULL, "Maximum number of children to expand in any level of depth." },
{ "max-string-summary-length" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of characters to show when using %s in summary strings." },
{ "max-memory-read-size" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of bytes that 'memory read' will fetch before --force must be specified." },
@@ -2978,6 +2979,7 @@ enum
ePropertyExecutableSearchPaths,
ePropertyDebugFileSearchPaths,
ePropertyClangModuleSearchPaths,
+ ePropertyAutoImportClangModules,
ePropertyMaxChildrenCount,
ePropertyMaxSummaryLength,
ePropertyMaxMemReadSize,
@@ -3332,6 +3334,13 @@ TargetProperties::GetClangModuleSearchPaths ()
}
bool
+TargetProperties::GetEnableAutoImportClangModules() const
+{
+ const uint32_t idx = ePropertyAutoImportClangModules;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
TargetProperties::GetEnableSyntheticValue () const
{
const uint32_t idx = ePropertyEnableSynthetic;
diff --git a/lldb/test/functionalities/data-formatter/typedef_array/Makefile b/lldb/test/functionalities/data-formatter/typedef_array/Makefile
index 3e2b0187b95..e69de29bb2d 100644
--- a/lldb/test/functionalities/data-formatter/typedef_array/Makefile
+++ b/lldb/test/functionalities/data-formatter/typedef_array/Makefile
@@ -1,4 +0,0 @@
-LEVEL = ../../../make
-CXX_SOURCES := main.cpp
-CXXFLAGS += -std=c++11
-include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/lang/objc/modules-auto-import/Makefile b/lldb/test/lang/objc/modules-auto-import/Makefile
new file mode 100644
index 00000000000..e42b59f9518
--- /dev/null
+++ b/lldb/test/lang/objc/modules-auto-import/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+OBJC_SOURCES := main.m
+
+CFLAGS += -fmodules -gmodules -g
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/lang/objc/modules-auto-import/TestModulesAutoImport.py b/lldb/test/lang/objc/modules-auto-import/TestModulesAutoImport.py
new file mode 100644
index 00000000000..997b4eebe86
--- /dev/null
+++ b/lldb/test/lang/objc/modules-auto-import/TestModulesAutoImport.py
@@ -0,0 +1,78 @@
+"""Test that importing modules in Objective-C works as expected."""
+
+import os, time
+import unittest2
+import lldb
+import platform
+import lldbutil
+
+from distutils.version import StrictVersion
+
+from lldbtest import *
+
+class ObjCModulesAutoImportTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ @dsym_test
+ @unittest2.expectedFailure("rdar://problem/19991953")
+ def test_expr_with_dsym(self):
+ self.buildDsym()
+ self.expr()
+
+ @dwarf_test
+ @skipIfFreeBSD
+ @skipIfLinux
+ def test_expr_with_dwarf(self):
+ self.buildDwarf()
+ self.expr()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break inside main().
+ self.line = line_number('main.m', '// Set breakpoint 0 here.')
+
+ def applies(self):
+ if platform.system() != "Darwin":
+ return False
+ if StrictVersion('12.0.0') > platform.release():
+ return False
+
+ return True
+
+ def common_setup(self):
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Break inside the foo function which takes a bar_ptr argument.
+ lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs = ['stopped',
+ 'stop reason = breakpoint'])
+
+ # The breakpoint should have a hit count of 1.
+ self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+ substrs = [' resolved, hit count = 1'])
+
+ def expr(self):
+ if not self.applies():
+ return
+
+ self.common_setup()
+
+ self.runCmd("settings set target.auto-import-clang-modules true")
+
+ self.expect("p getpid()", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["pid_t"])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/lang/objc/modules-auto-import/main.m b/lldb/test/lang/objc/modules-auto-import/main.m
new file mode 100644
index 00000000000..5452ffd9bd1
--- /dev/null
+++ b/lldb/test/lang/objc/modules-auto-import/main.m
@@ -0,0 +1,7 @@
+@import Darwin;
+
+int main()
+{
+ size_t ret = printf("Stop here\n"); // Set breakpoint 0 here.
+ return ret;
+}
diff --git a/lldb/test/lang/objc/modules-incomplete/TestIncompleteModules.py b/lldb/test/lang/objc/modules-incomplete/TestIncompleteModules.py
index af7cffd130f..b552fd566a9 100644
--- a/lldb/test/lang/objc/modules-incomplete/TestIncompleteModules.py
+++ b/lldb/test/lang/objc/modules-incomplete/TestIncompleteModules.py
@@ -75,6 +75,12 @@ class IncompleteModulesTestCase(TestBase):
self.expect("expr [myObject privateMethod]", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["int", "5"])
+ self.expect("expr MIN(2,3)", "#defined macro was found",
+ substrs = ["int", "2"])
+
+ self.expect("expr MAX(2,3)", "#undefd macro was correcltly not found",
+ error=True)
+
if __name__ == '__main__':
import atexit
lldb.SBDebugger.Initialize()
diff --git a/lldb/test/lang/objc/modules-incomplete/myModule.h b/lldb/test/lang/objc/modules-incomplete/myModule.h
index 8f28ce086e6..d03dde0d07a 100644
--- a/lldb/test/lang/objc/modules-incomplete/myModule.h
+++ b/lldb/test/lang/objc/modules-incomplete/myModule.h
@@ -1,5 +1,7 @@
@import Foundation;
+#undef MAX
+
@interface MyClass : NSObject {
};
-(void)publicMethod;
OpenPOWER on IntegriCloud