Skip to content

Commit 48b74a4

Browse files
committed
Merge remote-tracking branch 'origin/Kythera/copy-assignement-operator-support' into kythera-rebase
2 parents 1d1cd67 + cb48c99 commit 48b74a4

File tree

4 files changed

+73
-3
lines changed

4 files changed

+73
-3
lines changed

src/Generator/AST/Utils.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ public static bool CheckIgnoreMethod(Method method)
3636
if (method.IsDestructor)
3737
return true;
3838

39-
if (method.OperatorKind == CXXOperatorKind.Equal)
39+
if (method.Access == AccessSpecifier.Private && !method.IsOverride && !method.IsExplicitlyGenerated)
4040
return true;
4141

42-
if (method.Access == AccessSpecifier.Private && !method.IsOverride && !method.IsExplicitlyGenerated)
42+
// operator= does not make sense on static classes, but might be generated anyway, so ignore here
43+
if (method.OperatorKind == CXXOperatorKind.Equal && @class != null && @class.IsStatic)
4344
return true;
4445

4546
// Ignore copy constructor if a base class don't has or has a private copy constructor

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,33 @@ private bool GenerateFunctionSetter(Class @class, Property property)
10091009

10101010
private void GenerateFieldSetter(Field field, Class @class, QualifiedType fieldType)
10111011
{
1012+
if (field.Type.IsClass() && !field.Type.IsPointer())
1013+
{
1014+
if (field.Type.TryGetClass(out Class fieldClass) && !(fieldClass is ClassTemplateSpecialization))
1015+
{
1016+
var caop = fieldClass.Methods.FirstOrDefault(m => m.OperatorKind == CXXOperatorKind.Equal);
1017+
if (caop != null && caop.IsGenerated)
1018+
{
1019+
var fieldName = ((Class)field.Namespace).Layout.Fields.First(
1020+
f => f.FieldPtr == field.OriginalPtr).Name;
1021+
var typeName = TypePrinter.PrintNative(@class);
1022+
WriteLine($"var dest = new __IntPtr(&(({typeName}*)__Instance)->{fieldName});");
1023+
WriteLine($"var src = value.{Helpers.InstanceIdentifier};");
1024+
1025+
if (IsInternalClassNested(fieldClass))
1026+
typeName.RemoveNamespace();
1027+
1028+
WriteLine($"{fieldClass}.__Internal.OperatorEqual(dest, src);");
1029+
1030+
return;
1031+
}
1032+
}
1033+
}
1034+
1035+
10121036
string returnVar;
10131037
Type type = field.Type.Desugar();
1038+
10141039
var arrayType = type as ArrayType;
10151040
if (arrayType != null && @class.IsValueType)
10161041
{
@@ -1492,6 +1517,11 @@ public void GenerateClassMethods(IList<Method> methods)
14921517
continue;
14931518
}
14941519

1520+
// We only use the copy assignment operator internally,
1521+
// so do not generate a public method wrapper for it
1522+
if (method.OperatorKind == CXXOperatorKind.Equal)
1523+
continue;
1524+
14951525
GenerateMethod(method, @class);
14961526
}
14971527

src/Generator/Passes/CheckAmbiguousFunctions.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,43 @@ public override bool VisitFunctionDecl(AST.Function function)
6969

7070
private bool CheckDefaultParametersForAmbiguity(Function function, Function overload)
7171
{
72+
// detect if function and overload are copy assignment or move assignment operators
73+
// if both are either one of those types, ignore move assignment operator
74+
if (function.OperatorKind == CXXOperatorKind.Equal && overload.OperatorKind == CXXOperatorKind.Equal &&
75+
function.Parameters.Count == 1 && overload.Parameters.Count == 1)
76+
{
77+
var functionParamType = function.Parameters[0].Type;
78+
var overloadParamType = overload.Parameters[0].Type;
79+
80+
if (functionParamType is PointerType && overloadParamType is PointerType)
81+
{
82+
var functionParamPointerType = functionParamType as PointerType;
83+
var overloadParamPointerType = overloadParamType as PointerType;
84+
85+
var functionPointee = functionParamPointerType.GetPointee();
86+
var overloadPointee = overloadParamPointerType.GetPointee();
87+
88+
functionPointee.TryGetClass(out Class @functionPointeeClass);
89+
overloadPointee.TryGetClass(out Class @overloadPointeeClass);
90+
91+
if (functionPointeeClass == function.Namespace && @overloadPointeeClass == overload.Namespace)
92+
{
93+
if (functionParamPointerType.Modifier == PointerType.TypeModifier.RVReference &&
94+
overloadParamPointerType.Modifier == PointerType.TypeModifier.LVReference)
95+
{
96+
function.ExplicitlyIgnore();
97+
return true;
98+
}
99+
else if (functionParamPointerType.Modifier == PointerType.TypeModifier.LVReference &&
100+
overloadParamPointerType.Modifier == PointerType.TypeModifier.RVReference)
101+
{
102+
overload.ExplicitlyIgnore();
103+
return true;
104+
}
105+
}
106+
}
107+
}
108+
72109
List<Parameter> functionParams = RemoveOperatorParams(function);
73110
List<Parameter> overloadParams = RemoveOperatorParams(overload);
74111

src/Generator/Passes/ValidateOperatorsPass.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ private bool IsValidOperatorOverload(Method @operator)
5555
// The conversion operators can be overloaded
5656
case CXXOperatorKind.Conversion:
5757
case CXXOperatorKind.ExplicitConversion:
58+
59+
// Copy assignment operator is used internally
60+
case CXXOperatorKind.Equal:
5861
return true;
5962

6063
// The comparison operators can be overloaded if their return type is bool
@@ -127,7 +130,6 @@ private bool IsValidOperatorOverload(Method @operator)
127130
case CXXOperatorKind.PipePipe:
128131

129132
// These operators cannot be overloaded.
130-
case CXXOperatorKind.Equal:
131133
case CXXOperatorKind.Comma:
132134
case CXXOperatorKind.ArrowStar:
133135
case CXXOperatorKind.Arrow:

0 commit comments

Comments
 (0)