Skip to content

Commit 9395218

Browse files
authored
Merge pull request #9 from CognexVisionSoftware/feature/fix_using
'using' is not recognized
2 parents 224a3aa + 1ef651d commit 9395218

File tree

2 files changed

+87
-9
lines changed

2 files changed

+87
-9
lines changed

src/CppAst.Tests/TestMisc.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace CppAst.Tests
5+
{
6+
public class TestMisc : InlineTestBase
7+
{
8+
[Test]
9+
public void TestMiscFeatures()
10+
{
11+
ParseAssert(@"
12+
13+
class Foo
14+
{
15+
public:
16+
Foo(int x) : x_{x} {}
17+
private:
18+
int x_{0};
19+
};
20+
21+
class Bar : public Foo
22+
{
23+
public:
24+
using Foo::Foo;
25+
};
26+
",
27+
compilation =>
28+
{
29+
Assert.False(compilation.HasErrors);
30+
Assert.AreEqual(2, compilation.Classes.Count);
31+
Assert.AreEqual(1, compilation.Classes[0].Constructors.Count);
32+
// Bar will get 3 constructors
33+
Assert.AreEqual(3, compilation.Classes[1].Constructors.Count);
34+
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[0].Visibility);
35+
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[1].Visibility);
36+
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[2].Visibility);
37+
}
38+
);
39+
}
40+
}
41+
}

src/CppAst/CppModelBuilder.cs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,44 @@ private CppClass VisitClassDecl(CXCursor cursor, void* data)
297297
return cppStruct;
298298
}
299299

300+
private CppFunction VisitUsing(CXCursor cursor, CXCursor parent, void* data)
301+
{
302+
var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data);
303+
var container = contextContainer.DeclarationContainer;
304+
305+
if (container == null)
306+
{
307+
WarningUnhandled(cursor, parent);
308+
return null;
309+
}
310+
311+
cursor.VisitChildren((childCursor, funcCursor, clientData) =>
312+
{
313+
// Please note that this is not the complete using implementation,
314+
// it only works with constructors
315+
if (childCursor.Kind == CXCursorKind.CXCursor_OverloadedDeclRef)
316+
{
317+
// We simply copy the overloaded functions into the current class
318+
for (uint i=0;i< childCursor.NumOverloadedDecls; i++)
319+
{
320+
VisitFunctionDecl(cursor, childCursor.GetOverloadedDecl(i), parent, clientData);
321+
}
322+
return CXChildVisitResult.CXChildVisit_Break;
323+
}
324+
return CXChildVisitResult.CXChildVisit_Continue;
325+
}, new CXClientData((IntPtr)data));
326+
327+
return null;
328+
}
329+
300330
private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* data)
301331
{
302332
CppElement element = null;
303333
switch (cursor.Kind)
304334
{
335+
case CXCursorKind.CXCursor_UsingDeclaration:
336+
element = VisitUsing(cursor, parent, data);
337+
break;
305338
case CXCursorKind.CXCursor_FieldDecl:
306339
case CXCursorKind.CXCursor_VarDecl:
307340
{
@@ -390,7 +423,7 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
390423
case CXCursorKind.CXCursor_FunctionDecl:
391424
case CXCursorKind.CXCursor_Constructor:
392425
case CXCursorKind.CXCursor_CXXMethod:
393-
element = VisitFunctionDecl(cursor, parent, data);
426+
element = VisitFunctionDecl(cursor, cursor, parent, data);
394427
break;
395428

396429
case CXCursorKind.CXCursor_UsingDirective:
@@ -1227,43 +1260,47 @@ private static CppStorageQualifier GetStorageQualifier(CXCursor cursor)
12271260
return CppStorageQualifier.None;
12281261
}
12291262

1230-
private CppFunction VisitFunctionDecl(CXCursor cursor, CXCursor parent, void* data)
1263+
private CppFunction VisitFunctionDecl(CXCursor destinationCursor, CXCursor cursor, CXCursor parent, void* data)
12311264
{
1265+
var destinationContextContainer = GetOrCreateDeclarationContainer(destinationCursor.SemanticParent, data);
1266+
var destinationContainer = destinationContextContainer.DeclarationContainer;
12321267
var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data);
12331268
var container = contextContainer.DeclarationContainer;
12341269

1235-
if (container == null)
1270+
if (destinationContainer == null || container == null)
12361271
{
12371272
WarningUnhandled(cursor, parent);
12381273
return null;
12391274
}
12401275

1241-
var functionName = GetCursorSpelling(cursor);
1276+
// This (not using 'cursor', but 'destinationCursor') is only used when we pulling in constructors from Foo, into Bar
1277+
// We are renaming effectively the pulled in 'Foo' constructor into 'Bar'
1278+
var functionName = GetCursorSpelling(destinationCursor);
12421279

12431280
//We need ignore the function define out in the class definition here(Otherwise it will has two same functions here~)!
1244-
var semKind = cursor.SemanticParent.Kind;
1281+
var semKind = destinationCursor.SemanticParent.Kind;
12451282
if ((semKind == CXCursorKind.CXCursor_StructDecl || semKind == CXCursorKind.CXCursor_ClassDecl)
1246-
&& cursor.LexicalParent != cursor.SemanticParent)
1283+
&& destinationCursor.LexicalParent != destinationCursor.SemanticParent)
12471284
{
12481285
return null;
12491286
}
12501287

12511288
var cppFunction = new CppFunction(functionName)
12521289
{
1253-
Visibility = contextContainer.CurrentVisibility,
1290+
Visibility = destinationContextContainer.CurrentVisibility,
12541291
StorageQualifier = GetStorageQualifier(cursor),
12551292
LinkageKind = GetLinkage(cursor.Linkage),
12561293
};
12571294

12581295
if (cursor.Kind == CXCursorKind.CXCursor_Constructor)
12591296
{
1260-
var cppClass = (CppClass)container;
1297+
var cppClass = (CppClass)destinationContainer;
12611298
cppFunction.IsConstructor = true;
12621299
cppClass.Constructors.Add(cppFunction);
12631300
}
12641301
else
12651302
{
1266-
container.Functions.Add(cppFunction);
1303+
destinationContainer.Functions.Add(cppFunction);
12671304
}
12681305

12691306
if (cursor.kind == CXCursorKind.CXCursor_FunctionTemplate)

0 commit comments

Comments
 (0)