sivachandra created this revision. sivachandra added reviewers: clayborg, spyffe. sivachandra added a subscriber: lldb-commits.
While evaluating expressions when stopped in a class method, there was a problem of member variables hiding local variables. This was happening because, in the context of a method, clang already knew about member variables with their name and assumed that they were the only variables with those names in scope. Consequently, clang never checks with LLDB about the possibility of local variables with the same name and goes wrong. This change addresses the problem by using an artificial namespace "$__lldb_local_vars". All local variables in scope are declared in the "$__lldb_expr" method as follows: using $__lldb_local_vars::<local var 1>; using $__lldb_local_vars::<local var 2>; ... This hides the member variables with the same name and forces clang to enquire about the variables which it thinks are declared in $__lldb_local_vars. When LLDB notices that clang is enquiring about variables in $__lldb_local_vars, it looks up local vars and conveys their information if found. This way, member variables do not hide local variables, leading to correct evaluation of expressions. http://reviews.llvm.org/D16746 Files: include/lldb/Symbol/ClangASTContext.h source/Expression/ExpressionSourceCode.cpp source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h source/Symbol/ClangASTContext.cpp source/Target/StackFrame.cpp
Index: source/Target/StackFrame.cpp =================================================================== --- source/Target/StackFrame.cpp +++ source/Target/StackFrame.cpp @@ -597,7 +597,7 @@ var_list_sp.get()); } - if (m_sc.comp_unit) + if (m_sc.comp_unit && get_file_globals) { VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true)); if (global_variable_list_sp) Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -1804,10 +1804,11 @@ #pragma mark Namespace Declarations NamespaceDecl * -ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx) +ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx, ASTContext *ast) { NamespaceDecl *namespace_decl = nullptr; - ASTContext *ast = getASTContext(); + if (ast == nullptr) + ast = getASTContext(); TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl (); if (decl_ctx == nullptr) decl_ctx = translation_unit_decl; Index: source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -707,6 +707,9 @@ AddThisType(NameSearchContext &context, TypeFromUser &type, unsigned int current_id); + + ClangASTContext * + GetClangASTContext(); }; } // namespace lldb_private Index: source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -57,6 +57,11 @@ using namespace lldb_private; using namespace clang; +namespace +{ + const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; +} // anonymous namespace + ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, ExecutionContext &exe_ctx) : @@ -1004,6 +1009,24 @@ return VariableSP(); } +ClangASTContext * +ClangExpressionDeclMap::GetClangASTContext () +{ + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + if (frame == nullptr) + return nullptr; + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + if (sym_ctx.block == nullptr) + return nullptr; + + CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); + if (!frame_decl_context) + return nullptr; + + return llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem()); +} + // Interface for ClangASTSource void @@ -1039,6 +1062,13 @@ if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) { + if (namespace_context->getName().str() == std::string(g_lldb_local_vars_namespace_cstr)) + { + CompilerDeclContext compiler_decl_ctx(GetClangASTContext(), (void*)context.m_decl_context); + FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx, current_id); + return; + } + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); if (log && log->GetVerbose()) @@ -1335,6 +1365,32 @@ return; } + if (name == ConstString(g_lldb_local_vars_namespace_cstr)) + { + CompilerDeclContext frame_decl_context = sym_ctx.block != nullptr ? + sym_ctx.block->GetDeclContext() : + CompilerDeclContext(); + + if (frame_decl_context) + { + ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem()); + + if (ast) + { + clang::NamespaceDecl *namespace_decl = ast->GetUniqueNamespaceDeclaration( + name_unique_cstr, nullptr, m_ast_context); + if (namespace_decl) + { + context.AddNamedDecl(namespace_decl); + clang::DeclContext *clang_decl_ctx = clang::Decl::castToDeclContext(namespace_decl); + clang_decl_ctx->setHasExternalVisibleStorage(true); + } + } + } + + return; + } + // any other $__lldb names should be weeded out now if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) return; @@ -1403,7 +1459,9 @@ ValueObjectSP valobj; VariableSP var; - if (frame && !namespace_decl) + bool local_var_lookup = !namespace_decl || + (namespace_decl.GetName() == ConstString(g_lldb_local_vars_namespace_cstr)); + if (frame && local_var_lookup) { CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); Index: source/Expression/ExpressionSourceCode.cpp =================================================================== --- source/Expression/ExpressionSourceCode.cpp +++ source/Expression/ExpressionSourceCode.cpp @@ -16,7 +16,9 @@ #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/TypeSystem.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Platform.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -175,6 +177,51 @@ } } +static bool +IsCppMethod(StackFrame *frame, ConstString &object_name) +{ + if (frame == nullptr) + return false; + + Block *frame_block = frame->GetFrameBlock(); + if (frame_block == nullptr) + return false; + + Function *function = frame_block->CalculateSymbolContextFunction(); + if (function == nullptr) + return false; + + CompilerDeclContext decl_context = function->GetDeclContext(); + if (!decl_context.IsValid()) + return false; + + lldb::LanguageType lang_type; + if (!decl_context.IsClassMethod(&lang_type, nullptr, &object_name)) + return false; + + if (Language::LanguageIsCPlusPlus(lang_type)) + return true; + + return false; +} + +static void +AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, const ConstString &object_name, StreamString &stream) +{ + for (size_t i = 0; i < var_list_sp->GetSize(); i++) + { + lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); + + ConstString var_name = var_sp->GetName(); + if (var_name == object_name) + continue; + + const char *var_name_cstr = var_name.AsCString(); + + stream.Printf("using $__lldb_local_vars::%s;\n", var_name_cstr); + } +} + bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const { const char *target_specific_defines = "typedef signed char BOOL;\n"; @@ -239,6 +286,7 @@ } StreamString debug_macros_stream; + StreamString lldb_local_var_decls; if (StackFrame *frame = exe_ctx.GetFramePtr()) { const SymbolContext &sc = frame->GetSymbolContext( @@ -253,8 +301,15 @@ AddMacros(dm, sc.comp_unit, state, debug_macros_stream); } } + + ConstString object_name; + if (IsCppMethod(frame, object_name)) + { + lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false); + AddLocalVariableDecls(var_list_sp, object_name, lldb_local_var_decls); + } } - + if (m_wrap) { switch (wrapping_language) @@ -293,10 +348,12 @@ wrap_stream.Printf("void \n" "$__lldb_class::%s(void *$__lldb_arg) %s\n" "{ \n" + " %s \n" " %s; \n" "} \n", m_name.c_str(), (const_object ? "const" : ""), + lldb_local_var_decls.GetData(), m_body.c_str()); break; case lldb::eLanguageTypeObjC: @@ -339,6 +396,6 @@ { text.append(m_body); } - + return true; } Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -420,7 +420,8 @@ clang::NamespaceDecl * GetUniqueNamespaceDeclaration (const char *name, - clang::DeclContext *decl_ctx); + clang::DeclContext *decl_ctx, + clang::ASTContext *ast=nullptr); //------------------------------------------------------------------ // Function Types
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits