@@ -3160,9 +3160,19 @@ private string GetRemappedCursorName(NamedDecl namedDecl, out string nativeTypeN
31603160 Debug . Assert ( parent is not null ) ;
31613161 remappedName = GetRemappedCursorName ( parent ) ;
31623162 }
3163- else if ( namedDecl is FieldDecl fieldDecl )
3163+ else if ( ( namedDecl is FieldDecl fieldDecl ) && name . StartsWith ( "__AnonymousFieldDecl_" , StringComparison . Ordinal ) )
31643164 {
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
31663176 {
31673177 remappedName = "Anonymous" ;
31683178
@@ -3178,28 +3188,62 @@ private string GetRemappedCursorName(NamedDecl namedDecl, out string nativeTypeN
31783188 }
31793189 else if ( ( namedDecl is RecordDecl recordDecl ) && name . StartsWith ( "__AnonymousRecord_" , StringComparison . Ordinal ) )
31803190 {
3181- if ( recordDecl . Parent is RecordDecl parentRecordDecl )
3182- {
3183- remappedName = "_Anonymous" ;
3191+ remappedName = GetRemappedNameForAnonymousRecord ( recordDecl ) ;
3192+ }
31843193
3185- var matchingField = parentRecordDecl . Fields . Where ( ( fieldDecl ) => fieldDecl . Type . CanonicalType == recordDecl . TypeForDecl . CanonicalType ) . FirstOrDefault ( ) ;
3194+ return remappedName ;
3195+ }
31863196
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 )
31933215 {
31943216 var index = parentRecordDecl . AnonymousRecords . IndexOf ( recordDecl ) + 1 ;
3195- remappedName += index . ToString ( CultureInfo . InvariantCulture ) ;
3217+ Debug . Assert ( index > 0 ) ;
3218+ _ = remappedNameBuilder . Append ( index ) ;
31963219 }
31973220
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+ }
31993236 }
3200- }
32013237
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+ }
32033247 }
32043248
32053249 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
32983342 if ( IsType < RecordType > ( cursor , type , out var recordType ) && remappedName . StartsWith ( "__AnonymousRecord_" , StringComparison . Ordinal ) )
32993343 {
33003344 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 ) ;
33433346 }
33443347 else if ( IsType < EnumType > ( cursor , type , out var enumType ) && remappedName . StartsWith ( "__AnonymousEnum_" , StringComparison . Ordinal ) )
33453348 {
@@ -4566,7 +4569,7 @@ private bool HasBaseField(CXXRecordDecl cxxRecordDecl)
45664569
45674570 private bool HasField ( RecordDecl recordDecl )
45684571 {
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 ) ) ;
45704573
45714574 if ( ! hasField && ( recordDecl is CXXRecordDecl cxxRecordDecl ) )
45724575 {
@@ -5117,7 +5120,7 @@ bool IsEmptyRecord(RecordDecl recordDecl)
51175120
51185121 foreach ( var decl in recordDecl . Decls )
51195122 {
5120- if ( ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymousStructOrUnion && ! IsEmptyRecord ( nestedRecordDecl ) )
5123+ if ( ( decl is RecordDecl nestedRecordDecl ) && nestedRecordDecl . IsAnonymous && ! IsEmptyRecord ( nestedRecordDecl ) )
51215124 {
51225125 return false ;
51235126 }
@@ -6144,7 +6147,7 @@ private bool IsUnsafe(RecordDecl recordDecl)
61446147 {
61456148 return true ;
61466149 }
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 ) )
61486151 {
61496152 return true ;
61506153 }
0 commit comments