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
public override TypePrinterResult VisitFunctionDecl(Function function) 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; string @class;
switch (MethodScopeKind) switch (MethodScopeKind)
{ {
case TypePrintScopeKind.Qualified: case TypePrintScopeKind.Qualified:
@class = $"{method.Namespace.Visit(this)}::"; @class = $"{function.Namespace.Visit(this)}::";
break; break;
case TypePrintScopeKind.GlobalQualified: case TypePrintScopeKind.GlobalQualified:
@class = $"::{method.Namespace.Visit(this)}::"; @class = $"::{function.Namespace.Visit(this)}::";
break; break;
default: default:
@class = string.Empty; @class = string.Empty;
break; break;
} }
var @params = string.Join(", ", method.Parameters.Select(p => p.Visit(this))); var @params = string.Join(", ", function.Parameters.Select(p => p.Visit(this)));
var @const = method.IsConst ? " const" : string.Empty; var @const = function is Method method && method.IsConst ? " const" : string.Empty;
var name = method.OperatorKind == CXXOperatorKind.Conversion || var name = function.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion ? function.OperatorKind == CXXOperatorKind.ExplicitConversion ?
$"operator {method.OriginalReturnType.Visit(this)}" : $"operator {function.OriginalReturnType.Visit(this)}" :
method.OriginalName; 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); string exceptionType = Print(functionType.ExceptionSpecType);
var @return = function.OriginalReturnType.Visit(this);
if (!string.IsNullOrEmpty(@return.Type)) if (!string.IsNullOrEmpty(@return.Type))
@return.NamePrefix.Append(' '); @return.NamePrefix.Append(' ');
@return.NamePrefix.Append(@class).Append(name).Append('(').Append(@params).Append(')'); @return.Name = @class + name;
@return.NameSuffix.Append(@const).Append(exceptionType); @return.NameSuffix.Append('(').Append(@params).Append(')').Append(@const).Append(exceptionType);
return @return.ToString(); 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) public override TypePrinterResult VisitParameterDecl(Parameter parameter)

3
src/Generator/Generators/TypePrinter.cs

@ -43,7 +43,8 @@ namespace CppSharp.Generators
if (hasPlaceholder) if (hasPlaceholder)
return string.Format(Type, $"{NamePrefix}{Name}{NameSuffix}"); 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}"; return $"{Type}{namePrefix}{Name}{NameSuffix}";
} }
} }

19
src/Generator/Passes/SymbolsCodeGenerator.cs

@ -232,7 +232,7 @@ namespace CppSharp.Passes
string signature = GetSignature(function); string signature = GetSignature(function);
cppTypePrinter.PrintTags = false; cppTypePrinter.PrintTags = false;
string functionName = GetFunctionName(function, @namespace); string functionName = GetFunctionName(function);
if (function.FriendKind != FriendKind.None) if (function.FriendKind != FriendKind.None)
WriteRedeclaration(function, returnType, signature, functionName); WriteRedeclaration(function, returnType, signature, functionName);
@ -282,27 +282,14 @@ namespace CppSharp.Passes
return $"({paramTypes}{variadicType}){@const}{refQualifier}"; return $"({paramTypes}{variadicType}){@const}{refQualifier}";
} }
private string GetFunctionName(Function function, string @namespace) private string GetFunctionName(Function function)
{ {
var nameBuilder = new StringBuilder(); var nameBuilder = new StringBuilder();
if (function.Access != AccessSpecifier.Protected && nameBuilder.Append(function.Visit(cppTypePrinter).Name);
!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);
if (function.SpecializationInfo != null) if (function.SpecializationInfo != null)
nameBuilder.Append('<').Append(string.Join(", ", nameBuilder.Append('<').Append(string.Join(", ",
GetTemplateArguments(function.SpecializationInfo.Arguments))).Append('>'); GetTemplateArguments(function.SpecializationInfo.Arguments))).Append('>');
else if (isConversionToSpecialization)
nameBuilder.Append(function.OriginalReturnType.Visit(cppTypePrinter));
return nameBuilder.ToString(); return nameBuilder.ToString();
} }

1
tests/Common/Common.Tests.cs

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

8
tests/Common/Common.cpp

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

15
tests/Common/Common.h

@ -474,12 +474,23 @@ class DLL_API SomeClassExtendingTheStruct : public SomeStruct
namespace SomeNamespace namespace SomeNamespace
{ {
class DLL_API AbstractClass class DLL_API NamespacedAbstractClass
{ {
public: public:
~AbstractClass();
virtual void AbstractMethod() = 0; 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 // Test operator overloads

Loading…
Cancel
Save