Skip to content

Commit e5cbe78

Browse files
committedMay 3, 2019
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
1 parent 70f5e05 commit e5cbe78

File tree

8 files changed

+144
-13
lines changed

8 files changed

+144
-13
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
LEVEL = ../../make
2+
3+
CXX_SOURCES := main.cpp
4+
5+
include $(LEVEL)/Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
class TestNamespaceLocalVarSameNameCppAndC(TestBase):
7+
8+
mydir = TestBase.compute_mydir(__file__)
9+
10+
@skipUnlessDarwin
11+
@add_test_categories(["gmodules"])
12+
def test_namespace_local_var_same_name_cpp_and_c(self):
13+
self.build()
14+
15+
(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
16+
lldb.SBFileSpec("main.cpp", False))
17+
18+
self.expect("expr error",
19+
substrs=['(int) $0 = 1'])
20+
21+
lldbutil.continue_to_breakpoint(self.process, bkpt)
22+
23+
self.expect("expr error",
24+
substrs=['(int) $1 = 1'])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace error {
2+
int x;
3+
}
4+
5+
struct A {
6+
void foo() {
7+
int error=1;
8+
9+
return; // break here
10+
}
11+
};
12+
13+
int main() {
14+
int error=1;
15+
16+
A a;
17+
18+
a.foo();
19+
20+
return 0; // break here
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
LEVEL = ../../make
2+
OBJCXX_SOURCES := main.mm util.mm
3+
include $(LEVEL)/Makefile.rules
4+
5+
LDFLAGS += -framework Foundation
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
class TestNamespaceLocalVarSameNameObjC(TestBase):
7+
8+
mydir = TestBase.compute_mydir(__file__)
9+
10+
@skipUnlessDarwin
11+
@add_test_categories(["gmodules"])
12+
def test_namespace_local_var_same_name_obj_c(self):
13+
self.build()
14+
15+
(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
16+
lldb.SBFileSpec("util.mm", False))
17+
18+
self.expect("expr error",
19+
substrs=['(NSError *) $0 ='])
20+
21+
lldbutil.continue_to_breakpoint(self.process, bkpt)
22+
23+
self.expect("expr error",
24+
substrs=['(NSError *) $1 ='])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#import <Foundation/Foundation.h>
2+
@interface Util : NSObject
3+
+ (void)debugPrintErrorStatic;
4+
- (void)debugPrintError;
5+
@end
6+
7+
int main(int argc, const char * argv[]) {
8+
[Util debugPrintErrorStatic];
9+
10+
Util *u = [[Util alloc] init];
11+
12+
[u debugPrintError];
13+
14+
return 0;
15+
}
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#import <Foundation/Foundation.h>
2+
3+
namespace error {
4+
int blah;
5+
}
6+
7+
@interface Util : NSObject
8+
+ (void)debugPrintErrorStatic;
9+
- (void)debugPrintError;
10+
@end
11+
12+
@implementation Util
13+
+ (void)debugPrintErrorStatic {
14+
NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:nil];
15+
NSLog(@"xxx, error = %@", error); // break here
16+
}
17+
18+
- (void)debugPrintError {
19+
NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:nil];
20+
NSLog(@"xxx, error = %@", error); // break here
21+
}
22+
@end

Diff for: ‎lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp

+27-13
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,31 @@ static bool ExprBodyContainsVar(llvm::StringRef body, llvm::StringRef var) {
200200

201201
static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
202202
StreamString &stream,
203-
const std::string &expr) {
203+
const std::string &expr,
204+
lldb::LanguageType wrapping_language) {
204205
for (size_t i = 0; i < var_list_sp->GetSize(); i++) {
205206
lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
206207

207208
ConstString var_name = var_sp->GetName();
208-
if (!var_name || var_name == "this" || var_name == ".block_descriptor")
209+
210+
211+
// We can check for .block_descriptor w/o checking for langauge since this
212+
// is not a valid identifier in either C or C++.
213+
if (!var_name || var_name == ConstString(".block_descriptor"))
209214
continue;
210215

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

219+
if ((var_name == ConstString("self") || var_name == ConstString("_cmd")) &&
220+
(wrapping_language == lldb::eLanguageTypeObjC ||
221+
wrapping_language == lldb::eLanguageTypeObjC_plus_plus))
222+
continue;
223+
224+
if (var_name == ConstString("this") &&
225+
wrapping_language == lldb::eLanguageTypeC_plus_plus)
226+
continue;
227+
214228
stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
215229
}
216230
}
@@ -291,16 +305,14 @@ bool ClangExpressionSourceCode::GetText(
291305
}
292306
}
293307

294-
if (add_locals) {
295-
if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) {
296-
if (target->GetInjectLocalVariables(&exe_ctx)) {
297-
lldb::VariableListSP var_list_sp =
298-
frame->GetInScopeVariableList(false, true);
299-
AddLocalVariableDecls(var_list_sp, lldb_local_var_decls,
300-
force_add_all_locals ? "" : m_body);
301-
}
308+
if (add_locals)
309+
if (target->GetInjectLocalVariables(&exe_ctx)) {
310+
lldb::VariableListSP var_list_sp =
311+
frame->GetInScopeVariableList(false, true);
312+
AddLocalVariableDecls(var_list_sp, lldb_local_var_decls,
313+
force_add_all_locals ? "" : m_body,
314+
wrapping_language);
302315
}
303-
}
304316
}
305317

306318
if (m_wrap) {
@@ -378,11 +390,12 @@ bool ClangExpressionSourceCode::GetText(
378390
"@implementation $__lldb_objc_class ($__lldb_category) \n"
379391
"+(void)%s:(void *)$__lldb_arg \n"
380392
"{ \n"
393+
" %s; \n"
381394
"%s"
382395
"} \n"
383396
"@end \n",
384397
module_imports.c_str(), m_name.c_str(), m_name.c_str(),
385-
tagged_body.c_str());
398+
lldb_local_var_decls.GetData(), tagged_body.c_str());
386399
} else {
387400
wrap_stream.Printf(
388401
"%s"
@@ -392,11 +405,12 @@ bool ClangExpressionSourceCode::GetText(
392405
"@implementation $__lldb_objc_class ($__lldb_category) \n"
393406
"-(void)%s:(void *)$__lldb_arg \n"
394407
"{ \n"
408+
" %s; \n"
395409
"%s"
396410
"} \n"
397411
"@end \n",
398412
module_imports.c_str(), m_name.c_str(), m_name.c_str(),
399-
tagged_body.c_str());
413+
lldb_local_var_decls.GetData(), tagged_body.c_str());
400414
}
401415
break;
402416
}

0 commit comments

Comments
 (0)
Please sign in to comment.