Skip to content

Commit e94ae29

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 e94ae29

File tree

5 files changed

+155
-99
lines changed

5 files changed

+155
-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

+52-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,10 @@ 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 (var function in from function in context.Functions
279+
where function.IsGenerated
280+
select function)
278281
GenerateFunction(function, parentName);
279-
}
280282

281283
foreach (var variable in context.Variables.Where(
282284
v => v.IsGenerated && v.Access == AccessSpecifier.Public))
@@ -443,7 +445,10 @@ public override bool VisitClassDecl(Class @class)
443445
}
444446

445447
GenerateClassConstructors(@class);
446-
448+
foreach (var function in from function in @class.Functions
449+
where function.IsGenerated
450+
select function)
451+
GenerateFunction(function, @class.Name);
447452
GenerateClassMethods(@class.Methods);
448453
GenerateClassVariables(@class);
449454
GenerateClassProperties(@class);
@@ -649,6 +654,10 @@ private void GatherClassInternalFunctions(Class @class, bool includeCtors,
649654
&& !functions.Contains(prop.SetMethod))
650655
tryAddOverload(prop.SetMethod);
651656
}
657+
658+
functions.AddRange(from function in @class.Functions
659+
where function.IsGenerated && !function.IsSynthetized
660+
select function);
652661
}
653662

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

23242333
if (function.SynthKind == FunctionSynthKind.DefaultValueOverload)
23252334
GenerateOverloadCall(function);
2335+
else if (function.IsOperator)
2336+
GenerateOperator(function, default(QualifiedType));
23262337
else
23272338
GenerateInternalFunctionCall(function);
23282339

@@ -2650,24 +2661,24 @@ private string GetVirtualCallDelegate(Method method)
26502661
return delegateId;
26512662
}
26522663

2653-
private void GenerateOperator(Method method, QualifiedType returnType)
2664+
private void GenerateOperator(Function function, QualifiedType returnType)
26542665
{
2655-
if (method.SynthKind == FunctionSynthKind.ComplementOperator)
2666+
if (function.SynthKind == FunctionSynthKind.ComplementOperator)
26562667
{
2657-
if (method.Kind == CXXMethodKind.Conversion)
2668+
if (function is Method method && method.Kind == CXXMethodKind.Conversion)
26582669
{
26592670
// To avoid ambiguity when having the multiple inheritance pass enabled
2660-
var paramType = method.Parameters[0].Type.SkipPointerRefs().Desugar();
2671+
var paramType = function.Parameters[0].Type.SkipPointerRefs().Desugar();
26612672
paramType = (paramType.GetPointee() ?? paramType).Desugar();
26622673
Class paramClass;
26632674
Class @interface = null;
26642675
if (paramType.TryGetClass(out paramClass))
26652676
@interface = paramClass.GetInterface();
26662677

26672678
var paramName = string.Format("{0}{1}",
2668-
method.Parameters[0].Type.IsPrimitiveTypeConvertibleToRef() ?
2679+
function.Parameters[0].Type.IsPrimitiveTypeConvertibleToRef() ?
26692680
"ref *" : string.Empty,
2670-
method.Parameters[0].Name);
2681+
function.Parameters[0].Name);
26712682
var printedType = method.ConversionType.Visit(TypePrinter);
26722683
if (@interface != null)
26732684
{
@@ -2679,30 +2690,44 @@ private void GenerateOperator(Method method, QualifiedType returnType)
26792690
}
26802691
else
26812692
{
2682-
var @operator = Operators.GetOperatorOverloadPair(method.OperatorKind);
2693+
var @operator = Operators.GetOperatorOverloadPair(function.OperatorKind);
26832694

2684-
WriteLine("return !({0} {1} {2});", method.Parameters[0].Name,
2685-
@operator, method.Parameters[1].Name);
2695+
Type retType = function.OriginalReturnType.Type.Desugar();
2696+
bool regular = retType.IsPrimitiveType(PrimitiveType.Bool);
2697+
if (regular)
2698+
{
2699+
WriteLine($@"return !({function.Parameters[0].Name} {
2700+
@operator} {function.Parameters[1].Name});");
2701+
}
2702+
else
2703+
{
2704+
WriteLine($@"return global::System.Convert.ToInt32(({
2705+
function.Parameters[0].Name} {@operator} {
2706+
function.Parameters[1].Name}) == 0);");
2707+
}
26862708
}
26872709
return;
26882710
}
26892711

2690-
if (method.OperatorKind == CXXOperatorKind.EqualEqual ||
2691-
method.OperatorKind == CXXOperatorKind.ExclaimEqual)
2712+
if (function.OperatorKind == CXXOperatorKind.EqualEqual ||
2713+
function.OperatorKind == CXXOperatorKind.ExclaimEqual)
26922714
{
26932715
WriteLine("bool {0}Null = ReferenceEquals({0}, null);",
2694-
method.Parameters[0].Name);
2716+
function.Parameters[0].Name);
26952717
WriteLine("bool {0}Null = ReferenceEquals({0}, null);",
2696-
method.Parameters[1].Name);
2718+
function.Parameters[1].Name);
26972719
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 : ")");
2720+
function.Parameters[0].Name, function.Parameters[1].Name);
2721+
Type retType = function.OriginalReturnType.Type.Desugar();
2722+
bool regular = retType.IsPrimitiveType(PrimitiveType.Bool);
2723+
WriteLineIndent($@"return {(regular ? string.Empty : "global::System.Convert.ToInt32(")}{
2724+
(function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : "!(")}{
2725+
function.Parameters[0].Name}Null && {function.Parameters[1].Name}Null{
2726+
(function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : ")")}{
2727+
(regular ? string.Empty : ")")};");
27032728
}
27042729

2705-
GenerateInternalFunctionCall(method, returnType: returnType);
2730+
GenerateInternalFunctionCall(function, returnType: returnType);
27062731
}
27072732

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

src/Generator/Passes/CheckOperatorsOverloads.cs

+73-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,84 @@ 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)
143+
{
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+
List<Function> functions = HandleMissingOperatorOverloadPair(
153+
@class, @class.Functions, op1, op2);
154+
foreach (Method @operator in functions)
155+
{
156+
int index = @class.Declarations.IndexOf(
157+
@operator.OriginalFunction);
158+
@class.Methods.Insert(index, @operator);
159+
}
160+
}
161+
162+
private static List<T> HandleMissingOperatorOverloadPair<T>(Class @class,
163+
IEnumerable<T> functions, CXXOperatorKind op1,
164+
CXXOperatorKind op2) where T : Function, new()
133165
{
134-
foreach (var op in @class.Operators.Where(
166+
List<T> fs = new List<T>();
167+
foreach (var op in functions.Where(
135168
o => o.OperatorKind == op1 || o.OperatorKind == op2).ToList())
136169
{
137-
int index;
138-
var missingKind = CheckMissingOperatorOverloadPair(@class, out index, op1, op2,
139-
op.Parameters.First().Type, op.Parameters.Last().Type);
170+
var missingKind = CheckMissingOperatorOverloadPair(functions,
171+
op1, op2, op.Parameters.First().Type, op.Parameters.Last().Type);
140172

141173
if (missingKind == CXXOperatorKind.None || !op.IsGenerated)
142174
continue;
143175

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);
176+
var function = new T()
177+
{
178+
Name = Operators.GetOperatorIdentifier(missingKind),
179+
Namespace = @class,
180+
SynthKind = FunctionSynthKind.ComplementOperator,
181+
OperatorKind = missingKind,
182+
ReturnType = op.ReturnType,
183+
OriginalFunction = op
184+
};
185+
186+
var method = function as Method;
187+
if (method != null)
188+
method.Kind = CXXMethodKind.Operator;
189+
190+
function.Parameters.AddRange(op.Parameters.Select(
191+
p => new Parameter(p) { Namespace = function }));
192+
193+
fs.Add(function);
158194
}
195+
return fs;
159196
}
160-
161-
static CXXOperatorKind CheckMissingOperatorOverloadPair(Class @class, out int index,
162-
CXXOperatorKind op1, CXXOperatorKind op2, Type typeLeft, Type typeRight)
197+
198+
private static CXXOperatorKind CheckMissingOperatorOverloadPair(
199+
IEnumerable<Function> functions,
200+
CXXOperatorKind op1, CXXOperatorKind op2,
201+
Type typeLeft, Type typeRight)
163202
{
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));
203+
var first = functions.FirstOrDefault(
204+
o => o.IsGenerated && o.OperatorKind == op1 &&
205+
o.Parameters.First().Type.Equals(typeLeft) &&
206+
o.Parameters.Last().Type.Equals(typeRight));
207+
var second = functions.FirstOrDefault(
208+
o => o.IsGenerated && o.OperatorKind == op2 &&
209+
o.Parameters.First().Type.Equals(typeLeft) &&
210+
o.Parameters.Last().Type.Equals(typeRight));
168211

169212
var hasFirst = first != null;
170213
var hasSecond = second != null;
171214

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;
215+
return hasFirst && !hasSecond ? op2 : hasSecond && !hasFirst ? op1 : CXXOperatorKind.None;
186216
}
187217

188-
private bool IsValidOperatorOverload(Method @operator)
218+
private bool IsValidOperatorOverload(Function @operator)
189219
{
190220
// These follow the order described in MSDN (Overloadable Operators).
191221

0 commit comments

Comments
 (0)