Skip to content

Commit b00cdbf

Browse files
committed
Fixed anonymous types with field array
1 parent 1fbed1e commit b00cdbf

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

src/CppAst.Tests/TestStructs.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,45 @@ struct HelloWorld
206206
);
207207
}
208208

209+
[Test]
210+
public void TestAnonymousUnionWithField2()
211+
{
212+
ParseAssert(@"
213+
struct HelloWorld
214+
{
215+
int a;
216+
union {
217+
int c;
218+
int d;
219+
} e[4];
220+
};
221+
",
222+
compilation =>
223+
{
224+
Assert.False(compilation.HasErrors);
225+
226+
Assert.AreEqual(1, compilation.Classes.Count);
209227

228+
{
229+
var cppStruct = compilation.Classes[0];
230+
231+
// Only one union
232+
Assert.AreEqual(1, cppStruct.Classes.Count);
233+
234+
// Only 2 fields
235+
Assert.AreEqual(2, cppStruct.Fields.Count);
236+
237+
// Check the union
238+
Assert.AreEqual("e", cppStruct.Fields[1].Name);
239+
Assert.IsInstanceOf<CppArrayType>(cppStruct.Fields[1].Type);
240+
var cppArrayType = ((CppArrayType)cppStruct.Fields[1].Type);
241+
Assert.IsInstanceOf<CppClass>(cppArrayType.ElementType);
242+
var cppUnion = ((CppClass)cppArrayType.ElementType);
243+
Assert.AreEqual(CppClassKind.Union, cppUnion.ClassKind);
244+
Assert.AreEqual(2, cppUnion.Fields.Count);
245+
}
246+
}
247+
);
248+
}
210249
}
211250
}

src/CppAst/CppModelBuilder.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,25 @@ public static CppSourceLocation GetSourceLocation(CXSourceLocation start)
840840
return new CppSourceLocation(fileNameStr, (int)offset, (int)line, (int)column);
841841
}
842842

843+
private static bool IsAnonymousTypeUsed(CppType type, CppType anonymousType)
844+
{
845+
return IsAnonymousTypeUsed(type, anonymousType, new HashSet<CppType>());
846+
}
847+
848+
private static bool IsAnonymousTypeUsed(CppType type, CppType anonymousType, HashSet<CppType> visited)
849+
{
850+
if (!visited.Add(type)) return false;
851+
852+
if (ReferenceEquals(type, anonymousType)) return true;
853+
854+
if (type is CppTypeWithElementType typeWithElementType)
855+
{
856+
return IsAnonymousTypeUsed(typeWithElementType.ElementType, anonymousType);
857+
}
858+
859+
return false;
860+
}
861+
843862
private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCursor cursor, void* data)
844863
{
845864
var fieldName = CXUtil.GetCursorSpelling(cursor);
@@ -849,10 +868,11 @@ private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCu
849868
CppField cppField;
850869
// This happen in the type is anonymous, we create implicitly a field for it, but if type is the same
851870
// we should reuse the anonymous field we created just before
852-
if (previousField != null && previousField.IsAnonymous && ReferenceEquals(previousField.Type, type))
871+
if (previousField != null && previousField.IsAnonymous && IsAnonymousTypeUsed(type, previousField.Type))
853872
{
854873
cppField = previousField;
855874
cppField.Name = fieldName;
875+
cppField.Type = type;
856876
cppField.Offset = cursor.OffsetOfField / 8;
857877
}
858878
else

0 commit comments

Comments
 (0)