diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index 3b9a72192e7f..22281d946a89 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -6649,7 +6649,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (condition && ifbody) s = new AST.IfStatement(loc, param, condition, ifbody, elsebody, token.loc); else - s = null; // don't propagate parsing errors + s = new AST.ErrorStatement; // don't propagate parsing errors as null break; } @@ -6695,6 +6695,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (auto ds = parseDebugSpecification()) eSink.error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars); + // Not valid as a statement; return ErrorStatement instead of null so + // callers (string mixin semantic) do not null-deref. + s = new AST.ErrorStatement; break; } cond = parseDebugCondition(); @@ -6707,6 +6710,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (auto vs = parseVersionSpecification()) eSink.error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars); + // Not valid as a statement; return ErrorStatement instead of null so + // callers (string mixin semantic) do not null-deref. + s = new AST.ErrorStatement; break; } cond = parseVersionCondition(); diff --git a/compiler/src/dmd/statementsem.d b/compiler/src/dmd/statementsem.d index c48308a404e6..95505145f156 100644 --- a/compiler/src/dmd/statementsem.d +++ b/compiler/src/dmd/statementsem.d @@ -5082,7 +5082,9 @@ private Statements* flatten(Statement statement, Scope* sc) Statement s = p.parseStatement(ParseStatementFlags.curlyScope); if (!s || global.errors != errors) { - errorSupplemental(s.loc, "while parsing string mixin statement"); + // Prefer a real source location; ErrorStatement uses Loc.initial. + const loc = (s !is null && s.loc.isValid()) ? s.loc : cs.loc; + errorSupplemental(loc, "while parsing string mixin statement"); return errorStatements(); } a.push(s); diff --git a/compiler/test/fail_compilation/mixin_version_debug_assign.d b/compiler/test/fail_compilation/mixin_version_debug_assign.d new file mode 100644 index 000000000000..e69caef2ee89 --- /dev/null +++ b/compiler/test/fail_compilation/mixin_version_debug_assign.d @@ -0,0 +1,21 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/mixin_version_debug_assign.d-mixin-15(15): Error: version `foo` declaration must be at module level +fail_compilation/mixin_version_debug_assign.d(15): while parsing string mixin statement +fail_compilation/mixin_version_debug_assign.d-mixin-20(20): Error: identifier expected, not `1` +fail_compilation/mixin_version_debug_assign.d(20): while parsing string mixin statement +--- +*/ + +void main() +{ + // Previously crashed dmd with ACCESS_VIOLATION: parseStatement returned null, + // then string-mixin semantic did errorSupplemental(s.loc, ...). + mixin("version = foo;"); +} + +void other() +{ + mixin("debug = 1;"); +}