Skip to content

Commit 39ffd11

Browse files
committed
Support noexcept/noexcept(expression).
Issue #273
1 parent 8dfae16 commit 39ffd11

File tree

2 files changed

+110
-7
lines changed

2 files changed

+110
-7
lines changed

src/ast.rs

Lines changed: 105 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4146,14 +4146,71 @@ impl<'a> GetLeafName<'a> for QualifiedBuiltin {
41464146
}
41474147
}
41484148

4149+
/// The `<exception-spec>` production.
4150+
///
4151+
/// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
4152+
/// ::= DO <expression> E # computed (instantiation-dependent) noexcept
4153+
/// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
4154+
#[derive(Clone, Debug, PartialEq, Eq)]
4155+
pub enum ExceptionSpec {
4156+
/// noexcept
4157+
NoExcept,
4158+
/// noexcept(expression)
4159+
Computed(Expression),
4160+
// Dynamic exception specification is deprecated, lets see if we can get away with
4161+
// not implementing it.
4162+
}
4163+
4164+
impl Parse for ExceptionSpec {
4165+
fn parse<'a, 'b>(
4166+
ctx: &'a ParseContext,
4167+
subs: &'a mut SubstitutionTable,
4168+
input: IndexStr<'b>,
4169+
) -> Result<(ExceptionSpec, IndexStr<'b>)> {
4170+
try_begin_parse!("ExceptionSpec", ctx, input);
4171+
4172+
if let Ok(tail) = consume(b"Do", input) {
4173+
return Ok((ExceptionSpec::NoExcept, tail));
4174+
}
4175+
4176+
let tail = consume(b"DO", input)?;
4177+
let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4178+
let tail = consume(b"E", tail)?;
4179+
Ok((ExceptionSpec::Computed(expr), tail))
4180+
}
4181+
}
4182+
4183+
impl<'subs, W> Demangle<'subs, W> for ExceptionSpec
4184+
where
4185+
W: 'subs + DemangleWrite,
4186+
{
4187+
fn demangle<'prev, 'ctx>(
4188+
&'subs self,
4189+
ctx: &'ctx mut DemangleContext<'subs, W>,
4190+
scope: Option<ArgScopeStack<'prev, 'subs>>,
4191+
) -> fmt::Result {
4192+
let ctx = try_begin_demangle!(self, ctx, scope);
4193+
4194+
match *self {
4195+
ExceptionSpec::NoExcept => write!(ctx, "noexcept"),
4196+
ExceptionSpec::Computed(ref expr) => {
4197+
write!(ctx, "noexcept(")?;
4198+
expr.demangle(ctx, scope)?;
4199+
write!(ctx, ")")
4200+
}
4201+
}
4202+
}
4203+
}
4204+
41494205
/// The `<function-type>` production.
41504206
///
41514207
/// ```text
4152-
/// <function-type> ::= [<CV-qualifiers>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
4208+
/// <function-type> ::= [<CV-qualifiers>] [exception-spec] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
41534209
/// ```
41544210
#[derive(Clone, Debug, PartialEq, Eq)]
41554211
pub struct FunctionType {
41564212
cv_qualifiers: CvQualifiers,
4213+
exception_spec: Option<ExceptionSpec>,
41574214
transaction_safe: bool,
41584215
extern_c: bool,
41594216
bare: BareFunctionType,
@@ -4175,6 +4232,13 @@ impl Parse for FunctionType {
41754232
(Default::default(), input)
41764233
};
41774234

4235+
let (exception_spec, tail) =
4236+
if let Ok((exception_spec, tail)) = ExceptionSpec::parse(ctx, subs, tail) {
4237+
(Some(exception_spec), tail)
4238+
} else {
4239+
(None, tail)
4240+
};
4241+
41784242
let (transaction_safe, tail) = if let Ok(tail) = consume(b"Dx", tail) {
41794243
(true, tail)
41804244
} else {
@@ -4202,6 +4266,7 @@ impl Parse for FunctionType {
42024266

42034267
let func_ty = FunctionType {
42044268
cv_qualifiers: cv_qualifiers,
4269+
exception_spec: exception_spec,
42054270
transaction_safe: transaction_safe,
42064271
extern_c: extern_c,
42074272
bare: bare,
@@ -4227,6 +4292,11 @@ where
42274292
if ctx.pop_inner_if(self) {
42284293
self.demangle_as_inner(ctx, scope)?;
42294294
}
4295+
if let Some(ref es) = self.exception_spec {
4296+
// Print out a space before printing "noexcept"
4297+
ctx.ensure_space()?;
4298+
es.demangle(ctx, scope)?;
4299+
}
42304300
Ok(())
42314301
}
42324302
}
@@ -7792,12 +7862,12 @@ mod tests {
77927862
use super::{
77937863
ArrayType, BareFunctionType, BaseUnresolvedName, BuiltinType, CallOffset, ClassEnumType,
77947864
ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix, Decltype, DestructorName,
7795-
Discriminator, Encoding, ExprPrimary, Expression, FunctionParam, FunctionType,
7796-
GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName, MangledName, MemberName,
7797-
Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName, Parse, ParseContext,
7798-
PointerToMemberType, Prefix, PrefixHandle, RefQualifier, ResourceName, SeqId, SimpleId,
7799-
SimpleOperatorName, SourceName, SpecialName, StandardBuiltinType, Substitution, TaggedName,
7800-
TemplateArg, TemplateArgs, TemplateParam, TemplateTemplateParam,
7865+
Discriminator, Encoding, ExceptionSpec, ExprPrimary, Expression, FunctionParam,
7866+
FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName, MangledName,
7867+
MemberName, Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName, Parse,
7868+
ParseContext, PointerToMemberType, Prefix, PrefixHandle, RefQualifier, ResourceName, SeqId,
7869+
SimpleId, SimpleOperatorName, SourceName, SpecialName, StandardBuiltinType, Substitution,
7870+
TaggedName, TemplateArg, TemplateArgs, TemplateParam, TemplateTemplateParam,
78017871
TemplateTemplateParamHandle, Type, TypeHandle, UnnamedTypeName, UnqualifiedName,
78027872
UnresolvedName, UnresolvedQualifierLevel, UnresolvedType, UnresolvedTypeHandle,
78037873
UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle, VOffset, VectorType,
@@ -8649,6 +8719,7 @@ mod tests {
86498719
volatile: false,
86508720
const_: false,
86518721
},
8722+
exception_spec: None,
86528723
transaction_safe: false,
86538724
extern_c: false,
86548725
bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
@@ -8819,6 +8890,28 @@ mod tests {
88198890
});
88208891
}
88218892

8893+
#[test]
8894+
fn parse_exception_spec() {
8895+
assert_parse!(ExceptionSpec {
8896+
Ok => {
8897+
b"Do..." => {
8898+
ExceptionSpec::NoExcept,
8899+
b"..."
8900+
}
8901+
b"DOtrE..." => {
8902+
ExceptionSpec::Computed(Expression::Rethrow),
8903+
b"..."
8904+
}
8905+
}
8906+
Err => {
8907+
b"DOtre" => Error::UnexpectedText,
8908+
b"DOE" => Error::UnexpectedText,
8909+
b"D" => Error::UnexpectedEnd,
8910+
b"" => Error::UnexpectedEnd,
8911+
}
8912+
});
8913+
}
8914+
88228915
#[test]
88238916
fn parse_function_type() {
88248917
assert_parse!(FunctionType {
@@ -8835,6 +8928,7 @@ mod tests {
88358928
volatile: false,
88368929
const_: true,
88378930
},
8931+
exception_spec: None,
88388932
transaction_safe: true,
88398933
extern_c: true,
88408934
bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
@@ -8850,6 +8944,7 @@ mod tests {
88508944
volatile: false,
88518945
const_: false,
88528946
},
8947+
exception_spec: None,
88538948
transaction_safe: true,
88548949
extern_c: true,
88558950
bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
@@ -8865,6 +8960,7 @@ mod tests {
88658960
volatile: false,
88668961
const_: false,
88678962
},
8963+
exception_spec: None,
88688964
transaction_safe: false,
88698965
extern_c: true,
88708966
bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
@@ -8880,6 +8976,7 @@ mod tests {
88808976
volatile: false,
88818977
const_: false,
88828978
},
8979+
exception_spec: None,
88838980
transaction_safe: false,
88848981
extern_c: false,
88858982
bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
@@ -8895,6 +8992,7 @@ mod tests {
88958992
volatile: false,
88968993
const_: false,
88978994
},
8995+
exception_spec: None,
88988996
transaction_safe: false,
88998997
extern_c: false,
89008998
bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),

tests/tests.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,3 +600,8 @@ demangles!(
600600
_ZN4glslL7combineIhLi2EEEDvmlT0_Li4E_T_DvT0__S1_S3_S3_S3_,
601601
"unsigned char __vector((2)*(4)) glsl::combine<unsigned char, 2>(unsigned char __vector(2), unsigned char __vector(2), unsigned char __vector(2), unsigned char __vector(2))"
602602
);
603+
604+
demangles!(
605+
_Z14WasmMemoryCopyIPhPDoFPvS1_PKvmEjEiP9JSContextT_mT1_S9_S9_T0_,
606+
"int WasmMemoryCopy<unsigned char*, void* (*)(void*, void const*, unsigned long) noexcept, unsigned int>(JSContext*, unsigned char*, unsigned long, unsigned int, unsigned int, unsigned int, void* (*)(void*, void const*, unsigned long) noexcept)"
607+
);

0 commit comments

Comments
 (0)