From a4f160695607885709a71fff02c91b48ec5bca41 Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 16:04:37 +0100 Subject: [PATCH 1/8] Added better support for unary operators. --- src/AST/Method.cs | 6 ++++++ src/Generator/AST/Utils.cs | 8 ++++++++ src/Generator/Generators/CLI/CLISourcesTemplate.cs | 13 ++++++++----- tests/Basic/Basic.Tests.cs | 11 ++++++++++- tests/Basic/Basic.cpp | 8 ++++++++ tests/Basic/Basic.h | 1 + 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/AST/Method.cs b/src/AST/Method.cs index 7dfd67a5..5627b50e 100644 --- a/src/AST/Method.cs +++ b/src/AST/Method.cs @@ -10,6 +10,12 @@ namespace CppSharp.AST UsingDirective } + public enum CXXOperatorArity + { + Unary, + Binary + } + public enum CXXOperatorKind { None, diff --git a/src/Generator/AST/Utils.cs b/src/Generator/AST/Utils.cs index 75a72230..a4600c09 100644 --- a/src/Generator/AST/Utils.cs +++ b/src/Generator/AST/Utils.cs @@ -54,6 +54,14 @@ namespace CppSharp.AST public static class Operators { + public static CXXOperatorArity ClassifyOperator(Function function) + { + if (function.Parameters.Count == 1) + return CXXOperatorArity.Unary; + + return CXXOperatorArity.Binary; + } + public static string GetOperatorOverloadPair(CXXOperatorKind kind) { switch (kind) diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index 5627e237..b13e854c 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -745,15 +745,18 @@ namespace CppSharp.Generators.CLI if (function.IsOperator) { - var kind = function.OperatorKind; - - var isBinary = function.Parameters.Count > 0; var opName = function.Name.Replace("operator", "").Trim(); - // Binary operator - if (isBinary) + switch (Operators.ClassifyOperator(function)) + { + case CXXOperatorArity.Unary: + WriteLine("{0} {1};", opName, @params[0].Name); + break; + case CXXOperatorArity.Binary: WriteLine("{0} {1} {2};", @params[0].Name, opName, @params[1].Name); + break; + } } else { diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index e4aaf48e..3fcffcb8 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -44,7 +44,16 @@ public class BasicTests } [Test] - public void TestFunctionOperator() + public void TestUnaryOperator() + { + var bar = new Bar { A = 4, B = 7 }; + var barMinus = -bar; + Assert.That(barMinus.A, Is.EqualTo(-bar.A)); + Assert.That(barMinus.B, Is.EqualTo(-bar.B)); + } + + [Test] + public void TestBinaryOperator() { var bar = new Bar { A = 4, B = 7 }; var bar1 = new Bar { A = 5, B = 10 }; diff --git a/tests/Basic/Basic.cpp b/tests/Basic/Basic.cpp index 1744ff77..ecc1a521 100644 --- a/tests/Basic/Basic.cpp +++ b/tests/Basic/Basic.cpp @@ -81,6 +81,14 @@ const wchar_t* wcharFunction(const wchar_t* constWideChar) return constWideChar; } +Bar operator-(const Bar& b) +{ + Bar nb; + nb.A = -b.A; + nb.B = -b.B; + return nb; +} + Bar operator+(const Bar& b1, const Bar& b2) { Bar b; diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 7c4ae134..e0995ab9 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -71,6 +71,7 @@ public: int RetEnum(Enum); }; +DLL_API Bar operator-(const Bar &); DLL_API Bar operator+(const Bar &, const Bar &); int DLL_API unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)); From f704ca3a057c7599d46f40142b2057ea89fbe5bb Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 16:10:51 +0100 Subject: [PATCH 2/8] Only add missing operator overloads in C# generator. --- .../Passes/CheckOperatorsOverloads.cs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index 3cfb62ae..898fdd6d 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -24,18 +24,21 @@ namespace CppSharp.Passes // Check for C++ operators that cannot be represented in C#. CheckInvalidOperators(@class); - // The comparison operators, if overloaded, must be overloaded in pairs; - // that is, if == is overloaded, != must also be overloaded. The reverse - // is also true, and similar for < and >, and for <= and >=. + if (Driver.Options.IsCSharpGenerator) + { + // The comparison operators, if overloaded, must be overloaded in pairs; + // that is, if == is overloaded, != must also be overloaded. The reverse + // is also true, and similar for < and >, and for <= and >=. - HandleMissingOperatorOverloadPair(@class, CXXOperatorKind.EqualEqual, - CXXOperatorKind.ExclaimEqual); + HandleMissingOperatorOverloadPair(@class, CXXOperatorKind.EqualEqual, + CXXOperatorKind.ExclaimEqual); - HandleMissingOperatorOverloadPair(@class, CXXOperatorKind.Less, - CXXOperatorKind.Greater); + HandleMissingOperatorOverloadPair(@class, CXXOperatorKind.Less, + CXXOperatorKind.Greater); - HandleMissingOperatorOverloadPair(@class, CXXOperatorKind.LessEqual, - CXXOperatorKind.GreaterEqual); + HandleMissingOperatorOverloadPair(@class, CXXOperatorKind.LessEqual, + CXXOperatorKind.GreaterEqual); + } return false; } From 0c64c06271d27077e2bbfb99daa2c2e8b5311bbf Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 16:11:16 +0100 Subject: [PATCH 3/8] Remove extra newline from the output. --- src/Generator/Generators/CLI/CLIHeadersTemplate.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index c7a6842d..f9710ba4 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using CppSharp.AST; -using CppSharp.Generators.CSharp; using CppSharp.Types; namespace CppSharp.Generators.CLI @@ -632,7 +631,6 @@ namespace CppSharp.Generators.CLI } PopIndent(); - NewLine(); WriteLine("};"); PopBlock(NewLineKind.BeforeNextBlock); From 05c020f30182206486ea5b22d6e476e8b5e969fd Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 16:11:59 +0100 Subject: [PATCH 4/8] Fixed marshaling of pointers to classes in CLI generator. --- src/Generator/Generators/CLI/CLIMarshal.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 668c5dea..ba35d1c3 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -65,6 +65,15 @@ namespace CppSharp.Generators.CLI return true; } + Class @class; + if (pointee.Desugar().IsTagDecl(out @class)) + { + var instance = (pointer.IsReference) ? "&" + Context.ReturnVarName + : Context.ReturnVarName; + WriteClassInstance(@class, instance); + return true; + } + if (!pointee.Visit(this, quals)) return false; From aa0a78abf541cda7c3f93194557ccf61ab211035 Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 16:12:18 +0100 Subject: [PATCH 5/8] Fixed marshaling of function pointer typedefs in CLI generator. --- src/Generator/Generators/CLI/CLIMarshal.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index ba35d1c3..1ad00043 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -429,9 +429,9 @@ namespace CppSharp.Generators.CLI } FunctionType func; - if (decl.Type.IsPointerTo(out func)) + if (decl.Type.IsPointerTo(out func)) { - VisitDelegateType(func, typedef.Declaration.OriginalName); + VisitDelegateType(func, "::" + typedef.Declaration.QualifiedOriginalName); return true; } From 54dc21e7d21fc3f123b5a7c79acf54cdc9782826 Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 16:12:49 +0100 Subject: [PATCH 6/8] Fixed parsing of function code gen info to be more robust. --- src/Parser/Parser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index f70036fe..1917d65e 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -1621,6 +1621,8 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F, // Skip the first argument as it's the return type. if (I == CGInfo.arg_begin()) continue; + if (Index >= F->Parameters->Count) + continue; F->Parameters[Index++]->IsIndirect = I->info.isIndirect(); } } From cf8eaa3a352f7512e1b503fbf4ddbc2a5e8f9b01 Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 23:24:09 +0100 Subject: [PATCH 7/8] Optimized/fixed marshaling for fields as there is no need to create a copied instance of the native object. --- src/Generator/Generators/CLI/CLIMarshal.cs | 3 ++- src/Generator/Generators/CLI/CLISourcesTemplate.cs | 1 + src/Generator/Generators/Marshal.cs | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 1ad00043..551b4095 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -185,8 +185,9 @@ namespace CppSharp.Generators.CLI instance += "&"; instance += Context.ReturnVarName; + var needsCopy = !(Context.Declaration is Field); - if (@class.IsRefType) + if (@class.IsRefType && needsCopy) { var name = Generator.GeneratedIdentifier(Context.ReturnVarName); Context.SupportBefore.WriteLine("auto {0} = new ::{1}({2});", name, diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index b13e854c..6625d2a6 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -336,6 +336,7 @@ namespace CppSharp.Generators.CLI var ctx = new MarshalContext(Driver) { + Declaration = decl, ArgName = decl.Name, ReturnVarName = variable, ReturnType = decl.QualifiedType diff --git a/src/Generator/Generators/Marshal.cs b/src/Generator/Generators/Marshal.cs index 783179f5..8129b2be 100644 --- a/src/Generator/Generators/Marshal.cs +++ b/src/Generator/Generators/Marshal.cs @@ -19,6 +19,8 @@ namespace CppSharp.Generators public TextGenerator SupportBefore { get; private set; } public TextGenerator Return { get; private set; } + public Declaration Declaration { get; set; } + public string ReturnVarName { get; set; } public QualifiedType ReturnType { get; set; } From 13c5357e3f5db8237d4dab63ab75510ea42ad9b1 Mon Sep 17 00:00:00 2001 From: triton Date: Sun, 25 Aug 2013 23:24:45 +0100 Subject: [PATCH 8/8] Use references instead of pointers when creating new operator overloads methods. --- src/Generator/Passes/CheckOperatorsOverloads.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index 898fdd6d..38680f64 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -63,7 +63,7 @@ namespace CppSharp.Passes var type = new PointerType() { QualifiedPointee = new QualifiedType(new TagType(@class)), - Modifier = PointerType.TypeModifier.Pointer + Modifier = PointerType.TypeModifier.LVReference }; @operator.Parameters.Insert(0, new Parameter