authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-01-10 13:36:42+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-10 16:34:40-05:00
log570ffc470e1b3b186c079cea1c07adefe6d11c8a
tree2f93d933f85a402b0f33da68b8e4c7f780adc4e4
parente06a6b9645827fa35cfa388bbea8813206d444ad

Handle forward-declared functions

Closes #4130

5 files changed, 59 insertions(+), 4 deletions(-)

src-self-hosted/clang.zig+5
......@@ -761,6 +761,7 @@ pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*st
761761pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
762762pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
763763pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
764pub extern fn ZigClangTagDecl_isThisDeclarationADefinition(self: *const ZigClangTagDecl) bool;
764765pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;
765766pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
766767pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigClangFieldDecl) ?*const struct_ZigClangFieldDecl;
......@@ -847,7 +848,11 @@ pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunction
847848pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
848849pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
849850pub extern fn ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(self: *const ZigClangFunctionDecl) bool;
851pub extern fn ZigClangFunctionDecl_isThisDeclarationADefinition(self: *const ZigClangFunctionDecl) bool;
852pub extern fn ZigClangFunctionDecl_doesThisDeclarationHaveABody(self: *const ZigClangFunctionDecl) bool;
850853pub extern fn ZigClangFunctionDecl_isInlineSpecified(self: *const ZigClangFunctionDecl) bool;
854pub extern fn ZigClangFunctionDecl_isDefined(self: *const ZigClangFunctionDecl) bool;
855pub extern fn ZigClangFunctionDecl_getDefinition(self: *const ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl;
851856pub extern fn ZigClangFunctionDecl_getSectionAttribute(self: *const ZigClangFunctionDecl, len: *usize) ?[*]const u8;
852857
853858pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
src-self-hosted/translate_c.zig+12-3
......@@ -414,6 +414,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
414414 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
415415 if (c.global_scope.sym_table.contains(fn_name))
416416 return; // Avoid processing this decl twice
417
418 // Skip this declaration if a proper definition exists
419 if (!ZigClangFunctionDecl_isThisDeclarationADefinition(fn_decl)) {
420 if (ZigClangFunctionDecl_getDefinition(fn_decl)) |def|
421 return visitFnDecl(c, def);
422 }
423
417424 const rp = makeRestorePoint(c);
418425 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
419426 const has_body = ZigClangFunctionDecl_hasBody(fn_decl);
......@@ -671,7 +678,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
671678 return transTypeDefAsBuiltin(c, typedef_decl, "isize")
672679 else if (mem.eql(u8, checked_name, "size_t"))
673680 return transTypeDefAsBuiltin(c, typedef_decl, "usize");
674
681
675682 if (!top_level_visit) {
676683 return transCreateNodeIdentifier(c, checked_name);
677684 }
......@@ -703,7 +710,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
703710
704711 var bare_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, record_decl)));
705712 var is_unnamed = false;
706 if (ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) or bare_name.len == 0) {
713 // Record declarations such as `struct {...} x` have no name but they're not
714 // anonymous hence here isAnonymousStructOrUnion is not needed
715 if (bare_name.len == 0) {
707716 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
708717 is_unnamed = true;
709718 }
......@@ -769,7 +778,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
769778
770779 var is_anon = false;
771780 var raw_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, field_decl)));
772 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl) or raw_name.len == 0) {
781 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
773782 raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
774783 is_anon = true;
775784 }
src/zig_clang.cpp+25
......@@ -1734,6 +1734,31 @@ bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const
17341734 return casted->doesDeclarationForceExternallyVisibleDefinition();
17351735}
17361736
1737bool ZigClangFunctionDecl_isThisDeclarationADefinition(const struct ZigClangFunctionDecl *self) {
1738 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1739 return casted->isThisDeclarationADefinition();
1740}
1741
1742bool ZigClangFunctionDecl_doesThisDeclarationHaveABody(const struct ZigClangFunctionDecl *self) {
1743 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1744 return casted->doesThisDeclarationHaveABody();
1745}
1746
1747bool ZigClangFunctionDecl_isDefined(const struct ZigClangFunctionDecl *self) {
1748 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1749 return casted->isDefined();
1750}
1751
1752const ZigClangFunctionDecl* ZigClangFunctionDecl_getDefinition(const struct ZigClangFunctionDecl *self) {
1753 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1754 return reinterpret_cast<const ZigClangFunctionDecl *>(casted->getDefinition());
1755}
1756
1757bool ZigClangTagDecl_isThisDeclarationADefinition(const struct ZigClangTagDecl *self) {
1758 auto casted = reinterpret_cast<const clang::TagDecl *>(self);
1759 return casted->isThisDeclarationADefinition();
1760}
1761
17371762bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *self) {
17381763 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
17391764 return casted->isInlineSpecified();
src/zig_clang.h+6
......@@ -854,6 +854,8 @@ ZIG_EXTERN_C enum ZigClangPreprocessedEntity_EntityKind ZigClangPreprocessedEnti
854854ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty);
855855ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumType_getDecl(const struct ZigClangEnumType *record_ty);
856856
857ZIG_EXTERN_C bool ZigClangTagDecl_isThisDeclarationADefinition(const struct ZigClangTagDecl *);
858
857859ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangRecordDecl_getCanonicalDecl(const struct ZigClangRecordDecl *record_decl);
858860ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(const struct ZigClangEnumDecl *);
859861ZIG_EXTERN_C const struct ZigClangFieldDecl *ZigClangFieldDecl_getCanonicalDecl(const ZigClangFieldDecl *);
......@@ -880,7 +882,11 @@ ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(cons
880882ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i);
881883ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *);
882884ZIG_EXTERN_C bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const struct ZigClangFunctionDecl *);
885ZIG_EXTERN_C bool ZigClangFunctionDecl_isThisDeclarationADefinition(const struct ZigClangFunctionDecl *);
886ZIG_EXTERN_C bool ZigClangFunctionDecl_doesThisDeclarationHaveABody(const struct ZigClangFunctionDecl *);
883887ZIG_EXTERN_C bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *);
888ZIG_EXTERN_C bool ZigClangFunctionDecl_isDefined(const struct ZigClangFunctionDecl *);
889ZIG_EXTERN_C const struct ZigClangFunctionDecl* ZigClangFunctionDecl_getDefinition(const struct ZigClangFunctionDecl *);
884890ZIG_EXTERN_C const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *, size_t *);
885891
886892ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl);
test/run_translated_c.zig+11-1
......@@ -3,6 +3,16 @@ const tests = @import("tests.zig");
33const nl = std.cstr.line_sep;
44
55pub fn addCases(cases: *tests.RunTranslatedCContext) void {
6 cases.add("forward declarations",
7 \\#include <stdlib.h>
8 \\int foo(int);
9 \\int foo(int x) { return x + 1; }
10 \\int main(int argc, char **argv) {
11 \\ if (foo(2) != 3) abort();
12 \\ return 0;
13 \\}
14 , "");
15
616 cases.add("typedef and function pointer",
717 \\#include <stdlib.h>
818 \\typedef struct _Foo Foo;
......@@ -18,7 +28,7 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1828 \\ return 0;
1929 \\}
2030 , "");
21
31
2232 cases.add("ternary operator",
2333 \\#include <stdlib.h>
2434 \\static int cnt = 0;