Skip to content

Commit 9153e00

Browse files
committed
Adjust how nested anonymous record naming conflicts are resolved
1 parent e746850 commit 9153e00

37 files changed

+764
-721
lines changed

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
872872
return;
873873
}
874874

875-
if (IsPrevContextDecl<RecordDecl>(out var prevContext, out _) && prevContext.IsAnonymous)
875+
if (IsPrevContextDecl<RecordDecl>(out var prevContext, out _) && prevContext.IsAnonymousStructOrUnion)
876876
{
877877
// We shouldn't process indirect fields where the prev context is an anonymous record decl
878878
return;
@@ -887,7 +887,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
887887
var contextNameParts = new Stack<string>();
888888
var contextTypeParts = new Stack<string>();
889889

890-
while (rootRecordDecl.IsAnonymous && (rootRecordDecl.Parent is RecordDecl parentRecordDecl))
890+
while (rootRecordDecl.IsAnonymousStructOrUnion && (rootRecordDecl.Parent is RecordDecl parentRecordDecl))
891891
{
892892
// The name of a field of an anonymous type should be same as the type's name minus the
893893
// type kind tag at the end and the leading `_`.
@@ -1390,7 +1390,7 @@ private void VisitRecordDecl(RecordDecl recordDecl)
13901390
var maxAlignm = recordDecl.Fields.Any() ? recordDecl.Fields.Max((fieldDecl) => Math.Max(fieldDecl.Type.Handle.AlignOf, 1)) : alignment;
13911391

13921392
var isTopLevelStruct = _config.WithTypes.TryGetValue(name, out var withType) && withType.Equals("struct", StringComparison.Ordinal);
1393-
var generateTestsClass = !recordDecl.IsAnonymous && recordDecl.DeclContext is not RecordDecl;
1393+
var generateTestsClass = !recordDecl.IsAnonymousStructOrUnion && recordDecl.DeclContext is not RecordDecl;
13941394
var testOutputStarted = false;
13951395

13961396
var nullableUuid = (Guid?)null;

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,7 +3210,7 @@ private string GetRemappedCursorName(NamedDecl namedDecl, out string nativeTypeN
32103210
}
32113211
else if ((namedDecl is FieldDecl fieldDecl) && name.StartsWith("__AnonymousFieldDecl_", StringComparison.Ordinal))
32123212
{
3213-
if (fieldDecl.Type.AsCXXRecordDecl?.IsAnonymous == true)
3213+
if (fieldDecl.Type.AsCXXRecordDecl?.IsAnonymousStructOrUnion == true)
32143214
{
32153215
// For fields of anonymous types, use the name of the type but clean off the type
32163216
// kind tag at the end.
@@ -3242,12 +3242,72 @@ private string GetRemappedCursorName(NamedDecl namedDecl, out string nativeTypeN
32423242
return remappedName;
32433243
}
32443244

3245+
private static int GetAnonymousRecordIndex(RecordDecl recordDecl, RecordDecl parentRecordDecl)
3246+
{
3247+
var index = -1;
3248+
var parentAnonRecordCount = parentRecordDecl.AnonymousRecords.Count;
3249+
3250+
if (parentAnonRecordCount != 0)
3251+
{
3252+
index = parentRecordDecl.AnonymousRecords.IndexOf(recordDecl);
3253+
3254+
if (index != -1)
3255+
{
3256+
if (parentAnonRecordCount > 1)
3257+
{
3258+
index++;
3259+
}
3260+
3261+
if (parentRecordDecl.Parent is RecordDecl grandParentRecordDecl)
3262+
{
3263+
var parentIndex = GetAnonymousRecordIndex(parentRecordDecl, grandParentRecordDecl);
3264+
3265+
// We can't have the nested anonymous record have the same name as the parent
3266+
// so skip that index and just go one higher instead. This could still conflict
3267+
// with another anonymous record at a different level, but that is less likely
3268+
// and will still be unambiguous in total.
3269+
3270+
if (parentIndex == index)
3271+
{
3272+
if (recordDecl.IsUnion == parentRecordDecl.IsUnion)
3273+
{
3274+
index++;
3275+
}
3276+
}
3277+
else if ((parentIndex != 0) && (index > parentIndex))
3278+
{
3279+
if (recordDecl.IsUnion == parentRecordDecl.AnonymousRecords[parentIndex].IsUnion)
3280+
{
3281+
index++;
3282+
}
3283+
}
3284+
}
3285+
}
3286+
}
3287+
3288+
return index;
3289+
}
3290+
32453291
private string GetRemappedNameForAnonymousRecord(RecordDecl recordDecl)
32463292
{
32473293
if (recordDecl.Parent is RecordDecl parentRecordDecl)
32483294
{
32493295
var remappedNameBuilder = new StringBuilder();
3250-
var matchingField = parentRecordDecl.Fields.Where((fieldDecl) => fieldDecl.Type.CanonicalType == recordDecl.TypeForDecl.CanonicalType).FirstOrDefault();
3296+
var matchingField = null as FieldDecl;
3297+
3298+
if (!recordDecl.IsAnonymousStructOrUnion)
3299+
{
3300+
matchingField = parentRecordDecl.Fields.Where((fieldDecl) => {
3301+
var fieldType = fieldDecl.Type.CanonicalType;
3302+
3303+
if (fieldType is ArrayType arrayType)
3304+
{
3305+
fieldType = arrayType.ElementType.CanonicalType;
3306+
}
3307+
3308+
return fieldType == recordDecl.TypeForDecl.CanonicalType;
3309+
}).FirstOrDefault();
3310+
}
32513311

32523312
if ((matchingField is not null) && !matchingField.IsAnonymousField)
32533313
{
@@ -3258,28 +3318,11 @@ private string GetRemappedNameForAnonymousRecord(RecordDecl recordDecl)
32583318
{
32593319
_ = remappedNameBuilder.Append("_Anonymous");
32603320

3261-
// If there is more than one anonymous type, then add a numeral to differentiate.
3262-
if (parentRecordDecl.AnonymousRecords.Count > 1)
3263-
{
3264-
var index = parentRecordDecl.AnonymousRecords.IndexOf(recordDecl) + 1;
3265-
Debug.Assert(index > 0);
3266-
_ = remappedNameBuilder.Append(index);
3267-
}
3321+
var index = GetAnonymousRecordIndex(recordDecl, parentRecordDecl);
32683322

3269-
// C# doesn't allow a nested type to have the same name as the parent, so if the
3270-
// parent is also anonymous, add the nesting depth as a way to avoid conflicts with
3271-
// the parent's name.
3272-
if (parentRecordDecl.IsAnonymous)
3323+
if (index != 0)
32733324
{
3274-
var depth = 1;
3275-
var currentParent = parentRecordDecl.Parent;
3276-
while ((currentParent is RecordDecl currentParentRecordDecl) && currentParentRecordDecl.IsAnonymous)
3277-
{
3278-
depth++;
3279-
currentParent = currentParentRecordDecl.Parent;
3280-
}
3281-
_ = remappedNameBuilder.Append('_');
3282-
_ = remappedNameBuilder.Append(depth);
3325+
_ = remappedNameBuilder.Append(index);
32833326
}
32843327
}
32853328

@@ -4625,7 +4668,7 @@ private bool HasBaseField(CXXRecordDecl cxxRecordDecl)
46254668

46264669
private bool HasField(RecordDecl recordDecl)
46274670
{
4628-
var hasField = recordDecl.Fields.Any() || recordDecl.Decls.Any((decl) => (decl is RecordDecl nestedRecordDecl) && nestedRecordDecl.IsAnonymous && HasField(nestedRecordDecl));
4671+
var hasField = recordDecl.Fields.Any() || recordDecl.Decls.Any((decl) => (decl is RecordDecl nestedRecordDecl) && nestedRecordDecl.IsAnonymousStructOrUnion && HasField(nestedRecordDecl));
46294672

46304673
if (!hasField && (recordDecl is CXXRecordDecl cxxRecordDecl))
46314674
{
@@ -5170,7 +5213,7 @@ bool IsEmptyRecord(RecordDecl recordDecl)
51705213

51715214
foreach (var decl in recordDecl.Decls)
51725215
{
5173-
if ((decl is RecordDecl nestedRecordDecl) && nestedRecordDecl.IsAnonymous && !IsEmptyRecord(nestedRecordDecl))
5216+
if ((decl is RecordDecl nestedRecordDecl) && nestedRecordDecl.IsAnonymousStructOrUnion && !IsEmptyRecord(nestedRecordDecl))
51745217
{
51755218
return false;
51765219
}
@@ -6195,7 +6238,7 @@ private bool IsUnsafe(RecordDecl recordDecl)
61956238
{
61966239
return true;
61976240
}
6198-
else if ((decl is RecordDecl nestedRecordDecl) && nestedRecordDecl.IsAnonymous && (IsUnsafe(nestedRecordDecl) || Config.GenerateCompatibleCode))
6241+
else if ((decl is RecordDecl nestedRecordDecl) && nestedRecordDecl.IsAnonymousStructOrUnion && (IsUnsafe(nestedRecordDecl) || Config.GenerateCompatibleCode))
61996242
{
62006243
return true;
62016244
}

sources/ClangSharp/Cursors/Decls/RecordDecl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ private protected RecordDecl(CXCursor handle, CXCursorKind expectedCursorKind, C
3636

3737
_fields = LazyList.Create<FieldDecl>(Handle.NumFields, (i) => TranslationUnit.GetOrCreate<FieldDecl>(Handle.GetField(unchecked((uint)i))));
3838
_anonymousFields = new ValueLazy<List<FieldDecl>>(() => [.. Decls.OfType<FieldDecl>().Where(decl => decl.IsAnonymousField)]);
39-
_anonymousRecords = new ValueLazy<List<RecordDecl>>(() => [.. Decls.OfType<RecordDecl>().Where(decl => decl.IsAnonymous && !decl.IsInjectedClassName)]);
39+
_anonymousRecords = new ValueLazy<List<RecordDecl>>(() => [.. Decls.OfType<RecordDecl>().Where(decl => decl.IsAnonymousStructOrUnion && !decl.IsInjectedClassName)]);
4040
_indirectFields = new ValueLazy<List<IndirectFieldDecl>>(() => [.. Decls.OfType<IndirectFieldDecl>()]);
4141
_injectedClassName = new ValueLazy<RecordDecl?>(() => Decls.OfType<RecordDecl>().Where(decl => decl.IsInjectedClassName).SingleOrDefault());
4242
}
4343

44-
public bool IsAnonymous => Handle.IsAnonymous;
44+
public bool IsAnonymousStructOrUnion => Handle.IsAnonymousStructOrUnion;
4545

4646
public IReadOnlyList<FieldDecl> AnonymousFields => _anonymousFields.Value;
4747

sources/ClangSharpPInvokeGenerator/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"GenerateLocal": {
1313
"commandName": "Project",
1414
"commandLineArgs": "@generate.rsp",
15-
"workingDirectory": "D:\\Users\\tagoo\\source\\repos\\terrafx.interop.windows\\generation\\Windows\\um\\sapi"
15+
"workingDirectory": "D:\\repos\\terrafx.interop.windows\\generation\\DirectX\\um\\dcommon"
1616
}
1717
}
1818
}

0 commit comments

Comments
 (0)