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
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index c7d84e6..57e620b 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 @@
 
 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 @@
                               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 @@
     
     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 @@
     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 efa50b1..b4dd73b 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 @@
                                    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 @@
                    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 @@
     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 @@
         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 @@
     {
         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 @@
     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 @@
     
     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 @@
     
     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 @@
                                        uint32_t max_matches,
                                        std::vector <clang::NamedDecl*> &decls)
 {
+    if (!m_enabled)
+    {
+        return 0;
+    }
+
     if (!append)
         decls.clear();
     
@@ -257,14 +402,90 @@
 }
 
 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 08ee437..ba28431 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -458,7 +458,35 @@
     
     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 ef1b037..545476c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -446,6 +446,31 @@
         }
     }
     
+    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 28bfcb9..19faac4 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 @@
     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 @@
     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 @@
     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 1bf5c0d..2f0b3f0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -103,6 +103,7 @@
     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 @@
     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 @@
 
     GlobalVariableMap &
     GetGlobalAranges();
+    
+    void
+    UpdateExternalModuleListIfNeeded();
 
     lldb::ModuleWP                        m_debug_map_module_wp;
     SymbolFileDWARFDebugMap *             m_debug_map_symfile;
@@ -589,6 +600,7 @@
     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 @@
     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 3087bde..d5d60ae 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -227,18 +227,11 @@
                     
                     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 @@
     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 2a6e989..78ec761 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -70,6 +70,7 @@
     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 8e85d48..8eb3e3a 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -266,6 +266,12 @@
     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 914efe6..d606419 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -65,6 +65,9 @@
 
     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 6483258..d8e95ce 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -436,6 +436,23 @@
     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 6445efb..6ec9f38 100644
--- a/lldb/source/Symbol/SymbolVendor.cpp
+++ b/lldb/source/Symbol/SymbolVendor.cpp
@@ -198,6 +198,21 @@
     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 400cf47..6042a8f 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2927,6 +2927,7 @@
     { "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 @@
     ePropertyExecutableSearchPaths,
     ePropertyDebugFileSearchPaths,
     ePropertyClangModuleSearchPaths,
+    ePropertyAutoImportClangModules,
     ePropertyMaxChildrenCount,
     ePropertyMaxSummaryLength,
     ePropertyMaxMemReadSize,
@@ -3332,6 +3334,13 @@
 }
 
 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;