Browse Source

Added a new pass that checks for ambiguous function/method overloads.

pull/1/head
triton 13 years ago
parent
commit
99ab98c884
  1. 21
      src/Generator/AST/Utils.cs
  2. 3
      src/Generator/Diagnostics.cs
  3. 1
      src/Generator/Driver.cs
  4. 140
      src/Generator/Passes/CheckAmbiguousOverloads.cs

21
src/Generator/AST/Utils.cs

@ -0,0 +1,21 @@ @@ -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);
}
}
}

3
src/Generator/Diagnostics.cs

@ -4,7 +4,8 @@ namespace Cxxi @@ -4,7 +4,8 @@ namespace Cxxi
{
public enum DiagnosticId
{
InvalidOperatorOverload
AmbiguousOverload,
InvalidOperatorOverload,
SymbolNotFound
}

1
src/Generator/Driver.cs

@ -141,6 +141,7 @@ namespace Cxxi @@ -141,6 +141,7 @@ namespace Cxxi
passes.ResolveIncompleteDecls(TypeDatabase);
passes.CheckTypeReferences();
passes.CheckFlagEnums();
passes.CheckAmbiguousOverloads();
if (Options.GeneratorKind == LanguageGeneratorKind.CSharp)
passes.CheckAbiParameters(Options);

140
src/Generator/Passes/CheckAmbiguousOverloads.cs

@ -0,0 +1,140 @@ @@ -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…
Cancel
Save