Skip to content

Commit 02183f7

Browse files
committed
Fix forward typedef declaration
1 parent 0745a8d commit 02183f7

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

src/CppAst.Tests/TestFunctions.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,39 @@ typedef struct struct0 {
160160
}
161161

162162

163+
[Test]
164+
public void TestFunctionTypedefFields()
165+
{
166+
ParseAssert(@"
167+
typedef struct struct0 struct0;
168+
typedef void (*function0_t)(int a, float b);
169+
typedef void (*function1_t)(char, int);
170+
struct struct0
171+
{
172+
function0_t function0;
173+
function1_t function1;
174+
};
175+
",
176+
compilation =>
177+
{
178+
Assert.False(compilation.HasErrors);
179+
180+
var cls = compilation.Classes[0];
181+
Assert.AreEqual(2, cls.Fields.Count);
182+
183+
{
184+
var cppType = cls.Fields[0].Type;
185+
Assert.AreEqual(CppTypeKind.Typedef, cppType.TypeKind);
186+
}
187+
188+
{
189+
var cppType = cls.Fields[1].Type;
190+
Assert.AreEqual(CppTypeKind.Typedef, cppType.TypeKind);
191+
}
192+
}
193+
);
194+
}
195+
163196
[Test]
164197
public void TestFunctionExport()
165198
{

src/CppAst/CppModelBuilder.cs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Alexandre Mutel. All rights reserved.
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
22
// Licensed under the BSD-Clause 2 license.
33
// See license.txt file in the project root for full license information.
44

@@ -84,7 +84,7 @@ private CppType TryToCreateTemplateParameters(CXCursor cursor, void* data)
8484
return null;
8585
}
8686

87-
private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, void* data)
87+
private bool TryGetDeclarationContainer(CXCursor cursor, void* data, out string typeKey, out CppContainerContext containerContext)
8888
{
8989
while (cursor.Kind == CXCursorKind.CXCursor_LinkageSpec)
9090
{
@@ -97,8 +97,13 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi
9797
typeAsCString = CXUtil.GetCursorDisplayName(cursor);
9898
}
9999
// Try to workaround anonymous types
100-
var typeKey = $"{cursor.Kind}:{typeAsCString}{(cursor.IsAnonymous ? "/" + cursor.Hash : string.Empty)}";
101-
if (_containers.TryGetValue(typeKey, out var containerContext))
100+
typeKey = $"{cursor.Kind}:{typeAsCString}{(cursor.IsAnonymous ? "/" + cursor.Hash : string.Empty)}";
101+
return _containers.TryGetValue(typeKey, out containerContext);
102+
}
103+
104+
private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, void* data)
105+
{
106+
if (TryGetDeclarationContainer(cursor, data, out string typeKey, out var containerContext))
102107
{
103108
return containerContext;
104109
}
@@ -127,7 +132,6 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi
127132
break;
128133

129134
case CXCursorKind.CXCursor_EnumDecl:
130-
Debug.Assert(parent != null);
131135
var cppEnum = new CppEnum(CXUtil.GetCursorSpelling(cursor))
132136
{
133137
IsAnonymous = cursor.IsAnonymous,
@@ -142,7 +146,6 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi
142146
case CXCursorKind.CXCursor_ClassDecl:
143147
case CXCursorKind.CXCursor_StructDecl:
144148
case CXCursorKind.CXCursor_UnionDecl:
145-
Debug.Assert(parent != null);
146149
var cppClass = new CppClass(CXUtil.GetCursorSpelling(cursor));
147150
parentDeclarationContainer.Classes.Add(cppClass);
148151
symbol = cppClass;
@@ -243,10 +246,15 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi
243246
case CXCursorKind.CXCursor_TranslationUnit:
244247
case CXCursorKind.CXCursor_UnexposedDecl:
245248
case CXCursorKind.CXCursor_FirstInvalid:
249+
if (!_containers.ContainsKey(typeKey))
250+
{
251+
_containers.Add(typeKey, _rootContainerContext);
252+
}
246253
return _rootContainerContext;
247254
default:
248255
Unhandled(cursor);
249-
break;
256+
// TODO: Workaround for now, as the container below would have an empty symbol
257+
goto case CXCursorKind.CXCursor_TranslationUnit;
250258
}
251259

252260
containerContext = new CppContainerContext(symbol) { CurrentVisibility = defaultContainerVisibility };
@@ -1772,6 +1780,13 @@ private CppType VisitElaboratedDecl(CXCursor cursor, CXType type, CXCursor paren
17721780
return typeRef;
17731781
}
17741782

1783+
// If the type has been already declared, return it immediately.
1784+
if (TryGetDeclarationContainer(cursor, data, out _, out var containerContext))
1785+
{
1786+
return (CppType)containerContext.Container;
1787+
}
1788+
1789+
// TODO: Pseudo fix, we are not supposed to land here, as the TryGet before should resolve an existing type already declared (but not necessarily defined)
17751790
return GetCppType(type.CanonicalType.Declaration, type.CanonicalType, parent, data);
17761791
}
17771792

0 commit comments

Comments
 (0)