diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -325,13 +325,19 @@ /// \param[in] name /// The name to be considered. /// + /// \param[in] namespace_decl + /// The namespace decl that this name is being searched. This can be + /// invalid if we are searching the root namespace. + /// /// \param[in] ignore_all_dollar_names /// True if $-names of all sorts should be ignored. /// /// \return /// True if the name is one of a class of names that are ignored by /// global lookup for performance reasons. - bool IgnoreName(const ConstString name, bool ignore_all_dollar_names); + bool IgnoreName(const ConstString name, + const CompilerDeclContext &namespace_decl, + bool ignore_all_dollar_names); public: /// Copies a single Decl into the parser's AST context. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -574,13 +574,23 @@ } bool ClangASTSource::IgnoreName(const ConstString name, + const CompilerDeclContext &namespace_decl, bool ignore_all_dollar_names) { - static const ConstString id_name("id"); - static const ConstString Class_name("Class"); - - if (m_ast_context->getLangOpts().ObjC) - if (name == id_name || name == Class_name) + if (m_ast_context->getLangOpts().ObjC) { + static const ConstString id_name("id"); + static const ConstString Class_name("Class"); + if (name == id_name || name == Class_name) { + // Only disallow using "id" and "Class" if we are searching from the root + // namespace or translation unit level. If namespace_decl is valid, then + // this is not the root namespace. + if (namespace_decl.IsValid()) + return false; + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS), + " CAS::IgnoreName(name=\"{0}\") Ignoring reserved keryword", + name); return true; + } + } StringRef name_string_ref = name.GetStringRef(); @@ -600,7 +610,7 @@ SymbolContextList sc_list; const ConstString name(context.m_decl_name.getAsString().c_str()); - if (IgnoreName(name, true)) + if (IgnoreName(name, namespace_decl, true)) return; if (!m_target) @@ -663,7 +673,7 @@ NameSearchContext &context, lldb::ModuleSP module_sp, const CompilerDeclContext &namespace_decl) { const ConstString name(context.m_decl_name.getAsString().c_str()); - if (IgnoreName(name, true)) + if (IgnoreName(name, namespace_decl, true)) return; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1321,7 +1321,7 @@ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const ConstString name(context.m_decl_name.getAsString().c_str()); - if (IgnoreName(name, false)) + if (IgnoreName(name, namespace_decl, false)) return; // Only look for functions by name out in our symbols if the function doesn't diff --git a/lldb/test/API/commands/expression/ignore/Makefile b/lldb/test/API/commands/expression/ignore/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/commands/expression/ignore/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/expression/ignore/TestIgnoreName.py b/lldb/test/API/commands/expression/ignore/TestIgnoreName.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/commands/expression/ignore/TestIgnoreName.py @@ -0,0 +1,39 @@ +""" +Test calling user defined functions using expression evaluation. +This test checks that typesystem lookup works correctly for typedefs of +untagged structures. + +Ticket: https://llvm.org/bugs/show_bug.cgi?id=26790 +""" + + +import lldb + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestIgnoreName(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test that we can evaluate an expression that finds something inside + a namespace that uses an Objective C keyword. + """ + self.build() + exe_path = self.getBuildArtifact("a.out") + error = lldb.SBError() + triple = None + platform = None + add_dependent_modules = False + target = self.dbg.CreateTarget(exe_path, triple, platform, + add_dependent_modules, error) + self.assertTrue(error.Success(), "Make sure our target got created") + expr_result = target.EvaluateExpression("a::Class a; a") + self.assertTrue(expr_result.GetError().Success(), + "Make sure our expression evaluated without errors") + self.assertTrue(expr_result.GetValue() == None, + 'Expression value is None') + self.assertTrue(expr_result.GetType().GetName() == "a::Class", + 'Expression result type is "a::Class"') diff --git a/lldb/test/API/commands/expression/ignore/main.cpp b/lldb/test/API/commands/expression/ignore/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/commands/expression/ignore/main.cpp @@ -0,0 +1,10 @@ +namespace a { + struct Class { + }; +} + +int main(int argc, char **argv) +{ + a::Class c; + return 0; +}