Skip to content

Commit 2a40276

Browse files
authored
Merge pull request #102 from kornilova-l/fix-helpers-for-aliased-structs-and-unions
Check if type is alias for struct/union before generating setter/getter
2 parents 3cc6817 + 46d603e commit 2a40276

File tree

7 files changed

+106
-13
lines changed

7 files changed

+106
-13
lines changed

bindgen/Utils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <clang/AST/AST.h>
55

6+
#include "ir/TypeDef.h"
67
#include "ir/types/Type.h"
78
#include <algorithm>
89
#include <cctype>
@@ -100,4 +101,16 @@ template <typename T, typename PT> static inline bool isInstanceOf(PT *type) {
100101
return p != nullptr;
101102
}
102103

104+
/**
105+
* Types may be wrapper in a chain of typedefs.
106+
* @return true if given type is of type T or is an alias for type T.
107+
*/
108+
template <typename T> static inline bool isAliasForType(Type *type) {
109+
if (isInstanceOf<TypeDef>(type)) {
110+
auto *typeDef = dynamic_cast<TypeDef *>(type);
111+
return isAliasForType<T>(typeDef->getType().get());
112+
}
113+
return isInstanceOf<T>(type);
114+
}
115+
103116
#endif // UTILS_H

bindgen/ir/Struct.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ std::string Field::generateSetter(int fieldIndex) {
1212
std::string setter = handleReservedWords(getName(), "_=");
1313
std::string parameterType = type->str();
1414
std::string value = "value";
15-
if (isInstanceOf<ArrayType>(type.get()) ||
16-
isInstanceOf<Struct>(type.get())) {
15+
if (isAliasForType<ArrayType>(type.get()) ||
16+
isAliasForType<Struct>(type.get())) {
1717
parameterType = "native.Ptr[" + parameterType + "]";
1818
value = "!" + value;
1919
}
@@ -27,8 +27,8 @@ std::string Field::generateGetter(int fieldIndex) {
2727
std::string getter = handleReservedWords(getName());
2828
std::string returnType = type->str();
2929
std::string methodBody;
30-
if (isInstanceOf<ArrayType>(type.get()) ||
31-
isInstanceOf<Struct>(type.get())) {
30+
if (isAliasForType<ArrayType>(type.get()) ||
31+
isAliasForType<Struct>(type.get())) {
3232
returnType = "native.Ptr[" + returnType + "]";
3333
methodBody = "p._" + std::to_string(fieldIndex + 1);
3434
} else {

tests/samples/ReservedWords.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ object ReservedWordsHelpers {
3737
implicit class struct_finally_ops(val p: native.Ptr[struct_finally]) extends AnyVal {
3838
def `val`: `def` = !p._1
3939
def `val_=`(value: `def`): Unit = !p._1 = value
40-
def `finally`: `lazy` = !p._2
41-
def `finally_=`(value: `lazy`): Unit = !p._2 = value
40+
def `finally`: native.Ptr[`lazy`] = p._2
41+
def `finally_=`(value: native.Ptr[`lazy`]): Unit = !p._2 = !value
4242
}
4343

4444
def struct_finally()(implicit z: native.Zone): native.Ptr[struct_finally] = native.alloc[struct_finally]

tests/samples/Struct.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
#include "Struct.h"
22
#include <stdlib.h>
33

4-
point_s getPoint() {
4+
void setPoints(struct points *points, int x1, int y1, int x2, int y2) {
5+
points->p1.x = x1;
6+
points->p1.y = y1;
7+
points->p2.x = x2;
8+
points->p2.y = y2;
9+
}
10+
11+
int getPoint(struct points *points, enum pointIndex pointIndex) {
12+
switch (pointIndex) {
13+
case X1:
14+
return points->p1.x;
15+
case X2:
16+
return points->p2.x;
17+
case Y1:
18+
return points->p1.y;
19+
case Y2:
20+
return points->p2.y;
21+
}
22+
}
23+
24+
point_s createPoint() {
525
point_s point = malloc(sizeof(struct point));
626
point->x = 10;
727
point->y = 20;

tests/samples/Struct.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,22 @@ struct point {
33
int y;
44
};
55

6+
typedef struct point point;
7+
8+
struct points {
9+
struct point p1;
10+
point p2;
11+
};
12+
13+
enum pointIndex { X1, Y1, X2, Y2 };
14+
15+
void setPoints(struct points *points, int x1, int y1, int x2, int y2);
16+
17+
int getPoint(struct points *points, enum pointIndex pointIndex);
18+
619
typedef struct point *point_s;
720

8-
point_s getPoint();
21+
point_s createPoint();
922

1023
struct bigStruct {
1124
long one;

tests/samples/Struct.scala

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,29 @@ import scala.scalanative.native._
77
@native.extern
88
object Struct {
99
type struct_point = native.CStruct2[native.CInt, native.CInt]
10+
type point = struct_point
11+
type struct_points = native.CStruct2[struct_point, point]
12+
type enum_pointIndex = native.CUnsignedInt
1013
type point_s = native.Ptr[struct_point]
1114
type struct_bigStruct = native.CArray[Byte, native.Nat.Digit[native.Nat._1, native.Nat.Digit[native.Nat._1, native.Nat._2]]]
1215
type struct_structWithAnonymousStruct = native.CStruct2[native.CInt, native.CArray[Byte, native.Nat._8]]
13-
def getPoint(): native.Ptr[struct_point] = native.extern
16+
def setPoints(points: native.Ptr[struct_points], x1: native.CInt, y1: native.CInt, x2: native.CInt, y2: native.CInt): Unit = native.extern
17+
def getPoint(points: native.Ptr[struct_points], pointIndex: enum_pointIndex): native.CInt = native.extern
18+
def createPoint(): native.Ptr[struct_point] = native.extern
1419
def getBigStructSize(): native.CInt = native.extern
1520
def getCharFromAnonymousStruct(s: native.Ptr[struct_structWithAnonymousStruct]): native.CChar = native.extern
1621
def getIntFromAnonymousStruct(s: native.Ptr[struct_structWithAnonymousStruct]): native.CChar = native.extern
1722
}
1823

1924
import Struct._
2025

26+
object StructEnums {
27+
final val enum_pointIndex_X1: enum_pointIndex = 0.toUInt
28+
final val enum_pointIndex_Y1: enum_pointIndex = 1.toUInt
29+
final val enum_pointIndex_X2: enum_pointIndex = 2.toUInt
30+
final val enum_pointIndex_Y2: enum_pointIndex = 3.toUInt
31+
}
32+
2133
object StructHelpers {
2234

2335
implicit class struct_point_ops(val p: native.Ptr[struct_point]) extends AnyVal {
@@ -29,6 +41,15 @@ object StructHelpers {
2941

3042
def struct_point()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point]
3143

44+
implicit class struct_points_ops(val p: native.Ptr[struct_points]) extends AnyVal {
45+
def p1: native.Ptr[struct_point] = p._1
46+
def p1_=(value: native.Ptr[struct_point]): Unit = !p._1 = !value
47+
def p2: native.Ptr[point] = p._2
48+
def p2_=(value: native.Ptr[point]): Unit = !p._2 = !value
49+
}
50+
51+
def struct_points()(implicit z: native.Zone): native.Ptr[struct_points] = native.alloc[struct_points]
52+
3253
implicit class struct_structWithAnonymousStruct_ops(val p: native.Ptr[struct_structWithAnonymousStruct]) extends AnyVal {
3354
def a: native.CInt = !p._1
3455
def a_=(value: native.CInt): Unit = !p._1 = value

tests/samples/src/test/scala/org/scalanative/bindgen/samples/StructTests.scala

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,48 @@ package org.scalanative.bindgen.samples
33
import utest._
44
import scala.scalanative.native._
55
import org.scalanative.bindgen.samples.StructHelpers._
6+
import org.scalanative.bindgen.samples.StructEnums._
67

78
object StructTests extends TestSuite {
89
val tests = Tests {
9-
'getPoint - {
10-
val point = Struct.getPoint()
10+
'point - {
11+
val point = Struct.createPoint()
1112
assert(point.x == 10)
1213
assert(point.y == 20)
1314

14-
point.x_=(11)
15+
point.x = 11
1516
assert(point.x == 11)
1617
}
1718

1819
'bigStructSize - {
1920
assert(Struct.getBigStructSize() == sizeof[Struct.struct_bigStruct])
2021
}
2122

23+
'getFieldsOfInnerStruct - {
24+
Zone { implicit zone =>
25+
val points = struct_points()
26+
Struct.setPoints(points, 1, 2, 3, 4)
27+
assert(1 == points.p1.x)
28+
assert(2 == points.p1.y)
29+
assert(3 == points.p2.x)
30+
assert(4 == points.p2.y)
31+
}
32+
}
33+
34+
'setFieldsOfInnerStruct - {
35+
Zone { implicit zone =>
36+
val points = struct_points()
37+
points.p1.x = 1
38+
points.p1.y = 2
39+
points.p2.x = 3
40+
points.p2.y = 4
41+
assert(1 == Struct.getPoint(points, enum_pointIndex_X1))
42+
assert(2 == Struct.getPoint(points, enum_pointIndex_Y1))
43+
assert(3 == Struct.getPoint(points, enum_pointIndex_X2))
44+
assert(4 == Struct.getPoint(points, enum_pointIndex_Y2))
45+
}
46+
}
47+
2248
'innerAnonymousStruct - {
2349
type struct_anonymousStruct = CStruct2[CChar, CInt]
2450
Zone { implicit zone =>
@@ -28,7 +54,7 @@ object StructTests extends TestSuite {
2854

2955
val structWithAnonymousStruct = struct_structWithAnonymousStruct()
3056
val array = anonymousStruct.cast[Ptr[CArray[Byte, Nat._8]]]
31-
structWithAnonymousStruct.anonymousStruct_=(array)
57+
structWithAnonymousStruct.anonymousStruct = array
3258

3359
assert('a' == Struct.getCharFromAnonymousStruct(structWithAnonymousStruct))
3460
assert(42 == Struct.getIntFromAnonymousStruct(structWithAnonymousStruct))

0 commit comments

Comments
 (0)