From eec05041a379e31cde122c5cc9dd5da75d48da5b Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 26 Oct 2018 01:54:41 +0300 Subject: [PATCH] Fixed the generated C# for templates with > 1 ctor taking a pointer to a class. Signed-off-by: Dimitar Dobrev --- src/Generator/Driver.cs | 2 +- .../Generators/CSharp/CSharpSources.cs | 7 ++- .../Passes/CheckDuplicatedNamesPass.cs | 56 +++++++++++++------ tests/CSharp/CSharp.Tests.cs | 10 ++++ tests/CSharp/CSharpTemplates.h | 12 ++++ 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index c3ea4093..895c316b 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -234,9 +234,9 @@ namespace CppSharp TranslationUnitPasses.AddPass(new CheckStaticClass()); TranslationUnitPasses.AddPass(new MoveOperatorToClassPass()); TranslationUnitPasses.AddPass(new MoveFunctionToClassPass()); + TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions()); TranslationUnitPasses.AddPass(new ConstructorToConversionOperatorPass()); TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass()); - TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions()); TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass()); TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance()); TranslationUnitPasses.AddPass(new CleanCommentsPass()); diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index e4a746d5..a9212352 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -2598,6 +2598,7 @@ namespace CppSharp.Generators.CSharp { // To avoid ambiguity when having the multiple inheritance pass enabled var paramType = method.Parameters[0].Type.SkipPointerRefs().Desugar(); + paramType = (paramType.GetPointee() ?? paramType).Desugar(); Class paramClass; Class @interface = null; if (paramType.TryGetClass(out paramClass)) @@ -3175,8 +3176,10 @@ namespace CppSharp.Generators.CSharp var internalParams = function.GatherInternalParams( Context.ParserOptions.IsItaniumLikeAbi); var overloads = function.Namespace.GetOverloads(function) - .Where(f => !f.Ignore && (isForDelegate || internalParams.SequenceEqual( - f.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi), + .Where(f => (!f.Ignore || + (f.OriginalFunction != null && !f.OriginalFunction.Ignore)) && + (isForDelegate || internalParams.SequenceEqual( + f.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi), new MarshallingParamComparer()))).ToList(); var index = -1; if (overloads.Count > 1) diff --git a/src/Generator/Passes/CheckDuplicatedNamesPass.cs b/src/Generator/Passes/CheckDuplicatedNamesPass.cs index 9b6e7c8a..7b2f43d5 100644 --- a/src/Generator/Passes/CheckDuplicatedNamesPass.cs +++ b/src/Generator/Passes/CheckDuplicatedNamesPass.cs @@ -2,24 +2,24 @@ using System.Globalization; using System.Linq; using CppSharp.AST; -using CppSharp.Generators; +using CppSharp.AST.Extensions; namespace CppSharp.Passes { class DeclarationName { - private readonly Dictionary methodSignatures; + private readonly Dictionary functions; private int Count; public DeclarationName() { - methodSignatures = new Dictionary(); + functions = new Dictionary(); } public bool UpdateName(Declaration decl) { var function = decl as Function; - if (function != null && !(function.Namespace is ClassTemplateSpecialization)) + if (function != null) { return UpdateName(function); } @@ -50,19 +50,22 @@ namespace CppSharp.Passes (method.OperatorKind == CXXOperatorKind.Conversion || method.OperatorKind == CXXOperatorKind.ExplicitConversion)) @params = @params.Concat(new[] { method.ConversionType.ToString() }); - var signature = string.Format("{0}({1})", function.Name, string.Join( ", ", @params)); + var signature = $"{function.Name}({string.Join(", ", @params)})"; signature = FixSignatureForConversions(function, signature); if (Count == 0) Count++; - if (!methodSignatures.ContainsKey(signature)) + var duplicate = functions.Keys.FirstOrDefault(f => + f.Parameters.SequenceEqual(function.Parameters, ParameterTypeComparer.Instance)); + + if (duplicate == null) { - methodSignatures.Add(signature, 0); + functions.Add(function, 0); return false; } - var methodCount = ++methodSignatures[signature]; + var methodCount = ++functions[duplicate]; if (Count < methodCount + 1) Count = methodCount + 1; @@ -96,6 +99,34 @@ namespace CppSharp.Passes } return signature; } + + private class ParameterTypeComparer : IEqualityComparer + { + public static readonly ParameterTypeComparer Instance = new ParameterTypeComparer(); + + private ParameterTypeComparer() + { + } + + public bool Equals(Parameter x, Parameter y) + { + Type left = x.Type.Desugar(resolveTemplateSubstitution: false); + Type right = y.Type.Desugar(resolveTemplateSubstitution: false); + if (left.Equals(right)) + return true; + + // TODO: some target languages might maek a difference between values and pointers + Type leftPointee = left.GetPointee(); + Type rightPointee = right.GetPointee(); + return (leftPointee != null && leftPointee.Desugar(false).Equals(right)) || + (rightPointee != null && rightPointee.Desugar(false).Equals(left)); + } + + public int GetHashCode(Parameter obj) + { + return obj.Type.GetHashCode(); + } + } } public class CheckDuplicatedNamesPass : TranslationUnitPass @@ -180,15 +211,6 @@ namespace CppSharp.Passes return false; } - private static IEnumerable GetAllFields(Class @class, List fields = null) - { - fields = fields ?? new List(); - foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class != @class)) - GetAllFields(@base.Class, fields); - fields.AddRange(@class.Fields); - return fields; - } - private void CheckDuplicate(Declaration decl) { if (decl.IsDependent || !decl.IsGenerated) diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index 6a761ede..cd9fb012 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -84,6 +84,16 @@ public unsafe class CSharpTests : GeneratorTestFixture { } + using (var t1 = new T1()) + using (new IndependentFields(t1)) + { + } + + using (var t2 = new T2()) + using (new IndependentFields(t2)) + { + } + #pragma warning restore 0168 #pragma warning restore 0219 } diff --git a/tests/CSharp/CSharpTemplates.h b/tests/CSharp/CSharpTemplates.h index e773241c..bd3fe991 100644 --- a/tests/CSharp/CSharpTemplates.h +++ b/tests/CSharp/CSharpTemplates.h @@ -32,6 +32,8 @@ public: IndependentFields(); IndependentFields(const IndependentFields& other); IndependentFields(const T& t); + IndependentFields(T1* t1); + IndependentFields(T2* t2); IndependentFields(int i); ~IndependentFields(); explicit IndependentFields(const std::map &other); @@ -66,6 +68,16 @@ IndependentFields::IndependentFields(const T& t) : independent(1) { } +template +IndependentFields::IndependentFields(T1* t1) : independent(1) +{ +} + +template +IndependentFields::IndependentFields(T2* t2) : independent(1) +{ +} + template IndependentFields::IndependentFields(int i) {