Skip to content

Commit a6f7a9c

Browse files
committed
translate-c: we have our first test of self-hosted
See #1964
1 parent d065f29 commit a6f7a9c

File tree

7 files changed

+320
-123
lines changed

7 files changed

+320
-123
lines changed

src-self-hosted/clang.zig

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ pub const struct_ZigClangSkipFunctionBodiesScope = @OpaqueType();
5656
pub const struct_ZigClangSourceManager = @OpaqueType();
5757
pub const struct_ZigClangSourceRange = @OpaqueType();
5858
pub const struct_ZigClangStmt = @OpaqueType();
59-
pub const struct_ZigClangStorageClass = @OpaqueType();
6059
pub const struct_ZigClangStringLiteral = @OpaqueType();
6160
pub const struct_ZigClangStringRef = @OpaqueType();
6261
pub const struct_ZigClangSwitchStmt = @OpaqueType();
@@ -513,6 +512,10 @@ pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
513512

514513
pub extern fn ZigClangFunctionDecl_getType(self: *const struct_ZigClangFunctionDecl) struct_ZigClangQualType;
515514
pub extern fn ZigClangFunctionDecl_getLocation(self: *const struct_ZigClangFunctionDecl) struct_ZigClangSourceLocation;
515+
pub extern fn ZigClangFunctionDecl_hasBody(self: *const struct_ZigClangFunctionDecl) bool;
516+
pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const struct_ZigClangFunctionDecl) ZigClangStorageClass;
517+
pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const struct_ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
518+
516519
pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
517520

518521
pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool;
@@ -584,7 +587,6 @@ pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesSco
584587
pub const ZigClangSourceManager = struct_ZigClangSourceManager;
585588
pub const ZigClangSourceRange = struct_ZigClangSourceRange;
586589
pub const ZigClangStmt = struct_ZigClangStmt;
587-
pub const ZigClangStorageClass = struct_ZigClangStorageClass;
588590
pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
589591
pub const ZigClangStringRef = struct_ZigClangStringRef;
590592
pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
@@ -849,3 +851,12 @@ pub const ZigClangCallingConv = extern enum {
849851
PreserveAll,
850852
AArch64VectorCall,
851853
};
854+
855+
pub const ZigClangStorageClass = extern enum {
856+
None,
857+
Extern,
858+
Static,
859+
PrivateExtern,
860+
Auto,
861+
Register,
862+
};

src-self-hosted/translate_c.zig

Lines changed: 207 additions & 109 deletions
Large diffs are not rendered by default.

src/translate_c.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4038,15 +4038,15 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
40384038
}
40394039

40404040
proto_node->data.fn_proto.name = fn_name;
4041-
proto_node->data.fn_proto.is_extern = !((const clang::FunctionDecl*)fn_decl)->hasBody();
4041+
proto_node->data.fn_proto.is_extern = !ZigClangFunctionDecl_hasBody(fn_decl);
40424042

4043-
clang::StorageClass sc = ((const clang::FunctionDecl*)fn_decl)->getStorageClass();
4044-
if (sc == clang::SC_None) {
4043+
ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
4044+
if (sc == ZigClangStorageClass_None) {
40454045
proto_node->data.fn_proto.visib_mod = c->visib_mod;
4046-
proto_node->data.fn_proto.is_export = ((const clang::FunctionDecl*)fn_decl)->hasBody() ? c->want_export : false;
4047-
} else if (sc == clang::SC_Extern || sc == clang::SC_Static) {
4046+
proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
4047+
} else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
40484048
proto_node->data.fn_proto.visib_mod = c->visib_mod;
4049-
} else if (sc == clang::SC_PrivateExtern) {
4049+
} else if (sc == ZigClangStorageClass_PrivateExtern) {
40504050
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
40514051
return;
40524052
} else {
@@ -4058,7 +4058,7 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
40584058

40594059
for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
40604060
AstNode *param_node = proto_node->data.fn_proto.params.at(i);
4061-
const clang::ParmVarDecl *param = ((const clang::FunctionDecl*)fn_decl)->getParamDecl(i);
4061+
const ZigClangParmVarDecl *param = ZigClangFunctionDecl_getParamDecl(fn_decl, i);
40624062
const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param);
40634063

40644064
Buf *proto_param_name;
@@ -4077,15 +4077,15 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
40774077
param_node->data.param_decl.name = scope_var->zig_name;
40784078
}
40794079

4080-
if (!((const clang::FunctionDecl*)fn_decl)->hasBody()) {
4080+
if (!ZigClangFunctionDecl_hasBody(fn_decl)) {
40814081
// just a prototype
40824082
add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
40834083
return;
40844084
}
40854085

40864086
// actual function definition with body
40874087
c->ptr_params.clear();
4088-
const ZigClangStmt *body = bitcast(((const clang::FunctionDecl*)fn_decl)->getBody());
4088+
const ZigClangStmt *body = ZigClangFunctionDecl_getBody(fn_decl);
40894089
AstNode *actual_body_node;
40904090
TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
40914091
if (result_scope == nullptr) {

src/zig_clang.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,25 @@ static_assert((clang::CallingConv)ZigClangCallingConv_PreserveMost == clang::CC_
12361236
static_assert((clang::CallingConv)ZigClangCallingConv_PreserveAll == clang::CC_PreserveAll, "");
12371237
static_assert((clang::CallingConv)ZigClangCallingConv_AArch64VectorCall == clang::CC_AArch64VectorCall, "");
12381238

1239+
void ZigClang_detect_enum_StorageClass(clang::StorageClass x) {
1240+
switch (x) {
1241+
case clang::SC_None:
1242+
case clang::SC_Extern:
1243+
case clang::SC_Static:
1244+
case clang::SC_PrivateExtern:
1245+
case clang::SC_Auto:
1246+
case clang::SC_Register:
1247+
break;
1248+
}
1249+
}
1250+
1251+
static_assert((clang::StorageClass)ZigClangStorageClass_None == clang::SC_None, "");
1252+
static_assert((clang::StorageClass)ZigClangStorageClass_Extern == clang::SC_Extern, "");
1253+
static_assert((clang::StorageClass)ZigClangStorageClass_Static == clang::SC_Static, "");
1254+
static_assert((clang::StorageClass)ZigClangStorageClass_PrivateExtern == clang::SC_PrivateExtern, "");
1255+
static_assert((clang::StorageClass)ZigClangStorageClass_Auto == clang::SC_Auto, "");
1256+
static_assert((clang::StorageClass)ZigClangStorageClass_Register == clang::SC_Register, "");
1257+
12391258

12401259
static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
12411260
static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
@@ -1434,6 +1453,30 @@ struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigC
14341453
return bitcast(casted->getLocation());
14351454
}
14361455

1456+
bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *self) {
1457+
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1458+
return casted->hasBody();
1459+
}
1460+
1461+
enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *self) {
1462+
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1463+
return (ZigClangStorageClass)casted->getStorageClass();
1464+
}
1465+
1466+
const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *self,
1467+
unsigned i)
1468+
{
1469+
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1470+
const clang::ParmVarDecl *parm_var_decl = casted->getParamDecl(i);
1471+
return reinterpret_cast<const ZigClangParmVarDecl *>(parm_var_decl);
1472+
}
1473+
1474+
const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *self) {
1475+
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1476+
const clang::Stmt *stmt = casted->getBody();
1477+
return reinterpret_cast<const ZigClangStmt *>(stmt);
1478+
}
1479+
14371480
const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) {
14381481
auto casted = reinterpret_cast<const clang::TypedefType *>(self);
14391482
const clang::TypedefNameDecl *name_decl = casted->getDecl();

src/zig_clang.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ struct ZigClangSkipFunctionBodiesScope;
8888
struct ZigClangSourceManager;
8989
struct ZigClangSourceRange;
9090
struct ZigClangStmt;
91-
struct ZigClangStorageClass;
9291
struct ZigClangStringLiteral;
9392
struct ZigClangStringRef;
9493
struct ZigClangSwitchStmt;
@@ -700,6 +699,18 @@ enum ZigClangCallingConv {
700699
ZigClangCallingConv_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
701700
};
702701

702+
enum ZigClangStorageClass {
703+
// These are legal on both functions and variables.
704+
ZigClangStorageClass_None,
705+
ZigClangStorageClass_Extern,
706+
ZigClangStorageClass_Static,
707+
ZigClangStorageClass_PrivateExtern,
708+
709+
// These are only legal on variables.
710+
ZigClangStorageClass_Auto,
711+
ZigClangStorageClass_Register,
712+
};
713+
703714
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
704715
struct ZigClangSourceLocation Loc);
705716
ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
@@ -742,6 +753,10 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct
742753

743754
ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *);
744755
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *);
756+
ZIG_EXTERN_C bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *);
757+
ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *);
758+
ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i);
759+
ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *);
745760

746761
ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl);
747762
ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl);

test/tests.zig

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ pub const TranslateCContext = struct {
903903
sources: ArrayList(SourceFile),
904904
expected_lines: ArrayList([]const u8),
905905
allow_warnings: bool,
906+
stage2: bool,
906907

907908
const SourceFile = struct {
908909
filename: []const u8,
@@ -955,7 +956,8 @@ pub const TranslateCContext = struct {
955956
var zig_args = ArrayList([]const u8).init(b.allocator);
956957
zig_args.append(b.zig_exe) catch unreachable;
957958

958-
zig_args.append("translate-c") catch unreachable;
959+
const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
960+
zig_args.append(translate_c_cmd) catch unreachable;
959961
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
960962

961963
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
@@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct {
10521054
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
10531055
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
10541056
.allow_warnings = allow_warnings,
1057+
.stage2 = false,
10551058
};
10561059

10571060
tc.addSourceFile(filename, source);
@@ -1072,6 +1075,26 @@ pub const TranslateCContext = struct {
10721075
self.addCase(tc);
10731076
}
10741077

1078+
pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1079+
for ([]bool{ false, true }) |stage2| {
1080+
const tc = self.create(false, "source.c", name, source, expected_lines);
1081+
tc.stage2 = stage2;
1082+
self.addCase(tc);
1083+
}
1084+
}
1085+
1086+
pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1087+
const tc = self.create(false, "source.c", name, source, expected_lines);
1088+
tc.stage2 = true;
1089+
self.addCase(tc);
1090+
}
1091+
1092+
pub fn addC_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1093+
const tc = self.create(false, "source.c", name, source, expected_lines);
1094+
tc.stage2 = true;
1095+
self.addCase(tc);
1096+
}
1097+
10751098
pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
10761099
const tc = self.create(true, "source.h", name, source, expected_lines);
10771100
self.addCase(tc);
@@ -1080,7 +1103,8 @@ pub const TranslateCContext = struct {
10801103
pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
10811104
const b = self.b;
10821105

1083-
const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;
1106+
const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
1107+
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", translate_c_cmd, case.name) catch unreachable;
10841108
if (self.test_filter) |filter| {
10851109
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
10861110
}

test/translate_c.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ const tests = @import("tests.zig");
22
const builtin = @import("builtin");
33

44
pub fn addCases(cases: *tests.TranslateCContext) void {
5+
cases.add_both("simple noreturn fn",
6+
\\void __attribute__((noreturn)) foo(void);
7+
,
8+
\\extern fn foo() noreturn;
9+
);
10+
511
cases.add("macro with left shift",
612
\\#define REDISMODULE_READ (1<<0)
713
,

0 commit comments

Comments
 (0)