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(); } 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 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: 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 + GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) = 0; }; #endif // SymbolFileDWARF_DWARFASTParser_h_ 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 + GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override; + virtual lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override; @@ -173,7 +176,8 @@ typedef llvm::SmallPtrSet DIEPointerSet; typedef llvm::DenseMap DIEToDeclContextMap; - typedef llvm::DenseMap DeclContextToDIEMap; + //typedef llvm::DenseMap DeclContextToDIEMap; + typedef std::multimap DeclContextToDIEMap; typedef llvm::DenseMap DIEToDeclMap; typedef llvm::DenseMap 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 +#include + //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN #ifdef ENABLE_DEBUG_PRINTF @@ -2039,6 +2042,15 @@ return false; } +std::vector +DWARFASTParserClang::GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) +{ + std::vector 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::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/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 + GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override + { + return std::vector(); + } + private: size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic, std::vector &function_param_types); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ 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, Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ 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 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/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,12 +1750,29 @@ return nullptr; } +clang::DeclContext * +FindLCABetweenDecls(clang::DeclContext *left, clang::DeclContext *right, clang::DeclContext *root) +{ + if (root == nullptr) + return nullptr; + + std::set 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 searched; std::multimap 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(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(child)) + if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast(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(child)) + { + IdentifierInfo *ii = nd->getIdentifier(); + if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr))) + found_decls.push_back(nd); + } } } } Index: test/lang/cpp/nsimport/TestCppNsImport.py =================================================================== --- test/lang/cpp/nsimport/TestCppNsImport.py +++ test/lang/cpp/nsimport/TestCppNsImport.py @@ -80,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")