Take 2: Use an artifical namespace so that member vars do not hide local vars.

Summary: This relands r259810 with fix for failures on Mac.

Reviewers: spyffe, tfiala

Subscribers: tfiala, lldb-commits

Differential Revision: http://reviews.llvm.org/D16900

llvm-svn: 259902
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index f4d6b19..6092efa 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/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 = ClangASTContext::GetUniqueNamespaceDeclaration(
+                        m_ast_context, name_unique_cstr, nullptr);
+                    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,19 +1459,23 @@
         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();
 
             if (compiler_decl_context)
             {
-                // Make sure that the variables are parsed so that we have the declarations
+                // Make sure that the variables are parsed so that we have the declarations.
                 VariableListSP vars = frame->GetInScopeVariableList(true);
                 for (size_t i = 0; i < vars->GetSize(); i++)
                     vars->GetVariableAtIndex(i)->GetDecl();
 
-                // Search for declarations matching the name
-                std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name);
+                // Search for declarations matching the name. Do not include imported decls
+                // in the search if we are looking for decls in the artificial namespace
+                // $__lldb_local_vars.
+                std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name, namespace_decl.IsValid());
                 
                 bool variable_found = false;
                 for (CompilerDecl decl : found_decls)