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

2
src/Generator/AST/Utils.cs

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

6
src/Generator/Driver.cs

@ -276,7 +276,11 @@ namespace CppSharp @@ -276,7 +276,11 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new FindSymbolsPass());
TranslationUnitPasses.AddPass(new CheckStaticClass());
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 CheckOperatorsOverloadsPass());
TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance());

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

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

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

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

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

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

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

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

7
src/Generator/Options.cs

@ -111,6 +111,13 @@ namespace CppSharp @@ -111,6 +111,13 @@ namespace CppSharp
/// try to match for matching properties.
/// </summary>
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
public List<string> NoGenIncludeDirs;

2
src/Generator/Passes/CheckAmbiguousFunctions.cs

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

59
src/Generator/Passes/CheckOperatorsOverloads.cs

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

61
src/Generator/Passes/ConstructorToConversionOperatorPass.cs

@ -0,0 +1,61 @@ @@ -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 @@ -292,6 +292,16 @@ public class BasicTests : GeneratorTestFixture
var @class = new TestGetterSetterToProperties();
Assert.That(@class.Width, Is.EqualTo(640));
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 @@ -20,7 +20,8 @@ namespace CppSharp.Tests
driver.Options.GenerateVirtualTables = true;
driver.Options.GenerateCopyConstructors = 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)

690
tests/Basic/Basic.h

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

Loading…
Cancel
Save