Browse Source

Merge pull request #233 from azeno/property-improvements

Improved support for indexed properties
pull/232/merge
João Matos 12 years ago
parent
commit
4c9a1f5998
  1. 12
      src/AST/Property.cs
  2. 15
      src/Generator.Tests/Passes/TestPasses.cs
  3. 30
      src/Generator/Generators/CLI/CLIMarshal.cs
  4. 62
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  5. 66
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  6. 3
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  7. 20
      src/Generator/Library.cs
  8. 27
      src/Generator/Passes/CheckOperatorsOverloads.cs
  9. 2
      src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs
  10. 3
      src/Generator/Passes/GetterSetterToPropertyPass.cs
  11. 6
      src/Generator/Types/CppTypePrinter.cs
  12. 22
      tests/Basic/Basic.Tests.cs
  13. 36
      tests/Basic/Basic.h
  14. 7
      tests/Native/Passes.h

12
src/AST/Property.cs

@ -72,7 +72,10 @@ namespace CppSharp.AST
{ {
get get
{ {
return (GetMethod != null) || (Field != null); return (GetMethod != null &&
GetMethod.GenerationKind != GenerationKind.None) ||
(Field != null &&
Field.GenerationKind != GenerationKind.None);
} }
} }
@ -80,8 +83,11 @@ namespace CppSharp.AST
{ {
get get
{ {
return (SetMethod != null) || return (SetMethod != null &&
(Field != null && !Field.QualifiedType.Qualifiers.IsConst); SetMethod.GenerationKind != GenerationKind.None) ||
(Field != null &&
!Field.QualifiedType.Qualifiers.IsConst &&
Field.GenerationKind != GenerationKind.None);
} }
} }

15
src/Generator.Tests/Passes/TestPasses.cs

@ -108,5 +108,20 @@ namespace CppSharp.Generator.Tests.Passes
Assert.IsFalse(AstContext.FindClass("Foo").First().Methods.Find( Assert.IsFalse(AstContext.FindClass("Foo").First().Methods.Find(
m => m.Name == "toIgnore").IsGenerated); m => m.Name == "toIgnore").IsGenerated);
} }
[Test]
public void TestSetPropertyAsReadOnly()
{
const string className = "TestReadOnlyProperties";
passBuilder.AddPass(new FieldToPropertyPass());
passBuilder.AddPass(new GetterSetterToPropertyPass());
passBuilder.RunPasses(pass => pass.VisitLibrary(AstContext));
AstContext.SetPropertyAsReadOnly(className, "readOnlyProperty");
Assert.IsFalse(AstContext.FindClass(className).First().Properties.Find(
m => m.Name == "readOnlyProperty").HasSetter);
AstContext.SetPropertyAsReadOnly(className, "ReadOnlyPropertyMethod");
Assert.IsFalse(AstContext.FindClass(className).First().Properties.Find(
m => m.Name == "ReadOnlyPropertyMethod").HasSetter);
}
} }
} }

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

@ -93,11 +93,31 @@ namespace CppSharp.Generators.CLI
{ {
var returnVarName = Context.ReturnVarName; var returnVarName = Context.ReturnVarName;
if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst) if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst)
returnVarName = string.Format("const_cast<{0}>({1})", {
Context.ReturnType, Context.ReturnVarName); var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase, false);
if (pointer.Pointee is TypedefType) var constlessPointer = new PointerType()
Context.Return.Write("reinterpret_cast<{0}>({1})", pointer, {
returnVarName); IsDependent = pointer.IsDependent,
Modifier = pointer.Modifier,
QualifiedPointee = new QualifiedType(Context.ReturnType.Type.GetPointee())
};
var nativeConstlessTypeName = constlessPointer.Visit(nativeTypePrinter, new TypeQualifiers());
returnVarName = string.Format("const_cast<{0}>({1})",
nativeConstlessTypeName, Context.ReturnVarName);
}
if (pointer.Pointee is TypedefType)
{
var desugaredPointer = new PointerType()
{
IsDependent = pointer.IsDependent,
Modifier = pointer.Modifier,
QualifiedPointee = new QualifiedType(pointee)
};
var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase);
var nativeTypeName = desugaredPointer.Visit(nativeTypePrinter, quals);
Context.Return.Write("reinterpret_cast<{0}>({1})", nativeTypeName,
returnVarName);
}
else else
Context.Return.Write(returnVarName); Context.Return.Write(returnVarName);
return true; return true;

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

@ -372,16 +372,16 @@ namespace CppSharp.Generators.CLI
return; return;
} }
var param = new Parameter var param = new Parameter
{ {
Name = "value", Name = "value",
QualifiedType = decl.QualifiedType QualifiedType = new QualifiedType(type)
}; };
var ctx = new MarshalContext(Driver) var ctx = new MarshalContext(Driver)
{ {
Parameter = param, Parameter = param,
ArgName = param.Name, ArgName = param.Name,
}; };
var marshal = new CLIMarshalManagedToNativePrinter(ctx); var marshal = new CLIMarshalManagedToNativePrinter(ctx);
param.Visit(marshal); param.Visit(marshal);
@ -400,7 +400,10 @@ namespace CppSharp.Generators.CLI
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore); Write(marshal.Context.SupportBefore);
WriteLine("{0} = {1};", variable, marshal.Context.Return); if (isIndexer && decl.Type.IsPointer())
WriteLine("*({0}) = {1};", variable, marshal.Context.Return);
else
WriteLine("{0} = {1};", variable, marshal.Context.Return);
} }
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -432,7 +435,10 @@ namespace CppSharp.Generators.CLI
if (decl is Function) if (decl is Function)
{ {
var func = decl as Function; var func = decl as Function;
GenerateFunctionCall(func, @class); if (isIndexer && func.Type.IsAddress())
GenerateFunctionCall(func, @class, type);
else
GenerateFunctionCall(func, @class);
} }
else else
{ {
@ -832,11 +838,13 @@ namespace CppSharp.Generators.CLI
WriteCloseBraceIndent(); WriteCloseBraceIndent();
} }
public void GenerateFunctionCall(Function function, Class @class = null) public void GenerateFunctionCall(Function function, Class @class = null, Type publicRetType = null)
{ {
CheckArgumentRange(function); CheckArgumentRange(function);
var retType = function.ReturnType; var retType = function.ReturnType;
if (publicRetType == null)
publicRetType = retType.Type;
var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void); var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void);
const string valueMarshalName = "_this0"; const string valueMarshalName = "_this0";
@ -861,9 +869,12 @@ namespace CppSharp.Generators.CLI
var @params = GenerateFunctionParamsMarshal(function.Parameters, function); var @params = GenerateFunctionParamsMarshal(function.Parameters, function);
var returnIdentifier = Generator.GeneratedIdentifier("ret");
if (needsReturn) if (needsReturn)
Write("auto {0}{1} = ",(function.ReturnType.Type.IsReference())? "&": string.Empty, if (retType.Type.IsReference())
Generator.GeneratedIdentifier("ret")); Write("auto &{0} = ", returnIdentifier);
else
Write("auto {0} = ", returnIdentifier);
if (function.OperatorKind == CXXOperatorKind.Conversion || if (function.OperatorKind == CXXOperatorKind.Conversion ||
function.OperatorKind == CXXOperatorKind.ExplicitConversion) function.OperatorKind == CXXOperatorKind.ExplicitConversion)
@ -944,24 +955,33 @@ namespace CppSharp.Generators.CLI
if (retType.Type.IsPointer() && (isIntPtr || retTypeName.EndsWith("^"))) if (retType.Type.IsPointer() && (isIntPtr || retTypeName.EndsWith("^")))
{ {
WriteLine("if ({0} == nullptr) return {1};", WriteLine("if ({0} == nullptr) return {1};",
Generator.GeneratedIdentifier("ret"), returnIdentifier,
isIntPtr ? "System::IntPtr()" : "nullptr"); isIntPtr ? "System::IntPtr()" : "nullptr");
} }
var ctx = new MarshalContext(Driver) var ctx = new MarshalContext(Driver)
{ {
ArgName = Generator.GeneratedIdentifier("ret"), ArgName = returnIdentifier,
ReturnVarName = Generator.GeneratedIdentifier("ret"), ReturnVarName = returnIdentifier,
ReturnType = retType ReturnType = retType
}; };
var marshal = new CLIMarshalNativeToManagedPrinter(ctx); var marshal = new CLIMarshalNativeToManagedPrinter(ctx);
function.ReturnType.Visit(marshal); retType.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore); Write(marshal.Context.SupportBefore);
WriteLine("return {0};", marshal.Context.Return); // Special case for indexer - needs to dereference if the internal
// function is a pointer type and the property is not.
if (retType.Type.IsPointer() &&
retType.Type.GetPointee().Equals(publicRetType) &&
publicRetType.IsPrimitiveType())
WriteLine("return *({0});", marshal.Context.Return);
else if (retType.Type.IsReference() && publicRetType.IsReference())
WriteLine("return ({0})({1});", publicRetType, marshal.Context.Return);
else
WriteLine("return {0};", marshal.Context.Return);
} }
} }

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

@ -965,8 +965,8 @@ namespace CppSharp.Generators.CSharp
private void GenerateIndexerSetter(QualifiedType returnType, Function function) private void GenerateIndexerSetter(QualifiedType returnType, Function function)
{ {
Type type; Type type;
returnType.Type.IsPointerTo(out type); function.Type.IsPointerTo(out type);
PrimitiveType primitiveType; PrimitiveType primitiveType;
string internalFunction = GetFunctionNativeIdentifier(function); string internalFunction = GetFunctionNativeIdentifier(function);
if (type.IsPrimitiveType(out primitiveType)) if (type.IsPrimitiveType(out primitiveType))
@ -982,7 +982,7 @@ namespace CppSharp.Generators.CSharp
} }
} }
private void GeneratePropertyGetter<T>(T decl, Class @class) private void GeneratePropertyGetter<T>(QualifiedType returnType, T decl, Class @class)
where T : Declaration, ITypedDecl where T : Declaration, ITypedDecl
{ {
PushBlock(CSharpBlockKind.Method); PushBlock(CSharpBlockKind.Method);
@ -1002,19 +1002,9 @@ namespace CppSharp.Generators.CSharp
WriteStartBraceIndent(); WriteStartBraceIndent();
var method = function as Method; var method = function as Method;
if (method != null && method.IsOverride && method.IsSynthetized) if (method != null && method.IsOverride && method.IsSynthetized)
{
GenerateVirtualTableFunctionCall(method, @class); GenerateVirtualTableFunctionCall(method, @class);
}
else else
{ GenerateInternalFunctionCall(function, function.Parameters, returnType.Type);
bool isPrimitiveIndexer = function.OperatorKind == CXXOperatorKind.Subscript &&
function.ReturnType.Type.IsPointerToPrimitiveType();
if (isPrimitiveIndexer)
TypePrinter.PushContext(CSharpTypePrinterContextKind.PrimitiveIndexer);
GenerateInternalFunctionCall(function);
if (isPrimitiveIndexer)
TypePrinter.PopContext();
}
} }
else if (decl is Field) else if (decl is Field)
{ {
@ -1183,12 +1173,6 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.Property); PushBlock(CSharpBlockKind.Property);
// If this is an indexer that returns an address use the real type
// because there is a setter anyway.
var type = prop.Type;
if (prop.Parameters.Count > 0 && prop.Type.IsPointerToPrimitiveType())
type = ((PointerType) prop.Type).Pointee;
ArrayType arrayType = prop.Type as ArrayType; ArrayType arrayType = prop.Type as ArrayType;
if (arrayType != null && arrayType.Type.IsPointerToPrimitiveType() && prop.Field != null) if (arrayType != null && arrayType.Type.IsPointerToPrimitiveType() && prop.Field != null)
{ {
@ -1212,11 +1196,11 @@ namespace CppSharp.Generators.CSharp
else if (prop.IsVirtual) else if (prop.IsVirtual)
Write("virtual "); Write("virtual ");
WriteLine("{0} {1}", type, GetPropertyName(prop)); WriteLine("{0} {1}", prop.Type, GetPropertyName(prop));
} }
else else
{ {
WriteLine("{0} {1}.{2}", type, prop.ExplicitInterfaceImpl.Name, WriteLine("{0} {1}.{2}", prop.Type, prop.ExplicitInterfaceImpl.Name,
GetPropertyName(prop)); GetPropertyName(prop));
} }
WriteStartBraceIndent(); WriteStartBraceIndent();
@ -1224,7 +1208,7 @@ namespace CppSharp.Generators.CSharp
if (prop.Field != null) if (prop.Field != null)
{ {
if (prop.HasGetter) if (prop.HasGetter)
GeneratePropertyGetter(prop.Field, @class); GeneratePropertyGetter(prop.QualifiedType, prop.Field, @class);
if (prop.HasSetter) if (prop.HasSetter)
GeneratePropertySetter(prop.Field.QualifiedType, prop.Field, GeneratePropertySetter(prop.Field.QualifiedType, prop.Field,
@ -1232,13 +1216,11 @@ namespace CppSharp.Generators.CSharp
} }
else else
{ {
if (prop.HasGetter) if (prop.HasGetter)
GeneratePropertyGetter(prop.GetMethod, @class); GeneratePropertyGetter(prop.QualifiedType, prop.GetMethod, @class);
if (prop.HasSetter) if (prop.HasSetter)
GeneratePropertySetter(prop.GetMethod != null ? GeneratePropertySetter(prop.QualifiedType, prop.SetMethod, @class);
prop.GetMethod.ReturnType : prop.SetMethod.Parameters[0].QualifiedType,
prop.SetMethod, @class);
} }
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -1258,7 +1240,7 @@ namespace CppSharp.Generators.CSharp
WriteLine("public static {0} {1}", type, variable.Name); WriteLine("public static {0} {1}", type, variable.Name);
WriteStartBraceIndent(); WriteStartBraceIndent();
GeneratePropertyGetter(variable, @class); GeneratePropertyGetter(variable.QualifiedType, variable, @class);
if (!variable.QualifiedType.Qualifiers.IsConst) if (!variable.QualifiedType.Qualifiers.IsConst)
GeneratePropertySetter(variable.QualifiedType, variable, @class); GeneratePropertySetter(variable.QualifiedType, variable, @class);
@ -2183,8 +2165,8 @@ namespace CppSharp.Generators.CSharp
GenerateVTableClassSetupCall(@class); GenerateVTableClassSetupCall(@class);
} }
public void GenerateInternalFunctionCall(Function function, public void GenerateInternalFunctionCall(Function function,
List<Parameter> parameters = null) List<Parameter> parameters = null, Type returnType = null)
{ {
if (parameters == null) if (parameters == null)
parameters = function.Parameters; parameters = function.Parameters;
@ -2192,11 +2174,11 @@ namespace CppSharp.Generators.CSharp
CheckArgumentRange(function); CheckArgumentRange(function);
var functionName = string.Format("Internal.{0}", var functionName = string.Format("Internal.{0}",
GetFunctionNativeIdentifier(function)); GetFunctionNativeIdentifier(function));
GenerateFunctionCall(functionName, parameters, function); GenerateFunctionCall(functionName, parameters, function, returnType);
} }
public void GenerateFunctionCall(string functionName, List<Parameter> parameters, public void GenerateFunctionCall(string functionName, List<Parameter> parameters,
Function function) Function function, Type returnType = null)
{ {
if (function.IsPure) if (function.IsPure)
{ {
@ -2204,7 +2186,9 @@ namespace CppSharp.Generators.CSharp
return; return;
} }
var retType = function.OriginalReturnType; var retType = function.OriginalReturnType;
if (returnType == null)
returnType = retType.Type;
var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void); var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void);
var isValueType = false; var isValueType = false;
@ -2363,10 +2347,14 @@ namespace CppSharp.Generators.CSharp
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore); Write(marshal.Context.SupportBefore);
WriteLine( // Special case for indexer - needs to dereference if the internal
TypePrinter.ContextKind == CSharpTypePrinterContextKind.PrimitiveIndexer // function is a pointer type and the property is not.
? "return *{0};" if (retType.Type.IsAddress() &&
: "return {0};", marshal.Context.Return); retType.Type.GetPointee().Equals(returnType) &&
returnType.IsPrimitiveType())
WriteLine("return *{0};", marshal.Context.Return);
else
WriteLine("return {0};", marshal.Context.Return);
} }
} }

3
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -12,8 +12,7 @@ namespace CppSharp.Generators.CSharp
Native, Native,
Managed, Managed,
ManagedPointer, ManagedPointer,
GenericDelegate, GenericDelegate
PrimitiveIndexer
} }
public class CSharpTypePrinterContext : TypePrinterContext public class CSharpTypePrinterContext : TypePrinterContext

20
src/Generator/Library.cs

@ -204,6 +204,26 @@ namespace CppSharp
} }
} }
public static void SetPropertyAsReadOnly(this ASTContext context, string className, string propertyName)
{
var properties = context.FindClass(className)
.SelectMany(c => c.Properties.Where(p => p.Name == propertyName && p.HasSetter));
foreach (var property in properties)
if (property.SetMethod != null)
property.SetMethod.GenerationKind = GenerationKind.None;
else
{
var field = property.Field;
var quals = field.QualifiedType.Qualifiers;
quals.IsConst = true;
var qualType = field.QualifiedType;
qualType.Qualifiers = quals;
field.QualifiedType = qualType;
}
}
/// <summary> /// <summary>
/// Sets the parameter usage for a function parameter. /// Sets the parameter usage for a function parameter.
/// </summary> /// </summary>

27
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -97,21 +97,24 @@ namespace CppSharp.Passes
GetMethod = @operator GetMethod = @operator
}; };
if (!@operator.ReturnType.Qualifiers.IsConst && @operator.ReturnType.Type.IsAddress()) var returnType = @operator.Type;
property.SetMethod = @operator; if (returnType.IsAddress())
{
var pointer = returnType as PointerType;
var qualifiedPointee = pointer.QualifiedPointee;
if (!qualifiedPointee.Qualifiers.IsConst)
property.SetMethod = @operator;
}
// If we've a setter use the pointee as the type of the property.
var pointerType = property.Type as PointerType;
if (pointerType != null && property.HasSetter)
property.QualifiedType = new QualifiedType(
pointerType.Pointee, property.QualifiedType.Qualifiers);
if (Driver.Options.IsCLIGenerator) if (Driver.Options.IsCLIGenerator)
{
// If we've a setter use the pointee as the type of the property.
var pointerType = property.Type as PointerType;
if (pointerType != null && property.HasSetter)
{
property.QualifiedType = new QualifiedType(pointerType.Pointee, property.QualifiedType.Qualifiers);
property.GetMethod.ReturnType = property.QualifiedType;
}
// C++/CLI uses "default" as the indexer property name. // C++/CLI uses "default" as the indexer property name.
property.Name = "default"; property.Name = "default";
}
property.Parameters.AddRange(@operator.Parameters); property.Parameters.AddRange(@operator.Parameters);

2
src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs

@ -70,7 +70,7 @@ namespace CppSharp.Passes
public override bool VisitMethodDecl(Method method) public override bool VisitMethodDecl(Method method)
{ {
if (!method.IsConstructor && !method.IsDestructor && !method.IsOperator && if (!method.IsConstructor && !method.IsDestructor && !method.IsOperator &&
method.IsGenerated) method.IsGenerated && !method.IsSynthetized)
DistributeMethod(method); DistributeMethod(method);
return base.VisitMethodDecl(method); return base.VisitMethodDecl(method);
} }

3
src/Generator/Passes/GetterSetterToPropertyPass.cs

@ -87,6 +87,9 @@ namespace CppSharp.Passes
if (method.IsConstructor) if (method.IsConstructor)
return false; return false;
if (method.IsSynthetized)
return false;
if (IsGetter(method)) if (IsGetter(method))
{ {
var name = method.Name.Substring("get".Length); var name = method.Name.Substring("get".Length);

6
src/Generator/Types/CppTypePrinter.cs

@ -17,10 +17,12 @@ namespace CppSharp.Types
{ {
public CppTypePrintScopeKind PrintScopeKind; public CppTypePrintScopeKind PrintScopeKind;
public bool PrintLogicalNames; public bool PrintLogicalNames;
public bool PrintTypeQualifiers;
public CppTypePrinter(ITypeMapDatabase database) public CppTypePrinter(ITypeMapDatabase database, bool printTypeQualifiers = true)
{ {
PrintScopeKind = CppTypePrintScopeKind.GlobalQualified; PrintScopeKind = CppTypePrintScopeKind.GlobalQualified;
PrintTypeQualifiers = printTypeQualifiers;
} }
public string VisitTagType(TagType tag, TypeQualifiers quals) public string VisitTagType(TagType tag, TypeQualifiers quals)
@ -78,7 +80,7 @@ namespace CppSharp.Types
var pointeeType = pointer.Pointee.Visit(this, quals); var pointeeType = pointer.Pointee.Visit(this, quals);
var mod = ConvertModifierToString(pointer.Modifier); var mod = ConvertModifierToString(pointer.Modifier);
var s = quals.IsConst ? "const " : string.Empty; var s = PrintTypeQualifiers && quals.IsConst ? "const " : string.Empty;
s += string.Format("{0}{1}", pointeeType, mod); s += string.Format("{0}{1}", pointeeType, mod);
return s; return s;

22
tests/Basic/Basic.Tests.cs

@ -238,11 +238,23 @@ public class BasicTests : GeneratorTestFixture
[Test] [Test]
public unsafe void TestIndexers() public unsafe void TestIndexers()
{ {
var someStruct = new SomeStruct(); var indexedProperties = new TestIndexedProperties();
Assert.That(someStruct[0], Is.EqualTo(1)); Assert.AreEqual(1, indexedProperties[0]);
Assert.That(someStruct["foo"], Is.EqualTo(1)); Assert.AreEqual(1, indexedProperties["foo"]);
someStruct[0] = 2; indexedProperties[0] = 2;
Assert.That(someStruct[0], Is.EqualTo(2)); Assert.AreEqual(2, indexedProperties[0]);
indexedProperties[0f] = 3;
Assert.AreEqual(3, indexedProperties[0f]);
var properties = indexedProperties[(byte)0];
Assert.AreEqual(0, properties.Field);
var newProperties = new TestProperties();
newProperties.Field = 4;
indexedProperties[(byte)0] = newProperties;
Assert.AreEqual(4, indexedProperties[(byte)0].Field);
newProperties = indexedProperties[(short)0];
Assert.AreEqual(4, newProperties.Field);
newProperties.Field = 5;
Assert.AreEqual(5, indexedProperties[(byte)0].Field);
} }
[Test] [Test]

36
tests/Basic/Basic.h

@ -336,17 +336,11 @@ typedef unsigned long foo_t;
typedef struct DLL_API SomeStruct typedef struct DLL_API SomeStruct
{ {
SomeStruct(); SomeStruct();
foo_t& operator[](int i);
// CSharp backend can't deal with a setter here
foo_t operator[](const char* name);
foo_t p; foo_t p;
} SomeStruct; } SomeStruct;
SomeStruct::SomeStruct() : p(1) {} SomeStruct::SomeStruct() : p(1) {}
foo_t& SomeStruct::operator[](int i) { return p; }
foo_t SomeStruct::operator[](const char* name) { return p; }
class DLL_API SomeClassExtendingTheStruct : public SomeStruct class DLL_API SomeClassExtendingTheStruct : public SomeStruct
{ {
}; };
@ -396,6 +390,34 @@ TestProperties::TestProperties() : Field(0) {}
int TestProperties::getFieldValue() { return Field; } int TestProperties::getFieldValue() { return Field; }
void TestProperties::setFieldValue(int Value) { Field = Value; } void TestProperties::setFieldValue(int Value) { Field = Value; }
class DLL_API TestIndexedProperties
{
foo_t p;
TestProperties f;
public:
TestIndexedProperties();
// Should lead to a read/write indexer with return type uint
foo_t& operator[](int i);
// Should lead to a read/write indexer with return type uint
foo_t* operator[](float f);
// Should lead to a read-only indexer with return type uint
foo_t operator[](const char* name);
// Should lead to a read-only indexer with return type uint*
const foo_t& operator[](double d);
// Should lead to a read/write indexer with return type TestProperties
TestProperties* operator[](unsigned char b);
// Should lead to a read-only indexer with return type TestProperties
const TestProperties& operator[](short b);
};
TestIndexedProperties::TestIndexedProperties() : p(1), f() {}
foo_t& TestIndexedProperties::operator[](int i) { return p; }
foo_t TestIndexedProperties::operator[](const char* name) { return p; }
foo_t* TestIndexedProperties::operator[](float f) { return &p; }
const foo_t& TestIndexedProperties::operator[](double f) { return p; }
TestProperties* TestIndexedProperties::operator[](unsigned char b) { return &f; }
const TestProperties& TestIndexedProperties::operator[](short b) { return f; }
enum struct MyEnum { A, B, C }; enum struct MyEnum { A, B, C };
class DLL_API TestArraysPointers class DLL_API TestArraysPointers
@ -462,4 +484,4 @@ DLL_API void TestNullPtrType(decltype(nullptr))
DLL_API decltype(nullptr) TestNullPtrTypeRet() DLL_API decltype(nullptr) TestNullPtrTypeRet()
{ {
return nullptr; return nullptr;
} }

7
tests/Native/Passes.h

@ -26,6 +26,13 @@ struct TestRename
int lowerCaseField; int lowerCaseField;
}; };
struct TestReadOnlyProperties
{
int readOnlyProperty;
int getReadOnlyPropertyMethod() { return 0; }
void setReadOnlyPropertyMethod(int value) { }
};
#define TEST_ENUM_ITEM_NAME_0 0 #define TEST_ENUM_ITEM_NAME_0 0
#define TEST_ENUM_ITEM_NAME_1 1 #define TEST_ENUM_ITEM_NAME_1 1
#define TEST_ENUM_ITEM_NAME_2 2 #define TEST_ENUM_ITEM_NAME_2 2

Loading…
Cancel
Save