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

Reply via email to