[ddc] Fix non-null assertion crash

`VariableDeclaration.name` could be null when the variable
was synthetically introduced by the compiler. In this case the
expression compiler can ignore the variable because it's value
doesn't reflect the value of a variable in the original dart
source code.

Add a regression test for the expression compiler that
ensures code that introduces a synthetic variable will not
cause a crash when you stop at a breakpoint.

Fixes: https://github.com/dart-lang/sdk/issues/49373
Change-Id: Ifc5f72ab4e5733ead17a20889c222bcc46921f6b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250343
Commit-Queue: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Anna Gringauze <annagrin@google.com>
This commit is contained in:
Nicholas Shahan 2022-07-01 16:15:53 +00:00 committed by Commit Bot
parent d7df61e042
commit 0f2e021da8
2 changed files with 35 additions and 2 deletions

View file

@ -163,13 +163,17 @@ class DartScopeBuilder extends Visitor<void> with VisitorVoidMixin {
@override
void visitVariableDeclaration(VariableDeclaration decl) {
var name = decl.name;
// Collect locals and formals appearing before current breakpoint.
// Note that we include variables with no offset because the offset
// is not set in many cases in generated code, so omitting them would
// make expression evaluation fail in too many cases.
// Issue: https://github.com/dart-lang/sdk/issues/43966
if (decl.fileOffset < 0 || decl.fileOffset < _offset) {
_definitions[decl.name!] = decl.type;
//
// A null name signals that the variable was synthetically introduced by the
// compiler so they are skipped.
if ((decl.fileOffset < 0 || decl.fileOffset < _offset) && name != null) {
_definitions[name] = decl.type;
}
super.visitVariableDeclaration(decl);
}

View file

@ -356,6 +356,35 @@ void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
expectedResult: 'true');
});
});
group('Synthetic variables', () {
var source = r'''
dynamic couldReturnNull() => null;
main() {
var i = couldReturnNull() ?? 10;
// Breakpoint: bp
print(i);
}
''';
setUpAll(() async {
await driver.initSource(setup, source);
});
tearDownAll(() async {
await driver.cleanupTest();
});
test('do not cause a crash the expression compiler', () async {
// The null aware code in the test source causes the compiler to introduce
// a let statement that includes a synthetic variable declaration.
// That variable has no name and was causing a crash in the expression
// compiler https://github.com/dart-lang/sdk/issues/49373.
await driver.check(
breakpointId: 'bp', expression: 'true', expectedResult: 'true');
});
});
}
/// Shared tests that are valid in legacy (before 2.12) and are agnostic to