Skip to content

Commit 3b6ffb8

Browse files
Teemperormemfrob
authored and
memfrob
committed
[lldb] Fix that running a top level expression without a process fails with a cryptic error
Right now when running `expr --top-level -- void foo() {}`, LLDB just prints a cryptic `error: Couldn't find $__lldb_expr() in the module` error. The reason for that is that if we don't have a running process, we try to set our execution policy to always use the IR interpreter (ExecutionPolicyNever) which works even without a process. However that code didn't consider the special ExecutionPolicyTopLevel which we use for top-level expressions. By changing the execution policy to ExecutionPolicyNever, LLDB thinks we're actually trying to interpret a normal expression inside our `$__lldb_expr` function and then fails when looking for it. This just adds an exception for top-level expressions to that code and a bunch of tests. Reviewed By: shafik Differential Revision: https://reviews.llvm.org/D91723
1 parent 60d378e commit 3b6ffb8

File tree

4 files changed

+23
-2
lines changed

4 files changed

+23
-2
lines changed

lldb/source/Expression/UserExpression.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,12 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
187187
}
188188
}
189189

190-
if (process == nullptr || !process->CanJIT())
190+
// Explicitly force the IR interpreter to evaluate the expression when the
191+
// there is no process that supports running the expression for us. Don't
192+
// change the execution policy if we have the special top-level policy that
193+
// doesn't contain any expression and there is nothing to interpret.
194+
if (execution_policy != eExecutionPolicyTopLevel &&
195+
(process == nullptr || !process->CanJIT()))
191196
execution_policy = eExecutionPolicyNever;
192197

193198
// We need to set the expression execution thread here, turns out parse can

lldb/test/API/commands/expression/static-initializers/TestStaticInitializers.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ def test_failing_init(self):
3131
# FIXME: This error message is not even remotely helpful.
3232
self.expect("expr -p -- struct Foo2 { Foo2() { do_abort(); } }; Foo2 f;", error=True,
3333
substrs=["error: couldn't run static initializer:"])
34+
35+
def test_without_process(self):
36+
""" Test a static initializer without a running process. """
37+
self.expect("expr -p -- int i = 0; struct Foo3 { Foo3() { ++i; } }; Foo3 f;", error=True,
38+
substrs=["Top-level code needs to be inserted into a runnable target"])

lldb/test/API/commands/expression/top-level/TestTopLevelExprs.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,14 @@ def test_top_level_expressions(self):
9191
self.assertEqual(
9292
resultFromCode,
9393
resultFromTopLevel.GetValueAsUnsigned())
94+
95+
def test_top_level_expression_without_target(self):
96+
self.expect("expr --top-level -- void func() {}", error=True,
97+
substrs=["Top-level code needs to be inserted into a runnable target"])
98+
99+
# FIXME: This doesn't actually generate any code, so LLDB should probably
100+
# allow these expressions.
101+
self.expect("expr --top-level -- template<typename T> struct StructT { T m; };", error=True,
102+
substrs=["Top-level code needs to be inserted into a runnable target"])
103+
self.expect("expr --top-level -- struct Struct { int i; };", error=True,
104+
substrs=["Top-level code needs to be inserted into a runnable target"])

lldb/test/API/lang/cpp/elaborated-types/TestElaboratedTypes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test(self):
3434
# Declare a template that can actually be instantiated.
3535
# FIXME: The error message here is incorrect.
3636
self.expect("expr --top-level -- template<typename T> struct $V {};",
37-
error=True, substrs=["Couldn't find $__lldb_expr() in the module"])
37+
error=True, substrs=["Top-level code needs to be inserted into a runnable target"])
3838
result = self.expect_expr("$V<::Struct> s; s",
3939
result_type="$V< ::Struct>")
4040
self.assertEqual(result.GetTypeName(), "$V<Struct>")

0 commit comments

Comments
 (0)