Browse Source

Added support for explicit conversion operators and added new pass which will create implicit and explicit conversion operators out of single argument constructors.

Conflicts:
	src/Generator/Passes/CheckAmbiguousFunctions.cs
	src/Generator/Passes/CheckOperatorsOverloads.cs
pull/234/head
Elias Holzer 11 years ago committed by triton
parent
commit
474f82b513
  1. 3
      src/AST/Method.cs
  2. 2
      src/Generator/AST/Utils.cs
  3. 6
      src/Generator/Driver.cs
  4. 8
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  5. 6
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  6. 3
      src/Generator/Generators/CLI/CLITextTemplate.cs
  7. 27
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  8. 7
      src/Generator/Options.cs
  9. 2
      src/Generator/Passes/CheckAmbiguousFunctions.cs
  10. 59
      src/Generator/Passes/CheckOperatorsOverloads.cs
  11. 61
      src/Generator/Passes/ConstructorToConversionOperatorPass.cs
  12. 10
      tests/Basic/Basic.Tests.cs
  13. 3
      tests/Basic/Basic.cs
  14. 690
      tests/Basic/Basic.h
  15. 5
      tests/CSharpTemp/CSharpTemp.cs

3
src/AST/Method.cs

@ -64,7 +64,8 @@ namespace CppSharp.AST
Call, Call,
Subscript, Subscript,
Conditional, Conditional,
Conversion Conversion,
ExplicitConversion
} }
/// <summary> /// <summary>

2
src/Generator/AST/Utils.cs

@ -200,6 +200,8 @@ namespace CppSharp.AST
case CXXOperatorKind.Conversion: case CXXOperatorKind.Conversion:
return "implicit operator"; return "implicit operator";
case CXXOperatorKind.ExplicitConversion:
return "explicit operator";
} }
throw new NotSupportedException(); throw new NotSupportedException();

6
src/Generator/Driver.cs

@ -276,7 +276,11 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new FindSymbolsPass()); TranslationUnitPasses.AddPass(new FindSymbolsPass());
TranslationUnitPasses.AddPass(new CheckStaticClass()); TranslationUnitPasses.AddPass(new CheckStaticClass());
TranslationUnitPasses.AddPass(new MoveOperatorToClassPass()); TranslationUnitPasses.AddPass(new MoveOperatorToClassPass());
TranslationUnitPasses.AddPass(new MoveFunctionToClassPass()); TranslationUnitPasses.AddPass(new MoveFunctionToClassPass());
if (Options.GenerateConversionOperators)
TranslationUnitPasses.AddPass(new ConstructorToConversionOperatorPass());
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions()); TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass()); TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass());
TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance()); TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance());

8
src/Generator/Generators/CLI/CLIHeadersTemplate.cs

@ -679,10 +679,14 @@ namespace CppSharp.Generators.CLI
Operators.IsBuiltinOperator(method.OperatorKind); Operators.IsBuiltinOperator(method.OperatorKind);
if (method.IsStatic || isBuiltinOperator) if (method.IsStatic || isBuiltinOperator)
Write("static "); Write("static ");
if (method.OperatorKind == CXXOperatorKind.ExplicitConversion)
Write("explicit ");
if (method.IsConstructor || method.IsDestructor || if (method.IsConstructor || method.IsDestructor ||
method.OperatorKind == CXXOperatorKind.Conversion) method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion)
Write("{0}(", GetMethodName(method)); Write("{0}(", GetMethodName(method));
else else
Write("{0} {1}(", method.ReturnType, method.Name); Write("{0} {1}(", method.ReturnType, method.Name);

6
src/Generator/Generators/CLI/CLISourcesTemplate.cs

@ -691,7 +691,8 @@ namespace CppSharp.Generators.CLI
PushBlock(CLIBlockKind.Method, method); PushBlock(CLIBlockKind.Method, method);
if (method.IsConstructor || method.IsDestructor || if (method.IsConstructor || method.IsDestructor ||
method.OperatorKind == CXXOperatorKind.Conversion) method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion)
Write("{0}::{1}(", QualifiedIdentifier(@class), GetMethodName(method)); Write("{0}::{1}(", QualifiedIdentifier(@class), GetMethodName(method));
else else
Write("{0} {1}::{2}(", method.ReturnType, QualifiedIdentifier(@class), Write("{0} {1}::{2}(", method.ReturnType, QualifiedIdentifier(@class),
@ -865,7 +866,8 @@ namespace CppSharp.Generators.CLI
Write("auto {0}{1} = ",(function.ReturnType.Type.IsReference())? "&": string.Empty, Write("auto {0}{1} = ",(function.ReturnType.Type.IsReference())? "&": string.Empty,
Generator.GeneratedIdentifier("ret")); Generator.GeneratedIdentifier("ret"));
if (function.OperatorKind == CXXOperatorKind.Conversion) if (function.OperatorKind == CXXOperatorKind.Conversion ||
function.OperatorKind == CXXOperatorKind.ExplicitConversion)
{ {
var method = function as Method; var method = function as Method;
var typePrinter = new CppTypePrinter(Driver.TypeDatabase); var typePrinter = new CppTypePrinter(Driver.TypeDatabase);

3
src/Generator/Generators/CLI/CLITextTemplate.cs

@ -96,7 +96,8 @@ namespace CppSharp.Generators.CLI
public string GetMethodName(Method method) public string GetMethodName(Method method)
{ {
if (method.OperatorKind == CXXOperatorKind.Conversion) if (method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion)
return "operator " + method.ConversionType; return "operator " + method.ConversionType;
if (method.IsConstructor || method.IsDestructor) if (method.IsConstructor || method.IsDestructor)

27
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -2033,7 +2033,8 @@ namespace CppSharp.Generators.CSharp
else if (method.ExplicitInterfaceImpl != null) else if (method.ExplicitInterfaceImpl != null)
Write("{0} {1}.{2}(", method.OriginalReturnType, Write("{0} {1}.{2}(", method.OriginalReturnType,
method.ExplicitInterfaceImpl.Name, functionName); method.ExplicitInterfaceImpl.Name, functionName);
else if (method.OperatorKind == CXXOperatorKind.Conversion) else if (method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion)
Write("{0} {1}(", functionName, method.OriginalReturnType); Write("{0} {1}(", functionName, method.OriginalReturnType);
else else
Write("{0} {1}(", method.OriginalReturnType, functionName); Write("{0} {1}(", method.OriginalReturnType, functionName);
@ -2156,11 +2157,25 @@ namespace CppSharp.Generators.CSharp
private void GenerateOperator(Method method, Class @class) private void GenerateOperator(Method method, Class @class)
{ {
if (method.IsSynthetized) if (method.IsSynthetized)
{ {
var @operator = Operators.GetOperatorOverloadPair(method.OperatorKind); if (method.Kind == CXXMethodKind.Conversion)
{
WriteLine("return !({0} {1} {2});", method.Parameters[0].Name, // To avoid ambiguity when having the multiple inheritance pass enabled
@operator, method.Parameters[1].Name); var @interface = @class.Namespace.Classes.Find(c => c.OriginalClass == @class);
if (@interface != null)
WriteLine("return new {0}(({2}){1});", method.ConversionType,
method.Parameters[0].Name, @interface.Name);
else
WriteLine("return new {0}({1});", method.ConversionType,
method.Parameters[0].Name);
}
else
{
var @operator = Operators.GetOperatorOverloadPair(method.OperatorKind);
WriteLine("return !({0} {1} {2});", method.Parameters[0].Name,
@operator, method.Parameters[1].Name);
}
return; return;
} }

7
src/Generator/Options.cs

@ -111,6 +111,13 @@ namespace CppSharp
/// try to match for matching properties. /// try to match for matching properties.
/// </summary> /// </summary>
public bool GeneratePropertiesAdvanced; public bool GeneratePropertiesAdvanced;
/// <summary>
/// If set to true the generator will use ConstructorToConversionOperatorPass to
/// create implicit and explicit conversion operators out of single argument
/// constructors.
/// </summary>
public bool GenerateConversionOperators;
//List of include directories that are used but not generated //List of include directories that are used but not generated
public List<string> NoGenIncludeDirs; public List<string> NoGenIncludeDirs;

2
src/Generator/Passes/CheckAmbiguousFunctions.cs

@ -37,6 +37,8 @@ namespace CppSharp.Passes
{ {
if (function.OperatorKind == CXXOperatorKind.Conversion) if (function.OperatorKind == CXXOperatorKind.Conversion)
continue; continue;
if (function.OperatorKind == CXXOperatorKind.ExplicitConversion)
continue;
if (overload == function) continue; if (overload == function) continue;

59
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -170,35 +170,36 @@ namespace CppSharp.Passes
index = @class.Methods.IndexOf(second); index = @class.Methods.IndexOf(second);
return op1; return op1;
} }
index = 0; index = 0;
return CXXOperatorKind.None; return CXXOperatorKind.None;
} }
static bool IsValidOperatorOverload(Method @operator) static bool IsValidOperatorOverload(Method @operator)
{ {
// These follow the order described in MSDN (Overloadable Operators). // These follow the order described in MSDN (Overloadable Operators).
switch (@operator.OperatorKind) switch (@operator.OperatorKind)
{ {
// These unary operators can be overloaded // These unary operators can be overloaded
case CXXOperatorKind.Plus: case CXXOperatorKind.Plus:
case CXXOperatorKind.Minus: case CXXOperatorKind.Minus:
case CXXOperatorKind.Exclaim: case CXXOperatorKind.Exclaim:
case CXXOperatorKind.Tilde: case CXXOperatorKind.Tilde:
// These binary operators can be overloaded // These binary operators can be overloaded
case CXXOperatorKind.Slash: case CXXOperatorKind.Slash:
case CXXOperatorKind.Percent: case CXXOperatorKind.Percent:
case CXXOperatorKind.Amp: case CXXOperatorKind.Amp:
case CXXOperatorKind.Pipe: case CXXOperatorKind.Pipe:
case CXXOperatorKind.Caret: case CXXOperatorKind.Caret:
// The array indexing operator can be overloaded // The array indexing operator can be overloaded
case CXXOperatorKind.Subscript: case CXXOperatorKind.Subscript:
// The conversion operator can be overloaded // The conversion operators can be overloaded
case CXXOperatorKind.Conversion: case CXXOperatorKind.Conversion:
case CXXOperatorKind.ExplicitConversion:
return true; return true;
// The comparison operators can be overloaded if their return type is bool // The comparison operators can be overloaded if their return type is bool

61
src/Generator/Passes/ConstructorToConversionOperatorPass.cs

@ -0,0 +1,61 @@
using System.Linq;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators;
namespace CppSharp.Passes
{
/// <summary>
/// This pass will create conversion operators out of single argument
/// constructors.
/// </summary>
public class ConstructorToConversionOperatorPass : TranslationUnitPass
{
public override bool VisitMethodDecl(Method method)
{
if (!method.IsConstructor)
return false;
if (method.IsCopyConstructor)
return false;
if (method.Parameters.Count != 1)
return false;
var parameter = method.Parameters[0];
var parameterType = parameter.Type as PointerType;
if (parameterType == null)
return false;
if (!parameterType.IsReference)
return false;
var qualifiedPointee = parameterType.QualifiedPointee;
if (!qualifiedPointee.Qualifiers.IsConst)
return false;
Class castFromClass;
if (!qualifiedPointee.Type.IsTagDecl(out castFromClass))
return false;
var castToClass = method.OriginalNamespace as Class;
if (castToClass == null)
return false;
if (castFromClass == castToClass)
return false;
var operatorKind = CXXOperatorKind.Conversion;
if (method.Signature.StartsWith("explicit", System.StringComparison.OrdinalIgnoreCase))
operatorKind = CXXOperatorKind.ExplicitConversion;
var castToType = new TagType(castToClass);
var qualifiedCastToType = new QualifiedType(castToType);
var conversionOperator = new Method()
{
Name = Operators.GetOperatorIdentifier(operatorKind),
Namespace = castFromClass,
Kind = CXXMethodKind.Conversion,
IsSynthetized = true,
ConversionType = qualifiedCastToType,
ReturnType = qualifiedCastToType
};
conversionOperator.OperatorKind = operatorKind;
castFromClass.Methods.Add(conversionOperator);
return true;
}
}
}

10
tests/Basic/Basic.Tests.cs

@ -292,6 +292,16 @@ public class BasicTests : GeneratorTestFixture
var @class = new TestGetterSetterToProperties(); var @class = new TestGetterSetterToProperties();
Assert.That(@class.Width, Is.EqualTo(640)); Assert.That(@class.Width, Is.EqualTo(640));
Assert.That(@class.Height, Is.EqualTo(480)); Assert.That(@class.Height, Is.EqualTo(480));
}
[Test]
public unsafe void TestSingleArgumentCtorToCastOperator()
{
var classA = new ClassA(10);
ClassB classB = classA;
Assert.AreEqual(classA.Value, classB.Value);
ClassC classC = (ClassC)classB;
Assert.AreEqual(classB.Value, classC.Value);
} }
} }

3
tests/Basic/Basic.cs

@ -20,7 +20,8 @@ namespace CppSharp.Tests
driver.Options.GenerateVirtualTables = true; driver.Options.GenerateVirtualTables = true;
driver.Options.GenerateCopyConstructors = true; driver.Options.GenerateCopyConstructors = true;
driver.Options.MarshalCharAsManagedChar = true; driver.Options.MarshalCharAsManagedChar = true;
driver.Options.GenerateProperties = true; driver.Options.GenerateProperties = true;
driver.Options.GenerateConversionOperators = true;
} }
public override void Preprocess(Driver driver, ASTContext ctx) public override void Preprocess(Driver driver, ASTContext ctx)

690
tests/Basic/Basic.h

@ -1,324 +1,324 @@
#include "../Tests.h" #include "../Tests.h"
class DLL_API Foo class DLL_API Foo
{ {
public: public:
Foo(); Foo();
int A; int A;
float B; float B;
const char* GetANSI(); const char* GetANSI();
// TODO: VC++ does not support char16 // TODO: VC++ does not support char16
// char16 chr16; // char16 chr16;
// Not properly handled yet - ignore // Not properly handled yet - ignore
float nested_array[2][2]; float nested_array[2][2];
// Primitive pointer types // Primitive pointer types
const int* SomePointer; const int* SomePointer;
const int** SomePointerPointer; const int** SomePointerPointer;
}; };
struct DLL_API Bar struct DLL_API Bar
{ {
enum Item enum Item
{ {
Item1, Item1,
Item2 Item2
}; };
Bar(); Bar();
Item RetItem1(); Item RetItem1();
int A; int A;
float B; float B;
Bar* returnPointerToValueType(); Bar* returnPointerToValueType();
}; };
class DLL_API Foo2 : public Foo class DLL_API Foo2 : public Foo
{ {
struct Copy { struct Copy {
Foo A; Foo A;
}* copy; }* copy;
public: public:
Foo2(); Foo2();
int C; int C;
Foo2 operator<<(signed int i); Foo2 operator<<(signed int i);
Foo2 operator<<(signed long l); Foo2 operator<<(signed long l);
Bar valueTypeField; Bar valueTypeField;
char testCharMarshalling(char c); char testCharMarshalling(char c);
}; };
DLL_API Bar::Item operator |(Bar::Item left, Bar::Item right); DLL_API Bar::Item operator |(Bar::Item left, Bar::Item right);
struct DLL_API Bar2 : public Bar struct DLL_API Bar2 : public Bar
{ {
// Conversion operators // Conversion operators
struct DLL_API Nested struct DLL_API Nested
{ {
operator int() const; operator int() const;
}; };
operator int() const; operator int() const;
operator Foo2(); operator Foo2();
Foo2 needFixedInstance() const; Foo2 needFixedInstance() const;
typedef void *Bar2::*FunctionPointerResolvedAsVoidStar; typedef void *Bar2::*FunctionPointerResolvedAsVoidStar;
operator FunctionPointerResolvedAsVoidStar() const { return 0; } operator FunctionPointerResolvedAsVoidStar() const { return 0; }
int C; int C;
Bar* pointerToStruct; Bar* pointerToStruct;
int* pointerToPrimitive; int* pointerToPrimitive;
Foo2* pointerToClass; Foo2* pointerToClass;
Bar valueStruct; Bar valueStruct;
}; };
enum Enum enum Enum
{ {
A = 0, B = 2, C = 5, A = 0, B = 2, C = 5,
//D = 0x80000000, //D = 0x80000000,
E = 0x1, E = 0x1,
F = -9 F = -9
}; };
class DLL_API Hello class DLL_API Hello
{ {
union NestedPrivate { union NestedPrivate {
int i; int i;
float f; float f;
}; };
public: public:
union NestedPublic { union NestedPublic {
int j; int j;
float g; float g;
long l; long l;
}; };
Hello (); Hello ();
Hello(const Hello& hello); Hello(const Hello& hello);
void PrintHello(const char* s); void PrintHello(const char* s);
bool test1(int i, float f); bool test1(int i, float f);
int add(int a, int b); int add(int a, int b);
int AddFoo(Foo); int AddFoo(Foo);
int AddFooRef(Foo&); int AddFooRef(Foo&);
int AddFooPtr(Foo*); int AddFooPtr(Foo*);
int AddFooPtrRef(Foo*&); int AddFooPtrRef(Foo*&);
Foo RetFoo(int a, float b); Foo RetFoo(int a, float b);
int AddFoo2(Foo2); int AddFoo2(Foo2);
int AddBar(Bar); int AddBar(Bar);
int AddBar2(Bar2); int AddBar2(Bar2);
int RetEnum(Enum); int RetEnum(Enum);
Hello* RetNull(); Hello* RetNull();
bool TestPrimitiveOut(CS_OUT float* f); bool TestPrimitiveOut(CS_OUT float* f);
bool TestPrimitiveOutRef(CS_OUT float& f); bool TestPrimitiveOutRef(CS_OUT float& f);
}; };
class DLL_API AbstractFoo class DLL_API AbstractFoo
{ {
public: public:
virtual int pureFunction(int i) = 0; virtual int pureFunction(int i) = 0;
virtual int pureFunction1() = 0; virtual int pureFunction1() = 0;
virtual int pureFunction2() = 0; virtual int pureFunction2() = 0;
}; };
class DLL_API ImplementsAbstractFoo : public AbstractFoo class DLL_API ImplementsAbstractFoo : public AbstractFoo
{ {
public: public:
virtual int pureFunction(int i); virtual int pureFunction(int i);
virtual int pureFunction1(); virtual int pureFunction1();
virtual int pureFunction2(); virtual int pureFunction2();
}; };
class DLL_API ReturnsAbstractFoo class DLL_API ReturnsAbstractFoo
{ {
public: public:
ReturnsAbstractFoo(); ReturnsAbstractFoo();
const AbstractFoo& getFoo(); const AbstractFoo& getFoo();
private: private:
ImplementsAbstractFoo i; ImplementsAbstractFoo i;
}; };
int DLL_API unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)); int DLL_API unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int));
DLL_API Bar indirectReturn(); DLL_API Bar indirectReturn();
// Tests CheckVirtualOverrideReturnCovariance // Tests CheckVirtualOverrideReturnCovariance
struct Exception; struct Exception;
typedef Exception Ex1; typedef Exception Ex1;
struct DerivedException; struct DerivedException;
typedef DerivedException Ex2; typedef DerivedException Ex2;
struct DLL_API Exception struct DLL_API Exception
{ {
virtual Ex1* clone() = 0; virtual Ex1* clone() = 0;
}; };
struct DLL_API DerivedException : public Exception struct DLL_API DerivedException : public Exception
{ {
virtual Ex2* clone() override { return 0; } virtual Ex2* clone() override { return 0; }
}; };
// Tests for ambiguous call to native functions with default parameters // Tests for ambiguous call to native functions with default parameters
struct DLL_API DefaultParameters struct DLL_API DefaultParameters
{ {
void Foo(int a, int b = 0); void Foo(int a, int b = 0);
void Foo(int a); void Foo(int a);
void Bar() const; void Bar() const;
void Bar(); void Bar();
}; };
// The Curiously Recurring Template Pattern (CRTP) // The Curiously Recurring Template Pattern (CRTP)
template<class Derived> template<class Derived>
class Base class Base
{ {
// methods within Base can use template to access members of Derived // methods within Base can use template to access members of Derived
Derived* create() { return new Derived(); } Derived* create() { return new Derived(); }
}; };
class Derived : public Base<Derived> class Derived : public Base<Derived>
{ {
}; };
// Tests the MoveFunctionToClassPass // Tests the MoveFunctionToClassPass
class DLL_API basic class DLL_API basic
{ {
}; };
DLL_API int test(basic& s); DLL_API int test(basic& s);
// Tests the MoveOperatorToClassPass // Tests the MoveOperatorToClassPass
struct DLL_API TestMoveOperatorToClass struct DLL_API TestMoveOperatorToClass
{ {
TestMoveOperatorToClass(); TestMoveOperatorToClass();
int A; int A;
int B; int B;
}; };
TestMoveOperatorToClass::TestMoveOperatorToClass() {} TestMoveOperatorToClass::TestMoveOperatorToClass() {}
DLL_API int operator *(TestMoveOperatorToClass klass, int b) DLL_API int operator *(TestMoveOperatorToClass klass, int b)
{ {
return klass.A * b; return klass.A * b;
} }
DLL_API TestMoveOperatorToClass operator-(const TestMoveOperatorToClass& b) DLL_API TestMoveOperatorToClass operator-(const TestMoveOperatorToClass& b)
{ {
TestMoveOperatorToClass nb; TestMoveOperatorToClass nb;
nb.A = -b.A; nb.A = -b.A;
nb.B = -b.B; nb.B = -b.B;
return nb; return nb;
} }
DLL_API TestMoveOperatorToClass operator+(const TestMoveOperatorToClass& b1, DLL_API TestMoveOperatorToClass operator+(const TestMoveOperatorToClass& b1,
const TestMoveOperatorToClass& b2) const TestMoveOperatorToClass& b2)
{ {
TestMoveOperatorToClass b; TestMoveOperatorToClass b;
b.A = b1.A + b2.A; b.A = b1.A + b2.A;
b.B = b1.B + b2.B; b.B = b1.B + b2.B;
return b; return b;
} }
// Not a valid operator overload for Foo2 in managed code - comparison operators need to return bool. // Not a valid operator overload for Foo2 in managed code - comparison operators need to return bool.
DLL_API int operator==(const Foo2& a, const Foo2& b) DLL_API int operator==(const Foo2& a, const Foo2& b)
{ {
return 0; return 0;
} }
// Tests delegates // Tests delegates
typedef int (*DelegateInGlobalNamespace)(int); typedef int (*DelegateInGlobalNamespace)(int);
struct DLL_API TestDelegates struct DLL_API TestDelegates
{ {
typedef int (*DelegateInClass)(int); typedef int (*DelegateInClass)(int);
typedef int(TestDelegates::*MemberDelegate)(int); typedef int(TestDelegates::*MemberDelegate)(int);
TestDelegates(); TestDelegates();
static int Double(int N) { return N * 2; } static int Double(int N) { return N * 2; }
int Triple(int N) { return N * 3; } int Triple(int N) { return N * 3; }
DelegateInClass A; DelegateInClass A;
DelegateInGlobalNamespace B; DelegateInGlobalNamespace B;
// As long as we can't marshal them make sure they're ignored // As long as we can't marshal them make sure they're ignored
MemberDelegate C; MemberDelegate C;
}; };
TestDelegates::TestDelegates() : A(Double), B(Double), C(&TestDelegates::Triple) TestDelegates::TestDelegates() : A(Double), B(Double), C(&TestDelegates::Triple)
{ {
} }
// Tests delegate generation for attributed function types // Tests delegate generation for attributed function types
typedef int(__cdecl *AttributedDelegate)(int n); typedef int(__cdecl *AttributedDelegate)(int n);
DLL_API int __cdecl Double(int n) { return n * 2; } DLL_API int __cdecl Double(int n) { return n * 2; }
DLL_API AttributedDelegate GetAttributedDelegate() DLL_API AttributedDelegate GetAttributedDelegate()
{ {
return Double; return Double;
} }
// Tests memory leaks in constructors // Tests memory leaks in constructors
// C#: Marshal.FreeHGlobal(arg0); // C#: Marshal.FreeHGlobal(arg0);
struct DLL_API TestMemoryLeaks struct DLL_API TestMemoryLeaks
{ {
TestMemoryLeaks(const char* name) {} TestMemoryLeaks(const char* name) {}
}; };
// Tests that finalizers are generated // Tests that finalizers are generated
/* CLI: ~TestFinalizers() */ /* CLI: ~TestFinalizers() */
struct DLL_API TestFinalizers struct DLL_API TestFinalizers
{ {
}; };
// Tests static classes // Tests static classes
struct DLL_API TestStaticClass struct DLL_API TestStaticClass
{ {
static int Add(int a, int b); static int Add(int a, int b);
private: private:
TestStaticClass(); TestStaticClass();
}; };
int TestStaticClass::Add(int a, int b) { return a + b; } int TestStaticClass::Add(int a, int b) { return a + b; }
class HasIgnoredField class HasIgnoredField
{ {
Base<Derived> fieldOfIgnoredType; Base<Derived> fieldOfIgnoredType;
}; };
template <typename T> template <typename T>
class DependentTypeWithNestedIndependent class DependentTypeWithNestedIndependent
{ {
union union
{ {
int i; int i;
long l; long l;
}; };
}; };
class DLL_API TestCopyConstructorRef class DLL_API TestCopyConstructorRef
{ {
public: public:
TestCopyConstructorRef(); TestCopyConstructorRef();
TestCopyConstructorRef(const TestCopyConstructorRef& other); TestCopyConstructorRef(const TestCopyConstructorRef& other);
int A; int A;
float B; float B;
}; };
TestCopyConstructorRef::TestCopyConstructorRef() TestCopyConstructorRef::TestCopyConstructorRef()
{ {
} }
@ -327,13 +327,13 @@ TestCopyConstructorRef::TestCopyConstructorRef(const TestCopyConstructorRef& oth
{ {
A = other.A; A = other.A;
B = other.B; B = other.B;
} }
template <class T> template <class T>
struct EmptyNamedNestedEnum struct EmptyNamedNestedEnum
{ {
enum { Value = 10 }; enum { Value = 10 };
}; };
typedef unsigned long foo_t; typedef unsigned long foo_t;
typedef struct DLL_API SomeStruct typedef struct DLL_API SomeStruct
@ -362,30 +362,30 @@ namespace SomeNamespace
virtual void AbstractMethod() = 0; virtual void AbstractMethod() = 0;
}; };
} }
// Test operator overloads // Test operator overloads
class DLL_API ClassWithOverloadedOperators class DLL_API ClassWithOverloadedOperators
{ {
public: public:
ClassWithOverloadedOperators(); ClassWithOverloadedOperators();
operator char(); operator char();
operator int(); operator int();
operator short(); operator short();
}; };
ClassWithOverloadedOperators::ClassWithOverloadedOperators() {} ClassWithOverloadedOperators::ClassWithOverloadedOperators() {}
ClassWithOverloadedOperators::operator char() { return 1; } ClassWithOverloadedOperators::operator char() { return 1; }
ClassWithOverloadedOperators::operator int() { return 2; } ClassWithOverloadedOperators::operator int() { return 2; }
ClassWithOverloadedOperators::operator short() { return 3; } ClassWithOverloadedOperators::operator short() { return 3; }
// Tests global static function generation // Tests global static function generation
DLL_API int Function() DLL_API int Function()
{ {
return 5; return 5;
} }
// Tests properties // Tests properties
struct DLL_API TestProperties struct DLL_API TestProperties
{ {
TestProperties(); TestProperties();
@ -418,7 +418,35 @@ struct DLL_API TestGetterSetterToProperties
{ {
int getWidth(); int getWidth();
int getHeight(); int getHeight();
}; };
int TestGetterSetterToProperties::getWidth() { return 640; } int TestGetterSetterToProperties::getWidth() { return 640; }
int TestGetterSetterToProperties::getHeight() { return 480; } int TestGetterSetterToProperties::getHeight() { return 480; }
// Tests conversion operators of classes
class DLL_API ClassA
{
public:
ClassA(int value) { Value = value; }
int Value;
};
class DLL_API ClassB
{
public:
// conversion from ClassA (constructor):
ClassB(const ClassA& x) { Value = x.Value; }
int Value;
// conversion from ClassA (assignment):
//ClassB& operator= (const ClassA& x) { return *this; }
// conversion to ClassA (type-cast operator)
//operator ClassA() { return ClassA(); }
};
class DLL_API ClassC
{
public:
// This should NOT lead to a conversion
ClassC(const ClassA* x) { Value = x->Value; }
// This should lead to an explicit conversion
explicit ClassC(const ClassB& x) { Value = x.Value; }
int Value;
};

5
tests/CSharpTemp/CSharpTemp.cs

@ -62,7 +62,10 @@ namespace CppSharp.Tests
driver.Options.GenerateInterfacesForMultipleInheritance = true; driver.Options.GenerateInterfacesForMultipleInheritance = true;
driver.Options.GeneratePropertiesAdvanced = true; driver.Options.GeneratePropertiesAdvanced = true;
driver.Options.GenerateVirtualTables = true; driver.Options.GenerateVirtualTables = true;
driver.Options.GenerateCopyConstructors = true; driver.Options.GenerateCopyConstructors = true;
// To ensure that calls to constructors in conversion operators
// are not ambiguous with multiple inheritance pass enabled.
driver.Options.GenerateConversionOperators = true;
driver.TranslationUnitPasses.AddPass(new TestAttributesPass()); driver.TranslationUnitPasses.AddPass(new TestAttributesPass());
} }

Loading…
Cancel
Save