mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 06:54:44 +01:00
Fix a crash on invalid found by fuzzing. (#3404)
When a `namespace` keyword has no `;` following it, we recover by building a parse tree `Namespace` node from the `Namespace` token (as there isn't a `;` token). Allow this correspondence on errors. Also teach the diagnostics in this case to avoid the end-of-file token as that's almost always going to be a less meaningful location. Instead, we can point at the introducer which should at least be in the code that led to the error.
This commit is contained in:
@@ -27,7 +27,13 @@ static auto HandleDeclNameAndParams(Context& context, State after_name)
|
||||
CARBON_DIAGNOSTIC(ExpectedDeclName, Error,
|
||||
"`{0}` introducer should be followed by a name.",
|
||||
Lex::TokenKind);
|
||||
context.emitter().Emit(*context.position(), ExpectedDeclName,
|
||||
Lex::Token location = *context.position();
|
||||
if (context.tokens().GetKind(location) == Lex::TokenKind::EndOfFile) {
|
||||
// The end of file is often an especially unhelpful location. If that's
|
||||
// the best we can do here, back up the location to the introducer itself.
|
||||
location = state.token;
|
||||
}
|
||||
context.emitter().Emit(location, ExpectedDeclName,
|
||||
context.tokens().GetKind(state.token));
|
||||
context.ReturnErrorOnState();
|
||||
context.AddLeafNode(NodeKind::InvalidParse, *context.position(),
|
||||
|
||||
@@ -141,7 +141,9 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibrarySpecifier, 1, CARBON_TOKEN(Library))
|
||||
// _external_: Name or QualifiedDecl
|
||||
// Namespace
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamespaceStart, 0, CARBON_TOKEN(Namespace))
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(Namespace, 2, CARBON_TOKEN(Semi))
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(Namespace, 2,
|
||||
CARBON_TOKEN(Semi)
|
||||
CARBON_IF_ERROR(CARBON_TOKEN(Namespace)))
|
||||
|
||||
// A code block:
|
||||
// CodeBlockStart
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
|
||||
// CHECK:STDERR: namespace 123
|
||||
// CHECK:STDERR: ^
|
||||
namespace 123
|
||||
|
||||
// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
|
||||
// CHECK:STDERR: namespace ""
|
||||
// CHECK:STDERR: ^
|
||||
namespace ""
|
||||
|
||||
// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
|
||||
// CHECK:STDERR: namespace +
|
||||
// CHECK:STDERR: ^
|
||||
namespace +
|
||||
|
||||
// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
|
||||
// CHECK:STDERR: namespace bool
|
||||
// CHECK:STDERR: ^
|
||||
namespace bool
|
||||
|
||||
// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
|
||||
// CHECK:STDERR: namespace namespace namespace namespace namespace
|
||||
// CHECK:STDERR: ^
|
||||
namespace namespace namespace namespace namespace
|
||||
|
||||
// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:1: ERROR: `namespace` introducer should be followed by a name.
|
||||
// CHECK:STDERR: namespace
|
||||
// CHECK:STDERR: ^
|
||||
namespace
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_incomplete.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '123', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: 'namespace', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '""', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: 'namespace', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '+', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: 'namespace', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'bool', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: 'namespace', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'namespace', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: 'namespace', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: 'namespace', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
Reference in New Issue
Block a user