Skip to content

Commit d6f90c9

Browse files
authored
Support C23 _FloatN, _FloatNx, _BitInt(N), and C++23 std::bfloat16_t (#295)
* Support C23 _FloatN, _FloatNx, _BitInt(N), and C++23 std::bfloat16_t
1 parent ef3cb9f commit d6f90c9

File tree

3 files changed

+161
-15
lines changed

3 files changed

+161
-15
lines changed

examples/simple.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use cpp_demangle::Symbol;
22

33
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
4-
54
let mangled = b"_ZN5space3fooEibc";
6-
5+
76
let sym = Symbol::new(&mangled[..])?;
87
let demangled = sym.to_string();
98

src/ast.rs

Lines changed: 159 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4047,6 +4047,7 @@ define_vocabulary! {
40474047
/// ::= De # IEEE 754r decimal floating point (128 bits)
40484048
/// ::= Df # IEEE 754r decimal floating point (32 bits)
40494049
/// ::= Dh # IEEE 754r half-precision floating point (16 bits)
4050+
/// ::= DF16b # C++23 std::bfloat16_t
40504051
/// ::= Di # char32_t
40514052
/// ::= Ds # char16_t
40524053
/// ::= Du # char8_t
@@ -4081,6 +4082,7 @@ define_vocabulary! {
40814082
DecimalFloat128 (b"De", "decimal128"),
40824083
DecimalFloat32 (b"Df", "decimal32"),
40834084
DecimalFloat16 (b"Dh", "half"),
4085+
BFloat16 (b"DF16b", "std::bfloat16_t"),
40844086
Char32 (b"Di", "char32_t"),
40854087
Char16 (b"Ds", "char16_t"),
40864088
Char8 (b"Du", "char8_t"),
@@ -4090,12 +4092,116 @@ define_vocabulary! {
40904092
}
40914093
}
40924094

4095+
/// <builtin-type> ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits), C++23 std::floatN_t
4096+
/// ::= DF <number> x # IEEE extended precision formats, C23 _FloatNx (N bits)
4097+
/// ::= DB <number> _ # C23 signed _BitInt(N)
4098+
/// ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4099+
/// ::= DU <number> _ # C23 unsigned _BitInt(N)
4100+
/// ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4101+
#[derive(Clone, Debug, PartialEq, Eq)]
4102+
pub enum ParametricBuiltinType {
4103+
/// _FloatN
4104+
FloatN(Number),
4105+
/// _FloatNx
4106+
FloatNx(Number),
4107+
/// signed _BitInt(N)
4108+
SignedBitInt(Number),
4109+
/// unsigned _BitInt(N)
4110+
UnsignedBitInt(Number),
4111+
/// signed _BitInt(expr)
4112+
SignedBitIntExpression(Box<Expression>),
4113+
/// unsigned _BitInt(expr)
4114+
UnsignedBitIntExpression(Box<Expression>),
4115+
}
4116+
4117+
impl Parse for ParametricBuiltinType {
4118+
fn parse<'a, 'b>(
4119+
ctx: &'a ParseContext,
4120+
subs: &'a mut SubstitutionTable,
4121+
input: IndexStr<'b>,
4122+
) -> Result<(ParametricBuiltinType, IndexStr<'b>)> {
4123+
try_begin_parse!("ParametricBuiltinType", ctx, input);
4124+
4125+
let input = consume(b"D", input)?;
4126+
let (ch, input) = input.next_or(error::Error::UnexpectedEnd)?;
4127+
let allow_expression = match ch {
4128+
b'F' => false,
4129+
b'B' | b'U' => true,
4130+
_ => return Err(error::Error::UnexpectedText),
4131+
};
4132+
if input
4133+
.next_or(error::Error::UnexpectedEnd)?
4134+
.0
4135+
.is_ascii_digit()
4136+
{
4137+
let (bit_size, input) = parse_number(10, false, input)?;
4138+
if ch == b'F' {
4139+
if let Ok(input) = consume(b"x", input) {
4140+
return Ok((ParametricBuiltinType::FloatNx(bit_size), input));
4141+
}
4142+
}
4143+
let input = consume(b"_", input)?;
4144+
let t = match ch {
4145+
b'F' => ParametricBuiltinType::FloatN(bit_size),
4146+
b'B' => ParametricBuiltinType::SignedBitInt(bit_size),
4147+
b'U' => ParametricBuiltinType::UnsignedBitInt(bit_size),
4148+
_ => panic!("oh noes"),
4149+
};
4150+
Ok((t, input))
4151+
} else if allow_expression {
4152+
let (expr, input) = Expression::parse(ctx, subs, input)?;
4153+
let expr = Box::new(expr);
4154+
let t = match ch {
4155+
b'B' => ParametricBuiltinType::SignedBitIntExpression(expr),
4156+
b'U' => ParametricBuiltinType::UnsignedBitIntExpression(expr),
4157+
_ => panic!("oh noes"),
4158+
};
4159+
Ok((t, input))
4160+
} else {
4161+
Err(error::Error::UnexpectedText)
4162+
}
4163+
}
4164+
}
4165+
4166+
impl<'subs, W> Demangle<'subs, W> for ParametricBuiltinType
4167+
where
4168+
W: 'subs + DemangleWrite,
4169+
{
4170+
fn demangle<'prev, 'ctx>(
4171+
&'subs self,
4172+
ctx: &'ctx mut DemangleContext<'subs, W>,
4173+
scope: Option<ArgScopeStack<'prev, 'subs>>,
4174+
) -> fmt::Result {
4175+
let ctx = try_begin_demangle!(self, ctx, scope);
4176+
4177+
match *self {
4178+
Self::FloatN(n) => write!(ctx, "_Float{}", n),
4179+
Self::FloatNx(n) => write!(ctx, "_Float{}x", n),
4180+
Self::SignedBitInt(n) => write!(ctx, "signed _BitInt({})", n),
4181+
Self::UnsignedBitInt(n) => write!(ctx, "unsigned _BitInt({})", n),
4182+
Self::SignedBitIntExpression(ref expr) => {
4183+
write!(ctx, "signed _BitInt(")?;
4184+
expr.demangle(ctx, scope)?;
4185+
write!(ctx, ")")
4186+
}
4187+
Self::UnsignedBitIntExpression(ref expr) => {
4188+
write!(ctx, "unsigned _BitInt(")?;
4189+
expr.demangle(ctx, scope)?;
4190+
write!(ctx, ")")
4191+
}
4192+
}
4193+
}
4194+
}
4195+
40934196
/// The `<builtin-type>` production.
40944197
#[derive(Clone, Debug, PartialEq, Eq)]
40954198
pub enum BuiltinType {
4096-
/// A standards compliant builtin type.
4199+
/// A simple standards compliant builtin type.
40974200
Standard(StandardBuiltinType),
40984201

4202+
/// A standards compliant builtin type with a parameter, e.g. _BitInt(32).
4203+
Parametric(ParametricBuiltinType),
4204+
40994205
/// A non-standard, vendor extension type.
41004206
///
41014207
/// ```text
@@ -4116,9 +4222,15 @@ impl Parse for BuiltinType {
41164222
return Ok((BuiltinType::Standard(ty), tail));
41174223
}
41184224

4119-
let tail = consume(b"u", input)?;
4120-
let (name, tail) = SourceName::parse(ctx, subs, tail)?;
4121-
Ok((BuiltinType::Extension(name), tail))
4225+
if let Ok(tail) = consume(b"u", input) {
4226+
let (name, tail) = SourceName::parse(ctx, subs, tail)?;
4227+
Ok((BuiltinType::Extension(name), tail))
4228+
} else {
4229+
match try_recurse!(ParametricBuiltinType::parse(ctx, subs, input)) {
4230+
Ok((ty, tail)) => Ok((BuiltinType::Parametric(ty), tail)),
4231+
Err(e) => Err(e),
4232+
}
4233+
}
41224234
}
41234235
}
41244236

@@ -4135,6 +4247,7 @@ where
41354247

41364248
match *self {
41374249
BuiltinType::Standard(ref ty) => ty.demangle(ctx, scope),
4250+
BuiltinType::Parametric(ref ty) => ty.demangle(ctx, scope),
41384251
BuiltinType::Extension(ref name) => name.demangle(ctx, scope),
41394252
}
41404253
}
@@ -7986,14 +8099,14 @@ mod tests {
79868099
ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix, Decltype, DestructorName,
79878100
Discriminator, Encoding, ExceptionSpec, ExprPrimary, Expression, FunctionParam,
79888101
FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName, MangledName,
7989-
MemberName, Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName, Parse,
7990-
ParseContext, PointerToMemberType, Prefix, PrefixHandle, RefQualifier, ResourceName, SeqId,
7991-
SimpleId, SimpleOperatorName, SourceName, SpecialName, StandardBuiltinType, SubobjectExpr,
7992-
Substitution, TaggedName, TemplateArg, TemplateArgs, TemplateParam, TemplateTemplateParam,
7993-
TemplateTemplateParamHandle, Type, TypeHandle, UnnamedTypeName, UnqualifiedName,
7994-
UnresolvedName, UnresolvedQualifierLevel, UnresolvedType, UnresolvedTypeHandle,
7995-
UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle, VOffset, VectorType,
7996-
WellKnownComponent,
8102+
MemberName, Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName,
8103+
ParametricBuiltinType, Parse, ParseContext, PointerToMemberType, Prefix, PrefixHandle,
8104+
RefQualifier, ResourceName, SeqId, SimpleId, SimpleOperatorName, SourceName, SpecialName,
8105+
StandardBuiltinType, SubobjectExpr, Substitution, TaggedName, TemplateArg, TemplateArgs,
8106+
TemplateParam, TemplateTemplateParam, TemplateTemplateParamHandle, Type, TypeHandle,
8107+
UnnamedTypeName, UnqualifiedName, UnresolvedName, UnresolvedQualifierLevel, UnresolvedType,
8108+
UnresolvedTypeHandle, UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle,
8109+
VOffset, VectorType, WellKnownComponent,
79978110
};
79988111

79998112
use crate::error::Error;
@@ -11060,6 +11173,10 @@ mod tests {
1106011173
})),
1106111174
b"..."
1106211175
}
11176+
b"DF16b..." => {
11177+
BuiltinType::Standard(StandardBuiltinType::BFloat16),
11178+
b"..."
11179+
}
1106311180
}
1106411181
Err => {
1106511182
b"." => Error::UnexpectedText,
@@ -11068,6 +11185,36 @@ mod tests {
1106811185
});
1106911186
}
1107011187

11188+
#[test]
11189+
fn parse_parametric_builtin_type() {
11190+
assert_parse!(BuiltinType {
11191+
Ok => {
11192+
b"DB8_..." => {
11193+
BuiltinType::Parametric(ParametricBuiltinType::SignedBitInt(8)),
11194+
b"..."
11195+
}
11196+
b"DUsZT_" => {
11197+
BuiltinType::Parametric(ParametricBuiltinType::UnsignedBitIntExpression(Box::new(Expression::SizeofTemplatePack(TemplateParam(0))))),
11198+
b""
11199+
}
11200+
b"DF128_..." => {
11201+
BuiltinType::Parametric(ParametricBuiltinType::FloatN(128)),
11202+
b"..."
11203+
}
11204+
b"DF256x..." => {
11205+
BuiltinType::Parametric(ParametricBuiltinType::FloatNx(256)),
11206+
b"..."
11207+
}
11208+
}
11209+
Err => {
11210+
b"DB100000000000000000000000_" => Error::Overflow,
11211+
b"DFsZT_" => Error::UnexpectedText,
11212+
b"DB" => Error::UnexpectedEnd,
11213+
b"DB32" => Error::UnexpectedEnd,
11214+
}
11215+
});
11216+
}
11217+
1107111218
#[test]
1107211219
fn parse_template_param() {
1107311220
assert_parse!(TemplateParam {

src/index_str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl<'a> IndexStr<'a> {
6464
(self.range_to(..idx), self.range_from(idx..))
6565
}
6666

67-
/// The same as `split_at`, but returns a `Result` rather than panicking
67+
/// The same as `split_at`, but returns an `Option` rather than panicking
6868
/// when the index is out of bounds.
6969
#[inline]
7070
pub fn try_split_at(&self, idx: usize) -> Option<(IndexStr<'a>, IndexStr<'a>)> {

0 commit comments

Comments
 (0)