| author | |
| committer | |
| log | 294ee1bbc93a00ead5182234f824b0a665c579d9 |
| tree | 2938d0ebf9309bfbef8021bad0fbf9d6a7b5fd76 |
| parent | 0423f0f7d8afc24e48926849515f60a8a3a1e470 |
Add support for OffsetOfExpr that contain exactly 1 component, when that component
is a field.
For example, given:
```c
struct S {
float f;
double d;
};
struct T {
long l;
int i;
struct S s[10];
};
```
Then:
```c
offsetof(struct T, i) // supported
offsetof(struct T, s[2].d) // not supported currently
```6 files changed, 194 insertions(+), 0 deletions(-)
src/clang.zig+38| ... | @@ -432,6 +432,9 @@ pub const FieldDecl = opaque { | ... | @@ -432,6 +432,9 @@ pub const FieldDecl = opaque { |
| 432 | 432 | ||
| 433 | pub const getLocation = ZigClangFieldDecl_getLocation; | 433 | pub const getLocation = ZigClangFieldDecl_getLocation; |
| 434 | extern fn ZigClangFieldDecl_getLocation(*const FieldDecl) SourceLocation; | 434 | extern fn ZigClangFieldDecl_getLocation(*const FieldDecl) SourceLocation; |
| 435 | |||
| 436 | pub const getParent = ZigClangFieldDecl_getParent; | ||
| 437 | extern fn ZigClangFieldDecl_getParent(*const FieldDecl) ?*const RecordDecl; | ||
| 435 | }; | 438 | }; |
| 436 | 439 | ||
| 437 | pub const FileID = opaque {}; | 440 | pub const FileID = opaque {}; |
| ... | @@ -593,6 +596,34 @@ pub const TypeOfExprType = opaque { | ... | @@ -593,6 +596,34 @@ pub const TypeOfExprType = opaque { |
| 593 | extern fn ZigClangTypeOfExprType_getUnderlyingExpr(*const TypeOfExprType) *const Expr; | 596 | extern fn ZigClangTypeOfExprType_getUnderlyingExpr(*const TypeOfExprType) *const Expr; |
| 594 | }; | 597 | }; |
| 595 | 598 | ||
| 599 | pub const OffsetOfNode = opaque { | ||
| 600 | pub const getKind = ZigClangOffsetOfNode_getKind; | ||
| 601 | extern fn ZigClangOffsetOfNode_getKind(*const OffsetOfNode) OffsetOfNode_Kind; | ||
| 602 | |||
| 603 | pub const getArrayExprIndex = ZigClangOffsetOfNode_getArrayExprIndex; | ||
| 604 | extern fn ZigClangOffsetOfNode_getArrayExprIndex(*const OffsetOfNode) c_uint; | ||
| 605 | |||
| 606 | pub const getField = ZigClangOffsetOfNode_getField; | ||
| 607 | extern fn ZigClangOffsetOfNode_getField(*const OffsetOfNode) *FieldDecl; | ||
| 608 | }; | ||
| 609 | |||
| 610 | pub const OffsetOfExpr = opaque { | ||
| 611 | pub const getNumComponents = ZigClangOffsetOfExpr_getNumComponents; | ||
| 612 | extern fn ZigClangOffsetOfExpr_getNumComponents(*const OffsetOfExpr) c_uint; | ||
| 613 | |||
| 614 | pub const getNumExpressions = ZigClangOffsetOfExpr_getNumExpressions; | ||
| 615 | extern fn ZigClangOffsetOfExpr_getNumExpressions(*const OffsetOfExpr) c_uint; | ||
| 616 | |||
| 617 | pub const getIndexExpr = ZigClangOffsetOfExpr_getIndexExpr; | ||
| 618 | extern fn ZigClangOffsetOfExpr_getIndexExpr(*const OffsetOfExpr, idx: c_uint) *const Expr; | ||
| 619 | |||
| 620 | pub const getComponent = ZigClangOffsetOfExpr_getComponent; | ||
| 621 | extern fn ZigClangOffsetOfExpr_getComponent(*const OffsetOfExpr, idx: c_uint) *const OffsetOfNode; | ||
| 622 | |||
| 623 | pub const getBeginLoc = ZigClangOffsetOfExpr_getBeginLoc; | ||
| 624 | extern fn ZigClangOffsetOfExpr_getBeginLoc(*const OffsetOfExpr) SourceLocation; | ||
| 625 | }; | ||
| 626 | |||
| 596 | pub const MemberExpr = opaque { | 627 | pub const MemberExpr = opaque { |
| 597 | pub const getBase = ZigClangMemberExpr_getBase; | 628 | pub const getBase = ZigClangMemberExpr_getBase; |
| 598 | extern fn ZigClangMemberExpr_getBase(*const MemberExpr) *const Expr; | 629 | extern fn ZigClangMemberExpr_getBase(*const MemberExpr) *const Expr; |
| ... | @@ -1655,6 +1686,13 @@ pub const UnaryExprOrTypeTrait_Kind = extern enum { | ... | @@ -1655,6 +1686,13 @@ pub const UnaryExprOrTypeTrait_Kind = extern enum { |
| 1655 | PreferredAlignOf, | 1686 | PreferredAlignOf, |
| 1656 | }; | 1687 | }; |
| 1657 | 1688 | ||
| 1689 | pub const OffsetOfNode_Kind = extern enum { | ||
| 1690 | Array, | ||
| 1691 | Field, | ||
| 1692 | Identifier, | ||
| 1693 | Base, | ||
| 1694 | }; | ||
| 1695 | |||
| 1658 | pub const Stage2ErrorMsg = extern struct { | 1696 | pub const Stage2ErrorMsg = extern struct { |
| 1659 | filename_ptr: ?[*]const u8, | 1697 | filename_ptr: ?[*]const u8, |
| 1660 | filename_len: usize, | 1698 | filename_len: usize, |
src/translate_c.zig+52| ... | @@ -1069,12 +1069,64 @@ fn transStmt( | ... | @@ -1069,12 +1069,64 @@ fn transStmt( |
| 1069 | const expr = try transExpr(c, scope, source_expr, .used); | 1069 | const expr = try transExpr(c, scope, source_expr, .used); |
| 1070 | return maybeSuppressResult(c, scope, result_used, expr); | 1070 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1071 | }, | 1071 | }, |
| 1072 | .OffsetOfExprClass => return transOffsetOfExpr(c, scope, @ptrCast(*const clang.OffsetOfExpr, stmt), result_used), | ||
| 1072 | else => { | 1073 | else => { |
| 1073 | return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)}); | 1074 | return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)}); |
| 1074 | }, | 1075 | }, |
| 1075 | } | 1076 | } |
| 1076 | } | 1077 | } |
| 1077 | 1078 | ||
| 1079 | /// Translate a "simple" offsetof expression containing exactly one component, | ||
| 1080 | /// when that component is of kind .Field - e.g. offsetof(mytype, myfield) | ||
| 1081 | fn transSimpleOffsetOfExpr( | ||
| 1082 | c: *Context, | ||
| 1083 | scope: *Scope, | ||
| 1084 | expr: *const clang.OffsetOfExpr, | ||
| 1085 | ) TransError!Node { | ||
| 1086 | assert(expr.getNumComponents() == 1); | ||
| 1087 | const component = expr.getComponent(0); | ||
| 1088 | if (component.getKind() == .Field) { | ||
| 1089 | const field_decl = component.getField(); | ||
| 1090 | if (field_decl.getParent()) |record_decl| { | ||
| 1091 | if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |type_name| { | ||
| 1092 | const type_node = try Tag.type.create(c.arena, type_name); | ||
| 1093 | |||
| 1094 | var raw_field_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); | ||
| 1095 | const quoted_field_name = try std.fmt.allocPrint(c.arena, "\"{s}\"", .{raw_field_name}); | ||
| 1096 | const field_name_node = try Tag.string_literal.create(c.arena, quoted_field_name); | ||
| 1097 | |||
| 1098 | return Tag.byte_offset_of.create(c.arena, .{ | ||
| 1099 | .lhs = type_node, | ||
| 1100 | .rhs = field_name_node, | ||
| 1101 | }); | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "Failed to translate simple OffsetOfExpr", .{}); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | fn transOffsetOfExpr( | ||
| 1109 | c: *Context, | ||
| 1110 | scope: *Scope, | ||
| 1111 | expr: *const clang.OffsetOfExpr, | ||
| 1112 | result_used: ResultUsed, | ||
| 1113 | ) TransError!Node { | ||
| 1114 | if (expr.getNumComponents() == 1) { | ||
| 1115 | const offsetof_expr = try transSimpleOffsetOfExpr(c, scope, expr); | ||
| 1116 | return maybeSuppressResult(c, scope, result_used, offsetof_expr); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | // TODO implement OffsetOfExpr with more than 1 component | ||
| 1120 | // OffsetOfExpr API: | ||
| 1121 | // call expr.getComponent(idx) while idx < expr.getNumComponents() | ||
| 1122 | // component.getKind() will be either .Array or .Field (other kinds are C++-only) | ||
| 1123 | // if .Field, use component.getField() to retrieve *clang.FieldDecl | ||
| 1124 | // if .Array, use component.getArrayExprIndex() to get a c_uint which | ||
| 1125 | // can be passed to expr.getIndexExpr(expr_index) to get the *clang.Expr for the array index | ||
| 1126 | |||
| 1127 | return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO: implement complex OffsetOfExpr translation", .{}); | ||
| 1128 | } | ||
| 1129 | |||
| 1078 | fn transBinaryOperator( | 1130 | fn transBinaryOperator( |
| 1079 | c: *Context, | 1131 | c: *Context, |
| 1080 | scope: *Scope, | 1132 | scope: *Scope, |
src/translate_c/ast.zig+8| ... | @@ -148,6 +148,8 @@ pub const Node = extern union { | ... | @@ -148,6 +148,8 @@ pub const Node = extern union { |
| 148 | ptr_cast, | 148 | ptr_cast, |
| 149 | /// @divExact(lhs, rhs) | 149 | /// @divExact(lhs, rhs) |
| 150 | div_exact, | 150 | div_exact, |
| 151 | /// @byteOffsetOf(lhs, rhs) | ||
| 152 | byte_offset_of, | ||
| 151 | 153 | ||
| 152 | negate, | 154 | negate, |
| 153 | negate_wrap, | 155 | negate_wrap, |
| ... | @@ -303,6 +305,7 @@ pub const Node = extern union { | ... | @@ -303,6 +305,7 @@ pub const Node = extern union { |
| 303 | .std_mem_zeroinit, | 305 | .std_mem_zeroinit, |
| 304 | .ptr_cast, | 306 | .ptr_cast, |
| 305 | .div_exact, | 307 | .div_exact, |
| 308 | .byte_offset_of, | ||
| 306 | => Payload.BinOp, | 309 | => Payload.BinOp, |
| 307 | 310 | ||
| 308 | .integer_literal, | 311 | .integer_literal, |
| ... | @@ -1135,6 +1138,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1135,6 +1138,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1135 | const payload = node.castTag(.div_exact).?.data; | 1138 | const payload = node.castTag(.div_exact).?.data; |
| 1136 | return renderBuiltinCall(c, "@divExact", &.{ payload.lhs, payload.rhs }); | 1139 | return renderBuiltinCall(c, "@divExact", &.{ payload.lhs, payload.rhs }); |
| 1137 | }, | 1140 | }, |
| 1141 | .byte_offset_of => { | ||
| 1142 | const payload = node.castTag(.byte_offset_of).?.data; | ||
| 1143 | return renderBuiltinCall(c, "@byteOffsetOf", &.{ payload.lhs, payload.rhs }); | ||
| 1144 | }, | ||
| 1138 | .sizeof => { | 1145 | .sizeof => { |
| 1139 | const payload = node.castTag(.sizeof).?.data; | 1146 | const payload = node.castTag(.sizeof).?.data; |
| 1140 | return renderBuiltinCall(c, "@sizeOf", &.{payload}); | 1147 | return renderBuiltinCall(c, "@sizeOf", &.{payload}); |
| ... | @@ -2001,6 +2008,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { | ... | @@ -2001,6 +2008,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2001 | .array_type, | 2008 | .array_type, |
| 2002 | .bool_to_int, | 2009 | .bool_to_int, |
| 2003 | .div_exact, | 2010 | .div_exact, |
| 2011 | .byte_offset_of, | ||
| 2004 | => { | 2012 | => { |
| 2005 | // no grouping needed | 2013 | // no grouping needed |
| 2006 | return renderNode(c, node); | 2014 | return renderNode(c, node); |
src/zig_clang.cpp+45| ... | @@ -2609,6 +2609,46 @@ const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct | ... | @@ -2609,6 +2609,46 @@ const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct |
| 2609 | return reinterpret_cast<const struct ZigClangExpr *>(casted->getUnderlyingExpr()); | 2609 | return reinterpret_cast<const struct ZigClangExpr *>(casted->getUnderlyingExpr()); |
| 2610 | } | 2610 | } |
| 2611 | 2611 | ||
| 2612 | enum ZigClangOffsetOfNode_Kind ZigClangOffsetOfNode_getKind(const struct ZigClangOffsetOfNode *self) { | ||
| 2613 | auto casted = reinterpret_cast<const clang::OffsetOfNode *>(self); | ||
| 2614 | return (ZigClangOffsetOfNode_Kind)casted->getKind(); | ||
| 2615 | } | ||
| 2616 | |||
| 2617 | unsigned ZigClangOffsetOfNode_getArrayExprIndex(const struct ZigClangOffsetOfNode *self) { | ||
| 2618 | auto casted = reinterpret_cast<const clang::OffsetOfNode *>(self); | ||
| 2619 | return casted->getArrayExprIndex(); | ||
| 2620 | } | ||
| 2621 | |||
| 2622 | struct ZigClangFieldDecl *ZigClangOffsetOfNode_getField(const struct ZigClangOffsetOfNode *self) { | ||
| 2623 | auto casted = reinterpret_cast<const clang::OffsetOfNode *>(self); | ||
| 2624 | return reinterpret_cast<ZigClangFieldDecl *>(casted->getField()); | ||
| 2625 | } | ||
| 2626 | |||
| 2627 | unsigned ZigClangOffsetOfExpr_getNumComponents(const struct ZigClangOffsetOfExpr *self) { | ||
| 2628 | auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self); | ||
| 2629 | return casted->getNumComponents(); | ||
| 2630 | } | ||
| 2631 | |||
| 2632 | unsigned ZigClangOffsetOfExpr_getNumExpressions(const struct ZigClangOffsetOfExpr *self) { | ||
| 2633 | auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self); | ||
| 2634 | return casted->getNumExpressions(); | ||
| 2635 | } | ||
| 2636 | |||
| 2637 | const struct ZigClangExpr *ZigClangOffsetOfExpr_getIndexExpr(const struct ZigClangOffsetOfExpr *self, unsigned idx) { | ||
| 2638 | auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self); | ||
| 2639 | return reinterpret_cast<const struct ZigClangExpr *>(casted->getIndexExpr(idx)); | ||
| 2640 | } | ||
| 2641 | |||
| 2642 | const struct ZigClangOffsetOfNode *ZigClangOffsetOfExpr_getComponent(const struct ZigClangOffsetOfExpr *self, unsigned idx) { | ||
| 2643 | auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self); | ||
| 2644 | return reinterpret_cast<const struct ZigClangOffsetOfNode *>(&casted->getComponent(idx)); | ||
| 2645 | } | ||
| 2646 | |||
| 2647 | ZigClangSourceLocation ZigClangOffsetOfExpr_getBeginLoc(const ZigClangOffsetOfExpr *self) { | ||
| 2648 | auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self); | ||
| 2649 | return bitcast(casted->getBeginLoc()); | ||
| 2650 | } | ||
| 2651 | |||
| 2612 | struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) { | 2652 | struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) { |
| 2613 | auto casted = reinterpret_cast<const clang::ElaboratedType *>(self); | 2653 | auto casted = reinterpret_cast<const clang::ElaboratedType *>(self); |
| 2614 | return bitcast(casted->getNamedType()); | 2654 | return bitcast(casted->getNamedType()); |
| ... | @@ -3008,6 +3048,11 @@ ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldD | ... | @@ -3008,6 +3048,11 @@ ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldD |
| 3008 | return bitcast(casted->getLocation()); | 3048 | return bitcast(casted->getLocation()); |
| 3009 | } | 3049 | } |
| 3010 | 3050 | ||
| 3051 | const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const struct ZigClangFieldDecl *self) { | ||
| 3052 | auto casted = reinterpret_cast<const clang::FieldDecl *>(self); | ||
| 3053 | return reinterpret_cast<const ZigClangRecordDecl *>(casted->getParent()); | ||
| 3054 | } | ||
| 3055 | |||
| 3011 | ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *self) { | 3056 | ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *self) { |
| 3012 | auto casted = reinterpret_cast<const clang::FieldDecl *>(self); | 3057 | auto casted = reinterpret_cast<const clang::FieldDecl *>(self); |
| 3013 | return bitcast(casted->getType()); | 3058 | return bitcast(casted->getType()); |
src/zig_clang.h+18| ... | @@ -928,6 +928,13 @@ enum ZigClangUnaryExprOrTypeTrait_Kind { | ... | @@ -928,6 +928,13 @@ enum ZigClangUnaryExprOrTypeTrait_Kind { |
| 928 | ZigClangUnaryExprOrTypeTrait_KindPreferredAlignOf, | 928 | ZigClangUnaryExprOrTypeTrait_KindPreferredAlignOf, |
| 929 | }; | 929 | }; |
| 930 | 930 | ||
| 931 | enum ZigClangOffsetOfNode_Kind { | ||
| 932 | ZigClangOffsetOfNode_KindArray, | ||
| 933 | ZigClangOffsetOfNode_KindField, | ||
| 934 | ZigClangOffsetOfNode_KindIdentifier, | ||
| 935 | ZigClangOffsetOfNode_KindBase, | ||
| 936 | }; | ||
| 937 | |||
| 931 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *, | 938 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *, |
| 932 | struct ZigClangSourceLocation Loc); | 939 | struct ZigClangSourceLocation Loc); |
| 933 | ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *, | 940 | ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *, |
| ... | @@ -1161,6 +1168,16 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const | ... | @@ -1161,6 +1168,16 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const |
| 1161 | 1168 | ||
| 1162 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *); | 1169 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *); |
| 1163 | 1170 | ||
| 1171 | ZIG_EXTERN_C enum ZigClangOffsetOfNode_Kind ZigClangOffsetOfNode_getKind(const struct ZigClangOffsetOfNode *); | ||
| 1172 | ZIG_EXTERN_C unsigned ZigClangOffsetOfNode_getArrayExprIndex(const struct ZigClangOffsetOfNode *); | ||
| 1173 | ZIG_EXTERN_C struct ZigClangFieldDecl * ZigClangOffsetOfNode_getField(const struct ZigClangOffsetOfNode *); | ||
| 1174 | |||
| 1175 | ZIG_EXTERN_C unsigned ZigClangOffsetOfExpr_getNumComponents(const struct ZigClangOffsetOfExpr *); | ||
| 1176 | ZIG_EXTERN_C unsigned ZigClangOffsetOfExpr_getNumExpressions(const struct ZigClangOffsetOfExpr *); | ||
| 1177 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangOffsetOfExpr_getIndexExpr(const struct ZigClangOffsetOfExpr *, unsigned idx); | ||
| 1178 | ZIG_EXTERN_C const struct ZigClangOffsetOfNode *ZigClangOffsetOfExpr_getComponent(const struct ZigClangOffsetOfExpr *, unsigned idx); | ||
| 1179 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangOffsetOfExpr_getBeginLoc(const struct ZigClangOffsetOfExpr *); | ||
| 1180 | |||
| 1164 | ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *); | 1181 | ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *); |
| 1165 | ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *); | 1182 | ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *); |
| 1166 | 1183 | ||
| ... | @@ -1261,6 +1278,7 @@ ZIG_EXTERN_C bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *) | ... | @@ -1261,6 +1278,7 @@ ZIG_EXTERN_C bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *) |
| 1261 | ZIG_EXTERN_C bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *); | 1278 | ZIG_EXTERN_C bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *); |
| 1262 | ZIG_EXTERN_C struct ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *); | 1279 | ZIG_EXTERN_C struct ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *); |
| 1263 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *); | 1280 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *); |
| 1281 | ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const struct ZigClangFieldDecl *); | ||
| 1264 | 1282 | ||
| 1265 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *); | 1283 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *); |
| 1266 | ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *); | 1284 | ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *); |
test/run_translated_c.zig+33| ... | @@ -1073,4 +1073,37 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { | ... | @@ -1073,4 +1073,37 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 1073 | \\ return 0; | 1073 | \\ return 0; |
| 1074 | \\} | 1074 | \\} |
| 1075 | , ""); | 1075 | , ""); |
| 1076 | |||
| 1077 | cases.add("offsetof", | ||
| 1078 | \\#include <stddef.h> | ||
| 1079 | \\#include <stdlib.h> | ||
| 1080 | \\#define container_of(ptr, type, member) ({ \ | ||
| 1081 | \\ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | ||
| 1082 | \\ (type *)( (char *)__mptr - offsetof(type,member) );}) | ||
| 1083 | \\typedef struct { | ||
| 1084 | \\ int i; | ||
| 1085 | \\ struct { int x; char y; int z; } s; | ||
| 1086 | \\ float f; | ||
| 1087 | \\} container; | ||
| 1088 | \\int main(void) { | ||
| 1089 | \\ if (offsetof(container, i) != 0) abort(); | ||
| 1090 | \\ if (offsetof(container, s) <= offsetof(container, i)) abort(); | ||
| 1091 | \\ if (offsetof(container, f) <= offsetof(container, s)) abort(); | ||
| 1092 | \\ | ||
| 1093 | \\ container my_container; | ||
| 1094 | \\ typeof(my_container.s) *inner_member_pointer = &my_container.s; | ||
| 1095 | \\ float *float_member_pointer = &my_container.f; | ||
| 1096 | \\ int *anon_member_pointer = &my_container.s.z; | ||
| 1097 | \\ container *my_container_p; | ||
| 1098 | \\ | ||
| 1099 | \\ my_container_p = container_of(inner_member_pointer, container, s); | ||
| 1100 | \\ if (my_container_p != &my_container) abort(); | ||
| 1101 | \\ | ||
| 1102 | \\ my_container_p = container_of(float_member_pointer, container, f); | ||
| 1103 | \\ if (my_container_p != &my_container) abort(); | ||
| 1104 | \\ | ||
| 1105 | \\ if (container_of(anon_member_pointer, typeof(my_container.s), z) != inner_member_pointer) abort(); | ||
| 1106 | \\ return 0; | ||
| 1107 | \\} | ||
| 1108 | , ""); | ||
| 1076 | } | 1109 | } |