diff --git a/src/AST/Function.cs b/src/AST/Function.cs
index ae6d1838..a0f45e08 100644
--- a/src/AST/Function.cs
+++ b/src/AST/Function.cs
@@ -74,6 +74,16 @@ namespace CppSharp.AST
{
return visitor.VisitParameterDecl(this);
}
+
+ ///
+ /// HACK: in many cases QualifiedType.Qualifiers.IsConst does not work.
+ /// It's false in Clang to begin with. I tried fixing it to no avail.
+ /// I don't have any more time at the moment.
+ ///
+ public bool IsConst
+ {
+ get { return DebugText.StartsWith("const ", System.StringComparison.Ordinal); }
+ }
}
public class ParameterTypeComparer : IEqualityComparer
diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp
index adc2aa42..f1bf97b2 100644
--- a/src/CppParser/Parser.cpp
+++ b/src/CppParser/Parser.cpp
@@ -568,7 +568,7 @@ std::string Parser::GetTypeName(const clang::Type* Type)
return TypeName;
}
-static TypeQualifiers GetTypeQualifiers(clang::QualType Type)
+static TypeQualifiers GetTypeQualifiers(const clang::QualType& Type)
{
TypeQualifiers quals;
quals.IsConst = Type.isLocalConstQualified();
@@ -577,7 +577,7 @@ static TypeQualifiers GetTypeQualifiers(clang::QualType Type)
return quals;
}
-QualifiedType Parser::GetQualifiedType(clang::QualType qual, clang::TypeLoc* TL)
+QualifiedType Parser::GetQualifiedType(const clang::QualType& qual, clang::TypeLoc* TL)
{
QualifiedType qualType;
qualType.Type = WalkType(qual, TL);
@@ -2276,7 +2276,7 @@ Type* Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL,
auto PTL = PVD->getTypeSourceInfo()->getTypeLoc();
FA->Name = PVD->getNameAsString();
- FA->QualifiedType = GetQualifiedType(PVD->getType(), &PTL);
+ FA->QualifiedType = GetQualifiedType(PVD->getOriginalType(), &PTL);
}
else
{
@@ -2807,7 +2807,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
HandlePreprocessedEntities(P, paramRange, MacroLocation::FunctionParameters);
- P->QualifiedType = GetQualifiedType(VD->getType(), &PTL);
+ P->QualifiedType = GetQualifiedType(VD->getOriginalType(), &PTL);
P->HasDefaultValue = VD->hasDefaultArg();
P->_Namespace = NS;
P->Index = VD->getFunctionScopeIndex();
diff --git a/src/CppParser/Parser.h b/src/CppParser/Parser.h
index 6f78b913..ba6816d2 100644
--- a/src/CppParser/Parser.h
+++ b/src/CppParser/Parser.h
@@ -103,7 +103,7 @@ private:
std::vector WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, clang::TemplateSpecializationTypeLoc* TSTL);
std::vector WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL);
void WalkVTable(const clang::CXXRecordDecl* RD, Class* C);
- QualifiedType GetQualifiedType(clang::QualType qual, clang::TypeLoc* TL = 0);
+ QualifiedType GetQualifiedType(const clang::QualType& qual, clang::TypeLoc* TL = 0);
void ReadClassLayout(Class* Class, const clang::RecordDecl* RD, clang::CharUnits Offset, bool IncludeVirtualBases);
LayoutField WalkVTablePointer(Class* Class, const clang::CharUnits& Offset, const std::string& prefix);
VTableLayout WalkVTableLayout(const clang::VTableLayout& VTLayout);
diff --git a/src/Generator.Tests/AST/TestAST.cs b/src/Generator.Tests/AST/TestAST.cs
index 0a2e4018..d2a19b51 100644
--- a/src/Generator.Tests/AST/TestAST.cs
+++ b/src/Generator.Tests/AST/TestAST.cs
@@ -19,11 +19,6 @@ namespace CppSharp.Generator.Tests.AST
PrimitiveType primitiveType;
return type.IsPrimitiveType(out primitiveType) ? primitiveType.ToString() : string.Empty;
};
- }
-
- [SetUp]
- public void Setup()
- {
ParseLibrary("AST.h", "ASTExtensions.h");
}
diff --git a/src/Generator/Passes/CheckAmbiguousFunctions.cs b/src/Generator/Passes/CheckAmbiguousFunctions.cs
index 6ae4d594..4ce5cb4c 100644
--- a/src/Generator/Passes/CheckAmbiguousFunctions.cs
+++ b/src/Generator/Passes/CheckAmbiguousFunctions.cs
@@ -1,22 +1,36 @@
using System;
using System.Linq;
using CppSharp.AST;
+using CppSharp.AST.Extensions;
namespace CppSharp.Passes
{
///
/// 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;
- /// };
///
+ ///
+ /// void Qux(int& i);
+ ///
+ /// void Qux(int&& i);
+ ///
+ /// void Qux(const int& i);
+ ///
+ /// };
+ ///
/// 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
@@ -46,7 +60,8 @@ namespace CppSharp.Passes
if (!overload.IsGenerated) continue;
if (CheckConstnessForAmbiguity(function, overload) ||
- CheckDefaultParametersForAmbiguity(function, overload))
+ CheckDefaultParametersForAmbiguity(function, overload) ||
+ CheckSingleParameterPointerConstnessForAmbiguity(function, overload))
{
function.IsAmbiguous = true;
overload.IsAmbiguous = true;
@@ -120,5 +135,62 @@ namespace CppSharp.Passes
return false;
}
+
+ private static bool CheckSingleParameterPointerConstnessForAmbiguity(
+ Function function, Function overload)
+ {
+ var functionParams = function.Parameters.Where(
+ p => p.Kind == ParameterKind.Regular && p.Type.IsAddress()).ToList();
+ // It's difficult to handle this case for more than one parameter
+ // For example, if we have:
+ // void f(float&, const int&);
+ // void f(const float&, int&);
+ // what should we do? Generate both? Generate the first one encountered?
+ // Generate the one with the least amount of "complex" parameters?
+ // So let's just start with the simplest case for the time being
+ if (functionParams.Count != 1)
+ return false;
+ var overloadParams = overload.Parameters.Where(
+ p => p.Kind == ParameterKind.Regular && p.Type.IsAddress()).ToList();
+ if (overloadParams.Count != 1)
+ return false;
+
+ var parameterFunction = functionParams[0];
+ var parameterOverload = overloadParams[0];
+
+ if (!parameterFunction.Type.GetPointee().Equals(parameterOverload.Type.GetPointee()))
+ return false;
+
+ if (parameterFunction.IsConst && !parameterOverload.IsConst)
+ {
+ function.ExplicitlyIgnore();
+ return true;
+ }
+
+ if (parameterOverload.IsConst && !parameterFunction.IsConst)
+ {
+ overload.ExplicitlyIgnore();
+ return true;
+ }
+
+ var pointerParamFunction = (PointerType) parameterFunction.Type;
+ var pointerParamOverload = (PointerType) parameterOverload.Type;
+
+ if (pointerParamFunction.Modifier == PointerType.TypeModifier.RVReference &&
+ pointerParamOverload.Modifier != PointerType.TypeModifier.RVReference)
+ {
+ function.ExplicitlyIgnore();
+ return true;
+ }
+
+ if (pointerParamFunction.Modifier != PointerType.TypeModifier.RVReference &&
+ pointerParamOverload.Modifier == PointerType.TypeModifier.RVReference)
+ {
+ overload.ExplicitlyIgnore();
+ return true;
+ }
+
+ return false;
+ }
}
}
diff --git a/tests/Common/Common.cpp b/tests/Common/Common.cpp
index 3b570b07..1df2be3f 100644
--- a/tests/Common/Common.cpp
+++ b/tests/Common/Common.cpp
@@ -626,4 +626,24 @@ void FuncWithTypeAlias(custom_int_t i)
void FuncWithTemplateTypeAlias(TypeAliasTemplate i)
{
-}
\ No newline at end of file
+}
+
+HasOverloadsWithDifferentPointerKindsToSameType::HasOverloadsWithDifferentPointerKindsToSameType()
+{
+}
+
+HasOverloadsWithDifferentPointerKindsToSameType::~HasOverloadsWithDifferentPointerKindsToSameType()
+{
+}
+
+void HasOverloadsWithDifferentPointerKindsToSameType::overload(int& i)
+{
+}
+
+void HasOverloadsWithDifferentPointerKindsToSameType::overload(int&& i)
+{
+}
+
+void HasOverloadsWithDifferentPointerKindsToSameType::overload(const int& i)
+{
+}
diff --git a/tests/Common/Common.cs b/tests/Common/Common.cs
index cb08754e..a4eb0f7d 100644
--- a/tests/Common/Common.cs
+++ b/tests/Common/Common.cs
@@ -56,6 +56,7 @@ namespace CppSharp.Tests
base.Setup(driver);
driver.Options.OutputNamespace = "CommonTest";
+ driver.Options.UnityBuild = true;
}
public override void SetupPasses(Driver driver)
diff --git a/tests/Common/Common.h b/tests/Common/Common.h
index 6633e8c4..6c8f7968 100644
--- a/tests/Common/Common.h
+++ b/tests/Common/Common.h
@@ -1202,3 +1202,12 @@ enum
EmptyEnumsWithSameMemberPrefixAndUnderscore_4
};
+class DLL_API HasOverloadsWithDifferentPointerKindsToSameType
+{
+public:
+ HasOverloadsWithDifferentPointerKindsToSameType();
+ ~HasOverloadsWithDifferentPointerKindsToSameType();
+ void overload(int& i);
+ void overload(int&& i);
+ void overload(const int& i);
+};