Skip to content

Commit 722a1d7

Browse files
committed
Generate valid C++ for conversion operators in name-spaced classes
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent d9a4290 commit 722a1d7

File tree

6 files changed

+55
-51
lines changed

6 files changed

+55
-51
lines changed

src/Generator/Generators/C/CppTypePrinter.cs

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -571,50 +571,54 @@ public override TypePrinterResult VisitFieldDecl(Field field)
571571

572572
public override TypePrinterResult VisitFunctionDecl(Function function)
573573
{
574-
return VisitDeclaration(function);
575-
}
576-
577-
public override TypePrinterResult VisitMethodDecl(Method method)
578-
{
579-
// HACK: this should never happen but there's an inexplicable crash
580-
// with the 32-bit Windows CI - needs investigation.
581-
var functionType = method.FunctionType.Type.Desugar() as FunctionType;
582-
if (functionType == null)
583-
return string.Empty;
584-
585-
var @return = method.IsConstructor || method.IsDestructor ||
586-
method.OperatorKind == CXXOperatorKind.Conversion ||
587-
method.OperatorKind == CXXOperatorKind.ExplicitConversion ?
588-
new TypePrinterResult() : method.OriginalReturnType.Visit(this);
589-
590574
string @class;
591575
switch (MethodScopeKind)
592576
{
593577
case TypePrintScopeKind.Qualified:
594-
@class = $"{method.Namespace.Visit(this)}::";
578+
@class = $"{function.Namespace.Visit(this)}::";
595579
break;
596580
case TypePrintScopeKind.GlobalQualified:
597-
@class = $"::{method.Namespace.Visit(this)}::";
581+
@class = $"::{function.Namespace.Visit(this)}::";
598582
break;
599583
default:
600584
@class = string.Empty;
601585
break;
602586
}
603587

604-
var @params = string.Join(", ", method.Parameters.Select(p => p.Visit(this)));
605-
var @const = method.IsConst ? " const" : string.Empty;
606-
var name = method.OperatorKind == CXXOperatorKind.Conversion ||
607-
method.OperatorKind == CXXOperatorKind.ExplicitConversion ?
608-
$"operator {method.OriginalReturnType.Visit(this)}" :
609-
method.OriginalName;
610-
588+
var @params = string.Join(", ", function.Parameters.Select(p => p.Visit(this)));
589+
var @const = function is Method method && method.IsConst ? " const" : string.Empty;
590+
var name = function.OperatorKind == CXXOperatorKind.Conversion ||
591+
function.OperatorKind == CXXOperatorKind.ExplicitConversion ?
592+
$"operator {function.OriginalReturnType.Visit(this)}" :
593+
function.OriginalName;
594+
595+
FunctionType functionType;
596+
CppSharp.AST.Type desugared = function.FunctionType.Type.Desugar();
597+
if (!desugared.IsPointerTo(out functionType))
598+
functionType = (FunctionType) desugared;
611599
string exceptionType = Print(functionType.ExceptionSpecType);
612600

601+
var @return = function.OriginalReturnType.Visit(this);
613602
if (!string.IsNullOrEmpty(@return.Type))
614603
@return.NamePrefix.Append(' ');
615-
@return.NamePrefix.Append(@class).Append(name).Append('(').Append(@params).Append(')');
616-
@return.NameSuffix.Append(@const).Append(exceptionType);
617-
return @return.ToString();
604+
@return.Name = @class + name;
605+
@return.NameSuffix.Append('(').Append(@params).Append(')').Append(@const).Append(exceptionType);
606+
return @return;
607+
}
608+
609+
public override TypePrinterResult VisitMethodDecl(Method method)
610+
{
611+
var @return = VisitFunctionDecl(method);
612+
613+
if (method.IsConstructor || method.IsDestructor ||
614+
method.OperatorKind == CXXOperatorKind.Conversion ||
615+
method.OperatorKind == CXXOperatorKind.ExplicitConversion)
616+
{
617+
@return.Type = string.Empty;
618+
@return.NamePrefix.Clear();
619+
}
620+
621+
return @return;
618622
}
619623

620624
public override TypePrinterResult VisitParameterDecl(Parameter parameter)

src/Generator/Generators/TypePrinter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ public override string ToString()
4343
if (hasPlaceholder)
4444
return string.Format(Type, $"{NamePrefix}{Name}{NameSuffix}");
4545

46-
var namePrefix = (Name.Length > 0) ? $"{NamePrefix} " : NamePrefix.ToString();
46+
var namePrefix = (Name.Length > 0 && NamePrefix.Length > 0) ?
47+
$"{NamePrefix} " : NamePrefix.ToString();
4748
return $"{Type}{namePrefix}{Name}{NameSuffix}";
4849
}
4950
}

src/Generator/Passes/SymbolsCodeGenerator.cs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private void TakeFunctionAddress(Function function, string wrapper)
232232
string signature = GetSignature(function);
233233
cppTypePrinter.PrintTags = false;
234234

235-
string functionName = GetFunctionName(function, @namespace);
235+
string functionName = GetFunctionName(function);
236236
if (function.FriendKind != FriendKind.None)
237237
WriteRedeclaration(function, returnType, signature, functionName);
238238

@@ -282,27 +282,14 @@ private string GetSignature(Function function)
282282
return $"({paramTypes}{variadicType}){@const}{refQualifier}";
283283
}
284284

285-
private string GetFunctionName(Function function, string @namespace)
285+
private string GetFunctionName(Function function)
286286
{
287287
var nameBuilder = new StringBuilder();
288-
if (function.Access != AccessSpecifier.Protected &&
289-
!string.IsNullOrEmpty(@namespace))
290-
nameBuilder.Append(@namespace).Append("::");
291-
292-
bool isConversionToSpecialization =
293-
(function.OperatorKind == CXXOperatorKind.Conversion ||
294-
function.OperatorKind == CXXOperatorKind.ExplicitConversion) &&
295-
function.OriginalReturnType.Type.Desugar(
296-
).TryGetDeclaration(out ClassTemplateSpecialization specialization);
297-
298-
nameBuilder.Append(isConversionToSpecialization ?
299-
"operator " : function.OriginalName);
288+
nameBuilder.Append(function.Visit(cppTypePrinter).Name);
300289

301290
if (function.SpecializationInfo != null)
302291
nameBuilder.Append('<').Append(string.Join(", ",
303292
GetTemplateArguments(function.SpecializationInfo.Arguments))).Append('>');
304-
else if (isConversionToSpecialization)
305-
nameBuilder.Append(function.OriginalReturnType.Visit(cppTypePrinter));
306293

307294
return nameBuilder.ToString();
308295
}

tests/Common/Common.Tests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public unsafe void TestCodeGeneration()
7070
Common.TakeVoidStarStar(null);
7171
Common.OverloadPointer(IntPtr.Zero, 1);
7272
using (new DerivedFromSecondaryBaseWithIgnoredVirtualMethod()) { }
73+
using (new CommonTest.SomeNamespace.NamespacedAbstractImpl()) { }
7374

7475
#pragma warning restore 0168
7576
#pragma warning restore 0219

tests/Common/Common.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,6 @@ std::string& HasStdString::getStdString()
529529
return s;
530530
}
531531

532-
SomeNamespace::AbstractClass::~AbstractClass()
533-
{
534-
}
535-
536532
int Function()
537533
{
538534
return 5;
@@ -1242,6 +1238,10 @@ TestCopyConstructorRef::TestCopyConstructorRef(const TestCopyConstructorRef& oth
12421238

12431239
SomeStruct::SomeStruct() : p(1) {}
12441240

1241+
void SomeNamespace::NamespacedAbstractImpl::AbstractMethod()
1242+
{
1243+
}
1244+
12451245
ClassWithOverloadedOperators::ClassWithOverloadedOperators::operator char() { return 1; }
12461246
ClassWithOverloadedOperators::operator int() { return 2; }
12471247
ClassWithOverloadedOperators::operator short() { return 3; }

tests/Common/Common.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,12 +474,23 @@ class DLL_API SomeClassExtendingTheStruct : public SomeStruct
474474

475475
namespace SomeNamespace
476476
{
477-
class DLL_API AbstractClass
477+
class DLL_API NamespacedAbstractClass
478478
{
479479
public:
480-
~AbstractClass();
481480
virtual void AbstractMethod() = 0;
482481
};
482+
483+
class DLL_API NamespacedAbstractImpl
484+
{
485+
public:
486+
virtual void AbstractMethod();
487+
};
488+
489+
class DLL_API Inlines
490+
{
491+
public:
492+
inline operator NamespacedAbstractImpl () const { return NamespacedAbstractImpl(); }
493+
};
483494
}
484495

485496
// Test operator overloads

0 commit comments

Comments
 (0)