translate-c: Implement generic selection expressions
Enables translation of C code that uses the `_Generic` keyword
This commit is contained in:
committed by
Veikka Tuominen
parent
9a94415680
commit
c558a1ae26
@@ -537,6 +537,11 @@ pub const FunctionType = opaque {
|
||||
extern fn ZigClangFunctionType_getReturnType(*const FunctionType) QualType;
|
||||
};
|
||||
|
||||
pub const GenericSelectionExpr = opaque {
|
||||
pub const getResultExpr = ZigClangGenericSelectionExpr_getResultExpr;
|
||||
extern fn ZigClangGenericSelectionExpr_getResultExpr(*const GenericSelectionExpr) *const Expr;
|
||||
};
|
||||
|
||||
pub const IfStmt = opaque {
|
||||
pub const getThen = ZigClangIfStmt_getThen;
|
||||
extern fn ZigClangIfStmt_getThen(*const IfStmt) *const Stmt;
|
||||
|
||||
@@ -1058,6 +1058,10 @@ fn transStmt(
|
||||
const compound_literal = @ptrCast(*const clang.CompoundLiteralExpr, stmt);
|
||||
return transExpr(c, scope, compound_literal.getInitializer(), result_used);
|
||||
},
|
||||
.GenericSelectionExprClass => {
|
||||
const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, stmt);
|
||||
return transExpr(c, scope, gen_sel.getResultExpr(), result_used);
|
||||
},
|
||||
else => {
|
||||
return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});
|
||||
},
|
||||
@@ -1582,6 +1586,10 @@ fn exprIsNarrowStringLiteral(expr: *const clang.Expr) bool {
|
||||
const op_expr = @ptrCast(*const clang.ParenExpr, expr).getSubExpr();
|
||||
return exprIsNarrowStringLiteral(op_expr);
|
||||
},
|
||||
.GenericSelectionExprClass => {
|
||||
const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, expr);
|
||||
return exprIsNarrowStringLiteral(gen_sel.getResultExpr());
|
||||
},
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
@@ -2726,6 +2734,10 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {
|
||||
const opcode = un_op.getOpcode();
|
||||
return (opcode == .AddrOf or opcode == .Deref) and cIsFunctionDeclRef(un_op.getSubExpr());
|
||||
},
|
||||
.GenericSelectionExprClass => {
|
||||
const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, expr);
|
||||
return cIsFunctionDeclRef(gen_sel.getResultExpr());
|
||||
},
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2445,6 +2445,11 @@ struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClang
|
||||
return bitcast(casted->getReturnType());
|
||||
}
|
||||
|
||||
const struct ZigClangExpr *ZigClangGenericSelectionExpr_getResultExpr(const struct ZigClangGenericSelectionExpr *self) {
|
||||
auto casted = reinterpret_cast<const clang::GenericSelectionExpr *>(self);
|
||||
return reinterpret_cast<const struct ZigClangExpr *>(casted->getResultExpr());
|
||||
}
|
||||
|
||||
bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self) {
|
||||
auto casted = reinterpret_cast<const clang::FunctionProtoType *>(self);
|
||||
return casted->isVariadic();
|
||||
|
||||
@@ -1116,6 +1116,8 @@ ZIG_EXTERN_C bool ZigClangFunctionType_getNoReturnAttr(const struct ZigClangFunc
|
||||
ZIG_EXTERN_C enum ZigClangCallingConv ZigClangFunctionType_getCallConv(const struct ZigClangFunctionType *self);
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionType_getReturnType(const struct ZigClangFunctionType *self);
|
||||
|
||||
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangGenericSelectionExpr_getResultExpr(const struct ZigClangGenericSelectionExpr *self);
|
||||
|
||||
ZIG_EXTERN_C bool ZigClangFunctionProtoType_isVariadic(const struct ZigClangFunctionProtoType *self);
|
||||
ZIG_EXTERN_C unsigned ZigClangFunctionProtoType_getNumParams(const struct ZigClangFunctionProtoType *self);
|
||||
ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(const struct ZigClangFunctionProtoType *self, unsigned i);
|
||||
|
||||
@@ -1187,4 +1187,38 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
|
||||
cases.add("Generic selections",
|
||||
\\#include <stdlib.h>
|
||||
\\#include <string.h>
|
||||
\\#include <stdint.h>
|
||||
\\#define my_generic_fn(X) _Generic((X), \
|
||||
\\ int: abs, \
|
||||
\\ char *: strlen, \
|
||||
\\ size_t: malloc, \
|
||||
\\ default: free \
|
||||
\\)(X)
|
||||
\\#define my_generic_val(X) _Generic((X), \
|
||||
\\ int: 1, \
|
||||
\\ const char *: "bar" \
|
||||
\\)
|
||||
\\int main(void) {
|
||||
\\ if (my_generic_val(100) != 1) abort();
|
||||
\\
|
||||
\\ const char *foo = "foo";
|
||||
\\ const char *bar = my_generic_val(foo);
|
||||
\\ if (strcmp(bar, "bar") != 0) abort();
|
||||
\\
|
||||
\\ if (my_generic_fn(-42) != 42) abort();
|
||||
\\ if (my_generic_fn("hello") != 5) abort();
|
||||
\\
|
||||
\\ size_t size = 8192;
|
||||
\\ uint8_t *mem = my_generic_fn(size);
|
||||
\\ memset(mem, 42, size);
|
||||
\\ if (mem[size - 1] != 42) abort();
|
||||
\\ my_generic_fn(mem);
|
||||
\\
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user