From 813084948fdb855554234293ff2bfdc420fcd528 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sun, 22 Sep 2013 00:48:59 +0300 Subject: [PATCH 1/6] Fixed the resolution of overloads for conversion operators. Signed-off-by: Dimitar Dobrev --- src/AST/Class.cs | 5 +++-- src/AST/Namespace.cs | 5 +++-- src/Generator/Generators/CSharp/CSharpTextTemplate.cs | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 029d39b5..04a136ae 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -191,8 +191,9 @@ namespace CppSharp.AST public override IEnumerable GetFunctionOverloads(Function function) { - return Methods.Where(method => method.Name == function.Name) - .Cast(); + if (function.OperatorKind == CXXOperatorKind.Conversion) + return Methods.Where(fn => fn.OperatorKind == CXXOperatorKind.Conversion); + return Methods.Where(method => method.Name == function.Name); } public IEnumerable FindHierarchy(Func> func) diff --git a/src/AST/Namespace.cs b/src/AST/Namespace.cs index 06be0c09..98d2d7c0 100644 --- a/src/AST/Namespace.cs +++ b/src/AST/Namespace.cs @@ -242,8 +242,9 @@ namespace CppSharp.AST public virtual IEnumerable GetFunctionOverloads(Function function) { - return Functions.Where(fn => fn.Name == function.Name) - .ToList(); + if (function.OperatorKind == CXXOperatorKind.Conversion) + return Functions.Where(fn => fn.OperatorKind == CXXOperatorKind.Conversion); + return Functions.Where(fn => fn.Name == function.Name); } public bool HasDeclarations diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index ff4f550a..49dee947 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -2152,10 +2152,10 @@ namespace CppSharp.Generators.CSharp public static string GetFunctionNativeIdentifier(Function function) { - var identifier = SafeIdentifier(function.Name);; + var identifier = SafeIdentifier(function.Name); if (function.IsOperator) - identifier = "Operator" + function.OperatorKind.ToString(); + identifier = "Operator" + function.OperatorKind; var overloads = function.Namespace.GetFunctionOverloads(function) .ToList(); From 95687a22b6ae6418fc2d08d2445380a929f8f82b Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sun, 22 Sep 2013 01:35:16 +0300 Subject: [PATCH 2/6] Added two hacks: one for operators in general, one for a parser issue. 1. Visit the class as a declaration context when checking operator overloads - otherwise operators in nested types are not checked; this is, however, not the proper solution because all visiting of classes should be refactored so that this and any other methods are always called as necessary; 2. A single conversion operator in Qt misleads the parser into resolving a function pointer while it is (most probably) not; this caused a subsequent crash. Signed-off-by: Dimitar Dobrev --- .../Passes/CheckOperatorsOverloads.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index fd570a31..c46d8898 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -20,6 +20,9 @@ namespace CppSharp.Passes if (AlreadyVisited(@class)) return false; + if (!VisitDeclarationContext(@class)) + return false; + // Check for C++ operators that cannot be represented in C#. CheckInvalidOperators(@class); @@ -80,6 +83,30 @@ namespace CppSharp.Passes Kind = ParameterKind.OperatorParameter }); } + // HACK: in Qt's qobjectdefs.h we have this line: + // typedef void *Connection::*RestrictedBool; + // Our parser resolves this as a function pointer while judging by the next line of: + // operator RestrictedBool() const { return d_ptr ? &Connection::d_ptr : 0; } + // it seems not to be. So until the proper fix just use the pointee to avoid crashes + if (@operator.OperatorKind == CXXOperatorKind.Conversion) + { + var typedef = @operator.ReturnType.Type as TypedefType; + if (typedef != null) + { + var functionPointer = typedef.Desugar() as MemberPointerType; + if (functionPointer != null) + { + FunctionType functionType; + functionPointer.IsPointerTo(out functionType); + if (functionType == null) + { + @operator.ReturnType = + new QualifiedType(functionPointer.Pointee, + @operator.ReturnType.Qualifiers); + } + } + } + } } } From 1af78bd544c727018e25e742f87757cdc637f01b Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sun, 22 Sep 2013 01:36:32 +0300 Subject: [PATCH 3/6] Updated the news about the conversion operators. Signed-off-by: Dimitar Dobrev --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 059e9e5a..a1bf3c69 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ CppSharp is a library that allows you to generate .NET bindings that wrap C/C++ ## News +* September 22nd 2013 - Conversion (type cast) operators wrapped (thanks to @ddobrev) * September 21st 2013 - Multiple inheritance now supported (thanks to @ddobrev) * September 11th 2013 - Added wrapping of inlined functions (thanks to @ddobrev) From 2091d71242e6dbc3f03a14bc423268a75211c91c Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 23 Sep 2013 16:00:37 +0300 Subject: [PATCH 4/6] Added a test about the type def - to a function pointer - incorrectly resolved to void*. Signed-off-by: Dimitar Dobrev --- src/Generator/Passes/CheckAmbiguousFunctions.cs | 10 ++++++++++ tests/CSharpTemp/CSharpTemp.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/Generator/Passes/CheckAmbiguousFunctions.cs b/src/Generator/Passes/CheckAmbiguousFunctions.cs index a44f642e..3b04fb46 100644 --- a/src/Generator/Passes/CheckAmbiguousFunctions.cs +++ b/src/Generator/Passes/CheckAmbiguousFunctions.cs @@ -35,6 +35,16 @@ namespace CppSharp.Passes foreach (var overload in overloads) { + if (function.OperatorKind == CXXOperatorKind.Conversion) + { + if (function != overload && + function.OriginalReturnType == overload.OriginalReturnType) + { + overload.ExplicityIgnored = true; + function.IsAmbiguous = true; + } + continue; + } if (overload == function) continue; if (overload.Ignore) continue; diff --git a/tests/CSharpTemp/CSharpTemp.h b/tests/CSharpTemp/CSharpTemp.h index 4ff75db3..d79b7086 100644 --- a/tests/CSharpTemp/CSharpTemp.h +++ b/tests/CSharpTemp/CSharpTemp.h @@ -41,4 +41,7 @@ public: int takesQux(const Qux& qux); Qux returnQux(); operator int() const; + + typedef void *Baz::*FunctionPointerResolvedAsVoidStar; + operator FunctionPointerResolvedAsVoidStar() const { return 0; } }; From 5b6beaaf33b1d3fb4968baa97dc5f7dadfb0e476 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 23 Sep 2013 16:52:55 +0300 Subject: [PATCH 5/6] Added a test about operators in nested classes. Signed-off-by: Dimitar Dobrev --- src/Generator/Passes/CheckAmbiguousFunctions.cs | 9 +-------- tests/CSharpTemp/CSharpTemp.Tests.cs | 3 +++ tests/CSharpTemp/CSharpTemp.cpp | 5 +++++ tests/CSharpTemp/CSharpTemp.h | 6 ++++++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Generator/Passes/CheckAmbiguousFunctions.cs b/src/Generator/Passes/CheckAmbiguousFunctions.cs index 3b04fb46..bad22625 100644 --- a/src/Generator/Passes/CheckAmbiguousFunctions.cs +++ b/src/Generator/Passes/CheckAmbiguousFunctions.cs @@ -36,15 +36,8 @@ namespace CppSharp.Passes foreach (var overload in overloads) { if (function.OperatorKind == CXXOperatorKind.Conversion) - { - if (function != overload && - function.OriginalReturnType == overload.OriginalReturnType) - { - overload.ExplicityIgnored = true; - function.IsAmbiguous = true; - } continue; - } + if (overload == function) continue; if (overload.Ignore) continue; diff --git a/tests/CSharpTemp/CSharpTemp.Tests.cs b/tests/CSharpTemp/CSharpTemp.Tests.cs index fd7dc4cf..6d706a3a 100644 --- a/tests/CSharpTemp/CSharpTemp.Tests.cs +++ b/tests/CSharpTemp/CSharpTemp.Tests.cs @@ -46,5 +46,8 @@ public class CSharpTempTests Assert.That(baz.returnQux().farAwayFunc(), Is.EqualTo(20)); int cast = baz; Assert.That(cast, Is.EqualTo(500)); + var nested = new Baz.Nested(); + int nestedCast = nested; + Assert.That(nestedCast, Is.EqualTo(300)); } } \ No newline at end of file diff --git a/tests/CSharpTemp/CSharpTemp.cpp b/tests/CSharpTemp/CSharpTemp.cpp index ff0a74af..d030f5af 100644 --- a/tests/CSharpTemp/CSharpTemp.cpp +++ b/tests/CSharpTemp/CSharpTemp.cpp @@ -46,6 +46,11 @@ Foo& Bar::operator[](int i) return m_foo; } +Baz::Nested::operator int() const +{ + return 300; +} + int Baz::takesQux(const Qux& qux) { return qux.farAwayFunc(); diff --git a/tests/CSharpTemp/CSharpTemp.h b/tests/CSharpTemp/CSharpTemp.h index d79b7086..1d62fa39 100644 --- a/tests/CSharpTemp/CSharpTemp.h +++ b/tests/CSharpTemp/CSharpTemp.h @@ -38,6 +38,12 @@ private: class DLL_API Baz : public Foo, public Bar { public: + class DLL_API Nested + { + public: + operator int() const; + }; + int takesQux(const Qux& qux); Qux returnQux(); operator int() const; From d2e7e99bc3baf10dc9fab73474e6752206dd605d Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 23 Sep 2013 22:51:36 +0300 Subject: [PATCH 6/6] Fixed the issue about member pointers not pointing to a function. Turns out this is some "pointer to a data member" (?!) that is of little use so just ignore it. Signed-off-by: Dimitar Dobrev --- .../Passes/CheckOperatorsOverloads.cs | 24 ------------------- src/Generator/Types/Types.cs | 11 +++++++++ 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index c46d8898..04972842 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -83,30 +83,6 @@ namespace CppSharp.Passes Kind = ParameterKind.OperatorParameter }); } - // HACK: in Qt's qobjectdefs.h we have this line: - // typedef void *Connection::*RestrictedBool; - // Our parser resolves this as a function pointer while judging by the next line of: - // operator RestrictedBool() const { return d_ptr ? &Connection::d_ptr : 0; } - // it seems not to be. So until the proper fix just use the pointee to avoid crashes - if (@operator.OperatorKind == CXXOperatorKind.Conversion) - { - var typedef = @operator.ReturnType.Type as TypedefType; - if (typedef != null) - { - var functionPointer = typedef.Desugar() as MemberPointerType; - if (functionPointer != null) - { - FunctionType functionType; - functionPointer.IsPointerTo(out functionType); - if (functionType == null) - { - @operator.ReturnType = - new QualifiedType(functionPointer.Pointee, - @operator.ReturnType.Qualifiers); - } - } - } - } } } diff --git a/src/Generator/Types/Types.cs b/src/Generator/Types/Types.cs index d92f23f4..91a6e919 100644 --- a/src/Generator/Types/Types.cs +++ b/src/Generator/Types/Types.cs @@ -97,6 +97,17 @@ namespace CppSharp return base.VisitTypedefDecl(typedef); } + public override bool VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals) + { + FunctionType functionType; + if (!member.IsPointerTo(out functionType)) + { + Ignore(); + return false; + } + return base.VisitMemberPointerType(member, quals); + } + public override bool VisitTemplateSpecializationType( TemplateSpecializationType template, TypeQualifiers quals) {