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/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);