Skip to content

Commit

Permalink
Fixed the generated C# for indexers in templates.
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
  • Loading branch information
ddobrev committed Aug 6, 2017
1 parent 38ed4ab commit e078968
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 19 deletions.
19 changes: 15 additions & 4 deletions src/Generator/Generators/CSharp/CSharpMarshal.cs
Expand Up @@ -167,12 +167,23 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
return true;
}

if (Context.Context.Options.MarshalCharAsManagedChar && primitive == PrimitiveType.Char)
Context.Return.Write(string.Format("({0}) ", pointer));
if (Context.Context.Options.MarshalCharAsManagedChar &&
primitive == PrimitiveType.Char)
Context.Return.Write($"({pointer}) ");

var type = Context.ReturnType.Type.Desugar(
resolveTemplateSubstitution: false);
if (Context.Function != null &&
Context.Function.OperatorKind == CXXOperatorKind.Subscript &&
Context.ReturnType.Type.Desugar().IsPrimitiveType(primitive))
type.IsPrimitiveType(primitive))
{
var substitute = type as TemplateParameterSubstitutionType;
if (substitute != null)
Context.Return.Write($@"({
substitute.ReplacedParameter.Parameter.Name}) (object) ");
Context.Return.Write("*");
}

Context.Return.Write(Context.ReturnVarName);
return true;
}
Expand Down Expand Up @@ -732,7 +743,7 @@ private void MarshalRefClass(Class @class)
}

string param = Context.Parameter.Name;
Type type = Context.Parameter.Type.Desugar(false);
Type type = Context.Parameter.Type.Desugar(resolveTemplateSubstitution: false);
string paramInstance;
Class @interface;
var finalType = type.GetFinalPointee() ?? type;
Expand Down
34 changes: 21 additions & 13 deletions src/Generator/Generators/CSharp/CSharpSources.cs
Expand Up @@ -928,28 +928,36 @@ private void GenerateIndexerSetter(Function function)
{
Type type;
function.Type.IsPointerTo(out type);
PrimitiveType primitiveType;

var @internal = TypePrinter.PrintNative(function.Namespace);
var ctx = new CSharpMarshalContext(Context)
{
Parameter = new Parameter
{
Name = "value",
QualifiedType = new QualifiedType(type)
},
ReturnType = new QualifiedType(type)
};
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
type.Visit(marshal);
Write(marshal.Context.Before);

var internalFunction = GetFunctionNativeIdentifier(function);
var @internal = $@"{Helpers.InternalStruct}{
Helpers.GetSuffixForInternal(function.Namespace)}";
if (type.IsPrimitiveType(out primitiveType))
if (type.IsPrimitiveType())
{
WriteLine($@"*{@internal}.{internalFunction}({
GetInstanceParam(function)}, {function.Parameters[0].Name}) = value;");
GetInstanceParam(function)}, {function.Parameters[0].Name}) = {
marshal.Context.Return};");
}
else
{
var typeString = type.ToString();
Class @class;
var isValueType = (type.GetFinalPointee() ?? type).TryGetClass(out @class) &&
@class.IsValueType;
var typeInternal = TypePrinter.PrintNative(type);
var paramMarshal = GenerateFunctionParamMarshal(
function.Parameters[0], 0, function);
WriteLine($@"*({typeString}.{@internal}*) {@internal}.{internalFunction}({
WriteLine($@"*({typeInternal}*) {@internal}.{internalFunction}({
GetInstanceParam(function)}, {(paramMarshal.Context == null ?
paramMarshal.Name : paramMarshal.Context.Return)}) = {
(isValueType ? string.Empty : $@"*({typeString}.{@internal}*) ")}value.{
Helpers.InstanceIdentifier};");
paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};");
}
}

Expand Down
Expand Up @@ -146,7 +146,8 @@ private static void RemoveTemplateSubstitution(ref QualifiedType qualType)
var type = qualType.Type.Desugar();
while (type.IsAddress())
{
var pointee = ((PointerType) type).Pointee.Desugar(false);
var pointee = ((PointerType) type).Pointee.Desugar(
resolveTemplateSubstitution: false);
if (pointee.IsAddress())
type = pointee;
else
Expand Down
25 changes: 25 additions & 0 deletions tests/CSharp/CSharp.Tests.cs
Expand Up @@ -739,6 +739,31 @@ public void TestIndependentConstInIndependentTemplate()
Assert.That(IndependentFields<T1>.IndependentConst, Is.EqualTo(15));
}

[Test]
public void TestTemplateWithIndexer()
{
using (var templateWithIndexer = new TemplateWithIndexer<int>())
{
templateWithIndexer[0] = 5;
Assert.That(templateWithIndexer[0], Is.EqualTo(5));
templateWithIndexer["test"] = 15;
Assert.That(templateWithIndexer["test"], Is.EqualTo(15));
}
using (var templateWithIndexer = new TemplateWithIndexer<T1>())
{
using (var t1 = new T1(10))
{
templateWithIndexer[0] = t1;
Assert.That(templateWithIndexer[0].Field, Is.EqualTo(t1.Field));
}
using (var t1 = new T1(15))
{
templateWithIndexer["test"] = t1;
Assert.That(templateWithIndexer["test"].Field, Is.EqualTo(t1.Field));
}
}
}

[Test]
public void TestAbstractImplementatonsInPrimaryAndSecondaryBases()
{
Expand Down
33 changes: 32 additions & 1 deletion tests/CSharp/CSharpTemplates.h
Expand Up @@ -152,6 +152,34 @@ class HasDefaultTemplateArgument<bool, bool>
static bool staticField;
};

template <typename T>
class TemplateWithIndexer
{
public:
TemplateWithIndexer();
T& operator[](int i);
T& operator[](const char* string);
private:
T t[1];
};

template <typename T>
TemplateWithIndexer<T>::TemplateWithIndexer()
{
}

template <typename T>
T& TemplateWithIndexer<T>::operator[](int i)
{
return t[0];
}

template <typename T>
T& TemplateWithIndexer<T>::operator[](const char* string)
{
return t[0];
}

template <typename T, typename D>
HasDefaultTemplateArgument<T, D>::HasDefaultTemplateArgument()
{
Expand Down Expand Up @@ -307,7 +335,8 @@ struct MapResultType<InputSequence<T>, MapFunctor>
void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool> _2,
IndependentFields<T1> _3, IndependentFields<std::string> _4,
VirtualTemplate<int> _5, VirtualTemplate<bool> _6,
HasDefaultTemplateArgument<int, int> _7, DerivedChangesTypeName<T1> _8, std::string s);
HasDefaultTemplateArgument<int, int> _7, DerivedChangesTypeName<T1> _8,
TemplateWithIndexer<int> _9, TemplateWithIndexer<T1> _10, std::string s);

// force the symbols for the template instantiations because we do not have the auto-compilation for the generated C++ source
template class DLL_API IndependentFields<int>;
Expand All @@ -318,3 +347,5 @@ template class DLL_API VirtualTemplate<int>;
template class DLL_API VirtualTemplate<bool>;
template class DLL_API HasDefaultTemplateArgument<int, int>;
template class DLL_API DerivedChangesTypeName<T1>;
template class DLL_API TemplateWithIndexer<int>;
template class DLL_API TemplateWithIndexer<T1>;

0 comments on commit e078968

Please sign in to comment.