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 { @@ -358,6 +359,18 @@ CompilerDeclContext GetDeclContext(); + CompilerDeclContext + GetClangDecl() + { + return m_clang_decl_context; + } + + void + SetClangDecl(CompilerDeclContext decl) + { + m_clang_decl_context = decl; + } + //------------------------------------------------------------------ /// Get the memory cost of this object. /// @@ -476,6 +489,7 @@ bool m_parsed_block_info:1, ///< Set to true if this block and it's children have all been parsed m_parsed_block_variables:1, m_parsed_child_blocks:1; + CompilerDeclContext m_clang_decl_context; // A parent of child blocks can be asked to find a sibling block given // one of its child blocks Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -28,8 +28,10 @@ #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 { @@ -1069,6 +1071,52 @@ int tag_decl_kind, const ClangASTContext::TemplateParameterInfos &template_param_infos); + clang::DeclContext * + CreateBlockDeclaration (clang::DeclContext *ctx, lldb_private::Block *block) + { + if (ctx != nullptr && block != nullptr) + { + clang::DeclContext *decl = clang::BlockDecl::Create(*getASTContext(), ctx, clang::SourceLocation()); + CompilerDeclContext decl_context(this, (void *)decl); + block->SetClangDecl(decl_context); + return decl; + } + return nullptr; + } + + clang::VarDecl * + CreateVariableDeclaration (clang::DeclContext *decl_ctx, lldb::VariableSP var_sp, CompilerType clang_type) + { + if (decl_ctx != nullptr && var_sp && clang_type.IsValid()) + { + const char *name = var_sp->GetUnqualifiedName().AsCString(nullptr); + clang::VarDecl *var_decl = clang::VarDecl::Create(*getASTContext(), + decl_ctx, + clang::SourceLocation(), + clang::SourceLocation(), + name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, + GetQualType(clang_type), + nullptr, + clang::SC_None); + var_decl->setAccess(clang::AS_public); + decl_ctx->addDecl(var_decl); + decl_ctx->makeDeclVisibleInContext(var_decl); + m_decl_to_var.insert(std::make_pair(var_decl, var_sp)); + var_sp->SetVarDecl(CompilerDeclContext(this, var_decl)); + return var_decl; + } + return nullptr; + } + + lldb::VariableSP + GetVariableFromDecl (clang::VarDecl *var_decl) + { + auto decl_to_var_it = m_decl_to_var.find(var_decl); + if (decl_to_var_it != m_decl_to_var.end()) + return decl_to_var_it->second; + return lldb::VariableSP(); + } + protected: static clang::QualType GetQualType (void *type) @@ -1108,6 +1156,7 @@ void * m_callback_baton; uint32_t m_pointer_byte_size; bool m_ast_owned; + std::map m_decl_to_var; private: //------------------------------------------------------------------ Index: include/lldb/Symbol/Variable.h =================================================================== --- include/lldb/Symbol/Variable.h +++ include/lldb/Symbol/Variable.h @@ -18,6 +18,7 @@ #include "lldb/Core/UserID.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/Declaration.h" +#include "lldb/Symbol/CompilerDeclContext.h" namespace lldb_private { @@ -59,6 +60,9 @@ ConstString GetName() const; + ConstString + GetUnqualifiedName() const; + SymbolContextScope * GetSymbolContextScope() const { @@ -167,6 +171,21 @@ StringList &matches, bool &word_complete); + CompilerDeclContext + GetParentDeclContext (); + + CompilerDeclContext + GetVarDecl () + { + return m_var_decl; + } + + void + SetVarDecl (CompilerDeclContext 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 +198,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. + CompilerDeclContext m_var_decl; private: Variable(const Variable& rhs); Variable& operator=(const Variable& rhs); 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: source/Expression/ClangExpressionDeclMap.cpp =================================================================== --- source/Expression/ClangExpressionDeclMap.cpp +++ source/Expression/ClangExpressionDeclMap.cpp @@ -1031,6 +1031,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"); @@ -1042,7 +1045,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(); @@ -1348,6 +1350,36 @@ if (frame && !namespace_decl) { + CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetClangDecl() : CompilerDeclContext(); + ClangASTContext *ast_context = (ClangASTContext *)compiler_decl_context.GetTypeSystem(); + + if (ast_context != nullptr && compiler_decl_context.IsValid()) + { + std::vector found_vars; + + // Make sure that the variables are parsed so that we have the declarations + frame->GetInScopeVariableList(true); + + // TODO: take care of imported decls + + for (clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_context); decl_context != nullptr && found_vars.empty(); decl_context = decl_context->getParent()) + for (clang::Decl *child : decl_context->decls()) + if (clang::VarDecl *vd = llvm::dyn_cast(child)) + if (ast_context->GetVariableFromDecl(vd) && vd->getName().equals(name_unique_cstr)) + found_vars.push_back(vd); + + for (clang::VarDecl *var_decl : found_vars) + { + var = ast_context->GetVariableFromDecl(var_decl); + valobj = ValueObjectVariable::Create(frame, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + return; + } + } + } + /*if (frame && !namespace_decl) + { valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr, eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember | @@ -1364,8 +1396,7 @@ context.m_found.variable = true; return; } - } - + }*/ if (target) { var = FindGlobalVariable (*target, Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3200,7 +3200,6 @@ decl_ctx = ResolveNamespaceDIE (die); try_parsing_type = false; break; - default: break; } Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1321,6 +1321,17 @@ block->SetInlinedFunctionInfo (name, mangled_name, decl_ap.get(), call_ap.get()); } + CompilerDeclContext parent_decl_ctx; + if (block->GetParent() != nullptr && block->GetParent()->GetClangDecl().IsValid()) + parent_decl_ctx = block->GetParent()->GetClangDecl(); + else + parent_decl_ctx = block->GetDeclContext(); + + clang::DeclContext *containing_decl_context = ClangASTContext::DeclContextGetAsDeclContext(parent_decl_ctx); + if (containing_decl_context != nullptr) + GetClangASTContext().CreateBlockDeclaration(containing_decl_context, block); + + ++blocks_added; if (die.HasChildren()) @@ -4099,6 +4110,20 @@ // (missing location due to optimization, etc)) so we don't re-parse // this DIE over and over later... m_die_to_variable_sp[die.GetDIE()] = var_sp; + + if (var_sp && var_sp->GetType()) + { + SymbolContext sc; + var_sp->CalculateSymbolContext(&sc); + CompilerDeclContext var_decl_context; + if (sc.block != nullptr) + var_decl_context = sc.block->GetClangDecl(); + else + var_decl_context = var_sp->GetParentDeclContext(); + + if (var_decl_context) + GetClangASTContext().CreateVariableDeclaration(ClangASTContext::DeclContextGetAsDeclContext(var_decl_context), var_sp, var_sp->GetType()->GetForwardCompilerType()); + } } return var_sp; } Index: source/Symbol/Block.cpp =================================================================== --- source/Symbol/Block.cpp +++ source/Symbol/Block.cpp @@ -566,6 +566,7 @@ return CompilerDeclContext(); } + void Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) { 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: 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,26 @@ 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") + + # 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: test/lang/cpp/nsimport/main.cpp =================================================================== --- test/lang/cpp/nsimport/main.cpp +++ test/lang/cpp/nsimport/main.cpp @@ -16,13 +16,32 @@ } } -using namespace N; -using namespace Nested; +namespace Global +{ + int global; +} + +namespace Fun +{ + int fun_var; + int fun() + { + fun_var = 5; + return 0; // break 1 + } +} + +using namespace Global; + +int fun_var = 9; int main() { + using namespace N; + using namespace Nested; n = 1; anon = 2; nested = 3; - return 0; // break 0 + global = 4; + return Fun::fun(); // break 0 }