Browse Source

Properly handled nulls passed to C++ refs by throwing an exception.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/591/head
Dimitar Dobrev 10 years ago
parent
commit
d328b7ce34
  1. 19
      src/Generator/Generators/CLI/CLIMarshal.cs
  2. 23
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  3. 11
      tests/CSharp/CSharp.Tests.cs
  4. 9
      tests/Common/Common.Tests.cs
  5. 5
      tests/Common/Common.cpp
  6. 1
      tests/Common/Common.h

19
src/Generator/Generators/CLI/CLIMarshal.cs

@ -679,14 +679,28 @@ namespace CppSharp.Generators.CLI @@ -679,14 +679,28 @@ namespace CppSharp.Generators.CLI
private void MarshalRefClass(Class @class)
{
TypeMap typeMap = null;
TypeMap typeMap;
if (Context.Driver.TypeDatabase.FindTypeMap(@class, out typeMap) && typeMap.DoesMarshalling)
{
typeMap.CLIMarshalToNative(Context);
return;
}
if (!Context.Parameter.Type.Desugar().SkipPointerRefs().IsPointer())
var type = Context.Parameter.Type.Desugar();
var method = Context.Function as Method;
if (type.IsReference() && (method == null ||
// redundant for comparison operators, they are handled in a special way
(method.OperatorKind != CXXOperatorKind.EqualEqual &&
method.OperatorKind != CXXOperatorKind.ExclaimEqual)))
{
Context.SupportBefore.WriteLine("if (ReferenceEquals({0}, nullptr))", Context.Parameter.Name);
Context.SupportBefore.WriteLineIndent(
"throw gcnew ::System::ArgumentNullException(\"{0}\", " +
"\"{0} cannot be null because it is a C++ reference (&).\");",
Context.Parameter.Name);
}
if (!type.SkipPointerRefs().IsPointer())
{
Context.Return.Write("*");
@ -694,7 +708,6 @@ namespace CppSharp.Generators.CLI @@ -694,7 +708,6 @@ namespace CppSharp.Generators.CLI
VarPrefix.Write("&");
}
var method = Context.Function as Method;
if (method != null
&& method.Conversion == MethodConversionKind.FunctionToInstanceMethod
&& Context.ParameterIndex == 0)

23
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -654,12 +654,31 @@ namespace CppSharp.Generators.CSharp @@ -654,12 +654,31 @@ namespace CppSharp.Generators.CSharp
if (type.TryGetClass(out decl) && decl.IsValueType)
Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
else
{
if (type.IsPointer())
{
Context.Return.Write("{0}{1}.{2}",
method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
? string.Empty
: string.Format("ReferenceEquals({0}, null) ? global::System.IntPtr.Zero : ", param),
param,
Helpers.InstanceIdentifier, type);
param, Helpers.InstanceIdentifier, type);
}
else
{
if (method == null ||
// redundant for comparison operators, they are handled in a special way
(method.OperatorKind != CXXOperatorKind.EqualEqual &&
method.OperatorKind != CXXOperatorKind.ExclaimEqual))
{
Context.SupportBefore.WriteLine("if (ReferenceEquals({0}, null))", param);
Context.SupportBefore.WriteLineIndent(
"throw new global::System.ArgumentNullException(\"{0}\", " +
"\"{0} cannot be null because it is a C++ reference (&).\");",
param);
}
Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
}
}
return;
}

11
tests/CSharp/CSharp.Tests.cs

@ -103,18 +103,25 @@ public class CSharpTests : GeneratorTestFixture @@ -103,18 +103,25 @@ public class CSharpTests : GeneratorTestFixture
Assert.That(proprietor.Value, Is.EqualTo(20));
proprietor.Prop = 50;
Assert.That(proprietor.Prop, Is.EqualTo(50));
var p = new P((IQux) null) { Value = 20 };
using (var qux = new Qux())
{
using (var p = new P((IQux) qux) { Value = 20 })
{
Assert.That(p.Value, Is.EqualTo(30));
p.Prop = 50;
Assert.That(p.Prop, Is.EqualTo(150));
ComplexType complexType = new ComplexType();
using (var complexType = new ComplexType())
{
p.ComplexType = complexType;
Assert.That(p.ComplexType.Check(), Is.EqualTo(5));
}
Assert.That(p.Test, Is.True);
Assert.That(p.IsBool, Is.False);
}
}
}
[Test]
public void TestAttributes()

9
tests/Common/Common.Tests.cs

@ -590,6 +590,15 @@ public class CommonTests : GeneratorTestFixture @@ -590,6 +590,15 @@ public class CommonTests : GeneratorTestFixture
Assert.That(Foo.charArray, Is.EqualTo("abc"));
}
[Test]
public void TestPassingNullToRef()
{
using (var foo = new Foo())
{
Assert.Catch<ArgumentNullException>(() => foo.TakesRef(null));
}
}
private class CustomDerivedFromVirtual : AbstractWithVirtualDtor
{
public override void @abstract()

5
tests/Common/Common.cpp

@ -23,6 +23,11 @@ void Foo::TakesTypedefedPtr(FooPtr date) @@ -23,6 +23,11 @@ void Foo::TakesTypedefedPtr(FooPtr date)
{
}
int Foo::TakesRef(const Foo &other)
{
return other.A;
}
bool Foo::operator ==(const Foo& other) const
{
return A == other.A && B == other.B;

1
tests/Common/Common.h

@ -59,6 +59,7 @@ public: @@ -59,6 +59,7 @@ public:
typedef Foo* FooPtr;
void TakesTypedefedPtr(FooPtr date);
int TakesRef(const Foo& other);
bool operator ==(const Foo& other) const;
};

Loading…
Cancel
Save