Browse Source

Generate valid C++ for conversion operators in name-spaced classes

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1636/head
Dimitar Dobrev 4 years ago
parent
commit
722a1d735d
  1. 60
      src/Generator/Generators/C/CppTypePrinter.cs
  2. 3
      src/Generator/Generators/TypePrinter.cs
  3. 19
      src/Generator/Passes/SymbolsCodeGenerator.cs
  4. 1
      tests/Common/Common.Tests.cs
  5. 8
      tests/Common/Common.cpp
  6. 15
      tests/Common/Common.h

60
src/Generator/Generators/C/CppTypePrinter.cs

@ -571,50 +571,54 @@ namespace CppSharp.Generators.C @@ -571,50 +571,54 @@ namespace CppSharp.Generators.C
public override TypePrinterResult VisitFunctionDecl(Function function)
{
return VisitDeclaration(function);
}
public override TypePrinterResult VisitMethodDecl(Method method)
{
// HACK: this should never happen but there's an inexplicable crash
// with the 32-bit Windows CI - needs investigation.
var functionType = method.FunctionType.Type.Desugar() as FunctionType;
if (functionType == null)
return string.Empty;
var @return = method.IsConstructor || method.IsDestructor ||
method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion ?
new TypePrinterResult() : method.OriginalReturnType.Visit(this);
string @class;
switch (MethodScopeKind)
{
case TypePrintScopeKind.Qualified:
@class = $"{method.Namespace.Visit(this)}::";
@class = $"{function.Namespace.Visit(this)}::";
break;
case TypePrintScopeKind.GlobalQualified:
@class = $"::{method.Namespace.Visit(this)}::";
@class = $"::{function.Namespace.Visit(this)}::";
break;
default:
@class = string.Empty;
break;
}
var @params = string.Join(", ", method.Parameters.Select(p => p.Visit(this)));
var @const = method.IsConst ? " const" : string.Empty;
var name = method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion ?
$"operator {method.OriginalReturnType.Visit(this)}" :
method.OriginalName;
var @params = string.Join(", ", function.Parameters.Select(p => p.Visit(this)));
var @const = function is Method method && method.IsConst ? " const" : string.Empty;
var name = function.OperatorKind == CXXOperatorKind.Conversion ||
function.OperatorKind == CXXOperatorKind.ExplicitConversion ?
$"operator {function.OriginalReturnType.Visit(this)}" :
function.OriginalName;
FunctionType functionType;
CppSharp.AST.Type desugared = function.FunctionType.Type.Desugar();
if (!desugared.IsPointerTo(out functionType))
functionType = (FunctionType) desugared;
string exceptionType = Print(functionType.ExceptionSpecType);
var @return = function.OriginalReturnType.Visit(this);
if (!string.IsNullOrEmpty(@return.Type))
@return.NamePrefix.Append(' ');
@return.NamePrefix.Append(@class).Append(name).Append('(').Append(@params).Append(')');
@return.NameSuffix.Append(@const).Append(exceptionType);
return @return.ToString();
@return.Name = @class + name;
@return.NameSuffix.Append('(').Append(@params).Append(')').Append(@const).Append(exceptionType);
return @return;
}
public override TypePrinterResult VisitMethodDecl(Method method)
{
var @return = VisitFunctionDecl(method);
if (method.IsConstructor || method.IsDestructor ||
method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion)
{
@return.Type = string.Empty;
@return.NamePrefix.Clear();
}
return @return;
}
public override TypePrinterResult VisitParameterDecl(Parameter parameter)

3
src/Generator/Generators/TypePrinter.cs

@ -43,7 +43,8 @@ namespace CppSharp.Generators @@ -43,7 +43,8 @@ namespace CppSharp.Generators
if (hasPlaceholder)
return string.Format(Type, $"{NamePrefix}{Name}{NameSuffix}");
var namePrefix = (Name.Length > 0) ? $"{NamePrefix} " : NamePrefix.ToString();
var namePrefix = (Name.Length > 0 && NamePrefix.Length > 0) ?
$"{NamePrefix} " : NamePrefix.ToString();
return $"{Type}{namePrefix}{Name}{NameSuffix}";
}
}

19
src/Generator/Passes/SymbolsCodeGenerator.cs

@ -232,7 +232,7 @@ namespace CppSharp.Passes @@ -232,7 +232,7 @@ namespace CppSharp.Passes
string signature = GetSignature(function);
cppTypePrinter.PrintTags = false;
string functionName = GetFunctionName(function, @namespace);
string functionName = GetFunctionName(function);
if (function.FriendKind != FriendKind.None)
WriteRedeclaration(function, returnType, signature, functionName);
@ -282,27 +282,14 @@ namespace CppSharp.Passes @@ -282,27 +282,14 @@ namespace CppSharp.Passes
return $"({paramTypes}{variadicType}){@const}{refQualifier}";
}
private string GetFunctionName(Function function, string @namespace)
private string GetFunctionName(Function function)
{
var nameBuilder = new StringBuilder();
if (function.Access != AccessSpecifier.Protected &&
!string.IsNullOrEmpty(@namespace))
nameBuilder.Append(@namespace).Append("::");
bool isConversionToSpecialization =
(function.OperatorKind == CXXOperatorKind.Conversion ||
function.OperatorKind == CXXOperatorKind.ExplicitConversion) &&
function.OriginalReturnType.Type.Desugar(
).TryGetDeclaration(out ClassTemplateSpecialization specialization);
nameBuilder.Append(isConversionToSpecialization ?
"operator " : function.OriginalName);
nameBuilder.Append(function.Visit(cppTypePrinter).Name);
if (function.SpecializationInfo != null)
nameBuilder.Append('<').Append(string.Join(", ",
GetTemplateArguments(function.SpecializationInfo.Arguments))).Append('>');
else if (isConversionToSpecialization)
nameBuilder.Append(function.OriginalReturnType.Visit(cppTypePrinter));
return nameBuilder.ToString();
}

1
tests/Common/Common.Tests.cs

@ -70,6 +70,7 @@ public class CommonTests @@ -70,6 +70,7 @@ public class CommonTests
Common.TakeVoidStarStar(null);
Common.OverloadPointer(IntPtr.Zero, 1);
using (new DerivedFromSecondaryBaseWithIgnoredVirtualMethod()) { }
using (new CommonTest.SomeNamespace.NamespacedAbstractImpl()) { }
#pragma warning restore 0168
#pragma warning restore 0219

8
tests/Common/Common.cpp

@ -529,10 +529,6 @@ std::string& HasStdString::getStdString() @@ -529,10 +529,6 @@ std::string& HasStdString::getStdString()
return s;
}
SomeNamespace::AbstractClass::~AbstractClass()
{
}
int Function()
{
return 5;
@ -1242,6 +1238,10 @@ TestCopyConstructorRef::TestCopyConstructorRef(const TestCopyConstructorRef& oth @@ -1242,6 +1238,10 @@ TestCopyConstructorRef::TestCopyConstructorRef(const TestCopyConstructorRef& oth
SomeStruct::SomeStruct() : p(1) {}
void SomeNamespace::NamespacedAbstractImpl::AbstractMethod()
{
}
ClassWithOverloadedOperators::ClassWithOverloadedOperators::operator char() { return 1; }
ClassWithOverloadedOperators::operator int() { return 2; }
ClassWithOverloadedOperators::operator short() { return 3; }

15
tests/Common/Common.h

@ -474,12 +474,23 @@ class DLL_API SomeClassExtendingTheStruct : public SomeStruct @@ -474,12 +474,23 @@ class DLL_API SomeClassExtendingTheStruct : public SomeStruct
namespace SomeNamespace
{
class DLL_API AbstractClass
class DLL_API NamespacedAbstractClass
{
public:
~AbstractClass();
virtual void AbstractMethod() = 0;
};
class DLL_API NamespacedAbstractImpl
{
public:
virtual void AbstractMethod();
};
class DLL_API Inlines
{
public:
inline operator NamespacedAbstractImpl () const { return NamespacedAbstractImpl(); }
};
}
// Test operator overloads

Loading…
Cancel
Save