diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 62310e8bea00..546c2fe5278e 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -806,13 +806,13 @@ pub const enum_ZigClangAPValueKind = extern enum { ZigClangAPValueAddrLabelDiff, }; pub extern fn ZigClangSourceManager_getSpellingLoc(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation; -pub extern fn ZigClangSourceManager_getFilename(arg0: ?*const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) [*c]const u8; +pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8; pub extern fn ZigClangSourceManager_getSpellingLineNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; pub extern fn ZigClangSourceManager_getSpellingColumnNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8; pub extern fn ZigClangASTContext_getPointerType(arg0: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType; pub extern fn ZigClangASTUnit_getASTContext(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext; -pub extern fn ZigClangASTUnit_getSourceManager(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangSourceManager; +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 ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl; @@ -824,6 +824,7 @@ pub extern fn ZigClangEnumDecl_getDefinition(arg0: ?*const struct_ZigClangEnumDe pub extern fn ZigClangRecordDecl_getLocation(arg0: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation; pub extern fn ZigClangEnumDecl_getLocation(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation; pub extern fn ZigClangTypedefNameDecl_getLocation(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation; +pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation; pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool; pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool; pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool; @@ -833,7 +834,7 @@ pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: str pub extern fn ZigClangTypedefType_getDecl(arg0: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl; pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType; pub extern fn ZigClangQualType_getCanonicalType(arg0: struct_ZigClangQualType) struct_ZigClangQualType; -pub extern fn ZigClangQualType_getTypePtr(arg0: struct_ZigClangQualType) ?*const struct_ZigClangType; +pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType; pub extern fn ZigClangQualType_addConst(arg0: [*c]struct_ZigClangQualType) void; pub extern fn ZigClangQualType_eq(arg0: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool; pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) bool; @@ -841,7 +842,7 @@ pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool; pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) enum_ZigClangTypeClass; pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; -pub extern fn ZigClangType_getTypeClassName(self: ?*const struct_ZigClangType) [*c]const u8; +pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8; pub extern fn ZigClangStmt_getBeginLoc(self: ?*const struct_ZigClangStmt) struct_ZigClangSourceLocation; pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) enum_ZigClangStmtClass; pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; @@ -863,6 +864,10 @@ pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint; pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr; pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void; + +pub extern fn ZigClangFunctionDecl_getType(self: *const struct_ZigClangFunctionDecl) struct_ZigClangQualType; +pub extern fn ZigClangFunctionDecl_getLocation(self: *const struct_ZigClangFunctionDecl) struct_ZigClangSourceLocation; + pub const ZigClangSourceLocation = struct_ZigClangSourceLocation; pub const ZigClangQualType = struct_ZigClangQualType; pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase; @@ -944,6 +949,10 @@ pub const ZigClangStmtClass = enum_ZigClangStmtClass; pub const ZigClangCK = enum_ZigClangCK; pub const ZigClangAPValueKind = enum_ZigClangAPValueKind; +pub const struct_ZigClangSourceLocation = extern struct { + ID: c_uint, +}; + pub const Stage2ErrorMsg = extern struct { filename_ptr: ?[*]const u8, filename_len: usize, @@ -968,8 +977,8 @@ pub extern fn ZigClangLoadFromCommandLine( resources_path: [*c]const u8, ) ?*ZigClangASTUnit; - pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind; +pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8; pub const ZigClangDeclKind = extern enum { AccessSpec, @@ -1047,3 +1056,7 @@ pub const ZigClangDeclKind = extern enum { StaticAssert, TranslationUnit, }; + +pub const struct_ZigClangQualType = extern struct { + ptr: ?*c_void, +}; diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index 7a44e8f3a03b..da2dcb414c7c 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -90,7 +90,8 @@ export fn stage2_translate_c( .import => translate_c.Mode.import, .translate => translate_c.Mode.translate, }, &errors, resources_path) catch |err| switch (err) { - error.SemanticAnalyzeFail => { + // TODO after https://github.com/ziglang/zig/issues/769 we can remove error.UnsupportedType + error.SemanticAnalyzeFail, error.UnsupportedType => { out_errors_ptr.* = errors.ptr; out_errors_len.* = errors.len; return Error.CCompileErrors; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index ddf7c6f21da9..7b349764fbe0 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -13,12 +13,16 @@ pub const Mode = enum { pub const ClangErrMsg = Stage2ErrorMsg; -pub const Error = error{OutOfMemory}; +pub const Error = error{ + OutOfMemory, + UnsupportedType, +}; const Context = struct { tree: *ast.Tree, source_buffer: *std.Buffer, err: Error, + source_manager: *ZigClangSourceManager, fn a(c: *Context) *std.mem.Allocator { return &c.tree.arena_allocator.allocator; @@ -28,6 +32,17 @@ const Context = struct { fn str(c: *Context, s: [*]const u8) ![]u8 { return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s)); } + + /// Convert a clang source location to a file:line:column string + fn locStr(c: *Context, loc: ZigClangSourceLocation) ![]u8 { + const spelling_loc = ZigClangSourceManager_getSpellingLoc(c.source_manager, loc); + const filename_c = ZigClangSourceManager_getFilename(c.source_manager, spelling_loc); + const filename = if (filename_c) |s| try c.str(s) else ([]const u8)("(no file)"); + + const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc); + const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc); + return std.fmt.allocPrint(c.a(), "{}:{}:{}", filename, line, column); + } }; pub fn translate( @@ -78,6 +93,7 @@ pub fn translate( var context = Context{ .tree = tree, .source_buffer = &source_buffer, + .source_manager = ZigClangASTUnit_getSourceManager(ast_unit), .err = undefined, }; @@ -105,27 +121,57 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl)); }, .Typedef => { - try appendToken(c, .LineComment, "// TODO translate typedef"); + try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs"); }, .Enum => { - try appendToken(c, .LineComment, "// TODO translate enum"); + try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums"); }, .Record => { - try appendToken(c, .LineComment, "// TODO translate struct"); + try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs"); }, .Var => { - try appendToken(c, .LineComment, "// TODO translate variable"); + try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables"); }, else => { - // TODO emit_warning(c, bitcast(decl->getLocation()), "ignoring %s decl", decl->getDeclKindName()); - try appendToken(c, .LineComment, "// TODO translate unknown decl"); + const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl)); + try emitWarning(c, ZigClangDecl_getLocation(decl), "ignoring {} declaration", decl_name); }, } } fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { const fn_name = c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl))); - try appendToken(c, .LineComment, "// TODO translate function '{}'", fn_name); + + // TODO The C++ code has this: + //if (get_global(c, fn_name)) { + // // we already saw this function + // return; + //} + + const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); + const proto_node = transQualType(c, ZigClangFunctionDecl_getType(fn_decl), fn_decl_loc) catch |e| switch (e) { + error.UnsupportedType => { + try emitWarning(c, fn_decl_loc, "unable to resolve prototype of function '{}'", fn_name); + return; + }, + else => return e, + }; + + try emitWarning(c, fn_decl_loc, "TODO implement translate-c for function decls"); +} + +fn transQualType(c: *Context, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !*ast.Node { + return transType(c, ZigClangQualType_getTypePtr(qt), source_loc); +} + +fn transType(c: *Context, ty: *const ZigClangType, source_loc: ZigClangSourceLocation) !*ast.Node { + const type_name = c.str(ZigClangType_getTypeClassName(ty)); + try emitWarning(c, source_loc, "unsupported type: '{}'", type_name); + return error.UnsupportedType; +} + +fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void { + try appendToken(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args); } fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !void { diff --git a/src/translate_c.cpp b/src/translate_c.cpp index eefdf7e2601b..706d296fc036 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -4009,7 +4009,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt return child_scope; } -static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { +static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) { Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl)); if (get_global(c, fn_name)) { @@ -4017,26 +4017,28 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { return; } - AstNode *proto_node = trans_qual_type(c, bitcast(fn_decl->getType()), bitcast(fn_decl->getLocation())); + AstNode *proto_node = trans_qual_type(c, ZigClangFunctionDecl_getType(fn_decl), + ZigClangFunctionDecl_getLocation(fn_decl)); if (proto_node == nullptr) { - emit_warning(c, bitcast(fn_decl->getLocation()), "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); + emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), + "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); return; } proto_node->data.fn_proto.name = fn_name; - proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); + proto_node->data.fn_proto.is_extern = !((const clang::FunctionDecl*)fn_decl)->hasBody(); - clang::StorageClass sc = fn_decl->getStorageClass(); + clang::StorageClass sc = ((const clang::FunctionDecl*)fn_decl)->getStorageClass(); if (sc == clang::SC_None) { proto_node->data.fn_proto.visib_mod = c->visib_mod; - proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false; + proto_node->data.fn_proto.is_export = ((const clang::FunctionDecl*)fn_decl)->hasBody() ? c->want_export : false; } else if (sc == clang::SC_Extern || sc == clang::SC_Static) { proto_node->data.fn_proto.visib_mod = c->visib_mod; } else if (sc == clang::SC_PrivateExtern) { - emit_warning(c, bitcast(fn_decl->getLocation()), "unsupported storage class: private extern"); + emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern"); return; } else { - emit_warning(c, bitcast(fn_decl->getLocation()), "unsupported storage class: unknown"); + emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: unknown"); return; } @@ -4044,7 +4046,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(i); - const clang::ParmVarDecl *param = fn_decl->getParamDecl(i); + const clang::ParmVarDecl *param = ((const clang::FunctionDecl*)fn_decl)->getParamDecl(i); const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param); Buf *proto_param_name; @@ -4063,7 +4065,7 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { param_node->data.param_decl.name = scope_var->zig_name; } - if (!fn_decl->hasBody()) { + if (!((const clang::FunctionDecl*)fn_decl)->hasBody()) { // just a prototype add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node); return; @@ -4071,11 +4073,11 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { // actual function definition with body c->ptr_params.clear(); - const ZigClangStmt *body = bitcast(fn_decl->getBody()); + const ZigClangStmt *body = bitcast(((const clang::FunctionDecl*)fn_decl)->getBody()); AstNode *actual_body_node; TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node); if (result_scope == nullptr) { - emit_warning(c, bitcast(fn_decl->getLocation()), "unable to translate function"); + emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unable to translate function"); return; } assert(actual_body_node != nullptr); @@ -4558,7 +4560,7 @@ static bool decl_visitor(void *context, const ZigClangDecl *decl) { switch (ZigClangDecl_getKind(decl)) { case ZigClangDeclFunction: - visit_fn_decl(c, reinterpret_cast(decl)); + visit_fn_decl(c, reinterpret_cast(decl)); break; case ZigClangDeclTypedef: resolve_typedef_decl(c, reinterpret_cast(decl)); diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 17ee80005972..a96ec3aa46fc 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1142,6 +1142,16 @@ ZigClangQualType ZigClangEnumDecl_getIntegerType(const ZigClangEnumDecl *self) { return bitcast(reinterpret_cast(self)->getIntegerType()); } +struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *self) { + auto casted = reinterpret_cast(self); + return bitcast(casted->getType()); +} + +struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *self) { + auto casted = reinterpret_cast(self); + return bitcast(casted->getLocation()); +} + const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) { auto casted = reinterpret_cast(self); const clang::TypedefNameDecl *name_decl = casted->getDecl(); diff --git a/src/zig_clang.h b/src/zig_clang.h index 777ad8c34bf7..46074fc8402d 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -599,6 +599,9 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangEnumDecl_getLocation(const st ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const struct ZigClangTypedefNameDecl *); ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct ZigClangDecl *); +ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *); +ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *); + ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl); ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl); ZIG_EXTERN_C bool ZigClangRecordDecl_isAnonymousStructOrUnion(const struct ZigClangRecordDecl *record_decl);