@@ -3160,9 +3160,19 @@ private string GetRemappedCursorName(NamedDecl namedDecl, out string nativeTypeN
3160
3160
Debug . Assert ( parent is not null ) ;
3161
3161
remappedName = GetRemappedCursorName ( parent ) ;
3162
3162
}
3163
- else if ( namedDecl is FieldDecl fieldDecl )
3163
+ else if ( ( namedDecl is FieldDecl fieldDecl ) && name . StartsWith ( "__AnonymousFieldDecl_" , StringComparison . Ordinal ) )
3164
3164
{
3165
- if ( name . StartsWith ( "__AnonymousFieldDecl_" , StringComparison . Ordinal ) )
3165
+ if ( fieldDecl . Type . AsCXXRecordDecl ? . IsAnonymous == true )
3166
+ {
3167
+ // For fields of anonymous types, use the name of the type but clean off the type
3168
+ // kind tag at the end.
3169
+ var typeName = GetRemappedNameForAnonymousRecord ( fieldDecl . Type . AsCXXRecordDecl ) ;
3170
+ var tagIndex = typeName . LastIndexOf ( "_e__" , StringComparison . Ordinal ) ;
3171
+ Debug . Assert ( typeName [ 0 ] == '_' ) ;
3172
+ Debug . Assert ( tagIndex >= 0 ) ;
3173
+ remappedName = typeName . Substring ( 1 , tagIndex - 1 ) ;
3174
+ }
3175
+ else
3166
3176
{
3167
3177
remappedName = "Anonymous" ;
3168
3178
@@ -3178,28 +3188,62 @@ private string GetRemappedCursorName(NamedDecl namedDecl, out string nativeTypeN
3178
3188
}
3179
3189
else if ( ( namedDecl is RecordDecl recordDecl ) && name . StartsWith ( "__AnonymousRecord_" , StringComparison . Ordinal ) )
3180
3190
{
3181
- if ( recordDecl . Parent is RecordDecl parentRecordDecl )
3182
- {
3183
- remappedName = "_Anonymous" ;
3191
+ remappedName = GetRemappedNameForAnonymousRecord ( recordDecl ) ;
3192
+ }
3184
3193
3185
- var matchingField = parentRecordDecl . Fields . Where ( ( fieldDecl ) => fieldDecl . Type . CanonicalType == recordDecl . TypeForDecl . CanonicalType ) . FirstOrDefault ( ) ;
3194
+ return remappedName ;
3195
+ }
3186
3196
3187
- if ( matchingField is not null )
3188
- {
3189
- remappedName = "_" ;
3190
- remappedName += GetRemappedCursorName ( matchingField ) ;
3191
- }
3192
- else if ( parentRecordDecl . AnonymousRecords . Count > 1 )
3197
+ private string GetRemappedNameForAnonymousRecord ( RecordDecl recordDecl )
3198
+ {
3199
+ if ( recordDecl . Parent is RecordDecl parentRecordDecl )
3200
+ {
3201
+ var remappedNameBuilder = new StringBuilder ( ) ;
3202
+ var matchingField = parentRecordDecl . Fields . Where ( ( fieldDecl ) => fieldDecl . Type . CanonicalType == recordDecl . TypeForDecl . CanonicalType ) . FirstOrDefault ( ) ;
3203
+
3204
+ if ( ( matchingField is not null ) && ! matchingField . IsAnonymousField )
3205
+ {
3206
+ _ = remappedNameBuilder . Append ( '_' ) ;
3207
+ _ = remappedNameBuilder . Append ( GetRemappedCursorName ( matchingField ) ) ;
3208
+ }
3209
+ else
3210
+ {
3211
+ _ = remappedNameBuilder . Append ( "_Anonymous" ) ;
3212
+
3213
+ // If there is more than one anonymous type, then add a numeral to differentiate.
3214
+ if ( parentRecordDecl . AnonymousRecords . Count > 1 )
3193
3215
{
3194
3216
var index = parentRecordDecl . AnonymousRecords . IndexOf ( recordDecl ) + 1 ;
3195
- remappedName += index . ToString ( CultureInfo . InvariantCulture ) ;
3217
+ Debug . Assert ( index > 0 ) ;
3218
+ _ = remappedNameBuilder . Append ( index ) ;
3196
3219
}
3197
3220
3198
- remappedName += $ "_e__{ ( recordDecl . IsUnion ? "Union" : "Struct" ) } ";
3221
+ // C# doesn't allow a nested type to have the same name as the parent, so if the
3222
+ // parent is also anonymous, add the nesting depth as a way to avoid conflicts with
3223
+ // the parent's name.
3224
+ if ( parentRecordDecl . IsAnonymous )
3225
+ {
3226
+ var depth = 1 ;
3227
+ var currentParent = parentRecordDecl . Parent ;
3228
+ while ( ( currentParent is RecordDecl currentParentRecordDecl ) && currentParentRecordDecl . IsAnonymous )
3229
+ {
3230
+ depth ++ ;
3231
+ currentParent = currentParentRecordDecl . Parent ;
3232
+ }
3233
+ _ = remappedNameBuilder . Append ( '_' ) ;
3234
+ _ = remappedNameBuilder . Append ( depth ) ;
3235
+ }
3199
3236
}
3200
- }
3201
3237
3202
- return remappedName ;
3238
+ // Add the type kind tag.
3239
+ _ = remappedNameBuilder . Append ( "_e__" ) ;
3240
+ _ = remappedNameBuilder . Append ( recordDecl . IsUnion ? "Union" : "Struct" ) ;
3241
+ return remappedNameBuilder . ToString ( ) ;
3242
+ }
3243
+ else
3244
+ {
3245
+ return $ "_Anonymous_e__{ ( recordDecl . IsUnion ? "Union" : "Struct" ) } ";
3246
+ }
3203
3247
}
3204
3248
3205
3249
private string GetRemappedName ( string name , Cursor ? cursor , bool tryRemapOperatorName , out bool wasRemapped , bool skipUsing = false )
@@ -3298,48 +3342,7 @@ private string GetRemappedTypeName(Cursor? cursor, Cursor? context, Type type, o
3298
3342
if ( IsType < RecordType > ( cursor , type , out var recordType ) && remappedName . StartsWith ( "__AnonymousRecord_" , StringComparison . Ordinal ) )
3299
3343
{
3300
3344
var recordDecl = recordType . Decl ;
3301
- remappedName = "_Anonymous" ;
3302
-
3303
- if ( recordDecl . Parent is RecordDecl parentRecordDecl )
3304
- {
3305
- var matchingField = parentRecordDecl . Fields . Where ( ( fieldDecl ) => fieldDecl . Type . CanonicalType == recordType ) . FirstOrDefault ( ) ;
3306
-
3307
- if ( matchingField is not null )
3308
- {
3309
- remappedName = "_" ;
3310
- remappedName += GetRemappedCursorName ( matchingField ) ;
3311
- }
3312
- else
3313
- {
3314
- var index = 0 ;
3315
-
3316
- if ( parentRecordDecl . AnonymousRecords . Count > 1 )
3317
- {
3318
- index = parentRecordDecl . AnonymousRecords . IndexOf ( cursor ) + 1 ;
3319
- }
3320
-
3321
- while ( parentRecordDecl . IsAnonymousStructOrUnion && ( parentRecordDecl . IsUnion == recordType . Decl . IsUnion ) )
3322
- {
3323
- index += 1 ;
3324
-
3325
- if ( parentRecordDecl . Parent is RecordDecl parentRecordDeclParent )
3326
- {
3327
- if ( parentRecordDeclParent . AnonymousRecords . Count > 0 )
3328
- {
3329
- index += parentRecordDeclParent . AnonymousRecords . Count - 1 ;
3330
- }
3331
- parentRecordDecl = parentRecordDeclParent ;
3332
- }
3333
- }
3334
-
3335
- if ( index != 0 )
3336
- {
3337
- remappedName += index . ToString ( CultureInfo . InvariantCulture ) ;
3338
- }
3339
- }
3340
- }
3341
-
3342
- remappedName += $ "_e__{ ( recordDecl . IsUnion ? "Union" : "Struct" ) } ";
3345
+ remappedName = GetRemappedNameForAnonymousRecord ( recordDecl ) ;
3343
3346
}
3344
3347
else if ( IsType < EnumType > ( cursor , type , out var enumType ) && remappedName . StartsWith ( "__AnonymousEnum_" , StringComparison . Ordinal ) )
3345
3348
{
@@ -4566,7 +4569,7 @@ private bool HasBaseField(CXXRecordDecl cxxRecordDecl)
4566
4569
4567
4570
private bool HasField ( RecordDecl recordDecl )
4568
4571
{
4569
- var hasField = recordDecl . Fields . Any ( ) || recordDecl . Decls . Any ( ( decl ) => ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymousStructOrUnion && HasField ( nestedRecordDecl ) ) ;
4572
+ var hasField = recordDecl . Fields . Any ( ) || recordDecl . Decls . Any ( ( decl ) => ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymous && HasField ( nestedRecordDecl ) ) ;
4570
4573
4571
4574
if ( ! hasField && ( recordDecl is CXXRecordDecl cxxRecordDecl ) )
4572
4575
{
@@ -5117,7 +5120,7 @@ bool IsEmptyRecord(RecordDecl recordDecl)
5117
5120
5118
5121
foreach ( var decl in recordDecl . Decls )
5119
5122
{
5120
- if ( ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymousStructOrUnion && ! IsEmptyRecord ( nestedRecordDecl ) )
5123
+ if ( ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymous && ! IsEmptyRecord ( nestedRecordDecl ) )
5121
5124
{
5122
5125
return false ;
5123
5126
}
@@ -6144,7 +6147,7 @@ private bool IsUnsafe(RecordDecl recordDecl)
6144
6147
{
6145
6148
return true ;
6146
6149
}
6147
- else if ( ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymousStructOrUnion && ( IsUnsafe ( nestedRecordDecl ) || Config . GenerateCompatibleCode ) )
6150
+ else if ( ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymous && ( IsUnsafe ( nestedRecordDecl ) || Config . GenerateCompatibleCode ) )
6148
6151
{
6149
6152
return true ;
6150
6153
}
0 commit comments