forked from OSchip/llvm-project
Fix for ambiguous lookup in expressions between local variable and namespace
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
This commit is contained in:
parent
70f5e050e7
commit
e5cbe78259
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue