Skip to content

Commit f6f52ac

Browse files
committed
Directly move functions instead of making methods
This keeps the original functions instead of ignoring them which helps when rearranging passes - in particular when the pass for symbols is involved. Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent a00f34c commit f6f52ac

File tree

5 files changed

+153
-99
lines changed

5 files changed

+153
-99
lines changed

src/Generator/Generators/CLI/CLIHeaders.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -222,19 +222,25 @@ public void GenerateFunctions(DeclarationContext decl)
222222
{
223223
PushBlock(BlockKind.FunctionsClass);
224224

225-
WriteLine("public ref class {0}", TranslationUnit.FileNameWithoutExtension);
226-
WriteLine("{");
227-
WriteLine("public:");
228-
Indent();
225+
if (!(decl is Class))
226+
{
227+
WriteLine("public ref class {0}", TranslationUnit.FileNameWithoutExtension);
228+
WriteLine("{");
229+
WriteLine("public:");
230+
Indent();
231+
}
229232

230233
// Generate all the function declarations for the module.
231234
foreach (var function in decl.Functions)
232235
{
233236
GenerateFunction(function);
234237
}
235238

236-
Unindent();
237-
WriteLine("};");
239+
if (!(decl is Class))
240+
{
241+
Unindent();
242+
WriteLine("};");
243+
}
238244

239245
PopBlock(NewLineKind.BeforeNextBlock);
240246
}

src/Generator/Generators/CLI/CLISources.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -889,11 +889,9 @@ public void GenerateFunction(Function function, DeclarationContext @namespace)
889889

890890
GenerateDeclarationCommon(function);
891891

892-
var classSig = string.Format("{0}::{1}", QualifiedIdentifier(@namespace),
893-
TranslationUnit.FileNameWithoutExtension);
894-
895-
Write("{0} {1}::{2}(", function.ReturnType, classSig,
896-
function.Name);
892+
Write($@"{function.ReturnType} {QualifiedIdentifier(@namespace)}::{
893+
(@namespace is Class ? string.Empty : $@"{
894+
TranslationUnit.FileNameWithoutExtension}::")}{function.Name}(");
897895

898896
for (var i = 0; i < function.Parameters.Count; ++i)
899897
{

src/Generator/Generators/CSharp/CSharpSources.cs

+49-27
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,19 @@ private IEnumerable<Class> EnumerateClasses(DeclarationContext context)
239239

240240
public virtual void GenerateNamespaceFunctionsAndVariables(DeclarationContext context)
241241
{
242+
var hasGlobalFunctions = !(context is Class) && context.Functions.Any(
243+
f => f.IsGenerated);
244+
242245
var hasGlobalVariables = !(context is Class) && context.Variables.Any(
243246
v => v.IsGenerated && v.Access == AccessSpecifier.Public);
244247

245-
if (!context.Functions.Any(f => f.IsGenerated) && !hasGlobalVariables)
248+
if (!hasGlobalFunctions && !hasGlobalVariables)
246249
return;
247250

248-
PushBlock(BlockKind.Functions);
249251
var parentName = SafeIdentifier(context.TranslationUnit.FileNameWithoutExtension);
250252

253+
PushBlock(BlockKind.Functions);
254+
251255
var keyword = "class";
252256
var classes = EnumerateClasses().ToList();
253257
if (classes.FindAll(cls => cls.IsValueType && cls.Name == parentName && context.QualifiedLogicalName == cls.Namespace.QualifiedLogicalName).Any())
@@ -271,12 +275,8 @@ public virtual void GenerateNamespaceFunctionsAndVariables(DeclarationContext co
271275
UnindentAndWriteCloseBrace();
272276
PopBlock(NewLineKind.BeforeNextBlock);
273277

274-
foreach (var function in context.Functions)
275-
{
276-
if (!function.IsGenerated) continue;
277-
278+
foreach (Function function in context.Functions.Where(f => f.IsGenerated))
278279
GenerateFunction(function, parentName);
279-
}
280280

281281
foreach (var variable in context.Variables.Where(
282282
v => v.IsGenerated && v.Access == AccessSpecifier.Public))
@@ -443,7 +443,8 @@ public override bool VisitClassDecl(Class @class)
443443
}
444444

445445
GenerateClassConstructors(@class);
446-
446+
foreach (Function function in @class.Functions.Where(f => f.IsGenerated))
447+
GenerateFunction(function, @class.Name);
447448
GenerateClassMethods(@class.Methods);
448449
GenerateClassVariables(@class);
449450
GenerateClassProperties(@class);
@@ -649,6 +650,10 @@ private void GatherClassInternalFunctions(Class @class, bool includeCtors,
649650
&& !functions.Contains(prop.SetMethod))
650651
tryAddOverload(prop.SetMethod);
651652
}
653+
654+
functions.AddRange(from function in @class.Functions
655+
where function.IsGenerated && !function.IsSynthetized
656+
select function);
652657
}
653658

654659
private IEnumerable<string> GatherInternalParams(Function function, out TypePrinterResult retType)
@@ -2323,6 +2328,8 @@ public void GenerateFunction(Function function, string parentName)
23232328

23242329
if (function.SynthKind == FunctionSynthKind.DefaultValueOverload)
23252330
GenerateOverloadCall(function);
2331+
else if (function.IsOperator)
2332+
GenerateOperator(function, default(QualifiedType));
23262333
else
23272334
GenerateInternalFunctionCall(function);
23282335

@@ -2650,24 +2657,24 @@ private string GetVirtualCallDelegate(Method method)
26502657
return delegateId;
26512658
}
26522659

2653-
private void GenerateOperator(Method method, QualifiedType returnType)
2660+
private void GenerateOperator(Function function, QualifiedType returnType)
26542661
{
2655-
if (method.SynthKind == FunctionSynthKind.ComplementOperator)
2662+
if (function.SynthKind == FunctionSynthKind.ComplementOperator)
26562663
{
2657-
if (method.Kind == CXXMethodKind.Conversion)
2664+
if (function is Method method && method.Kind == CXXMethodKind.Conversion)
26582665
{
26592666
// To avoid ambiguity when having the multiple inheritance pass enabled
2660-
var paramType = method.Parameters[0].Type.SkipPointerRefs().Desugar();
2667+
var paramType = function.Parameters[0].Type.SkipPointerRefs().Desugar();
26612668
paramType = (paramType.GetPointee() ?? paramType).Desugar();
26622669
Class paramClass;
26632670
Class @interface = null;
26642671
if (paramType.TryGetClass(out paramClass))
26652672
@interface = paramClass.GetInterface();
26662673

26672674
var paramName = string.Format("{0}{1}",
2668-
method.Parameters[0].Type.IsPrimitiveTypeConvertibleToRef() ?
2675+
function.Parameters[0].Type.IsPrimitiveTypeConvertibleToRef() ?
26692676
"ref *" : string.Empty,
2670-
method.Parameters[0].Name);
2677+
function.Parameters[0].Name);
26712678
var printedType = method.ConversionType.Visit(TypePrinter);
26722679
if (@interface != null)
26732680
{
@@ -2679,30 +2686,45 @@ private void GenerateOperator(Method method, QualifiedType returnType)
26792686
}
26802687
else
26812688
{
2682-
var @operator = Operators.GetOperatorOverloadPair(method.OperatorKind);
2689+
var @operator = Operators.GetOperatorOverloadPair(function.OperatorKind);
26832690

2684-
WriteLine("return !({0} {1} {2});", method.Parameters[0].Name,
2685-
@operator, method.Parameters[1].Name);
2691+
// handle operators for comparison which return int instead of bool
2692+
Type retType = function.OriginalReturnType.Type.Desugar();
2693+
bool regular = retType.IsPrimitiveType(PrimitiveType.Bool);
2694+
if (regular)
2695+
{
2696+
WriteLine($@"return !({function.Parameters[0].Name} {
2697+
@operator} {function.Parameters[1].Name});");
2698+
}
2699+
else
2700+
{
2701+
WriteLine($@"return global::System.Convert.ToInt32(({
2702+
function.Parameters[0].Name} {@operator} {
2703+
function.Parameters[1].Name}) == 0);");
2704+
}
26862705
}
26872706
return;
26882707
}
26892708

2690-
if (method.OperatorKind == CXXOperatorKind.EqualEqual ||
2691-
method.OperatorKind == CXXOperatorKind.ExclaimEqual)
2709+
if (function.OperatorKind == CXXOperatorKind.EqualEqual ||
2710+
function.OperatorKind == CXXOperatorKind.ExclaimEqual)
26922711
{
26932712
WriteLine("bool {0}Null = ReferenceEquals({0}, null);",
2694-
method.Parameters[0].Name);
2713+
function.Parameters[0].Name);
26952714
WriteLine("bool {0}Null = ReferenceEquals({0}, null);",
2696-
method.Parameters[1].Name);
2715+
function.Parameters[1].Name);
26972716
WriteLine("if ({0}Null || {1}Null)",
2698-
method.Parameters[0].Name, method.Parameters[1].Name);
2699-
WriteLineIndent("return {0}{1}Null && {2}Null{3};",
2700-
method.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : "!(",
2701-
method.Parameters[0].Name, method.Parameters[1].Name,
2702-
method.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : ")");
2717+
function.Parameters[0].Name, function.Parameters[1].Name);
2718+
Type retType = function.OriginalReturnType.Type.Desugar();
2719+
bool regular = retType.IsPrimitiveType(PrimitiveType.Bool);
2720+
WriteLineIndent($@"return {(regular ? string.Empty : "global::System.Convert.ToInt32(")}{
2721+
(function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : "!(")}{
2722+
function.Parameters[0].Name}Null && {function.Parameters[1].Name}Null{
2723+
(function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : ")")}{
2724+
(regular ? string.Empty : ")")};");
27032725
}
27042726

2705-
GenerateInternalFunctionCall(method, returnType: returnType);
2727+
GenerateInternalFunctionCall(function, returnType: returnType);
27062728
}
27072729

27082730
private void GenerateClassConstructor(Method method, Class @class)

src/Generator/Passes/CheckOperatorsOverloads.cs

+74-43
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System.Collections.Generic;
2+
using System.Linq;
23
using CppSharp.AST;
34
using CppSharp.AST.Extensions;
45
using CppSharp.Generators;
@@ -65,6 +66,15 @@ private void CheckInvalidOperators(Class @class)
6566
else
6667
CreateOperator(@class, @operator);
6768
}
69+
70+
foreach (var @operator in @class.Functions.Where(
71+
f => f.IsGenerated && f.IsOperator &&
72+
!IsValidOperatorOverload(f) && !f.IsExplicitlyGenerated))
73+
{
74+
Diagnostics.Debug("Invalid operator overload {0}::{1}",
75+
@class.OriginalName, @operator.OperatorKind);
76+
@operator.ExplicitlyIgnore();
77+
}
6878
}
6979

7080
private static void CreateOperator(Class @class, Method @operator)
@@ -128,64 +138,85 @@ private void CreateIndexer(Class @class, Method @operator)
128138
@operator.GenerationKind = GenerationKind.Internal;
129139
}
130140

131-
private static void HandleMissingOperatorOverloadPair(Class @class, CXXOperatorKind op1,
132-
CXXOperatorKind op2)
141+
private static void HandleMissingOperatorOverloadPair(Class @class,
142+
CXXOperatorKind op1, CXXOperatorKind op2)
133143
{
134-
foreach (var op in @class.Operators.Where(
144+
List<Method> methods = HandleMissingOperatorOverloadPair(
145+
@class, @class.Operators, op1, op2);
146+
foreach (Method @operator in methods)
147+
{
148+
int index = @class.Methods.IndexOf(
149+
(Method) @operator.OriginalFunction);
150+
@class.Methods.Insert(index, @operator);
151+
}
152+
153+
List<Function> functions = HandleMissingOperatorOverloadPair(
154+
@class, @class.Functions, op1, op2);
155+
foreach (Method @operator in functions)
156+
{
157+
int index = @class.Declarations.IndexOf(
158+
@operator.OriginalFunction);
159+
@class.Methods.Insert(index, @operator);
160+
}
161+
}
162+
163+
private static List<T> HandleMissingOperatorOverloadPair<T>(Class @class,
164+
IEnumerable<T> functions, CXXOperatorKind op1,
165+
CXXOperatorKind op2) where T : Function, new()
166+
{
167+
List<T> fs = new List<T>();
168+
foreach (var op in functions.Where(
135169
o => o.OperatorKind == op1 || o.OperatorKind == op2).ToList())
136170
{
137-
int index;
138-
var missingKind = CheckMissingOperatorOverloadPair(@class, out index, op1, op2,
139-
op.Parameters.First().Type, op.Parameters.Last().Type);
171+
var missingKind = CheckMissingOperatorOverloadPair(functions,
172+
op1, op2, op.Parameters.First().Type, op.Parameters.Last().Type);
140173

141174
if (missingKind == CXXOperatorKind.None || !op.IsGenerated)
142175
continue;
143176

144-
var method = new Method()
145-
{
146-
Name = Operators.GetOperatorIdentifier(missingKind),
147-
Namespace = @class,
148-
SynthKind = FunctionSynthKind.ComplementOperator,
149-
Kind = CXXMethodKind.Operator,
150-
OperatorKind = missingKind,
151-
ReturnType = op.ReturnType
152-
};
153-
154-
method.Parameters.AddRange(op.Parameters.Select(
155-
p => new Parameter(p) { Namespace = method }));
156-
157-
@class.Methods.Insert(index, method);
177+
var function = new T()
178+
{
179+
Name = Operators.GetOperatorIdentifier(missingKind),
180+
Namespace = @class,
181+
SynthKind = FunctionSynthKind.ComplementOperator,
182+
OperatorKind = missingKind,
183+
ReturnType = op.ReturnType,
184+
OriginalFunction = op
185+
};
186+
187+
var method = function as Method;
188+
if (method != null)
189+
method.Kind = CXXMethodKind.Operator;
190+
191+
function.Parameters.AddRange(op.Parameters.Select(
192+
p => new Parameter(p) { Namespace = function }));
193+
194+
fs.Add(function);
158195
}
196+
return fs;
159197
}
160-
161-
static CXXOperatorKind CheckMissingOperatorOverloadPair(Class @class, out int index,
162-
CXXOperatorKind op1, CXXOperatorKind op2, Type typeLeft, Type typeRight)
198+
199+
private static CXXOperatorKind CheckMissingOperatorOverloadPair(
200+
IEnumerable<Function> functions,
201+
CXXOperatorKind op1, CXXOperatorKind op2,
202+
Type typeLeft, Type typeRight)
163203
{
164-
var first = @class.Operators.FirstOrDefault(o => o.IsGenerated && o.OperatorKind == op1 &&
165-
o.Parameters.First().Type.Equals(typeLeft) && o.Parameters.Last().Type.Equals(typeRight));
166-
var second = @class.Operators.FirstOrDefault(o => o.IsGenerated && o.OperatorKind == op2 &&
167-
o.Parameters.First().Type.Equals(typeLeft) && o.Parameters.Last().Type.Equals(typeRight));
204+
var first = functions.FirstOrDefault(
205+
o => o.IsGenerated && o.OperatorKind == op1 &&
206+
o.Parameters.First().Type.Equals(typeLeft) &&
207+
o.Parameters.Last().Type.Equals(typeRight));
208+
var second = functions.FirstOrDefault(
209+
o => o.IsGenerated && o.OperatorKind == op2 &&
210+
o.Parameters.First().Type.Equals(typeLeft) &&
211+
o.Parameters.Last().Type.Equals(typeRight));
168212

169213
var hasFirst = first != null;
170214
var hasSecond = second != null;
171215

172-
if (hasFirst && !hasSecond)
173-
{
174-
index = @class.Methods.IndexOf(first);
175-
return op2;
176-
}
177-
178-
if (hasSecond && !hasFirst)
179-
{
180-
index = @class.Methods.IndexOf(second);
181-
return op1;
182-
}
183-
184-
index = 0;
185-
return CXXOperatorKind.None;
216+
return hasFirst && !hasSecond ? op2 : hasSecond && !hasFirst ? op1 : CXXOperatorKind.None;
186217
}
187218

188-
private bool IsValidOperatorOverload(Method @operator)
219+
private bool IsValidOperatorOverload(Function @operator)
189220
{
190221
// These follow the order described in MSDN (Overloadable Operators).
191222

0 commit comments

Comments
 (0)