Skip to content

Commit

Permalink
Fix for ambiguous lookup in expressions between local variable and na…
Browse files Browse the repository at this point in the history
…mespace

Summary:
In an Objective-C context a local variable and namespace can cause an ambiguous name lookup when used in an expression. The solution involves mimicking the existing C++ solution which is to add local using declarations for local variables. This causes a different type of lookup to be used which eliminates the namespace during acceptable results filtering.

Differential Revision: https://reviews.llvm.org/D59960

llvm-svn: 359921
  • Loading branch information
shafik authored and MrSidims committed May 17, 2019
1 parent 461821f commit 9bd4a2a
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 13 deletions.
@@ -0,0 +1,5 @@
LEVEL = ../../make

CXX_SOURCES := main.cpp

include $(LEVEL)/Makefile.rules
@@ -0,0 +1,24 @@
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil

class TestNamespaceLocalVarSameNameCppAndC(TestBase):

mydir = TestBase.compute_mydir(__file__)

@skipUnlessDarwin
@add_test_categories(["gmodules"])
def test_namespace_local_var_same_name_cpp_and_c(self):
self.build()

(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
lldb.SBFileSpec("main.cpp", False))

self.expect("expr error",
substrs=['(int) $0 = 1'])

lldbutil.continue_to_breakpoint(self.process, bkpt)

self.expect("expr error",
substrs=['(int) $1 = 1'])
@@ -0,0 +1,21 @@
namespace error {
int x;
}

struct A {
void foo() {
int error=1;

return; // break here
}
};

int main() {
int error=1;

A a;

a.foo();

return 0; // break here
}
@@ -0,0 +1,5 @@
LEVEL = ../../make
OBJCXX_SOURCES := main.mm util.mm
include $(LEVEL)/Makefile.rules

LDFLAGS += -framework Foundation
@@ -0,0 +1,24 @@
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil

class TestNamespaceLocalVarSameNameObjC(TestBase):

mydir = TestBase.compute_mydir(__file__)

@skipUnlessDarwin
@add_test_categories(["gmodules"])
def test_namespace_local_var_same_name_obj_c(self):
self.build()

(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
lldb.SBFileSpec("util.mm", False))

self.expect("expr error",
substrs=['(NSError *) $0 ='])

lldbutil.continue_to_breakpoint(self.process, bkpt)

self.expect("expr error",
substrs=['(NSError *) $1 ='])
@@ -0,0 +1,16 @@
#import <Foundation/Foundation.h>
@interface Util : NSObject
+ (void)debugPrintErrorStatic;
- (void)debugPrintError;
@end

int main(int argc, const char * argv[]) {
[Util debugPrintErrorStatic];

Util *u = [[Util alloc] init];

[u debugPrintError];

return 0;
}

@@ -0,0 +1,22 @@
#import <Foundation/Foundation.h>

namespace error {
int blah;
}

@interface Util : NSObject
+ (void)debugPrintErrorStatic;
- (void)debugPrintError;
@end

@implementation Util
+ (void)debugPrintErrorStatic {
NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:nil];
NSLog(@"xxx, error = %@", error); // break here
}

- (void)debugPrintError {
NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:nil];
NSLog(@"xxx, error = %@", error); // break here
}
@end
Expand Up @@ -200,17 +200,31 @@ static bool ExprBodyContainsVar(llvm::StringRef body, llvm::StringRef var) {

static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
StreamString &stream,
const std::string &expr) {
const std::string &expr,
lldb::LanguageType wrapping_language) {
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 || var_name == "this" || var_name == ".block_descriptor")


// We can check for .block_descriptor w/o checking for langauge since this
// is not a valid identifier in either C or C++.
if (!var_name || var_name == ConstString(".block_descriptor"))
continue;

if (!expr.empty() && !ExprBodyContainsVar(expr, var_name.GetStringRef()))
continue;

if ((var_name == ConstString("self") || var_name == ConstString("_cmd")) &&
(wrapping_language == lldb::eLanguageTypeObjC ||
wrapping_language == lldb::eLanguageTypeObjC_plus_plus))
continue;

if (var_name == ConstString("this") &&
wrapping_language == lldb::eLanguageTypeC_plus_plus)
continue;

stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
}
}
Expand Down Expand Up @@ -291,16 +305,14 @@ bool ClangExpressionSourceCode::GetText(
}
}

if (add_locals) {
if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) {
if (target->GetInjectLocalVariables(&exe_ctx)) {
lldb::VariableListSP var_list_sp =
frame->GetInScopeVariableList(false, true);
AddLocalVariableDecls(var_list_sp, lldb_local_var_decls,
force_add_all_locals ? "" : m_body);
}
if (add_locals)
if (target->GetInjectLocalVariables(&exe_ctx)) {
lldb::VariableListSP var_list_sp =
frame->GetInScopeVariableList(false, true);
AddLocalVariableDecls(var_list_sp, lldb_local_var_decls,
force_add_all_locals ? "" : m_body,
wrapping_language);
}
}
}

if (m_wrap) {
Expand Down Expand Up @@ -378,11 +390,12 @@ bool ClangExpressionSourceCode::GetText(
"@implementation $__lldb_objc_class ($__lldb_category) \n"
"+(void)%s:(void *)$__lldb_arg \n"
"{ \n"
" %s; \n"
"%s"
"} \n"
"@end \n",
module_imports.c_str(), m_name.c_str(), m_name.c_str(),
tagged_body.c_str());
lldb_local_var_decls.GetData(), tagged_body.c_str());
} else {
wrap_stream.Printf(
"%s"
Expand All @@ -392,11 +405,12 @@ bool ClangExpressionSourceCode::GetText(
"@implementation $__lldb_objc_class ($__lldb_category) \n"
"-(void)%s:(void *)$__lldb_arg \n"
"{ \n"
" %s; \n"
"%s"
"} \n"
"@end \n",
module_imports.c_str(), m_name.c_str(), m_name.c_str(),
tagged_body.c_str());
lldb_local_var_decls.GetData(), tagged_body.c_str());
}
break;
}
Expand Down

0 comments on commit 9bd4a2a

Please sign in to comment.