Browse Source

Added a new pass that checks for ambiguous overloads.

pull/53/merge
triton 12 years ago
parent
commit
871a05511c
  1. 1
      src/AST/Function.cs
  2. 1
      src/Generator/Driver.cs
  3. 126
      src/Generator/Passes/CheckAmbiguousFunctions.cs
  4. 8
      tests/Basic/Basic.Tests.cs
  5. 16
      tests/Basic/Basic.cpp
  6. 10
      tests/Basic/Basic.h

1
src/AST/Function.cs

@ -100,6 +100,7 @@ namespace CppSharp.AST @@ -100,6 +100,7 @@ namespace CppSharp.AST
public bool IsVariadic { get; set; }
public bool IsInline { get; set; }
public bool IsPure { get; set; }
public bool IsAmbiguous { get; set; }
public CXXOperatorKind OperatorKind { get; set; }
public bool IsOperator { get { return OperatorKind != CXXOperatorKind.None; } }

1
src/Generator/Driver.cs

@ -137,6 +137,7 @@ namespace CppSharp @@ -137,6 +137,7 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new MoveOperatorToClassPass());
TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass());
TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance());
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
library.SetupPasses(this);

126
src/Generator/Passes/CheckAmbiguousFunctions.cs

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
using System;
using CppSharp.AST;
namespace CppSharp.Passes
{
/// <summary>
/// Checks for ambiguous functions/method declarations.
/// Example:
///
/// struct S
/// {
/// void Foo(int a, int b = 0);
/// void Foo(int a);
///
/// void Bar();
/// void Bar() const;
/// };
///
/// When we call Foo(0) the compiler will not know which call we want and
/// will error out so we need to detect this and either ignore the methods
/// or flag them such that the generator can explicitly disambiguate when
/// generating the call to the native code.
/// </summary>
public class CheckAmbiguousFunctions : TranslationUnitPass
{
public override bool VisitMethodDecl(Method method)
{
if (method.Kind != CXXMethodKind.Normal)
return false;
return base.VisitMethodDecl(method);
}
public override bool VisitFunctionDecl(AST.Function function)
{
if (AlreadyVisited(function))
return false;
if (function.IsAmbiguous)
return false;
var overloads = function.Namespace.GetFunctionOverloads(function);
foreach (var overload in overloads)
{
if (overload == function) continue;
if (overload.Ignore) continue;
if (!CheckDefaultParameters(function, overload))
continue;
if (!CheckConstness(function, overload))
continue;
function.IsAmbiguous = true;
overload.IsAmbiguous = true;
}
if (function.IsAmbiguous)
Driver.Diagnostics.EmitWarning("Found ambiguous overload: {0}",
function.QualifiedOriginalName);
return true;
}
static bool CheckDefaultParameters(Function function, Function overload)
{
var commonParameters = Math.Min(function.Parameters.Count, overload.Parameters.Count);
var i = 0;
for (; i < commonParameters; ++i)
{
var funcParam = function.Parameters[i];
var overloadParam = overload.Parameters[i];
if (!funcParam.QualifiedType.Equals(overloadParam.QualifiedType))
return false;
}
for (; i < function.Parameters.Count; ++i)
{
var funcParam = function.Parameters[i];
if (!funcParam.HasDefaultValue)
return false;
}
for (; i < overload.Parameters.Count; ++i)
{
var overloadParam = overload.Parameters[i];
if (!overloadParam.HasDefaultValue)
return false;
}
if (function.Parameters.Count > overload.Parameters.Count)
overload.ExplicityIgnored = true;
else
function.ExplicityIgnored = true;
return true;
}
static bool CheckConstness(Function function, Function overload)
{
if (function is Method && overload is Method)
{
var method1 = function as Method;
var method2 = overload as Method;
if (method1.IsConst && !method2.IsConst)
{
method1.ExplicityIgnored = true;
return false;
}
if (method2.IsConst && !method1.IsConst)
{
method2.ExplicityIgnored = true;
return false;
}
}
return true;
}
}
}

8
tests/Basic/Basic.Tests.cs

@ -69,6 +69,14 @@ public class BasicTests @@ -69,6 +69,14 @@ public class BasicTests
Assert.That(barSum.B, Is.EqualTo(bar.B + bar1.B));
}
[Test]
public void TestAmbiguous()
{
var def = new DefaultParameters();
def.Foo(1, 2);
def.Bar();
}
[Test, Ignore]
public void TestLeftShiftOperator()
{

16
tests/Basic/Basic.cpp

@ -120,3 +120,19 @@ Bar indirectReturn() @@ -120,3 +120,19 @@ Bar indirectReturn()
{
return Bar();
}
void DefaultParameters::Foo(int a, int b)
{
}
void DefaultParameters::Foo(int a)
{
}
void DefaultParameters::Bar() const
{
}
void DefaultParameters::Bar()
{
}

10
tests/Basic/Basic.h

@ -103,3 +103,13 @@ struct DLL_API DerivedException : public Exception @@ -103,3 +103,13 @@ struct DLL_API DerivedException : public Exception
{
virtual Ex2* clone() override { return 0; }
};
// Tests for ambiguous call to native functions with default parameters
struct DLL_API DefaultParameters
{
void Foo(int a, int b = 0);
void Foo(int a);
void Bar() const;
void Bar();
};
Loading…
Cancel
Save