mirror of https://github.com/mono/CppSharp.git
5 changed files with 184 additions and 151 deletions
@ -0,0 +1,156 @@ |
|||||||
|
using System.Linq; |
||||||
|
using CppSharp.AST; |
||||||
|
using CppSharp.AST.Extensions; |
||||||
|
using CppSharp.Generators; |
||||||
|
|
||||||
|
namespace CppSharp.Passes |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Validates operators for C# (if they can be overloaded).
|
||||||
|
/// </summary>
|
||||||
|
public class ValidateOperatorsPass : TranslationUnitPass |
||||||
|
{ |
||||||
|
public ValidateOperatorsPass() => |
||||||
|
VisitOptions.VisitClassBases = |
||||||
|
VisitOptions.VisitClassFields = |
||||||
|
VisitOptions.VisitEventParameters = |
||||||
|
VisitOptions.VisitFunctionParameters = |
||||||
|
VisitOptions.VisitFunctionReturnType = |
||||||
|
VisitOptions.VisitNamespaceEnums = |
||||||
|
VisitOptions.VisitNamespaceEvents = |
||||||
|
VisitOptions.VisitNamespaceTemplates = |
||||||
|
VisitOptions.VisitNamespaceTypedefs = |
||||||
|
VisitOptions.VisitNamespaceVariables = |
||||||
|
VisitOptions.VisitPropertyAccessors = |
||||||
|
VisitOptions.VisitTemplateArguments = false; |
||||||
|
|
||||||
|
public override bool VisitMethodDecl(Method method) |
||||||
|
{ |
||||||
|
if (!base.VisitMethodDecl(method) || |
||||||
|
!method.IsOperator || !method.IsGenerated) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (!IsValidOperatorOverload(method) || method.IsPure) |
||||||
|
{ |
||||||
|
Diagnostics.Debug("Invalid operator overload {0}::{1}", |
||||||
|
method.Namespace.Name, method.OperatorKind); |
||||||
|
method.ExplicitlyIgnore(); |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private bool IsValidOperatorOverload(Method @operator) |
||||||
|
{ |
||||||
|
// These follow the order described in MSDN (Overloadable Operators).
|
||||||
|
|
||||||
|
switch (@operator.OperatorKind) |
||||||
|
{ |
||||||
|
// These unary operators can be overloaded
|
||||||
|
case CXXOperatorKind.Plus: |
||||||
|
case CXXOperatorKind.Minus: |
||||||
|
case CXXOperatorKind.Exclaim: |
||||||
|
case CXXOperatorKind.Tilde: |
||||||
|
|
||||||
|
// These binary operators can be overloaded
|
||||||
|
case CXXOperatorKind.Slash: |
||||||
|
case CXXOperatorKind.Percent: |
||||||
|
case CXXOperatorKind.Amp: |
||||||
|
case CXXOperatorKind.Pipe: |
||||||
|
case CXXOperatorKind.Caret: |
||||||
|
|
||||||
|
// The array indexing operator can be overloaded
|
||||||
|
case CXXOperatorKind.Subscript: |
||||||
|
|
||||||
|
// The conversion operators can be overloaded
|
||||||
|
case CXXOperatorKind.Conversion: |
||||||
|
case CXXOperatorKind.ExplicitConversion: |
||||||
|
return true; |
||||||
|
|
||||||
|
// The comparison operators can be overloaded if their return type is bool
|
||||||
|
case CXXOperatorKind.EqualEqual: |
||||||
|
case CXXOperatorKind.ExclaimEqual: |
||||||
|
case CXXOperatorKind.Less: |
||||||
|
case CXXOperatorKind.Greater: |
||||||
|
case CXXOperatorKind.LessEqual: |
||||||
|
case CXXOperatorKind.GreaterEqual: |
||||||
|
return @operator.ReturnType.Type.IsPrimitiveType(PrimitiveType.Bool); |
||||||
|
|
||||||
|
// Only prefix operators can be overloaded
|
||||||
|
case CXXOperatorKind.PlusPlus: |
||||||
|
case CXXOperatorKind.MinusMinus: |
||||||
|
Class @class; |
||||||
|
var returnType = @operator.OriginalReturnType.Type.Desugar(); |
||||||
|
returnType = (returnType.GetFinalPointee() ?? returnType).Desugar(); |
||||||
|
return returnType.TryGetClass(out @class) && |
||||||
|
@class.GetNonIgnoredRootBase() == |
||||||
|
((Class) @operator.Namespace).GetNonIgnoredRootBase() && |
||||||
|
@operator.Parameters.Count == 0; |
||||||
|
|
||||||
|
// Bitwise shift operators can only be overloaded if the second parameter is int
|
||||||
|
case CXXOperatorKind.LessLess: |
||||||
|
case CXXOperatorKind.GreaterGreater: |
||||||
|
{ |
||||||
|
Parameter parameter = @operator.Parameters.Last(); |
||||||
|
Type type = parameter.Type.Desugar(); |
||||||
|
switch (Options.GeneratorKind) |
||||||
|
{ |
||||||
|
case GeneratorKind.CLI: |
||||||
|
return type.IsPrimitiveType(PrimitiveType.Int); |
||||||
|
case GeneratorKind.CSharp: |
||||||
|
Types.TypeMap typeMap; |
||||||
|
if (Context.TypeMaps.FindTypeMap(type, out typeMap)) |
||||||
|
{ |
||||||
|
var mappedTo = typeMap.CSharpSignatureType( |
||||||
|
new TypePrinterContext |
||||||
|
{ |
||||||
|
Parameter = parameter, |
||||||
|
Type = type |
||||||
|
}); |
||||||
|
var cilType = mappedTo as CILType; |
||||||
|
if (cilType?.Type == typeof(int)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// No parameters means the dereference operator - cannot be overloaded
|
||||||
|
case CXXOperatorKind.Star: |
||||||
|
return @operator.Parameters.Count > 0; |
||||||
|
|
||||||
|
// Assignment operators cannot be overloaded
|
||||||
|
case CXXOperatorKind.PlusEqual: |
||||||
|
case CXXOperatorKind.MinusEqual: |
||||||
|
case CXXOperatorKind.StarEqual: |
||||||
|
case CXXOperatorKind.SlashEqual: |
||||||
|
case CXXOperatorKind.PercentEqual: |
||||||
|
case CXXOperatorKind.AmpEqual: |
||||||
|
case CXXOperatorKind.PipeEqual: |
||||||
|
case CXXOperatorKind.CaretEqual: |
||||||
|
case CXXOperatorKind.LessLessEqual: |
||||||
|
case CXXOperatorKind.GreaterGreaterEqual: |
||||||
|
|
||||||
|
// The conditional logical operators cannot be overloaded
|
||||||
|
case CXXOperatorKind.AmpAmp: |
||||||
|
case CXXOperatorKind.PipePipe: |
||||||
|
|
||||||
|
// These operators cannot be overloaded.
|
||||||
|
case CXXOperatorKind.Equal: |
||||||
|
case CXXOperatorKind.Comma: |
||||||
|
case CXXOperatorKind.ArrowStar: |
||||||
|
case CXXOperatorKind.Arrow: |
||||||
|
case CXXOperatorKind.Call: |
||||||
|
case CXXOperatorKind.Conditional: |
||||||
|
case CXXOperatorKind.Coawait: |
||||||
|
case CXXOperatorKind.New: |
||||||
|
case CXXOperatorKind.Delete: |
||||||
|
case CXXOperatorKind.Array_New: |
||||||
|
case CXXOperatorKind.Array_Delete: |
||||||
|
default: |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue