Commit 715370a10a
Changed files (4)
lib/std/c/builtins.zig
@@ -188,3 +188,9 @@ pub fn __builtin_memcpy(
pub fn __builtin_expect(expr: c_long, c: c_long) callconv(.Inline) c_long {
return expr;
}
+
+// __builtin_alloca_with_align is not currently implemented.
+// It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented
+// builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the
+// run-translated-c test and the test-translate-c test to use a different non-implemented builtin.
+// pub fn __builtin_alloca_with_align(size: usize, alignment: usize) callconv(.Inline) *c_void {}
src/translate_c.zig
@@ -11,6 +11,7 @@ const math = std.math;
const ast = @import("translate_c/ast.zig");
const Node = ast.Node;
const Tag = Node.Tag;
+const c_builtins = std.c.builtins;
const CallingConvention = std.builtin.CallingConvention;
@@ -1526,7 +1527,7 @@ fn transImplicitCastExpr(
return maybeSuppressResult(c, scope, result_used, ne);
},
.BuiltinFnToFnPtr => {
- return transExpr(c, scope, sub_expr, result_used);
+ return transBuiltinFnExpr(c, scope, sub_expr, result_used);
},
.ToVoid => {
// Should only appear in the rhs and lhs of a ConditionalOperator
@@ -1542,6 +1543,22 @@ fn transImplicitCastExpr(
}
}
+fn isBuiltinDefined(name: []const u8) bool {
+ inline for (std.meta.declarations(c_builtins)) |decl| {
+ if (std.mem.eql(u8, name, decl.name)) return true;
+ }
+ return false;
+}
+
+fn transBuiltinFnExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
+ const node = try transExpr(c, scope, expr, used);
+ if (node.castTag(.identifier)) |ident| {
+ const name = ident.data;
+ if (!isBuiltinDefined(name)) return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO implement function '{s}' in std.c.builtins", .{name});
+ }
+ return node;
+}
+
fn transBoolExpr(
c: *Context,
scope: *Scope,
@@ -4759,6 +4776,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
},
.Identifier => {
const mangled_name = scope.getAlias(slice);
+ if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) {
+ try m.fail(c, "TODO implement function '{s}' in std.c.builtins", .{mangled_name});
+ return error.ParseError;
+ }
return Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
},
.LParen => {
test/run_translated_c.zig
@@ -1221,4 +1221,16 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ // See __builtin_alloca_with_align comment in std.c.builtins
+ cases.add("use of unimplemented builtin in unused function does not prevent compilation",
+ \\#include <stdlib.h>
+ \\void unused() {
+ \\ __builtin_alloca_with_align(1, 8);
+ \\}
+ \\int main(void) {
+ \\ if (__builtin_sqrt(1.0) != 1.0) abort();
+ \\ return 0;
+ \\}
+ , "");
}
test/translate_c.zig
@@ -3418,4 +3418,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const MAY_NEED_PROMOTION_HEX = @import("std").meta.promoteIntLiteral(c_int, 0x80000000, .hexadecimal);
\\pub const MAY_NEED_PROMOTION_OCT = @import("std").meta.promoteIntLiteral(c_int, 0o20000000000, .octal);
});
+
+ // See __builtin_alloca_with_align comment in std.c.builtins
+ cases.add("demote un-implemented builtins",
+ \\#define FOO(X) __builtin_alloca_with_align((X), 8)
+ , &[_][]const u8{
+ \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.c.builtins");
+ });
}