Skip to content

Commit bb2ca20

Browse files
Merge pull request #8680 from augusto2112/diag-noncopyable
[lldb] Diagnose expressions that evaluate to ~Copyable types
2 parents b18f7e6 + 11c0285 commit bb2ca20

File tree

6 files changed

+65
-0
lines changed

6 files changed

+65
-0
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,23 @@ void SwiftASTManipulator::InsertError(swift::VarDecl *error_var,
687687
m_catch_stmt->setBody(body_stmt);
688688
}
689689

690+
691+
bool SwiftASTManipulator::IsExpressionResultNonCopyable() {
692+
VariableInfo *result_var =
693+
llvm::find_if(m_variables, [&](const VariableInfo &var) {
694+
return var.GetName().str() == GetResultName();
695+
});
696+
if (result_var == m_variables.end())
697+
return false;
698+
699+
swift::VarDecl *decl = result_var->GetDecl();
700+
if (!decl)
701+
return false;
702+
703+
swift::Type type = decl->getTypeInContext();
704+
return type->isNoncopyable();
705+
}
706+
690707
llvm::Error SwiftASTManipulator::FixupResultAfterTypeChecking() {
691708
if (!IsValid())
692709
return llvm::createStringError(llvm::inconvertibleErrorCode(),

lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ class SwiftASTManipulator : public SwiftASTManipulatorBase {
250250
bool make_private = true,
251251
swift::DeclContext *decl_ctx = nullptr);
252252

253+
/// Returns true if $__lldb_result is a non copyable type.
254+
/// Currently LLDB cannot deal with expressions whose result is a non copyable
255+
/// type, this function exists so LLDB can diagnose this situation and provide
256+
/// a proper error message.
257+
bool IsExpressionResultNonCopyable();
258+
253259
llvm::Error FixupResultAfterTypeChecking();
254260

255261
static const char *GetArgumentName() { return "$__lldb_arg"; }

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,17 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
18431843
m_options.GetPlaygroundTransformHighPerformance());
18441844
}
18451845

1846+
/// Currently LLDB cannot deal with expressions whose result is a non copyable
1847+
/// type, because there's no easy way to assign $__lldb_result to the result
1848+
/// of the expression.
1849+
if (parsed_expr->code_manipulator &&
1850+
parsed_expr->code_manipulator->IsExpressionResultNonCopyable()) {
1851+
diagnostic_manager.PutString(
1852+
eSeverityError,
1853+
"Cannot evaluate an expression that results in a ~Copyable type");
1854+
return ParseResult::unrecoverable_error;
1855+
}
1856+
18461857
// FIXME: We now should have to do the name binding and type
18471858
// checking again, but there should be only the result
18481859
// variable to bind up at this point.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
include Makefile.rules
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import unittest2
6+
7+
8+
class TestSwiftNonCopyableTypeError(TestBase):
9+
@skipUnlessDarwin
10+
@swiftTest
11+
def test(self):
12+
self.build()
13+
target, process, thread, _ = lldbutil.run_to_source_breakpoint(
14+
self, "break here", lldb.SBFileSpec("main.swift")
15+
)
16+
17+
self.expect("expression s", substrs=["Cannot evaluate an expression that results in a ~Copyable type"], error=True)
18+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
struct S: ~Copyable {
2+
let i = 42
3+
}
4+
5+
func f() {
6+
let s = S()
7+
print("break here")
8+
}
9+
10+
f()

0 commit comments

Comments
 (0)