Skip to content

Commit eec0504

Browse files
committed
Fixed the generated C# for templates with > 1 ctor taking a pointer to a class.
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent 3ca1579 commit eec0504

File tree

5 files changed

+67
-20
lines changed

5 files changed

+67
-20
lines changed

src/Generator/Driver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ public void SetupPasses(ILibrary library)
234234
TranslationUnitPasses.AddPass(new CheckStaticClass());
235235
TranslationUnitPasses.AddPass(new MoveOperatorToClassPass());
236236
TranslationUnitPasses.AddPass(new MoveFunctionToClassPass());
237+
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
237238
TranslationUnitPasses.AddPass(new ConstructorToConversionOperatorPass());
238239
TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass());
239-
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
240240
TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass());
241241
TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance());
242242
TranslationUnitPasses.AddPass(new CleanCommentsPass());

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,6 +2598,7 @@ private void GenerateOperator(Method method, QualifiedType returnType)
25982598
{
25992599
// To avoid ambiguity when having the multiple inheritance pass enabled
26002600
var paramType = method.Parameters[0].Type.SkipPointerRefs().Desugar();
2601+
paramType = (paramType.GetPointee() ?? paramType).Desugar();
26012602
Class paramClass;
26022603
Class @interface = null;
26032604
if (paramType.TryGetClass(out paramClass))
@@ -3175,8 +3176,10 @@ public string GetFunctionNativeIdentifier(Function function,
31753176
var internalParams = function.GatherInternalParams(
31763177
Context.ParserOptions.IsItaniumLikeAbi);
31773178
var overloads = function.Namespace.GetOverloads(function)
3178-
.Where(f => !f.Ignore && (isForDelegate || internalParams.SequenceEqual(
3179-
f.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi),
3179+
.Where(f => (!f.Ignore ||
3180+
(f.OriginalFunction != null && !f.OriginalFunction.Ignore)) &&
3181+
(isForDelegate || internalParams.SequenceEqual(
3182+
f.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi),
31803183
new MarshallingParamComparer()))).ToList();
31813184
var index = -1;
31823185
if (overloads.Count > 1)

src/Generator/Passes/CheckDuplicatedNamesPass.cs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22
using System.Globalization;
33
using System.Linq;
44
using CppSharp.AST;
5-
using CppSharp.Generators;
5+
using CppSharp.AST.Extensions;
66

77
namespace CppSharp.Passes
88
{
99
class DeclarationName
1010
{
11-
private readonly Dictionary<string, int> methodSignatures;
11+
private readonly Dictionary<Function, int> functions;
1212
private int Count;
1313

1414
public DeclarationName()
1515
{
16-
methodSignatures = new Dictionary<string, int>();
16+
functions = new Dictionary<Function, int>();
1717
}
1818

1919
public bool UpdateName(Declaration decl)
2020
{
2121
var function = decl as Function;
22-
if (function != null && !(function.Namespace is ClassTemplateSpecialization))
22+
if (function != null)
2323
{
2424
return UpdateName(function);
2525
}
@@ -50,19 +50,22 @@ private bool UpdateName(Function function)
5050
(method.OperatorKind == CXXOperatorKind.Conversion ||
5151
method.OperatorKind == CXXOperatorKind.ExplicitConversion))
5252
@params = @params.Concat(new[] { method.ConversionType.ToString() });
53-
var signature = string.Format("{0}({1})", function.Name, string.Join( ", ", @params));
53+
var signature = $"{function.Name}({string.Join(", ", @params)})";
5454
signature = FixSignatureForConversions(function, signature);
5555

5656
if (Count == 0)
5757
Count++;
5858

59-
if (!methodSignatures.ContainsKey(signature))
59+
var duplicate = functions.Keys.FirstOrDefault(f =>
60+
f.Parameters.SequenceEqual(function.Parameters, ParameterTypeComparer.Instance));
61+
62+
if (duplicate == null)
6063
{
61-
methodSignatures.Add(signature, 0);
64+
functions.Add(function, 0);
6265
return false;
6366
}
6467

65-
var methodCount = ++methodSignatures[signature];
68+
var methodCount = ++functions[duplicate];
6669

6770
if (Count < methodCount + 1)
6871
Count = methodCount + 1;
@@ -96,6 +99,34 @@ public static string FixSignatureForConversions(Function function, string signat
9699
}
97100
return signature;
98101
}
102+
103+
private class ParameterTypeComparer : IEqualityComparer<Parameter>
104+
{
105+
public static readonly ParameterTypeComparer Instance = new ParameterTypeComparer();
106+
107+
private ParameterTypeComparer()
108+
{
109+
}
110+
111+
public bool Equals(Parameter x, Parameter y)
112+
{
113+
Type left = x.Type.Desugar(resolveTemplateSubstitution: false);
114+
Type right = y.Type.Desugar(resolveTemplateSubstitution: false);
115+
if (left.Equals(right))
116+
return true;
117+
118+
// TODO: some target languages might maek a difference between values and pointers
119+
Type leftPointee = left.GetPointee();
120+
Type rightPointee = right.GetPointee();
121+
return (leftPointee != null && leftPointee.Desugar(false).Equals(right)) ||
122+
(rightPointee != null && rightPointee.Desugar(false).Equals(left));
123+
}
124+
125+
public int GetHashCode(Parameter obj)
126+
{
127+
return obj.Type.GetHashCode();
128+
}
129+
}
99130
}
100131

101132
public class CheckDuplicatedNamesPass : TranslationUnitPass
@@ -180,15 +211,6 @@ public override bool VisitClassDecl(Class @class)
180211
return false;
181212
}
182213

183-
private static IEnumerable<Field> GetAllFields(Class @class, List<Field> fields = null)
184-
{
185-
fields = fields ?? new List<Field>();
186-
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class != @class))
187-
GetAllFields(@base.Class, fields);
188-
fields.AddRange(@class.Fields);
189-
return fields;
190-
}
191-
192214
private void CheckDuplicate(Declaration decl)
193215
{
194216
if (decl.IsDependent || !decl.IsGenerated)

tests/CSharp/CSharp.Tests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ public void TestUncompilableCode()
8484
{
8585
}
8686

87+
using (var t1 = new T1())
88+
using (new IndependentFields<int>(t1))
89+
{
90+
}
91+
92+
using (var t2 = new T2())
93+
using (new IndependentFields<int>(t2))
94+
{
95+
}
96+
8797
#pragma warning restore 0168
8898
#pragma warning restore 0219
8999
}

tests/CSharp/CSharpTemplates.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class DLL_API IndependentFields : public T1
3232
IndependentFields();
3333
IndependentFields(const IndependentFields<T>& other);
3434
IndependentFields(const T& t);
35+
IndependentFields(T1* t1);
36+
IndependentFields(T2* t2);
3537
IndependentFields(int i);
3638
~IndependentFields();
3739
explicit IndependentFields(const std::map<T, T> &other);
@@ -66,6 +68,16 @@ IndependentFields<T>::IndependentFields(const T& t) : independent(1)
6668
{
6769
}
6870

71+
template <typename T>
72+
IndependentFields<T>::IndependentFields(T1* t1) : independent(1)
73+
{
74+
}
75+
76+
template <typename T>
77+
IndependentFields<T>::IndependentFields(T2* t2) : independent(1)
78+
{
79+
}
80+
6981
template <typename T>
7082
IndependentFields<T>::IndependentFields(int i)
7183
{

0 commit comments

Comments
 (0)