paulherman updated this revision to Diff 34609.
paulherman added a comment.

[WIP] Search variables based on clang::DeclContext and clang::Decl tree

This revision fixes some of the comments. There are some things I'm not sure 
about. The problem is that at some point there will be the need to link decls 
with the object they represent (Function, Variable, CompileUnit, etc). Is the 
approach of getting the VariableSP from the TypeSystem the right one? Also, 
should ParseVariableDIE be moved to DWARFASTParser in order to create the decl 
there or should there only be a method CreateVariableDecl(VariableSP var)?


http://reviews.llvm.org/D12658

Files:
  include/lldb/Symbol/Block.h
  include/lldb/Symbol/ClangASTContext.h
  include/lldb/Symbol/CompilerDecl.h
  include/lldb/Symbol/CompilerDeclContext.h
  include/lldb/Symbol/TypeSystem.h
  include/lldb/Symbol/Variable.h
  include/lldb/lldb-forward.h
  source/Expression/ClangASTSource.cpp
  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/SymbolFileDWARF.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  source/Symbol/CMakeLists.txt
  source/Symbol/ClangASTContext.cpp
  source/Symbol/CompilerDecl.cpp
  source/Symbol/CompilerDeclContext.cpp
  source/Symbol/Variable.cpp
  test/lang/cpp/nsimport/TestCppNsImport.py
  test/lang/cpp/nsimport/main.cpp

Index: test/lang/cpp/nsimport/main.cpp
===================================================================
--- test/lang/cpp/nsimport/main.cpp
+++ test/lang/cpp/nsimport/main.cpp
@@ -16,13 +16,49 @@
     }
 }
 
-using namespace N;
-using namespace Nested;
+namespace Global
+{
+    int global;
+}
+
+namespace Fun
+{
+    int fun_var;
+    int fun()
+    {
+        fun_var = 5;
+        return 0; // break 1
+    }
+}
+
+namespace Single
+{
+    int single = 3;
+}
+
+namespace NotImportedBefore
+{
+    int not_imported = 45;
+}
+
+using namespace Global;
+
+int not_imported = 35;
+int fun_var = 9;
+
+namespace NotImportedAfter
+{
+    int not_imported = 55;
+}
 
 int main()
 {
+    using namespace N;
+    using namespace Nested;
+    using Single::single;
     n = 1;
     anon = 2;
     nested = 3;
-    return 0; // break 0
+    global = 4;
+    return Fun::fun(); // break 0
 }
Index: test/lang/cpp/nsimport/TestCppNsImport.py
===================================================================
--- test/lang/cpp/nsimport/TestCppNsImport.py
+++ test/lang/cpp/nsimport/TestCppNsImport.py
@@ -45,6 +45,8 @@
         # Break on main function
         break_0 = target.BreakpointCreateBySourceRegex("// break 0", src_file_spec)
         self.assertTrue(break_0.IsValid() and break_0.GetNumLocations() >= 1, VALID_BREAKPOINT)
+        break_1 = target.BreakpointCreateBySourceRegex("// break 1", src_file_spec)
+        self.assertTrue(break_1.IsValid() and break_1.GetNumLocations() >= 1, VALID_BREAKPOINT)
 
         # Launch the process
         args = None
@@ -72,6 +74,32 @@
         test_result = frame.EvaluateExpression("anon")
         self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 2, "anon = 2")
 
+        test_result = frame.EvaluateExpression("global")
+        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 4, "global = 4")
+
+        test_result = frame.EvaluateExpression("fun_var")
+        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 9, "fun_var = 9")
+
+        test_result = frame.EvaluateExpression("not_imported")
+        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 35, "not_imported = 35")
+
+        test_result = frame.EvaluateExpression("single")
+        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 3, "single = 3")
+
+        # Continue to second breakpoint
+        process.Continue()
+
+        # Get the thread of the process
+        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED)
+        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+
+        # Get current fream of the thread at the breakpoint
+        frame = thread.GetSelectedFrame()
+
+        # Test function inside namespace
+        test_result = frame.EvaluateExpression("fun_var")
+        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 5, "fun_var = 5")
+        
 
 if __name__ == '__main__':
     import atexit
Index: source/Symbol/Variable.cpp
===================================================================
--- source/Symbol/Variable.cpp
+++ source/Symbol/Variable.cpp
@@ -18,6 +18,7 @@
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/ABI.h"
@@ -89,6 +90,13 @@
     return m_name;
 }
 
+ConstString
+Variable::GetUnqualifiedName() const
+{
+    return m_name;
+}
+
+
 bool
 Variable::NameMatches (const ConstString &name) const
 {
@@ -230,6 +238,12 @@
     return sizeof(Variable);
 }
 
+CompilerDeclContext
+Variable::GetParentDeclContext ()
+{
+    Type *type = GetType();
+    return type->GetSymbolFile()->GetDeclContextContainingUID(GetID());
+}
 
 void
 Variable::CalculateSymbolContext (SymbolContext *sc)
Index: source/Symbol/CompilerDeclContext.cpp
===================================================================
--- source/Symbol/CompilerDeclContext.cpp
+++ source/Symbol/CompilerDeclContext.cpp
@@ -8,10 +8,25 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/CompilerDecl.h"
 #include "lldb/Symbol/TypeSystem.h"
+#include <vector>
 
 using namespace lldb_private;
 
+std::vector<CompilerDecl>
+CompilerDeclContext::FindDeclByName (ConstString name)
+{
+    std::vector<CompilerDecl> found_decls;
+    if (IsValid())
+    {
+        std::vector<void *> found_opaque_decls = m_type_system->DeclContextFindDeclByName(m_opaque_decl_ctx, name);
+        for (void *opaque_decl : found_opaque_decls)
+            found_decls.push_back(CompilerDecl(m_type_system, opaque_decl));
+    }
+    return found_decls;
+}
+
 bool
 CompilerDeclContext::IsClang () const
 {
Index: source/Symbol/CompilerDecl.cpp
===================================================================
--- /dev/null
+++ source/Symbol/CompilerDecl.cpp
@@ -0,0 +1,46 @@
+//===-- CompilerDecl.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+using namespace lldb_private;
+
+bool
+CompilerDecl::IsClang () const
+{
+    return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang;
+}
+
+ConstString
+CompilerDecl::GetName() const
+{
+    return m_type_system->DeclGetName(m_opaque_decl);
+}
+
+lldb::VariableSP
+CompilerDecl::GetAsVariable ()
+{
+    return m_type_system->DeclGetVariable(m_opaque_decl);
+}
+
+bool
+lldb_private::operator == (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs)
+{
+    return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueDecl() == rhs.GetOpaqueDecl();
+}
+
+
+bool
+lldb_private::operator != (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs)
+{
+    return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl();
+}
+
Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ source/Symbol/ClangASTContext.cpp
@@ -1750,6 +1750,82 @@
 }
 
 
+clang::BlockDecl *
+ClangASTContext::CreateBlockDeclaration (clang::DeclContext *ctx)
+{
+    if (ctx != nullptr)
+    {
+        clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, clang::SourceLocation());
+        ctx->addDecl(decl);
+        return decl;
+    }
+    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::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(*getASTContext(),
+            decl_ctx,
+            clang::SourceLocation(),
+            clang::SourceLocation(),
+            clang::NestedNameSpecifierLoc(),
+            clang::SourceLocation(),
+            ns_decl,
+            GetTranslationUnitDecl(getASTContext()));
+        decl_ctx->addDecl(using_decl);
+        return using_decl;
+    }
+    return nullptr;
+}
+
+clang::UsingDecl *
+ClangASTContext::CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target)
+{
+    if (current_decl_ctx != nullptr && target != nullptr)
+    {
+        clang::UsingDecl *using_decl = clang::UsingDecl::Create(*getASTContext(),
+            current_decl_ctx,
+            clang::SourceLocation(),
+            clang::NestedNameSpecifierLoc(),
+            clang::DeclarationNameInfo(),
+            false);
+        clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(*getASTContext(),
+            current_decl_ctx,
+            clang::SourceLocation(),
+            using_decl,
+            target);
+        using_decl->addShadowDecl(shadow_decl);
+        current_decl_ctx->addDecl(using_decl);
+        return using_decl;
+    }
+    return nullptr;
+}
+
+clang::VarDecl *
+ClangASTContext::CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type)
+{
+    if (decl_context != nullptr)
+    {
+        clang::VarDecl *var_decl = clang::VarDecl::Create(*getASTContext(),
+            decl_context,
+            clang::SourceLocation(),
+            clang::SourceLocation(),
+            name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr,
+            type,
+            nullptr,
+            clang::SC_None);
+        var_decl->setAccess(clang::AS_public);
+        decl_context->addDecl(var_decl);
+        decl_context->makeDeclVisibleInContext(var_decl);
+        return var_decl;
+    }
+    return nullptr;
+}
+
 #pragma mark Function Types
 
 FunctionDecl *
@@ -8812,9 +8888,94 @@
 }
 
 //----------------------------------------------------------------------
+// CompilerDecl override functions
+//----------------------------------------------------------------------
+lldb::VariableSP
+ClangASTContext::DeclGetVariable (void *opaque_decl)
+{
+    if (llvm::dyn_cast<clang::VarDecl>((clang::Decl *)opaque_decl))
+    {
+        auto decl_search_it = m_decl_objects.find(opaque_decl);
+        if (decl_search_it != m_decl_objects.end())
+            return std::static_pointer_cast<Variable>(decl_search_it->second);
+    }
+    return VariableSP();
+}
+
+void
+ClangASTContext::DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object)
+{
+    assert(m_decl_objects.find(opaque_decl) == m_decl_objects.end());
+    m_decl_objects.insert(std::make_pair(opaque_decl, object));
+}
+
+ConstString
+ClangASTContext::DeclGetName (void *opaque_decl)
+{
+    if (opaque_decl)
+    {
+        clang::NamedDecl *nd = llvm::dyn_cast<NamedDecl>((clang::Decl*)opaque_decl);
+        if (nd != nullptr)
+            return ConstString(nd->getName());
+    }
+    return ConstString();
+}
+
+//----------------------------------------------------------------------
 // CompilerDeclContext functions
 //----------------------------------------------------------------------
 
+std::vector<void *>
+ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name)
+{
+    std::vector<void *> found_decls;
+    if (opaque_decl_ctx)
+    {
+        DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
+        std::set<DeclContext *> searched;
+        std::multimap<DeclContext *, DeclContext *> search_queue;
+
+        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);
+                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))
+                    {
+                        clang::DeclContext *from = ud->getCommonAncestor();
+                        if (searched.find(ud->getNominatedNamespace()) == searched.end())
+                            search_queue.insert(std::make_pair(from, ud->getNominatedNamespace()));
+                    }
+                    else if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child))
+                    {
+                        for (clang::UsingShadowDecl *usd : ud->shadows())
+                        {
+                            clang::Decl *target = usd->getTargetDecl();
+                            if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target))
+                            {
+                                IdentifierInfo *ii = nd->getIdentifier();
+                                if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
+                                    found_decls.push_back(nd);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return found_decls;
+}
+
 bool
 ClangASTContext::DeclContextIsStructUnionOrClass (void *opaque_decl_ctx)
 {
Index: source/Symbol/CMakeLists.txt
===================================================================
--- source/Symbol/CMakeLists.txt
+++ source/Symbol/CMakeLists.txt
@@ -4,6 +4,7 @@
   ClangASTImporter.cpp
   ClangExternalASTSourceCallbacks.cpp
   ClangExternalASTSourceCommon.cpp
+  CompilerDecl.cpp
   CompilerDeclContext.cpp
   CompilerType.cpp
   CompileUnit.cpp
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -400,6 +400,12 @@
                     bool parse_children,
                     lldb_private::VariableList* cc_variable_list = NULL);
 
+    void
+    ParseImportedNamespace (
+        const lldb_private::SymbolContext &sc,
+        const DWARFDIE die,
+        const lldb::addr_t func_low_pc);
+
     bool
     ClassOrStructIsVirtual (const DWARFDIE &die);
 
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -48,6 +48,8 @@
 #include "lldb/Interpreter/OptionValueProperties.h"
 
 #include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
@@ -3048,6 +3050,8 @@
                     case DW_TAG_structure_type:
                     case DW_TAG_union_type:
                     case DW_TAG_class_type:
+                    case DW_TAG_lexical_block:
+                    case DW_TAG_subprogram:
                         return die;
                         
                     default:
@@ -3697,13 +3701,80 @@
 
                     }
                 }
+                if (DWARFDIE cu_die = dwarf_cu->GetDIE(dwarf_cu->GetFirstDIEOffset()))
+                    for (auto d = cu_die.GetFirstChild(); d; d = d.GetSibling())
+                        ParseImportedNamespace(sc, d, LLDB_INVALID_ADDRESS);
             }
             return vars_added;
         }
     }
     return 0;
 }
 
+void
+SymbolFileDWARF::ParseImportedNamespace
+(
+    const SymbolContext &sc,
+    const DWARFDIE die,
+    const lldb::addr_t func_low_pc
+)
+{
+    return;
+    if (!die || (die.Tag() != DW_TAG_imported_module && die.Tag() != DW_TAG_imported_declaration))
+        return;
+
+    dw_offset_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET);
+    if (UserIDMatches(imported_uid))
+    {
+        DWARFDebugInfo *debug_info = DebugInfo();
+        if (debug_info)
+        {
+            const DWARFDIE imported_die = debug_info->GetDIE(DIERef(imported_uid));
+            TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
+            if (type_system)
+            {
+                DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+                if (dwarf_ast != nullptr)
+                {
+                    sc.comp_unit->GetVariableList(true); 
+                    clang::DeclContext *context = nullptr;
+                    if (sc.block != nullptr)
+                        context = ClangASTContext::DeclContextGetAsDeclContext(sc.block->GetDeclContext());
+                    else
+                        context = GetClangASTContext().GetTranslationUnitDecl(GetClangASTContext().getASTContext());
+
+                    if (context != nullptr)
+                    {
+                        if (die.Tag() == DW_TAG_imported_module)
+                        {
+                            CompilerDeclContext ns_decl_context = dwarf_ast->GetDeclContextForUIDFromDWARF(imported_die);
+                            if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(ns_decl_context))
+                                GetClangASTContext().CreateUsingDirectiveDeclaration(context, ns_decl);
+                        }
+                        else if (die.Tag() == DW_TAG_imported_declaration)
+                        {
+                            // TODO: handle imported declarations (using Namespace::Symbol) for other tags
+                            if (imported_die.Tag() == DW_TAG_variable)
+                            {
+                                VariableSP var = ParseVariableDIE(sc, imported_die, func_low_pc);
+                                if (var)
+                                {
+                                    CompilerDecl clang_var_decl = var->GetVarDecl();
+                                    if (clang_var_decl)
+                                    {
+                                        clang::VarDecl *var_decl = (clang::VarDecl *)clang_var_decl.GetOpaqueDecl();
+                                        GetClangASTContext().CreateUsingDeclaration(context, var_decl);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
 VariableSP
 SymbolFileDWARF::ParseVariableDIE
 (
@@ -3732,6 +3803,7 @@
     {
         DWARFAttributes attributes;
         const size_t num_attributes = die.GetAttributes(attributes);
+        DWARFDIE spec_die;
         if (num_attributes > 0)
         {
             const char *name = NULL;
@@ -3853,7 +3925,17 @@
                             }
                         }
                         break;
-
+                    case DW_AT_specification:
+                    {
+                        dw_offset_t spec_uid = form_value.Reference();
+                        if (UserIDMatches(spec_uid))
+                        {
+                            DWARFDebugInfo* debug_info = DebugInfo();
+                            if (debug_info)
+                                spec_die = debug_info->GetDIE(DIERef(spec_uid));
+                        }
+                        break;
+                    }
                     case DW_AT_artificial:      is_artificial = form_value.Boolean(); break;
                     case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
                     case DW_AT_declaration:
@@ -3865,15 +3947,14 @@
                     default:
                     case DW_AT_abstract_origin:
                     case DW_AT_sibling:
-                    case DW_AT_specification:
                         break;
                     }
                 }
             }
 
             const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
             const dw_tag_t parent_tag = die.GetParent().Tag();
-            bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type);
+            bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type );
 
             ValueType scope = eValueTypeInvalid;
 
@@ -4069,6 +4150,26 @@
         // (missing location due to optimization, etc)) so we don't re-parse
         // this DIE over and over later...
         GetDIEToVariable()[die.GetDIE()] = var_sp;
+        if (spec_die)
+            GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
+
+        if (var_sp && var_sp->GetType())
+        {
+            CompilerDeclContext decl_context = var_sp->GetParentDeclContext();
+            if (decl_context)
+            {
+                clang::DeclContext *dc = ClangASTContext::DeclContextGetAsDeclContext(decl_context);
+                if (dc)
+                {
+                    clang::VarDecl *clang_var_decl = GetClangASTContext().CreateVariableDeclaration(
+                        dc,
+                        var_sp->GetUnqualifiedName().AsCString(nullptr), 
+                        GetClangASTContext().GetQualType(var_sp->GetType()->GetForwardCompilerType()));
+                    if (clang_var_decl)
+                        GetClangASTContext().DeclLinkToObject((void *)clang_var_decl, var_sp);
+                }
+            }
+        }
     }
     return var_sp;
 }
@@ -4232,6 +4333,8 @@
                     }
                 }
             }
+            else if (tag == DW_TAG_imported_module || tag == DW_TAG_imported_declaration)
+                ParseImportedNamespace(sc, die, func_low_pc);
         }
 
         bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -83,6 +83,9 @@
         llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
     };
 
+    clang::BlockDecl *
+    ResolveBlockDIE (const DWARFDIE &die);
+
     clang::NamespaceDecl *
     ResolveNamespaceDIE (const DWARFDIE &die);
 
@@ -156,6 +159,9 @@
     LinkDeclContextToDIE (clang::DeclContext *decl_ctx,
                           const DWARFDIE &die);
 
+    void
+    LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die);
+
     typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
     typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -111,7 +111,6 @@
     }
 };
 
-
 TypeSP
 DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
                                          const DWARFDIE &die,
@@ -2202,7 +2201,6 @@
 };
 #endif
 
-
 Function *
 DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc,
                                              const DWARFDIE &die)
@@ -3197,6 +3195,11 @@
                 try_parsing_type = false;
                 break;
 
+            case DW_TAG_lexical_block:
+                decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die);
+                try_parsing_type = false;
+                break;
+
             default:
                 break;
         }
@@ -3217,6 +3220,28 @@
     return nullptr;
 }
 
+clang::BlockDecl *
+DWARFASTParserClang::ResolveBlockDIE (const DWARFDIE &die)
+{
+    if (die && die.Tag() == DW_TAG_lexical_block)
+    {
+        clang::BlockDecl *decl = llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]);
+        
+        if (!decl)
+        {
+            DWARFDIE decl_context_die;
+            clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die);
+            decl = m_ast.CreateBlockDeclaration(decl_context);
+
+            if (decl)
+                LinkDeclContextToDIE((clang::DeclContext *)decl, die);
+        }
+
+        return decl;
+    }
+    return nullptr;
+}
+
 clang::NamespaceDecl *
 DWARFASTParserClang::ResolveNamespaceDIE (const DWARFDIE &die)
 {
@@ -3285,10 +3310,6 @@
     return m_ast.GetTranslationUnitDecl();
 }
 
-
-
-
-
 clang::DeclContext *
 DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die)
 {
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -27,7 +27,6 @@
                         lldb_private::Log *log,
                         bool *type_is_new_ptr) = 0;
 
-
     virtual lldb_private::Function *
     ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
                             const DWARFDIE &die) = 0;
@@ -42,7 +41,6 @@
 
     virtual lldb_private::CompilerDeclContext
     GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0;
-
 };
 
 #endif  // SymbolFileDWARF_DWARFASTParser_h_
Index: source/Expression/ClangExpressionDeclMap.cpp
===================================================================
--- source/Expression/ClangExpressionDeclMap.cpp
+++ source/Expression/ClangExpressionDeclMap.cpp
@@ -28,6 +28,7 @@
 #include "lldb/Expression/Materializer.h"
 #include "lldb/Host/Endian.h"
 #include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerDecl.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
@@ -1035,6 +1036,9 @@
     // doesn't start with our phony prefix of '$'
     Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
     StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+    SymbolContext sym_ctx;
+    if (frame != nullptr)
+        sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
     if (name_unique_cstr[0] == '$' && !namespace_decl)
     {
         static ConstString g_lldb_class_name ("$__lldb_class");
@@ -1046,7 +1050,6 @@
             if (frame == NULL)
                 return;
 
-            SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
 
             // Find the block that defines the function represented by "sym_ctx"
             Block *function_block = sym_ctx.GetFunctionBlock();
@@ -1352,24 +1355,28 @@
 
         if (frame && !namespace_decl)
         {
-            valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr,
-                                                              eNoDynamicValues,
-                                                              StackFrame::eExpressionPathOptionCheckPtrVsMember |
-                                                              StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
-                                                              StackFrame::eExpressionPathOptionsNoSyntheticChildren |
-                                                              StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
-                                                              var,
-                                                              err);
-
-            // If we found a variable in scope, no need to pull up function names
-            if (err.Success() && var)
+            CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext();
+
+            if (compiler_decl_context)
             {
-                AddOneVariable(context, var, valobj, current_id);
-                context.m_found.variable = true;
-                return;
+                // Make sure that the variables are parsed so that we have the declarations
+                frame->GetInScopeVariableList(true);
+
+                // Search for declarations matching the name
+                std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name);
+                for (CompilerDecl decl : found_decls)
+                {
+                    var = decl.GetAsVariable();
+                    if (var)
+                    {
+                        valobj = ValueObjectVariable::Create(frame, var);
+                        AddOneVariable(context, var, valobj, current_id);
+                        context.m_found.variable = true;
+                        return;
+                    }
+                }
             }
         }
-
         if (target)
         {
             var = FindGlobalVariable (*target,
Index: source/Expression/ClangASTSource.cpp
===================================================================
--- source/Expression/ClangASTSource.cpp
+++ source/Expression/ClangASTSource.cpp
@@ -515,7 +515,7 @@
                 else
                     log->Printf("  FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString());
             }
-
+            
             Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl);
 
             if (!copied_decl)
Index: include/lldb/lldb-forward.h
===================================================================
--- include/lldb/lldb-forward.h
+++ include/lldb/lldb-forward.h
@@ -64,6 +64,7 @@
 class   CommandReturnObject;
 class   Communication;
 class   CompactUnwindInfo;
+class   CompilerDecl;
 class   CompilerDeclContext;
 class   CompilerType;
 class   CompileUnit;
Index: include/lldb/Symbol/Variable.h
===================================================================
--- include/lldb/Symbol/Variable.h
+++ include/lldb/Symbol/Variable.h
@@ -18,6 +18,8 @@
 #include "lldb/Core/UserID.h"
 #include "lldb/Expression/DWARFExpression.h"
 #include "lldb/Symbol/Declaration.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
 
 namespace lldb_private {
 
@@ -59,6 +61,9 @@
     ConstString
     GetName() const;
 
+    ConstString
+    GetUnqualifiedName() const;
+
     SymbolContextScope *
     GetSymbolContextScope() const
     {
@@ -167,6 +172,21 @@
                   StringList &matches,
                   bool &word_complete);
 
+    CompilerDeclContext
+    GetParentDeclContext ();
+
+    CompilerDecl
+    GetVarDecl ()
+    {
+        return m_var_decl;
+    }
+
+    void
+    SetVarDecl (CompilerDecl var_decl)
+    {
+        m_var_decl = var_decl;
+    }
+
 protected:
     ConstString m_name;                 // The basename of the variable (no namespaces)
     Mangled m_mangled;                  // The mangled name of the variable
@@ -179,6 +199,7 @@
             m_artificial:1,             // Non-zero if the variable is not explicitly declared in source
             m_loc_is_const_data:1,      // The m_location expression contains the constant variable value data, not a DWARF location
             m_static_member:1;          // Non-zero if variable is static member of a class or struct.
+    CompilerDecl m_var_decl;
 private:
     Variable(const Variable& rhs);
     Variable& operator=(const Variable& rhs);
Index: include/lldb/Symbol/TypeSystem.h
===================================================================
--- include/lldb/Symbol/TypeSystem.h
+++ include/lldb/Symbol/TypeSystem.h
@@ -97,8 +97,23 @@
     }
 
     //----------------------------------------------------------------------
+    // CompilerDecl functions
+    //----------------------------------------------------------------------
+    virtual ConstString
+    DeclGetName (void *opaque_decl) = 0;
+
+    virtual lldb::VariableSP
+    DeclGetVariable (void *opaque_decl) = 0;
+
+    virtual void
+    DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) = 0;
+
+    //----------------------------------------------------------------------
     // CompilerDeclContext functions
     //----------------------------------------------------------------------
+    
+    virtual std::vector<void *>
+    DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) = 0;
 
     virtual bool
     DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) = 0;
Index: include/lldb/Symbol/CompilerDeclContext.h
===================================================================
--- include/lldb/Symbol/CompilerDeclContext.h
+++ include/lldb/Symbol/CompilerDeclContext.h
@@ -9,7 +9,6 @@
 
 #ifndef liblldb_CompilerDeclContext_h_
 #define liblldb_CompilerDeclContext_h_
-
 #include "lldb/lldb-private.h"
 #include "lldb/Core/ConstString.h"
 
@@ -50,7 +49,7 @@
     operator < (const CompilerDeclContext &rhs) const
     {
         if (m_type_system == rhs.m_type_system)
-            return m_type_system < rhs.m_type_system;
+            return m_opaque_decl_ctx < rhs.m_opaque_decl_ctx;
         return m_type_system < rhs.m_type_system;
     }
 
@@ -63,6 +62,9 @@
     bool
     IsClang () const;
 
+    std::vector<CompilerDecl>
+    FindDeclByName (ConstString name);
+
     //----------------------------------------------------------------------
     /// Checks if this decl context represents a method of a class.
     ///
Index: include/lldb/Symbol/CompilerDecl.h
===================================================================
--- /dev/null
+++ include/lldb/Symbol/CompilerDecl.h
@@ -0,0 +1,116 @@
+//===-- CompilerDecl.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CompilerDecl_h_
+#define liblldb_CompilerDecl_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+
+namespace lldb_private {
+
+class CompilerDecl
+{
+public:
+    //----------------------------------------------------------------------
+    // Constructors and Destructors
+    //----------------------------------------------------------------------
+    CompilerDecl () :
+        m_type_system  (nullptr),
+        m_opaque_decl (nullptr)
+    {
+    }
+
+    CompilerDecl (TypeSystem *type_system, void *decl) :
+        m_type_system (type_system),
+        m_opaque_decl (decl)
+    {
+    }
+
+    ~CompilerDecl ()
+    {
+    }
+
+    //----------------------------------------------------------------------
+    // Tests
+    //----------------------------------------------------------------------
+
+    explicit operator bool () const
+    {
+        return IsValid ();
+    }
+    
+    bool
+    operator < (const CompilerDecl &rhs) const
+    {
+        if (m_type_system == rhs.m_type_system)
+            return m_opaque_decl < rhs.m_opaque_decl;
+        return m_type_system < rhs.m_type_system;
+    }
+
+    bool
+    IsValid () const
+    {
+        return m_type_system != nullptr && m_opaque_decl != nullptr;
+    }
+
+    bool
+    IsClang () const;
+
+    //----------------------------------------------------------------------
+    // Object linked to the decl
+    //----------------------------------------------------------------------
+    lldb::VariableSP
+    GetAsVariable ();
+
+    //----------------------------------------------------------------------
+    // Accessors
+    //----------------------------------------------------------------------
+    
+    TypeSystem *
+    GetTypeSystem() const
+    {
+        return m_type_system;
+    }
+    
+    void *
+    GetOpaqueDecl() const
+    {
+        return m_opaque_decl;
+    }
+
+    void
+    SetDecl (TypeSystem* type_system, void* decl)
+    {
+        m_type_system = type_system;
+        m_opaque_decl = decl;
+    }
+
+    void
+    Clear()
+    {
+        m_type_system = nullptr;
+        m_opaque_decl = nullptr;
+    }
+
+    ConstString
+    GetName () const;
+
+private:
+    TypeSystem *m_type_system;
+    void *m_opaque_decl;
+};
+    
+bool operator == (const CompilerDecl &lhs, const CompilerDecl &rhs);
+bool operator != (const CompilerDecl &lhs, const CompilerDecl &rhs);
+
+    
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_CompilerDecl_h_
Index: include/lldb/Symbol/ClangASTContext.h
===================================================================
--- include/lldb/Symbol/ClangASTContext.h
+++ include/lldb/Symbol/ClangASTContext.h
@@ -23,13 +23,17 @@
 #include "llvm/ADT/SmallVector.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/TemplateBase.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 
 // Project includes
 #include "lldb/lldb-enumerations.h"
 #include "lldb/Core/ClangForward.h"
 #include "lldb/Core/ConstString.h"
+#include "lldb/Symbol/Block.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Symbol/Variable.h"
 
 namespace lldb_private {
 
@@ -508,8 +512,23 @@
                      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
 
     //----------------------------------------------------------------------
+    // CompilerDecl override functions
+    //----------------------------------------------------------------------
+    lldb::VariableSP
+    DeclGetVariable (void *opaque_decl) override;
+
+    void
+    DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) override;
+    
+    ConstString
+    DeclGetName (void *opaque_decl) override;
+
+    //----------------------------------------------------------------------
     // CompilerDeclContext override functions
     //----------------------------------------------------------------------
+    
+    std::vector<void *>
+    DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name);
 
     bool
     DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) override;
@@ -1071,6 +1090,17 @@
                             int tag_decl_kind,
                             const ClangASTContext::TemplateParameterInfos &template_param_infos);
 
+    clang::BlockDecl *
+    CreateBlockDeclaration (clang::DeclContext *ctx);
+
+    clang::UsingDirectiveDecl *
+    CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl);
+
+    clang::UsingDecl *
+    CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target);
+
+    clang::VarDecl *
+    CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type);
 protected:
     static clang::QualType
     GetQualType (void *type)
@@ -1110,6 +1140,7 @@
     void *                                          m_callback_baton;
     uint32_t                                        m_pointer_byte_size;
     bool                                            m_ast_owned;
+    std::map<void *, std::shared_ptr<void>>         m_decl_objects;
 
 private:
     //------------------------------------------------------------------
Index: include/lldb/Symbol/Block.h
===================================================================
--- include/lldb/Symbol/Block.h
+++ include/lldb/Symbol/Block.h
@@ -18,6 +18,7 @@
 #include "lldb/Symbol/LineEntry.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
 
 namespace lldb_private {
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to