Skip to content

Commit 224df6f

Browse files
committed
Reorder parsing of type qualifiers to match the spec.
The spec says that the `qualified-type` production (within `type`) is parsed second only to the `builtin-type` production. The `qualified-type` production is ambiguous with later productions (in particular with the "Ul" inside `class-enum-type`) so the order does matter. This reorders things for "Ul" and brings along the other parts of the `qualified-type` production. To preserve the existing behavior for `function-type`, rather than attempt to pass down a leading `CV-qualifiers` we simply skip them if the tail remaining indicates a `function-type` production is imminent.
1 parent a6213a0 commit 224df6f

File tree

1 file changed

+47
-23
lines changed

1 file changed

+47
-23
lines changed

src/ast.rs

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3533,6 +3533,40 @@ impl Parse for TypeHandle {
35333533
return Ok((handle, tail));
35343534
}
35353535

3536+
// ::= <qualified-type>
3537+
// We don't have a separate type for the <qualified-type> production.
3538+
// Process these all up front, so that any ambiguity that might exist
3539+
// with later productions is handled correctly.
3540+
3541+
// ::= <extended-qualifier>
3542+
if let Ok(tail) = consume(b"U", input) {
3543+
let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3544+
let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
3545+
(Some(args), tail)
3546+
} else {
3547+
(None, tail)
3548+
};
3549+
let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3550+
let ty = Type::VendorExtension(name, args, ty);
3551+
return insert_and_return_handle(ty, subs, tail);
3552+
}
3553+
3554+
// ::= <CV-qualifiers>
3555+
if let Ok((qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
3556+
// CvQualifiers can parse successfully without consuming any input,
3557+
// but we don't want to recurse unless we know we did consume some
3558+
// input, lest we go into an infinite loop and blow the stack.
3559+
if tail.len() < input.len() {
3560+
// If the following production is a <function-type>, we want to let
3561+
// it pick up these <CV-qualifiers>.
3562+
if !FunctionType::starts_with(&tail) {
3563+
let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3564+
let ty = Type::Qualified(qualifiers, ty);
3565+
return insert_and_return_handle(ty, subs, tail);
3566+
}
3567+
}
3568+
}
3569+
35363570
if let Ok((ty, tail)) = ClassEnumType::parse(ctx, subs, input) {
35373571
let ty = Type::ClassEnum(ty);
35383572
return insert_and_return_handle(ty, subs, tail);
@@ -3625,17 +3659,6 @@ impl Parse for TypeHandle {
36253659
return insert_and_return_handle(ty, subs, tail);
36263660
}
36273661

3628-
if let Ok((qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
3629-
// CvQualifiers can parse successfully without consuming any input,
3630-
// but we don't want to recurse unless we know we did consume some
3631-
// input, lest we go into an infinite loop and blow the stack.
3632-
if tail.len() < input.len() {
3633-
let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3634-
let ty = Type::Qualified(qualifiers, ty);
3635-
return insert_and_return_handle(ty, subs, tail);
3636-
}
3637-
}
3638-
36393662
if let Ok(tail) = consume(b"P", input) {
36403663
let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
36413664
let ty = Type::PointerTo(ty);
@@ -3666,18 +3689,6 @@ impl Parse for TypeHandle {
36663689
return insert_and_return_handle(ty, subs, tail);
36673690
}
36683691

3669-
if let Ok(tail) = consume(b"U", input) {
3670-
let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3671-
let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
3672-
(Some(args), tail)
3673-
} else {
3674-
(None, tail)
3675-
};
3676-
let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3677-
let ty = Type::VendorExtension(name, args, ty);
3678-
return insert_and_return_handle(ty, subs, tail);
3679-
}
3680-
36813692
let tail = consume(b"Dp", input)?;
36823693
let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
36833694
let ty = Type::PackExpansion(ty);
@@ -4330,6 +4341,18 @@ where
43304341
}
43314342
}
43324343

4344+
impl FunctionType {
4345+
#[inline]
4346+
fn starts_with(input: &IndexStr) -> bool {
4347+
input.peek() == Some(b'F')
4348+
|| (input.peek() == Some(b'D')
4349+
&& (matches!(
4350+
input.peek_second(),
4351+
Some(b'o') | Some(b'O') | Some(b'x') | Some(b'w')
4352+
)))
4353+
}
4354+
}
4355+
43334356
/// The `<bare-function-type>` production.
43344357
///
43354358
/// ```text
@@ -8953,6 +8976,7 @@ mod tests {
89538976
b"Dp" => Error::UnexpectedEnd,
89548977
b"D" => Error::UnexpectedEnd,
89558978
b"P" => Error::UnexpectedEnd,
8979+
b"UlvE_" => Error::UnexpectedText,
89568980
b"" => Error::UnexpectedEnd,
89578981
}
89588982
}

0 commit comments

Comments
 (0)