paulherman created this revision.
paulherman added reviewers: sivachandra, chaoren, clayborg.
paulherman added a subscriber: lldb-commits.

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.

http://reviews.llvm.org/D12897

Files:
  include/lldb/Symbol/SymbolFile.h
  source/Expression/ClangExpressionDeclMap.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
  source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  source/Symbol/ClangASTContext.cpp
  test/lang/cpp/nsimport/TestCppNsImport.py

Index: test/lang/cpp/nsimport/TestCppNsImport.py
===================================================================
--- test/lang/cpp/nsimport/TestCppNsImport.py
+++ test/lang/cpp/nsimport/TestCppNsImport.py
@@ -16,8 +16,6 @@
         self.buildDsym()
         self.check()
 
-    # This test is expected to fail because DW_TAG_imported_declaration and DW_TAG_imported_module are not parsed in SymbolFileDWARF
-    @expectedFailureAll
     @dwarf_test
     def test_with_dwarf_and_run_command(self):
         """Tests imported namespaces in C++."""
@@ -82,18 +80,21 @@
         test_result = frame.EvaluateExpression("fun_var")
         self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 9, "fun_var = 9")
 
+        test_result = frame.EvaluateExpression("Fun::fun_var")
+        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 0, "Fun::fun_var = 0")
+
         test_result = frame.EvaluateExpression("not_imported")
         self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 35, "not_imported = 35")
 
-        # Disabled the "imported" test since it isn't valid. It should actually test for ambiguity
-        #test_result = frame.EvaluateExpression("imported")
-        #self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 99, "imported = 99")
-
-        test_result = frame.EvaluateExpression("::imported")
-        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 89, "::imported = 89")
+        # Currently there is no way to distinguish between "::imported" and "imported" in ClangExpressionDeclMap so this fails
+        #test_result = frame.EvaluateExpression("::imported")
+        #self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 89, "::imported = 89")
 
         test_result = frame.EvaluateExpression("Imported::imported")
         self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 99, "Imported::imported = 99")
+        
+        test_result = frame.EvaluateExpression("imported")
+        self.assertTrue(test_result.IsValid() and test_result.GetError().Fail(), "imported is ambiguous")
 
         test_result = frame.EvaluateExpression("single")
         self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 3, "single = 3")
Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ 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,20 +1750,37 @@
     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(),
             clang::SourceLocation(),
             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;
@@ -8940,23 +8938,20 @@
         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())
         {
             search_queue.insert(std::make_pair(decl_context, decl_context));
 
             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())
@@ -8975,6 +8970,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);
+                    }
                 }
             }
         }
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -161,6 +161,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,
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1393,6 +1393,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)
 {
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
+++ 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);
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ 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;
 
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ 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
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ 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_
Index: source/Expression/ClangExpressionDeclMap.cpp
===================================================================
--- source/Expression/ClangExpressionDeclMap.cpp
+++ 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)
Index: include/lldb/Symbol/SymbolFile.h
===================================================================
--- include/lldb/Symbol/SymbolFile.h
+++ include/lldb/Symbol/SymbolFile.h
@@ -131,6 +131,7 @@
     virtual size_t          ParseVariablesForContext (const SymbolContext& sc) = 0;
     virtual Type*           ResolveTypeUID (lldb::user_id_t type_uid) = 0;
     virtual bool            CompleteType (CompilerType &clang_type) = 0;
+    virtual void            ParseDeclsForContext (CompilerDeclContext decl_ctx) {}
     virtual CompilerDecl    GetDeclForUID (lldb::user_id_t uid) { return CompilerDecl(); }
     virtual CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) { return CompilerDeclContext(); }
     virtual CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) { return CompilerDeclContext(); }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to