Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/CppAst.Tests/TestMisc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using NUnit.Framework;

namespace CppAst.Tests
{
public class TestMisc : InlineTestBase
{
[Test]
public void TestMiscFeatures()
{
ParseAssert(@"

class Foo
{
public:
Foo(int x) : x_{x} {}
private:
int x_{0};
};

class Bar : public Foo
{
public:
using Foo::Foo;
};
",
compilation =>
{
Assert.False(compilation.HasErrors);
Assert.AreEqual(2, compilation.Classes.Count);
Assert.AreEqual(1, compilation.Classes[0].Constructors.Count);
// Bar will get 3 constructors
Assert.AreEqual(3, compilation.Classes[1].Constructors.Count);
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[0].Visibility);
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[1].Visibility);
Assert.AreEqual(CppVisibility.Public, compilation.Classes[1].Constructors[2].Visibility);
}
);
}
}
}
55 changes: 46 additions & 9 deletions src/CppAst/CppModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,44 @@ private CppClass VisitClassDecl(CXCursor cursor, void* data)
return cppStruct;
}

private CppFunction VisitUsing(CXCursor cursor, CXCursor parent, void* data)
{
var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data);
var container = contextContainer.DeclarationContainer;

if (container == null)
{
WarningUnhandled(cursor, parent);
return null;
}

cursor.VisitChildren((childCursor, funcCursor, clientData) =>
{
// Please note that this is not the complete using implementation,
// it only works with constructors
if (childCursor.Kind == CXCursorKind.CXCursor_OverloadedDeclRef)
{
// We simply copy the overloaded functions into the current class
for (uint i=0;i< childCursor.NumOverloadedDecls; i++)
{
VisitFunctionDecl(cursor, childCursor.GetOverloadedDecl(i), parent, clientData);
}
return CXChildVisitResult.CXChildVisit_Break;
}
return CXChildVisitResult.CXChildVisit_Continue;
}, new CXClientData((IntPtr)data));

return null;
}

private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* data)
{
CppElement element = null;
switch (cursor.Kind)
{
case CXCursorKind.CXCursor_UsingDeclaration:
element = VisitUsing(cursor, parent, data);
break;
case CXCursorKind.CXCursor_FieldDecl:
case CXCursorKind.CXCursor_VarDecl:
{
Expand Down Expand Up @@ -390,7 +423,7 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
case CXCursorKind.CXCursor_FunctionDecl:
case CXCursorKind.CXCursor_Constructor:
case CXCursorKind.CXCursor_CXXMethod:
element = VisitFunctionDecl(cursor, parent, data);
element = VisitFunctionDecl(cursor, cursor, parent, data);
break;

case CXCursorKind.CXCursor_UsingDirective:
Expand Down Expand Up @@ -1212,43 +1245,47 @@ private static CppStorageQualifier GetStorageQualifier(CXCursor cursor)
return CppStorageQualifier.None;
}

private CppFunction VisitFunctionDecl(CXCursor cursor, CXCursor parent, void* data)
private CppFunction VisitFunctionDecl(CXCursor destinationCursor, CXCursor cursor, CXCursor parent, void* data)
{
var destinationContextContainer = GetOrCreateDeclarationContainer(destinationCursor.SemanticParent, data);
var destinationContainer = destinationContextContainer.DeclarationContainer;
var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data);
var container = contextContainer.DeclarationContainer;

if (container == null)
if (destinationContainer == null || container == null)
{
WarningUnhandled(cursor, parent);
return null;
}

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

//We need ignore the function define out in the class definition here(Otherwise it will has two same functions here~)!
var semKind = cursor.SemanticParent.Kind;
var semKind = destinationCursor.SemanticParent.Kind;
if ((semKind == CXCursorKind.CXCursor_StructDecl || semKind == CXCursorKind.CXCursor_ClassDecl)
&& cursor.LexicalParent != cursor.SemanticParent)
&& destinationCursor.LexicalParent != destinationCursor.SemanticParent)
{
return null;
}

var cppFunction = new CppFunction(functionName)
{
Visibility = contextContainer.CurrentVisibility,
Visibility = destinationContextContainer.CurrentVisibility,
StorageQualifier = GetStorageQualifier(cursor),
LinkageKind = GetLinkage(cursor.Linkage),
};

if (cursor.Kind == CXCursorKind.CXCursor_Constructor)
{
var cppClass = (CppClass)container;
var cppClass = (CppClass)destinationContainer;
cppFunction.IsConstructor = true;
cppClass.Constructors.Add(cppFunction);
}
else
{
container.Functions.Add(cppFunction);
destinationContainer.Functions.Add(cppFunction);
}

if (cursor.kind == CXCursorKind.CXCursor_FunctionTemplate)
Expand Down