Skip to content

Commit 10c8211

Browse files
committed
Fixed the generated C# when a template interface specialised with another specialisation returns a template parameter.
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent 08bebbb commit 10c8211

File tree

4 files changed

+88
-8
lines changed

4 files changed

+88
-8
lines changed

src/AST/Function.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ public Function(Function function)
157157
Parameters.AddRange(function.Parameters.Select(p => new Parameter(p)));
158158
foreach (var parameter in Parameters)
159159
parameter.Namespace = this;
160+
InstantiatedFrom = function.InstantiatedFrom;
160161
IsVariadic = function.IsVariadic;
161162
IsInline = function.IsInline;
162163
IsPure = function.IsPure;

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ private void GenerateFieldGetter(Field field, Class @class, QualifiedType return
12061206
{
12071207
var final = field.Type.GetFinalPointee().Desugar(resolveTemplateSubstitution: false);
12081208
var templateSubstitution = final as TemplateParameterSubstitutionType;
1209-
if (templateSubstitution != null)
1209+
if (templateSubstitution != null && returnType.Type.IsDependent)
12101210
Write($"({templateSubstitution.ReplacedParameter.Parameter.Name}) (object) ");
12111211
if ((final.IsPrimitiveType() && !final.IsPrimitiveType(PrimitiveType.Void) &&
12121212
(!final.IsPrimitiveType(PrimitiveType.Char) &&

src/Generator/Passes/ParamTypeToInterfacePass.cs

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System.Collections.Generic;
2+
using System.Linq;
23
using CppSharp.AST;
34
using CppSharp.AST.Extensions;
45

@@ -21,7 +22,13 @@ public override bool VisitFunctionDecl(Function function)
2122
if (!base.VisitFunctionDecl(function))
2223
return false;
2324

24-
if (!function.IsOperator || function.Parameters.Count > 1)
25+
// parameters and returns from a specialised interface
26+
// must not be replaced if the templated interface uses a template parameter
27+
Function templateInterfaceFunction = GetTemplateInterfaceFunction(function);
28+
29+
if ((!function.IsOperator || function.Parameters.Count > 1) &&
30+
(templateInterfaceFunction == null ||
31+
!IsTemplateParameter(templateInterfaceFunction.OriginalReturnType)))
2532
{
2633
var originalReturnType = function.OriginalReturnType;
2734
ChangeToInterfaceType(ref originalReturnType);
@@ -30,13 +37,27 @@ public override bool VisitFunctionDecl(Function function)
3037

3138
if (function.OperatorKind != CXXOperatorKind.Conversion &&
3239
function.OperatorKind != CXXOperatorKind.ExplicitConversion)
33-
foreach (var parameter in function.Parameters.Where(
34-
p => p.Kind != ParameterKind.OperatorParameter))
40+
{
41+
IList<Parameter> parameters = function.Parameters.Where(
42+
p => p.Kind != ParameterKind.OperatorParameter &&
43+
p.Kind != ParameterKind.IndirectReturnType).ToList();
44+
45+
var templateFunctionParameters = new List<Parameter>();
46+
if (templateInterfaceFunction != null)
47+
templateFunctionParameters.AddRange(
48+
templateInterfaceFunction.Parameters.Where(
49+
p => p.Kind != ParameterKind.OperatorParameter &&
50+
p.Kind != ParameterKind.IndirectReturnType));
51+
for (int i = 0; i < parameters.Count; i++)
3552
{
36-
var qualifiedType = parameter.QualifiedType;
53+
if (templateFunctionParameters.Any() &&
54+
IsTemplateParameter(templateFunctionParameters[i].QualifiedType))
55+
continue;
56+
var qualifiedType = parameters[i].QualifiedType;
3757
ChangeToInterfaceType(ref qualifiedType);
38-
parameter.QualifiedType = qualifiedType;
58+
parameters[i].QualifiedType = qualifiedType;
3959
}
60+
}
4061

4162
return true;
4263
}
@@ -46,12 +67,55 @@ public override bool VisitProperty(Property property)
4667
if (!base.VisitProperty(property))
4768
return false;
4869

70+
var templateInterfaceProperty = GetTemplateInterfaceProperty(property);
71+
72+
if (templateInterfaceProperty != null &&
73+
IsTemplateParameter(templateInterfaceProperty.QualifiedType))
74+
return false;
75+
4976
var type = property.QualifiedType;
5077
ChangeToInterfaceType(ref type);
5178
property.QualifiedType = type;
5279
return true;
5380
}
5481

82+
private static Function GetTemplateInterfaceFunction(Function function)
83+
{
84+
Function templateInterfaceFunction = null;
85+
Class @class = function.OriginalNamespace as Class;
86+
if (@class != null && @class.IsInterface)
87+
templateInterfaceFunction = @class.Methods.First(
88+
m => m.OriginalFunction == function.OriginalFunction).InstantiatedFrom;
89+
return templateInterfaceFunction;
90+
}
91+
92+
private static Property GetTemplateInterfaceProperty(Property property)
93+
{
94+
if (property.GetMethod != null &&
95+
property.GetMethod.SynthKind == FunctionSynthKind.InterfaceInstance)
96+
return null;
97+
98+
Property templateInterfaceProperty = null;
99+
Class @class = property.OriginalNamespace as Class;
100+
if (@class != null && @class.IsInterface)
101+
{
102+
var specialization = @class as ClassTemplateSpecialization;
103+
if (specialization != null)
104+
{
105+
Class template = specialization.TemplatedDecl.TemplatedClass;
106+
templateInterfaceProperty = template.Properties.FirstOrDefault(
107+
p => p.Name == property.Name);
108+
}
109+
}
110+
111+
return templateInterfaceProperty;
112+
}
113+
114+
private static bool IsTemplateParameter(QualifiedType type)
115+
{
116+
return (type.Type.Desugar().GetFinalPointee() ?? type.Type).Desugar() is TemplateParameterType;
117+
}
118+
55119
private static void ChangeToInterfaceType(ref QualifiedType type)
56120
{
57121
var finalType = (type.Type.GetFinalPointee() ?? type.Type).Desugar();

tests/CSharp/CSharpTemplates.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class DLL_API DependentPointerFields
220220
public:
221221
DependentPointerFields();
222222
~DependentPointerFields();
223+
T property();
224+
T takeField(T t);
223225
T* field;
224226
};
225227

@@ -233,6 +235,18 @@ DependentPointerFields<T>::~DependentPointerFields()
233235
{
234236
}
235237

238+
template <typename T>
239+
T DependentPointerFields<T>::property()
240+
{
241+
return *field;
242+
}
243+
244+
template <typename T>
245+
T DependentPointerFields<T>::takeField(T t)
246+
{
247+
return *field;
248+
}
249+
236250
template <typename K, typename V>
237251
class TwoTemplateArgs
238252
{
@@ -463,7 +477,8 @@ class DLL_API SpecializedInterfaceForMap : InternalWithExtension<char>
463477
~SpecializedInterfaceForMap();
464478
};
465479

466-
class DLL_API HasSpecializationForSecondaryBase : T1, DependentValueFields<int>, IndependentFields<int>, InternalWithExtension<float>
480+
class DLL_API HasSpecializationForSecondaryBase : T1, DependentValueFields<int>, IndependentFields<int>,
481+
InternalWithExtension<float>, DependentPointerFields<DependentValueFields<int>>
467482
{
468483
public:
469484
HasSpecializationForSecondaryBase();

0 commit comments

Comments
 (0)