diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index a569113b9d..d2db306be8 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -768,6 +768,7 @@ pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigC pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl; pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl; pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl; +pub extern fn ZigClangParmVarDecl_getOriginalType(self: ?*const struct_ZigClangParmVarDecl) struct_ZigClangQualType; pub extern fn ZigClangVarDecl_getCanonicalDecl(self: ?*const struct_ZigClangVarDecl) ?*const struct_ZigClangVarDecl; pub extern fn ZigClangVarDecl_getSectionAttribute(self: *const ZigClangVarDecl, len: *usize) ?[*]const u8; pub extern fn ZigClangFunctionDecl_getAlignedAttribute(self: *const ZigClangFunctionDecl, *const ZigClangASTContext) c_uint; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 093acf1083..18c4cafbe3 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -485,6 +485,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { block_scope.block_node = block_node; var it = proto_node.params.iterator(0); + var param_id: c_uint = 0; while (it.next()) |p| { const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*); const param_name = if (param.name_token) |name_tok| @@ -498,18 +499,27 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { const mangled_param_name = try block_scope.makeMangledName(c, param_name); + const c_param = ZigClangFunctionDecl_getParamDecl(fn_decl, param_id); + const qual_type = ZigClangParmVarDecl_getOriginalType(c_param); + const is_const = ZigClangQualType_isConstQualified(qual_type); + const arg_name = blk: { - const bare_arg_name = try std.fmt.allocPrint(c.a(), "arg_{}", .{mangled_param_name}); + const param_prefix = if (is_const) "" else "arg_"; + const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{param_prefix, mangled_param_name}); break :blk try block_scope.makeMangledName(c, bare_arg_name); }; - const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name); - node.eq_token = try appendToken(c, .Equal, "="); - node.init_node = try transCreateNodeIdentifier(c, arg_name); - node.semicolon_token = try appendToken(c, .Semicolon, ";"); - try block_node.statements.push(&node.base); - param.name_token = try appendIdentifier(c, arg_name); - _ = try appendToken(c, .Colon, ":"); + if (!is_const) { + const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name); + node.eq_token = try appendToken(c, .Equal, "="); + node.init_node = try transCreateNodeIdentifier(c, arg_name); + node.semicolon_token = try appendToken(c, .Semicolon, ";"); + try block_node.statements.push(&node.base); + param.name_token = try appendIdentifier(c, arg_name); + _ = try appendToken(c, .Colon, ":"); + } + + param_id += 1; } transCompoundStmtInline(rp, &block_scope.base, @ptrCast(*const ZigClangCompoundStmt, body_stmt), block_node) catch |err| switch (err) { diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 348c85b87b..8a1baa2d49 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1625,6 +1625,10 @@ unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionD return 0; } +ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self) { + return bitcast(reinterpret_cast(self)->getOriginalType()); +} + const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) { const clang::RecordDecl *record_decl = reinterpret_cast(zig_record_decl); const clang::RecordDecl *definition = record_decl->getDefinition(); diff --git a/src/zig_clang.h b/src/zig_clang.h index 6f8d786bf6..f7de9c2cee 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -866,6 +866,8 @@ ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigCla ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx); ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); +ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); + ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *); ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *); ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *); diff --git a/test/translate_c.zig b/test/translate_c.zig index df2c872bf9..a596ff3eb7 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -2615,4 +2615,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return foo((@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(c)))) != @intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b)))))); \\} }); + + cases.add("Don't make const parameters mutable", + \\int max(const int x, int y) { + \\ return (x > y) ? x : y; + \\} + , &[_][]const u8{ + \\pub export fn max(x: c_int, arg_y: c_int) c_int { + \\ var y = arg_y; + \\ return if (x > y) x else y; + \\} + }); + }