authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-03-09 20:49:24-08:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-03-17 00:07:33+02:00
logc558a1ae26eaa8c59e97e80ec01990e35ef50f3a
treed2afebf241d8cd363ca00b71e02f6137e1a44333
parent9a9441568070320d6549fe286300b45ffffd7b4d

translate-c: Implement generic selection expressions

Enables translation of C code that uses the `_Generic` keyword

5 files changed, 58 insertions(+), 0 deletions(-)

src/clang.zig+5
......@@ -537,6 +537,11 @@ pub const FunctionType = opaque {
537537 extern fn ZigClangFunctionType_getReturnType(*const FunctionType) QualType;
538538};
539539
540pub const GenericSelectionExpr = opaque {
541 pub const getResultExpr = ZigClangGenericSelectionExpr_getResultExpr;
542 extern fn ZigClangGenericSelectionExpr_getResultExpr(*const GenericSelectionExpr) *const Expr;
543};
544
540545pub const IfStmt = opaque {
541546 pub const getThen = ZigClangIfStmt_getThen;
542547 extern fn ZigClangIfStmt_getThen(*const IfStmt) *const Stmt;
src/translate_c.zig+12
......@@ -1058,6 +1058,10 @@ fn transStmt(
10581058 const compound_literal = @ptrCast(*const clang.CompoundLiteralExpr, stmt);
10591059 return transExpr(c, scope, compound_literal.getInitializer(), result_used);
10601060 },
1061 .GenericSelectionExprClass => {
1062 const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, stmt);
1063 return transExpr(c, scope, gen_sel.getResultExpr(), result_used);
1064 },
10611065 else => {
10621066 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});
10631067 },
......@@ -1582,6 +1586,10 @@ fn exprIsNarrowStringLiteral(expr: *const clang.Expr) bool {
15821586 const op_expr = @ptrCast(*const clang.ParenExpr, expr).getSubExpr();
15831587 return exprIsNarrowStringLiteral(op_expr);
15841588 },
1589 .GenericSelectionExprClass => {
1590 const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, expr);
1591 return exprIsNarrowStringLiteral(gen_sel.getResultExpr());
1592 },
15851593 else => return false,
15861594 }
15871595}
......@@ -2726,6 +2734,10 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {
27262734 const opcode = un_op.getOpcode();
27272735 return (opcode == .AddrOf or opcode == .Deref) and cIsFunctionDeclRef(un_op.getSubExpr());
27282736 },
2737 .GenericSelectionExprClass => {
2738 const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, expr);
2739 return cIsFunctionDeclRef(gen_sel.getResultExpr());
2740 },
27292741 else => return false,
27302742 }
27312743}
src/zig_clang.cpp+5
......@@ -2445,6 +2445,11 @@ struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClang
24452445 return bitcast(casted->getReturnType());
24462446}
24472447
2448const struct ZigClangExpr *ZigClangGenericSelectionExpr_getResultExpr(const struct ZigClangGenericSelectionExpr *self) {
2449 auto casted = reinterpret_cast<const clang::GenericSelectionExpr *>(self);
2450 return reinterpret_cast<const struct ZigClangExpr *>(casted->getResultExpr());
2451}
2452
24482453bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self) {
24492454 auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
24502455 return casted->isVariadic();
src/zig_clang.h+2
......@@ -1116,6 +1116,8 @@ ZIG_EXTERN_C bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunc
11161116ZIG_EXTERN_C enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self);
11171117ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self);
11181118
1119ZIG_EXTERN_C const struct ZigClangExpr *ZigClangGenericSelectionExpr_getResultExpr(const struct ZigClangGenericSelectionExpr *self);
1120
11191121ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self);
11201122ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self);
11211123ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i);
test/run_translated_c.zig+34
......@@ -1187,4 +1187,38 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
11871187 \\ return 0;
11881188 \\}
11891189 , "");
1190
1191 cases.add("Generic selections",
1192 \\#include <stdlib.h>
1193 \\#include <string.h>
1194 \\#include <stdint.h>
1195 \\#define my_generic_fn(X) _Generic((X), \
1196 \\ int: abs, \
1197 \\ char *: strlen, \
1198 \\ size_t: malloc, \
1199 \\ default: free \
1200 \\)(X)
1201 \\#define my_generic_val(X) _Generic((X), \
1202 \\ int: 1, \
1203 \\ const char *: "bar" \
1204 \\)
1205 \\int main(void) {
1206 \\ if (my_generic_val(100) != 1) abort();
1207 \\
1208 \\ const char *foo = "foo";
1209 \\ const char *bar = my_generic_val(foo);
1210 \\ if (strcmp(bar, "bar") != 0) abort();
1211 \\
1212 \\ if (my_generic_fn(-42) != 42) abort();
1213 \\ if (my_generic_fn("hello") != 5) abort();
1214 \\
1215 \\ size_t size = 8192;
1216 \\ uint8_t *mem = my_generic_fn(size);
1217 \\ memset(mem, 42, size);
1218 \\ if (mem[size - 1] != 42) abort();
1219 \\ my_generic_fn(mem);
1220 \\
1221 \\ return 0;
1222 \\}
1223 , "");
11901224}