https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/87767
>From f27a547ab85463f182ab63949bb6f11140a2f33f Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Fri, 5 Apr 2024 11:51:47 +0100 Subject: [PATCH 1/2] [lldb][ClangExpressionParser] Don't by default enable Objecitve-C support when evaluating C++ expressions This patch attempts to decouple C++ expression evaluation from Objective-C support. We've previously enabled it by default (if a runtime existed), but that meant we're opting into extra work we only need to do for Objective-C, which complicates/slows down C++ expression evaluation. Of course there's a valid use-case for this, which is calling Objective-C APIs when stopped in C++ frames (which Objective-C++ developers might want to do). In those case we should really prompt the user to add the `expr --language objc++` flag. To accomodate a likely frequent use-case where a user breaks in a system C++ library (without debug-symbols) but their application is actually an Objective-C app, we allow Objective-C support in C++ expressions if the current frame doesn't have debug-info. This fixes https://github.com/llvm/llvm-project/issues/75443 and allows us to add more `LangOpts.ObjC` guards around the expression evaluator in the future (e.g., we could avoid looking into the Objective-C runtime during C++ expression evaluation, which we currently do unconditionally). Depends on https://github.com/llvm/llvm-project/pull/87657 --- .../Clang/ClangExpressionParser.cpp | 5 ++++- .../diagnostics/TestExprDiagnostics.py | 2 +- .../expression/options/TestExprOptions.py | 1 - .../objc-builtin-types/TestObjCBuiltinTypes.py | 2 +- .../Makefile | 4 ++++ .../TestObjCFromCppFramesWithoutDebugInfo.py | 17 +++++++++++++++++ .../main.cpp | 1 + 7 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/Makefile create mode 100644 lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py create mode 100644 lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/main.cpp diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 822d286cd6c3c4..f48bdc730d9160 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -526,7 +526,10 @@ ClangExpressionParser::ClangExpressionParser( [[fallthrough]]; case lldb::eLanguageTypeC_plus_plus_03: lang_opts.CPlusPlus = true; - if (process_sp) + if (process_sp + // We're stopped in a frame without debug-info. The user probably + // intends to make global queries (which should include Objective-C). + && !(frame_sp && frame_sp->HasDebugInformation())) lang_opts.ObjC = process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC) != nullptr; break; diff --git a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py index d64e9897a844f1..ddc1c3598480cf 100644 --- a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py +++ b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py @@ -172,7 +172,7 @@ def test_source_locations_from_objc_modules(self): # Import foundation so that the Obj-C module is loaded (which contains source locations # that can be used by LLDB). - self.runCmd("expr @import Foundation") + self.runCmd("expr --language objective-c++ -- @import Foundation") value = frame.EvaluateExpression("NSLog(1);") self.assertFalse(value.GetError().Success()) # LLDB should print the source line that defines NSLog. To not rely on any diff --git a/lldb/test/API/commands/expression/options/TestExprOptions.py b/lldb/test/API/commands/expression/options/TestExprOptions.py index 6652c71083a958..01899f3b97cf44 100644 --- a/lldb/test/API/commands/expression/options/TestExprOptions.py +++ b/lldb/test/API/commands/expression/options/TestExprOptions.py @@ -59,7 +59,6 @@ def test_expr_options(self): self.assertTrue(val.IsValid()) self.assertFalse(val.GetError().Success()) - @skipIfDarwin def test_expr_options_lang(self): """These expression language options should work as expected.""" self.build() diff --git a/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py index 1eb7205f1bb465..280994fbde71ab 100644 --- a/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py +++ b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py @@ -53,5 +53,5 @@ def test_with_python_api(self): ) self.expect( "expr --language C++ -- id my_id = 0; my_id", - patterns=["\(id\) \$.* = nullptr"], + error=True ) diff --git a/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/Makefile b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/Makefile new file mode 100644 index 00000000000000..7c3c32d6f82df4 --- /dev/null +++ b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -g0 + +include Makefile.rules diff --git a/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py new file mode 100644 index 00000000000000..ba33d44732c924 --- /dev/null +++ b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py @@ -0,0 +1,17 @@ +""" +Test that the the expression parser enables ObjC support +when stopped in a C++ frame without debug-info. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestObjCFromCppFramesWithoutDebugInfo(TestBase): + def test(self): + self.build() + (_, process, _, _) = lldbutil.run_to_name_breakpoint(self, "main") + + self.assertState(process.GetState(), lldb.eStateStopped) + self.expect("expr id", error=False) diff --git a/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/main.cpp b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/main.cpp new file mode 100644 index 00000000000000..76e8197013aabc --- /dev/null +++ b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } >From 3919045a75cc36dc4e14c7f087792436d2c52df4 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Fri, 5 Apr 2024 12:05:21 +0100 Subject: [PATCH 2/2] fixup! python format --- .../lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py | 5 +---- .../TestObjCFromCppFramesWithoutDebugInfo.py | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py index 280994fbde71ab..611c7388999058 100644 --- a/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py +++ b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py @@ -51,7 +51,4 @@ def test_with_python_api(self): "expr --language Objective-C++ -- id my_id = 0; my_id", patterns=["\(id\) \$.* = nil"], ) - self.expect( - "expr --language C++ -- id my_id = 0; my_id", - error=True - ) + self.expect("expr --language C++ -- id my_id = 0; my_id", error=True) diff --git a/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py index ba33d44732c924..ef8d5540fa4ef9 100644 --- a/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py +++ b/lldb/test/API/lang/objcxx/objc-from-cpp-frames-without-debuginfo/TestObjCFromCppFramesWithoutDebugInfo.py @@ -8,6 +8,7 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil + class TestObjCFromCppFramesWithoutDebugInfo(TestBase): def test(self): self.build() _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits