Add using directives to the clang::DeclContext and fix decls for variables inside namespaces

Summary: Supports the parsing of the "using namespace XXX" and "using XXX::XXX" directives. Added ambiguity errors when it two decls with the same name are encountered (see comments in TestCppNsImport). Fixes using directives being duplicated for anonymous namespaces. Fixes GetDeclForUID for specification DIEs.

Reviewers: sivachandra, chaoren, clayborg

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D12897

llvm-svn: 247836
diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp
index 1678d83..235288a 100644
--- a/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp
@@ -1351,7 +1351,6 @@
     {
         ValueObjectSP valobj;
         VariableSP var;
-        Error err;
 
         if (frame && !namespace_decl)
         {
@@ -1366,17 +1365,21 @@
 
                 // Search for declarations matching the name
                 std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name);
+                
+                bool variable_found = false;
                 for (CompilerDecl decl : found_decls)
                 {
                     var = decl.GetAsVariable();
                     if (var)
                     {
+                        variable_found = true;
                         valobj = ValueObjectVariable::Create(frame, var);
                         AddOneVariable(context, var, valobj, current_id);
                         context.m_found.variable = true;
-                        return;
                     }
                 }
+                if (variable_found)
+                    return;
             }
         }
         if (target)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 11d231d..7af63b7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -45,6 +45,9 @@
 
     virtual lldb_private::CompilerDeclContext
     GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0;
+
+    virtual std::vector<DWARFDIE>
+    GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) = 0;
 };
 
 #endif  // SymbolFileDWARF_DWARFASTParser_h_
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 29c31ed..8782ac9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -35,6 +35,9 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 
+#include <map>
+#include <vector>
+
 //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
 
 #ifdef ENABLE_DEBUG_PRINTF
@@ -2039,6 +2042,15 @@
     return false;
 }
 
+std::vector<DWARFDIE>
+DWARFASTParserClang::GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) 
+{
+    std::vector<DWARFDIE> result;
+    for (auto it = m_decl_ctx_to_die.find((clang::DeclContext *)decl_context.GetOpaqueDeclContext()); it != m_decl_ctx_to_die.end(); it++)
+        result.push_back(it->second);
+    return result;
+}
+
 CompilerDecl
 DWARFASTParserClang::GetDeclForUIDFromDWARF (const DWARFDIE &die)
 {
@@ -3213,6 +3225,9 @@
     if (!die)
         return nullptr;
 
+    if (die.GetReferencedDIE(DW_AT_specification))
+        return GetClangDeclForDIE(die.GetReferencedDIE(DW_AT_specification));
+
     clang::Decl *decl = m_die_to_decl[die.GetDIE()];
     if (decl != nullptr)
         return decl;
@@ -3261,8 +3276,8 @@
                 if (imported_decl)
                 {
                     clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
-                    if (clang::NamespaceDecl *clang_imported_decl = llvm::dyn_cast<clang::NamespaceDecl>((clang::DeclContext *)imported_decl.GetOpaqueDeclContext()))
-                        decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, clang_imported_decl);
+                    if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl))
+                        decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl);
                 }
             }
             break;
@@ -3431,7 +3446,8 @@
 {
     m_die_to_decl_ctx[die.GetDIE()] = decl_ctx;
     // There can be many DIEs for a single decl context
-    m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());
+    //m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());
+    m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die));
 }
 
 bool
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 1bfeace..4d0f928 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -51,6 +51,9 @@
     virtual lldb_private::CompilerDecl
     GetDeclForUIDFromDWARF (const DWARFDIE &die) override;
 
+    virtual std::vector<DWARFDIE>
+    GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override;
+
     virtual lldb_private::CompilerDeclContext
     GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override;
 
@@ -173,7 +176,8 @@
 
     typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
-    typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
+    //typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
+    typedef std::multimap<const clang::DeclContext *, const DWARFDIE> DeclContextToDIEMap;
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> DIEToDeclMap;
     typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
index 7857fc5..85b2425 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
@@ -12,6 +12,7 @@
 
 #include "DWARFDefines.h"
 #include "DWARFASTParser.h"
+#include "DWARFDIE.h"
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -57,6 +58,12 @@
         return lldb_private::CompilerDecl();
     }
 
+    virtual std::vector<DWARFDIE>
+    GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override
+    {
+        return std::vector<DWARFDIE>();
+    }
+
   private:
     size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic,
                                 std::vector<lldb_private::CompilerType> &function_param_types);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 8a99bc2..b654f26 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1392,6 +1392,18 @@
     return false;
 }
 
+void
+SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx)
+{
+    TypeSystem *type_system = decl_ctx.GetTypeSystem();
+    DWARFASTParser *ast_parser = type_system->GetDWARFParser();
+    std::vector<DWARFDIE> decl_ctx_die_list = ast_parser->GetDIEForDeclContext(decl_ctx);
+
+    for (DWARFDIE decl_ctx_die : decl_ctx_die_list)
+        for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; decl = decl.GetSibling())
+            ast_parser->GetDeclForUIDFromDWARF(decl);
+}
+
 CompilerDecl
 SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid)
 {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index cc0ccc9..3530e35 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -162,6 +162,10 @@
     lldb_private::CompilerDeclContext
     GetDeclContextContainingUID (lldb::user_id_t uid) override;
 
+    void
+    ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override;
+    
+
     uint32_t
     ResolveSymbolContext (const lldb_private::Address& so_addr,
                           uint32_t resolve_scope,
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 97a5a7f..712c5dd 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -1730,24 +1730,6 @@
                 // BAD!!!
             }
         }
-        
-
-        if (namespace_decl)
-        {
-            // If we make it here, we are creating the anonymous namespace decl
-            // for the first time, so we need to do the using directive magic
-            // like SEMA does
-            UsingDirectiveDecl* using_directive_decl = UsingDirectiveDecl::Create (*ast, 
-                                                                                   decl_ctx, 
-                                                                                   SourceLocation(),
-                                                                                   SourceLocation(),
-                                                                                   NestedNameSpecifierLoc(),
-                                                                                   SourceLocation(),
-                                                                                   namespace_decl,
-                                                                                   decl_ctx);
-            using_directive_decl->setImplicit();
-            decl_ctx->addDecl(using_directive_decl);
-        }
     }
 #ifdef LLDB_CONFIGURATION_DEBUG
     VerifyDecl(namespace_decl);
@@ -1768,12 +1750,29 @@
     return nullptr;
 }
 
+clang::DeclContext *
+FindLCABetweenDecls(clang::DeclContext *left, clang::DeclContext *right, clang::DeclContext *root)
+{
+    if (root == nullptr)
+        return nullptr;
+
+    std::set<clang::DeclContext *> path_left;
+    for (clang::DeclContext *d = left; d != nullptr; d = d->getParent())
+        path_left.insert(d);
+
+    for (clang::DeclContext *d = right; d != nullptr; d = d->getParent())
+        if (path_left.find(d) != path_left.end())
+            return d;
+
+    return nullptr;
+}
+
 clang::UsingDirectiveDecl *
 ClangASTContext::CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl)
 {
     if (decl_ctx != nullptr && ns_decl != nullptr)
     {
-        // TODO: run LCA between decl_tx and ns_decl
+        clang::TranslationUnitDecl *translation_unit = (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext());
         clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(*getASTContext(),
             decl_ctx,
             clang::SourceLocation(),
@@ -1781,7 +1780,7 @@
             clang::NestedNameSpecifierLoc(),
             clang::SourceLocation(),
             ns_decl,
-            GetTranslationUnitDecl(getASTContext()));
+            FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit));
         decl_ctx->addDecl(using_decl);
         return using_decl;
     }
@@ -1826,7 +1825,6 @@
             clang::SC_None);
         var_decl->setAccess(clang::AS_public);
         decl_context->addDecl(var_decl);
-        decl_context->makeDeclVisibleInContext(var_decl);
         return var_decl;
     }
     return nullptr;
@@ -8867,6 +8865,7 @@
         DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
         std::set<DeclContext *> searched;
         std::multimap<DeclContext *, DeclContext *> search_queue;
+        SymbolFile *symbol_file = GetSymbolFile();
 
         for (clang::DeclContext *decl_context = root_decl_ctx; decl_context != nullptr && found_decls.empty(); decl_context = decl_context->getParent())
         {
@@ -8875,15 +8874,11 @@
             for (auto it = search_queue.find(decl_context); it != search_queue.end(); it++)
             {
                 searched.insert(it->second);
+                symbol_file->ParseDeclsForContext(CompilerDeclContext(this, it->second));
+
                 for (clang::Decl *child : it->second->decls())
                 {
-                    if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(child))
-                    {
-                        IdentifierInfo *ii = nd->getIdentifier();
-                        if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
-                            found_decls.push_back(nd);
-                    }
-                    else if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child))
+                    if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child))
                     {
                         clang::DeclContext *from = ud->getCommonAncestor();
                         if (searched.find(ud->getNominatedNamespace()) == searched.end())
@@ -8902,6 +8897,12 @@
                             }
                         }
                     }
+                    else if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(child))
+                    {
+                        IdentifierInfo *ii = nd->getIdentifier();
+                        if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
+                            found_decls.push_back(nd);
+                    }
                 }
             }
         }