Skip to content

Commit fdfc68f

Browse files
committed
CSharp: More default parameter fixes
- Expression generation for `ConstructorReference` now also recursively calls `VisitExpression` for the argument if only one argument is detected. This allows correct overload generation for functions taking a variable as the default parameter value. - Default parameters of pointer-to-enumeration types are now correctly generated similar to primitive types.
1 parent 1ce9cb7 commit fdfc68f

File tree

8 files changed

+80
-39
lines changed

8 files changed

+80
-39
lines changed

src/AST/TypeExtensions.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,25 @@ public static bool IsPointerToPrimitiveType(this Type t, PrimitiveType primitive
9292
return ptr.Pointee.IsPrimitiveType(primitive);
9393
}
9494

95+
public static bool IsPointerToEnum(this Type t)
96+
{
97+
var ptr = t as PointerType;
98+
if (ptr == null)
99+
return false;
100+
return ptr.Pointee.IsEnumType();
101+
}
102+
103+
public static bool IsPointerToEnum(this Type t, out Enumeration @enum)
104+
{
105+
var ptr = t as PointerType;
106+
if (ptr == null)
107+
{
108+
@enum = null;
109+
return false;
110+
}
111+
return ptr.Pointee.TryGetEnum(out @enum);
112+
}
113+
95114
public static bool IsPointerTo<T>(this Type t, out T type) where T : Type
96115
{
97116
var pointee = t.GetPointee();

src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public string VisitExpression(ExpressionObsolete expr)
6868
case StatementClass.ConstructorReference:
6969
var constructorExpr = (CXXConstructExprObsolete)expr;
7070
if (constructorExpr.Arguments.Count == 1 &&
71-
constructorExpr.Arguments[0].Declaration is Enumeration.Item)
72-
return constructorExpr.Arguments[0].Declaration.Visit(typePrinter).Type;
71+
constructorExpr.Arguments[0].Class != StatementClass.Any)
72+
return VisitExpression(constructorExpr.Arguments[0]);
7373
goto default;
7474
default:
7575
return expr.String;

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,7 +2783,7 @@ private bool GenerateMethodBody(Class @class, Method method,
27832783

27842784
private string OverloadParamNameWithDefValue(Parameter p, ref int index)
27852785
{
2786-
return p.Type.IsPointerToPrimitiveType() && p.Usage == ParameterUsage.InOut && p.HasDefaultValue
2786+
return (p.Type.IsPointerToPrimitiveType() || p.Type.IsPointerToEnum()) && p.Usage == ParameterUsage.InOut && p.HasDefaultValue
27872787
? "ref param" + index++
27882788
: ExpressionPrinter.VisitParameter(p);
27892789
}
@@ -2802,13 +2802,15 @@ private void GenerateOverloadCall(Function function)
28022802
for (int i = 0, j = 0; i < function.Parameters.Count; i++)
28032803
{
28042804
var parameter = function.Parameters[i];
2805-
PrimitiveType primitiveType;
2805+
PrimitiveType primitiveType = PrimitiveType.Null;
2806+
Enumeration enumeration = null;
28062807
if (parameter.Kind == ParameterKind.Regular && parameter.Ignore &&
2807-
parameter.Type.IsPointerToPrimitiveType(out primitiveType) &&
2808+
(parameter.Type.IsPointerToPrimitiveType(out primitiveType) ||
2809+
parameter.Type.IsPointerToEnum(out enumeration)) &&
28082810
parameter.Usage == ParameterUsage.InOut && parameter.HasDefaultValue)
28092811
{
28102812
var pointeeType = ((PointerType)parameter.Type).Pointee.ToString();
2811-
WriteLine($@"{pointeeType} param{j++} = {(primitiveType == PrimitiveType.Bool ? "false" : "0")};");
2813+
WriteLine($@"{pointeeType} param{j++} = {(primitiveType == PrimitiveType.Bool ? "false" : $"({pointeeType})0")};");
28122814
}
28132815
}
28142816

tests/dotnet/CSharp/CSharp.Tests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ public void TestDefaultArguments()
346346
methodsWithDefaultValues.DefaultWithSpecialization();
347347
methodsWithDefaultValues.DefaultOverloadedImplicitCtor();
348348
methodsWithDefaultValues.DefaultWithParamNamedSameAsMethod(5);
349+
Assert.That(methodsWithDefaultValues.DefaultIntAssignedAnEnumWithBinaryOperatorAndFlags(), Is.EqualTo((int)(Bar.Items.Item1 | Bar.Items.Item2)));
350+
Assert.That(methodsWithDefaultValues.DefaultWithConstantFlags(), Is.EqualTo(CSharp.CSharp.ConstFlag1 | CSharp.CSharp.ConstFlag2 | CSharp.CSharp.ConstFlag3));
351+
Assert.IsTrue(methodsWithDefaultValues.DefaultWithPointerToEnum());
352+
Assert.AreEqual(CSharp.CSharp.DefaultSmallPODInstance.__Instance, methodsWithDefaultValues.DefaultWithNonPrimitiveType().__Instance);
349353
}
350354
}
351355

tests/dotnet/CSharp/CSharp.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ MethodsWithDefaultValues::QMargins::QMargins(int left, int top, int right, int b
568568
{
569569
}
570570

571+
struct SmallPOD DefaultSmallPODInstance;
572+
571573
const char* MethodsWithDefaultValues::stringConstant = "test";
572574
int MethodsWithDefaultValues::intConstant = 5;
573575

@@ -808,6 +810,26 @@ int MethodsWithDefaultValues::DefaultWithParamNamedSameAsMethod(int DefaultWithP
808810
return 1;
809811
}
810812

813+
int MethodsWithDefaultValues::defaultIntAssignedAnEnumWithBinaryOperatorAndFlags(int f)
814+
{
815+
return f;
816+
}
817+
818+
int MethodsWithDefaultValues::defaultWithConstantFlags(int f)
819+
{
820+
return f;
821+
}
822+
823+
bool MethodsWithDefaultValues::defaultWithPointerToEnum(UntypedFlags* f1, int* f2)
824+
{
825+
return (f1 == NULL || *f1 == (UntypedFlags)0) && (f2 == NULL || *f2 == 0);
826+
}
827+
828+
SmallPOD* MethodsWithDefaultValues::defaultWithNonPrimitiveType(SmallPOD& pod)
829+
{
830+
return &pod;
831+
}
832+
811833
int MethodsWithDefaultValues::getA()
812834
{
813835
return m_foo.A;
@@ -1299,36 +1321,36 @@ TestString::TestString() : unicodeConst(L"ქართული ენა"), uni
12991321
{
13001322
}
13011323

1302-
TestChar32String::TestChar32String() :
1324+
TestChar32String::TestChar32String() :
13031325
thirtyTwoBitConst(U"ქართული ენა")
13041326
{
13051327
static std::u32string nonConst = U"Test String";
13061328
thirtyTwoBitNonConst = &nonConst[0];
13071329
}
13081330

13091331
TestChar32String::~TestChar32String() {}
1310-
void TestChar32String::UpdateString(const char32_t* s)
1311-
{
1332+
void TestChar32String::UpdateString(const char32_t* s)
1333+
{
13121334
static std::u32string nativeOwnedMemory = s;
13131335
thirtyTwoBitConst = nativeOwnedMemory.data();
13141336
}
13151337

13161338
const char32_t* TestChar32String::RetrieveString() { return thirtyTwoBitConst; }
13171339
void TestChar32String::functionPointerUTF32(void(*ptr)(const char32_t*)) {}
13181340

1319-
TestChar16String::TestChar16String() :
1320-
sixteenBitConst(u"ქართული ენა")
1341+
TestChar16String::TestChar16String() :
1342+
sixteenBitConst(u"ქართული ენა")
13211343
{
13221344
static std::u16string nonConst = u"Test String";
13231345
sixteenBitNonConst = &nonConst[0];
13241346
}
13251347

13261348
TestChar16String::~TestChar16String() {}
13271349

1328-
void TestChar16String::UpdateString(const char16_t* s)
1329-
{
1350+
void TestChar16String::UpdateString(const char16_t* s)
1351+
{
13301352
static std::u16string nativeOwnedMemory = s;
1331-
sixteenBitConst = nativeOwnedMemory.data();
1353+
sixteenBitConst = nativeOwnedMemory.data();
13321354
}
13331355
const char16_t* TestChar16String::RetrieveString() { return sixteenBitConst; }
13341356

@@ -1667,7 +1689,7 @@ const unsigned ClassCustomTypeAlignmentOffsets[5]
16671689
offsetof(ClassCustomTypeAlignment, align8),
16681690
};
16691691

1670-
const unsigned ClassCustomObjectAlignmentOffsets[2] {
1692+
const unsigned ClassCustomObjectAlignmentOffsets[2] {
16711693
offsetof(ClassCustomObjectAlignment, boolean),
16721694
offsetof(ClassCustomObjectAlignment, charAligned8),
16731695
};

tests/dotnet/CSharp/CSharp.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,12 @@ enum class Empty : unsigned long long int
405405
class _ClassWithLeadingUnderscore {
406406
};
407407

408+
const int ConstFlag1 = 1;
409+
const int ConstFlag2 = 2;
410+
const int ConstFlag3 = 4;
411+
412+
extern DLL_API struct SmallPOD DefaultSmallPODInstance;
413+
408414
class DLL_API MethodsWithDefaultValues : public Quux
409415
{
410416
public:
@@ -480,6 +486,10 @@ class DLL_API MethodsWithDefaultValues : public Quux
480486
void defaultWithSpecialization(IndependentFields<int> specialization = IndependentFields<int>());
481487
void defaultOverloadedImplicitCtor(P p);
482488
void defaultOverloadedImplicitCtor(Qux q = Qux());
489+
int defaultIntAssignedAnEnumWithBinaryOperatorAndFlags(int f = Bar::Item1 | Bar::Item2);
490+
int defaultWithConstantFlags(int f = ConstFlag1 | ConstFlag2 | ConstFlag3);
491+
bool defaultWithPointerToEnum(UntypedFlags* f1 = NULL, int* f2 = NULL);
492+
SmallPOD* defaultWithNonPrimitiveType(SmallPOD& pod = DefaultSmallPODInstance);
483493
int DefaultWithParamNamedSameAsMethod(int DefaultWithParamNamedSameAsMethod, const Foo& defaultArg = Foo());
484494
int getA();
485495
private:
@@ -1082,9 +1092,9 @@ class DLL_API VariablesWithInitializer {
10821092
static constexpr const char* StringArray1[1] { "Str" "F,\"or" };
10831093
static constexpr const char* StringArray3[3] { "Str" "F,\"or", "C#", String };
10841094
static constexpr const char* StringArray30[30] {
1085-
"Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str",
1086-
"Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str",
1087-
"Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str",
1095+
"Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str",
1096+
"Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str",
1097+
"Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str",
10881098
};
10891099
static constexpr const char* StringArray3EmptyInitList[3] { };
10901100
static constexpr const wchar_t* WideStringArray[2] { L"Str", L"C#" };
@@ -1278,7 +1288,7 @@ struct StructTestArrayTypeFromTypedef
12781288
#define MY_MACRO_TEST2_4 (1 << 3)
12791289
#define MY_MACRO_TEST2_ALL (1 << 4) - 1
12801290

1281-
#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_1 1 << 5
1291+
#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_1 1 << 5
12821292
#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_2 1 << 22
12831293
#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_3 1L << 32
12841294
#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_4 -1
@@ -1465,9 +1475,9 @@ struct DLL_API ConversionFunctions
14651475
short field = 100;
14661476
};
14671477

1468-
struct DLL_API ClassCustomTypeAlignment
1478+
struct DLL_API ClassCustomTypeAlignment
14691479
{
1470-
struct alignas(1) Align1 { };
1480+
struct alignas(1) Align1 { };
14711481
struct alignas(8) Align8 { };
14721482
struct alignas(16) Align16 {
14731483
double a;
@@ -1476,7 +1486,7 @@ struct DLL_API ClassCustomTypeAlignment
14761486

14771487
bool boolean;
14781488
Align16 align16;
1479-
Align1 align1;
1489+
Align1 align1;
14801490
double dbl;
14811491
Align8 align8;
14821492
};
@@ -1524,7 +1534,7 @@ DLL_API extern const unsigned StructWithEmbeddedArrayOfStructObjectAlignmentOffs
15241534

15251535
DLL_API const char* TestCSharpString(const char* in, CS_OUT const char** out);
15261536
DLL_API const wchar_t* TestCSharpStringWide(const wchar_t* in, CS_OUT const wchar_t** out);
1527-
DLL_API const char16_t* TestCSharpString16(const char16_t* in, CS_OUT const char16_t** out);
1537+
DLL_API const char16_t* TestCSharpString16(const char16_t* in, CS_OUT const char16_t** out);
15281538
DLL_API const char32_t* TestCSharpString32(const char32_t* in, CS_OUT const char32_t** out);
15291539

15301540
struct DLL_API FTIStruct { int a; };

tests/dotnet/Common/Common.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,11 +1274,3 @@ extern "C"
12741274
return s;
12751275
}
12761276
} // extern "C"
1277-
1278-
void DLL_API FunctionWithFlagsAsDefaultParameter(int defaultParam)
1279-
{
1280-
}
1281-
1282-
void DLL_API FunctionWithConstFlagsAsDefaultParameter(int defaultParam)
1283-
{
1284-
}

tests/dotnet/Common/Common.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,11 +1567,3 @@ extern "C"
15671567
DLL_API void takeConflictName(struct system* self);
15681568
DLL_API struct system freeFunctionReturnByValue();
15691569
} // extern "C"
1570-
1571-
void DLL_API FunctionWithFlagsAsDefaultParameter(int defaultParam = A | B);
1572-
1573-
const int ConstFlag1 = 1;
1574-
const int ConstFlag2 = 2;
1575-
const int ConstFlag3 = 4;
1576-
1577-
void DLL_API FunctionWithConstFlagsAsDefaultParameter(int defaultParam = ConstFlag1 | ConstFlag2 | ConstFlag3);

0 commit comments

Comments
 (0)