diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index c87d2dc942..46e9eef723 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -761,6 +761,7 @@ pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*st pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager; pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool; pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl; +pub extern fn ZigClangTagDecl_isThisDeclarationADefinition(self: *const ZigClangTagDecl) bool; pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl; pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl; pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigClangFieldDecl) ?*const struct_ZigClangFieldDecl; @@ -847,7 +848,11 @@ pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunction pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl; pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt; pub extern fn ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(self: *const ZigClangFunctionDecl) bool; +pub extern fn ZigClangFunctionDecl_isThisDeclarationADefinition(self: *const ZigClangFunctionDecl) bool; +pub extern fn ZigClangFunctionDecl_doesThisDeclarationHaveABody(self: *const ZigClangFunctionDecl) bool; pub extern fn ZigClangFunctionDecl_isInlineSpecified(self: *const ZigClangFunctionDecl) bool; +pub extern fn ZigClangFunctionDecl_isDefined(self: *const ZigClangFunctionDecl) bool; +pub extern fn ZigClangFunctionDecl_getDefinition(self: *const ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl; pub extern fn ZigClangFunctionDecl_getSectionAttribute(self: *const ZigClangFunctionDecl, len: *usize) ?[*]const u8; pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index b3064869fc..3cf00bc4e7 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -414,6 +414,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl))); if (c.global_scope.sym_table.contains(fn_name)) return; // Avoid processing this decl twice + + // Skip this declaration if a proper definition exists + if (!ZigClangFunctionDecl_isThisDeclarationADefinition(fn_decl)) { + if (ZigClangFunctionDecl_getDefinition(fn_decl)) |def| + return visitFnDecl(c, def); + } + const rp = makeRestorePoint(c); const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); const has_body = ZigClangFunctionDecl_hasBody(fn_decl); @@ -671,7 +678,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l return transTypeDefAsBuiltin(c, typedef_decl, "isize") else if (mem.eql(u8, checked_name, "size_t")) return transTypeDefAsBuiltin(c, typedef_decl, "usize"); - + if (!top_level_visit) { return transCreateNodeIdentifier(c, checked_name); } @@ -703,7 +710,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl))); var is_unnamed = false; - if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) { + // Record declarations such as `struct {...} x` have no name but they're not + // anonymous hence here isAnonymousStructOrUnion is not needed + if (bare_name.len == 0) { bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); is_unnamed = true; } @@ -769,7 +778,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* var is_anon = false; var raw_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl))); - if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl) or raw_name.len == 0) { + if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) { raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); is_anon = true; } diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 426fec2c0c..dd003a4f9c 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1734,6 +1734,31 @@ bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const return casted->doesDeclarationForceExternallyVisibleDefinition(); } +bool ZigClangFunctionDecl_isThisDeclarationADefinition(const struct ZigClangFunctionDecl *self) { + auto casted = reinterpret_cast(self); + return casted->isThisDeclarationADefinition(); +} + +bool ZigClangFunctionDecl_doesThisDeclarationHaveABody(const struct ZigClangFunctionDecl *self) { + auto casted = reinterpret_cast(self); + return casted->doesThisDeclarationHaveABody(); +} + +bool ZigClangFunctionDecl_isDefined(const struct ZigClangFunctionDecl *self) { + auto casted = reinterpret_cast(self); + return casted->isDefined(); +} + +const ZigClangFunctionDecl* ZigClangFunctionDecl_getDefinition(const struct ZigClangFunctionDecl *self) { + auto casted = reinterpret_cast(self); + return reinterpret_cast(casted->getDefinition()); +} + +bool ZigClangTagDecl_isThisDeclarationADefinition(const struct ZigClangTagDecl *self) { + auto casted = reinterpret_cast(self); + return casted->isThisDeclarationADefinition(); +} + bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *self) { auto casted = reinterpret_cast(self); return casted->isInlineSpecified(); diff --git a/src/zig_clang.h b/src/zig_clang.h index 9cc945f8b8..e9bf207b2a 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -854,6 +854,8 @@ ZIG_EXTERN_C enum ZigClangPreprocessedEntity_EntityKind ZigClangPreprocessedEnti ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty); ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struct ZigClangEnumType *record_ty); +ZIG_EXTERN_C bool ZigClangTagDecl_isThisDeclarationADefinition(const struct ZigClangTagDecl *); + ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl); ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *); ZIG_EXTERN_C const struct ZigClangFieldDecl *ZigClangFieldDecl_getCanonicalDecl(const ZigClangFieldDecl *); @@ -880,7 +882,11 @@ ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(cons ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i); ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *); ZIG_EXTERN_C bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const struct ZigClangFunctionDecl *); +ZIG_EXTERN_C bool ZigClangFunctionDecl_isThisDeclarationADefinition(const struct ZigClangFunctionDecl *); +ZIG_EXTERN_C bool ZigClangFunctionDecl_doesThisDeclarationHaveABody(const struct ZigClangFunctionDecl *); ZIG_EXTERN_C bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *); +ZIG_EXTERN_C bool ZigClangFunctionDecl_isDefined(const struct ZigClangFunctionDecl *); +ZIG_EXTERN_C const struct ZigClangFunctionDecl* ZigClangFunctionDecl_getDefinition(const struct ZigClangFunctionDecl *); ZIG_EXTERN_C const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *, size_t *); ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl); diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index dd34713ee3..d48c3dc5c0 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -3,6 +3,16 @@ const tests = @import("tests.zig"); const nl = std.cstr.line_sep; pub fn addCases(cases: *tests.RunTranslatedCContext) void { + cases.add("forward declarations", + \\#include + \\int foo(int); + \\int foo(int x) { return x + 1; } + \\int main(int argc, char **argv) { + \\ if (foo(2) != 3) abort(); + \\ return 0; + \\} + , ""); + cases.add("typedef and function pointer", \\#include \\typedef struct _Foo Foo; @@ -18,7 +28,7 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); - + cases.add("ternary operator", \\#include \\static int cnt = 0;