@@ -3619,6 +3619,11 @@ pub enum Type {
36193619
36203620 /// A pack expansion.
36213621 PackExpansion ( TypeHandle ) ,
3622+
3623+ /// Builtin type eligible for substitutions, e.g. vendor extended type or _BitInt(N).
3624+ /// Note: most builtin types are excluded from substitutions, and we store them directly
3625+ /// in TypeHandle without creating a Type.
3626+ Builtin ( BuiltinType ) ,
36223627}
36233628
36243629define_handle ! {
@@ -3665,6 +3670,30 @@ impl Parse for TypeHandle {
36653670 if let Ok ( ( builtin, tail) ) = try_recurse ! ( BuiltinType :: parse( ctx, subs, input) ) {
36663671 // Builtin types are one of two exceptions that do not end up in the
36673672 // substitutions table.
3673+
3674+ // But there are exceptions to the exception:
3675+ // * "vendor extended type" builtin types do go in the substitution table.
3676+ // * Quirk: clang treats `_BitInt` types (`DB<n>_`, `DU<n>_`) as substitutable,
3677+ // even though they're <builtin-type>. This contradicts the current Itanium ABI spec.
3678+ // This behavior is consistent between clang's mangler and demangler.
3679+ // It seems more likely that the ABI spec will be changed to match clang, rather than
3680+ // the other way around. So we do what clang does and put _BitInt-s into the substitution table.
3681+ let substitutable = match & builtin {
3682+ BuiltinType :: Parametric ( p) => match p {
3683+ ParametricBuiltinType :: SignedBitInt ( _) |
3684+ ParametricBuiltinType :: UnsignedBitInt ( _) |
3685+ ParametricBuiltinType :: SignedBitIntExpression ( _) |
3686+ ParametricBuiltinType :: UnsignedBitIntExpression ( _) => true ,
3687+ _ => false ,
3688+ }
3689+ BuiltinType :: Extension ( _) => true ,
3690+ _ => false ,
3691+ } ;
3692+ if substitutable {
3693+ let ty = Type :: Builtin ( builtin) ;
3694+ return insert_and_return_handle ( ty, subs, tail) ;
3695+ }
3696+
36683697 let handle = TypeHandle :: Builtin ( builtin) ;
36693698 return Ok ( ( handle, tail) ) ;
36703699 }
@@ -3908,6 +3937,7 @@ where
39083937 }
39093938 Ok ( ( ) )
39103939 }
3940+ Type :: Builtin ( ref builtin) => builtin. demangle ( ctx, scope) ,
39113941 }
39123942 }
39133943}
@@ -4309,6 +4339,7 @@ impl Parse for ParametricBuiltinType {
43094339 Ok ( ( t, input) )
43104340 } else if allow_expression {
43114341 let ( expr, input) = Expression :: parse ( ctx, subs, input) ?;
4342+ let input = consume ( b"_" , input) ?;
43124343 let expr = Box :: new ( expr) ;
43134344 let t = match ch {
43144345 b'B' => ParametricBuiltinType :: SignedBitIntExpression ( expr) ,
@@ -4336,10 +4367,10 @@ where
43364367 match * self {
43374368 Self :: FloatN ( n) => write ! ( ctx, "_Float{}" , n) ,
43384369 Self :: FloatNx ( n) => write ! ( ctx, "_Float{}x" , n) ,
4339- Self :: SignedBitInt ( n) => write ! ( ctx, "signed _BitInt({})" , n) ,
4370+ Self :: SignedBitInt ( n) => write ! ( ctx, "_BitInt({})" , n) ,
43404371 Self :: UnsignedBitInt ( n) => write ! ( ctx, "unsigned _BitInt({})" , n) ,
43414372 Self :: SignedBitIntExpression ( ref expr) => {
4342- write ! ( ctx, "signed _BitInt(" ) ?;
4373+ write ! ( ctx, "_BitInt(" ) ?;
43434374 expr. demangle ( ctx, scope) ?;
43444375 write ! ( ctx, ")" )
43454376 }
@@ -11615,7 +11646,7 @@ mod tests {
1161511646 BuiltinType :: Parametric ( ParametricBuiltinType :: SignedBitInt ( 8 ) ) ,
1161611647 b"..."
1161711648 }
11618- b"DUsZT_ " => {
11649+ b"DUsZT__ " => {
1161911650 BuiltinType :: Parametric ( ParametricBuiltinType :: UnsignedBitIntExpression ( Box :: new( Expression :: SizeofTemplatePack ( TemplateParam ( 0 ) ) ) ) ) ,
1162011651 b""
1162111652 }
0 commit comments