mirror of https://github.com/mono/CppSharp.git
4 changed files with 164 additions and 1 deletions
@ -0,0 +1,21 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace Cxxi.AST |
||||||
|
{ |
||||||
|
public static class Utils |
||||||
|
{ |
||||||
|
public static IList<Function> GetFunctionOverloads(Function function, |
||||||
|
Class @class = null) |
||||||
|
{ |
||||||
|
var overloads = new List<Function>(); |
||||||
|
|
||||||
|
if (@class == null) |
||||||
|
{ |
||||||
|
var @namespace = function.Namespace; |
||||||
|
return @namespace.GetFunctionOverloads(function); |
||||||
|
} |
||||||
|
|
||||||
|
return @class.GetFunctionOverloads(function); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,140 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using Cxxi.Generators; |
||||||
|
|
||||||
|
namespace Cxxi.Passes |
||||||
|
{ |
||||||
|
struct OverloadSignature |
||||||
|
{ |
||||||
|
public string Return; |
||||||
|
public List<string> Parameters; |
||||||
|
public Function Function; |
||||||
|
|
||||||
|
public OverloadSignature(Function function) |
||||||
|
{ |
||||||
|
Function = function; |
||||||
|
|
||||||
|
var typePrinter = Type.TypePrinter; |
||||||
|
|
||||||
|
Return = function.ReturnType.Visit(typePrinter); |
||||||
|
Parameters = new List<string>(); |
||||||
|
|
||||||
|
foreach (var param in function.Parameters) |
||||||
|
{ |
||||||
|
var paramType = param.Type.Visit(typePrinter); |
||||||
|
Parameters.Add(paramType); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static bool IsAmbiguous(OverloadSignature overload1, |
||||||
|
OverloadSignature overload2, Class @class) |
||||||
|
{ |
||||||
|
if (overload1.Function == overload2.Function) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (TextTemplate.CheckIgnoreFunction(@class, overload1.Function)) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (TextTemplate.CheckIgnoreFunction(@class, overload2.Function)) |
||||||
|
return false; |
||||||
|
|
||||||
|
// TODO: Default parameters?
|
||||||
|
if (overload1.Parameters.Count != overload2.Parameters.Count) |
||||||
|
return false; |
||||||
|
|
||||||
|
if (overload1.Parameters.Count == 0) |
||||||
|
return true; |
||||||
|
|
||||||
|
for (var i = 0; i < overload1.Parameters.Count; i++) |
||||||
|
{ |
||||||
|
if (overload1.Parameters[i] != overload2.Parameters[i]) |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public class CheckAmbiguousOverloads : TranslationUnitPass |
||||||
|
{ |
||||||
|
private Class currentClass; |
||||||
|
private readonly ISet<Function> visited; |
||||||
|
|
||||||
|
public CheckAmbiguousOverloads() |
||||||
|
{ |
||||||
|
visited = new HashSet<Function>(); |
||||||
|
Options.VisitNamespaceEnums = false; |
||||||
|
Options.VisitNamespaceTemplates = false; |
||||||
|
Options.VisitNamespaceTypedefs = false; |
||||||
|
|
||||||
|
Options.VisitClassBases = false; |
||||||
|
Options.VisitClassFields = false; |
||||||
|
Options.VisitClassProperties = false; |
||||||
|
Options.VisitClassEvents = false; |
||||||
|
Options.VisitClassVariables = false; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool VisitClassDecl(Class @class) |
||||||
|
{ |
||||||
|
visited.Clear(); |
||||||
|
|
||||||
|
currentClass = @class; |
||||||
|
return base.VisitClassDecl(@class); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool VisitMethodDecl(Method method) |
||||||
|
{ |
||||||
|
CheckOverloads(method); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool VisitFunctionDecl(Function function) |
||||||
|
{ |
||||||
|
CheckOverloads(function); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private bool CheckOverloads(Function function) |
||||||
|
{ |
||||||
|
if (visited.Contains(function)) |
||||||
|
return false; |
||||||
|
|
||||||
|
var overloads = AST.Utils.GetFunctionOverloads(function, currentClass); |
||||||
|
var signatures = overloads.Select(fn => new OverloadSignature(fn)).ToList(); |
||||||
|
|
||||||
|
foreach (var sig1 in signatures) |
||||||
|
{ |
||||||
|
visited.Add(sig1.Function); |
||||||
|
|
||||||
|
foreach (var sig2 in signatures) |
||||||
|
{ |
||||||
|
if (!OverloadSignature.IsAmbiguous(sig1, sig2, currentClass)) |
||||||
|
continue; |
||||||
|
|
||||||
|
Driver.Diagnostics.EmitWarning(DiagnosticId.AmbiguousOverload, |
||||||
|
"Overload {0}::{1} is ambiguous, renaming automatically", |
||||||
|
currentClass.OriginalName, sig1.Function.QualifiedOriginalName); |
||||||
|
|
||||||
|
RenameOverload(sig1.Function); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public void RenameOverload(Function function) |
||||||
|
{ |
||||||
|
function.Name = function.Name + "0"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static class CheckAmbiguousOverloadsExtensions |
||||||
|
{ |
||||||
|
public static void CheckAmbiguousOverloads(this PassBuilder builder) |
||||||
|
{ |
||||||
|
var pass = new CheckAmbiguousOverloads(); |
||||||
|
builder.AddPass(pass); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue