| ... | @@ -208,14 +208,14 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { | ... | @@ -208,14 +208,14 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 208 | | 208 | |
| 209 | fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | 209 | fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 210 | if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice | 210 | if (try c.decl_table.put(@ptrToInt(fn_decl), {})) |_| return; // Avoid processing this decl twice |
| 211 | | 211 | const rp = makeRestorePoint(c); |
| 212 | const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl))); | 212 | const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl))); |
| 213 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); | 213 | const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl); |
| 214 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); | 214 | const fn_qt = ZigClangFunctionDecl_getType(fn_decl); |
| 215 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); | 215 | const fn_type = ZigClangQualType_getTypePtr(fn_qt); |
| 216 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { | 216 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { |
| 217 | .FunctionProto => transFnProto( | 217 | .FunctionProto => transFnProto( |
| 218 | c, | 218 | rp, |
| 219 | @ptrCast(*const ZigClangFunctionProtoType, fn_type), | 219 | @ptrCast(*const ZigClangFunctionProtoType, fn_type), |
| 220 | fn_decl_loc, | 220 | fn_decl_loc, |
| 221 | fn_decl, | 221 | fn_decl, |
| ... | @@ -242,32 +242,35 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { | ... | @@ -242,32 +242,35 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void { |
| 242 | try c.tree.root_node.decls.push(decl_node); | 242 | try c.tree.root_node.decls.push(decl_node); |
| 243 | } | 243 | } |
| 244 | | 244 | |
| 245 | fn transQualType(c: *Context, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !*ast.Node { | 245 | fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) Error!*ast.Node { |
| 246 | return transType(c, ZigClangQualType_getTypePtr(qt), source_loc); | 246 | return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc); |
| | 247 | } |
| | 248 | |
| | 249 | fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType { |
| | 250 | const canon = ZigClangQualType_getCanonicalType(qt); |
| | 251 | return ZigClangQualType_getTypePtr(canon); |
| 247 | } | 252 | } |
| 248 | | 253 | |
| 249 | const RestorePoint = struct { | 254 | const RestorePoint = struct { |
| 250 | context: *Context, | 255 | c: *Context, |
| 251 | token_index: ast.TokenIndex, | 256 | token_index: ast.TokenIndex, |
| 252 | src_buf_index: usize, | 257 | src_buf_index: usize, |
| 253 | | 258 | |
| 254 | fn activate(self: RestorePoint) void { | 259 | fn activate(self: RestorePoint) void { |
| 255 | self.context.tree.tokens.shrink(self.token_index); | 260 | self.c.tree.tokens.shrink(self.token_index); |
| 256 | self.context.source_buffer.shrink(self.src_buf_index); | 261 | self.c.source_buffer.shrink(self.src_buf_index); |
| 257 | } | 262 | } |
| 258 | }; | 263 | }; |
| 259 | | 264 | |
| 260 | fn makeRestorePoint(c: *Context) RestorePoint { | 265 | fn makeRestorePoint(c: *Context) RestorePoint { |
| 261 | return RestorePoint{ | 266 | return RestorePoint{ |
| 262 | .context = c, | 267 | .c = c, |
| 263 | .token_index = c.tree.tokens.len, | 268 | .token_index = c.tree.tokens.len, |
| 264 | .src_buf_index = c.source_buffer.len(), | 269 | .src_buf_index = c.source_buffer.len(), |
| 265 | }; | 270 | }; |
| 266 | } | 271 | } |
| 267 | | 272 | |
| 268 | fn transType(c: *Context, ty: *const ZigClangType, source_loc: ZigClangSourceLocation) !*ast.Node { | 273 | fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSourceLocation) Error!*ast.Node { |
| 269 | const rp = makeRestorePoint(c); | | |
| 270 | | | |
| 271 | switch (ZigClangType_getTypeClass(ty)) { | 274 | switch (ZigClangType_getTypeClass(ty)) { |
| 272 | .Builtin => { | 275 | .Builtin => { |
| 273 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); | 276 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| ... | @@ -275,23 +278,26 @@ fn transType(c: *Context, ty: *const ZigClangType, source_loc: ZigClangSourceLoc | ... | @@ -275,23 +278,26 @@ fn transType(c: *Context, ty: *const ZigClangType, source_loc: ZigClangSourceLoc |
| 275 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type"), | 278 | else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type"), |
| 276 | } | 279 | } |
| 277 | }, | 280 | }, |
| 278 | .FunctionProto => return transFnProto(c, @ptrCast(*const ZigClangFunctionType, ty), source_loc, null, false), | 281 | .FunctionProto => { |
| | 282 | const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty); |
| | 283 | const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, null); |
| | 284 | return &fn_proto.base; |
| | 285 | }, |
| 279 | else => { | 286 | else => { |
| 280 | const type_name = c.str(ZigClangType_getTypeClassName(ty)); | 287 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); |
| 281 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", type_name); | 288 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", type_name); |
| 282 | }, | 289 | }, |
| 283 | } | 290 | } |
| 284 | } | 291 | } |
| 285 | | 292 | |
| 286 | fn transFnProto( | 293 | fn transFnProto( |
| 287 | c: *Context, | 294 | rp: RestorePoint, |
| 288 | fn_proto_ty: *const ZigClangFunctionProtoType, | 295 | fn_proto_ty: *const ZigClangFunctionProtoType, |
| 289 | source_loc: ZigClangSourceLocation, | 296 | source_loc: ZigClangSourceLocation, |
| 290 | opt_fn_decl: ?*const ZigClangFunctionDecl, | 297 | opt_fn_decl: ?*const ZigClangFunctionDecl, |
| 291 | fn_name: ?[]const u8, | 298 | fn_name: ?[]const u8, |
| 292 | ) !*ast.Node.FnProto { | 299 | ) !*ast.Node.FnProto { |
| 293 | const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty); | 300 | const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty); |
| 294 | const rp = makeRestorePoint(c); | | |
| 295 | const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) { | 301 | const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) { |
| 296 | .C => CallingConvention.C, | 302 | .C => CallingConvention.C, |
| 297 | .X86StdCall => CallingConvention.Stdcall, | 303 | .X86StdCall => CallingConvention.Stdcall, |
| ... | @@ -323,13 +329,13 @@ fn transFnProto( | ... | @@ -323,13 +329,13 @@ fn transFnProto( |
| 323 | // TODO check for align attribute | 329 | // TODO check for align attribute |
| 324 | | 330 | |
| 325 | // extern fn name(...) T | 331 | // extern fn name(...) T |
| 326 | const cc_tok = if (cc == .Stdcall) try appendToken(c, .Keyword_stdcallcc, "stdcallcc") else null; | 332 | const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null; |
| 327 | const is_export = exp: { | 333 | const is_export = exp: { |
| 328 | const fn_decl = opt_fn_decl orelse break :exp false; | 334 | const fn_decl = opt_fn_decl orelse break :exp false; |
| 329 | const has_body = ZigClangFunctionDecl_hasBody(fn_decl); | 335 | const has_body = ZigClangFunctionDecl_hasBody(fn_decl); |
| 330 | const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl); | 336 | const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl); |
| 331 | break :exp switch (storage_class) { | 337 | break :exp switch (storage_class) { |
| 332 | .None => switch (c.mode) { | 338 | .None => switch (rp.c.mode) { |
| 333 | .import => false, | 339 | .import => false, |
| 334 | .translate => has_body, | 340 | .translate => has_body, |
| 335 | }, | 341 | }, |
| ... | @@ -340,48 +346,44 @@ fn transFnProto( | ... | @@ -340,48 +346,44 @@ fn transFnProto( |
| 340 | }; | 346 | }; |
| 341 | }; | 347 | }; |
| 342 | const extern_export_inline_tok = if (is_export) | 348 | const extern_export_inline_tok = if (is_export) |
| 343 | try appendToken(c, .Keyword_export, "export") | 349 | try appendToken(rp.c, .Keyword_export, "export") |
| 344 | else if (cc == .C) | 350 | else if (cc == .C) |
| 345 | try appendToken(c, .Keyword_extern, "extern") | 351 | try appendToken(rp.c, .Keyword_extern, "extern") |
| 346 | else | 352 | else |
| 347 | null; | 353 | null; |
| 348 | const fn_tok = try appendToken(c, .Keyword_fn, "fn"); | 354 | const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn"); |
| 349 | const name_tok = if (fn_name) |n| try appendToken(c, .Identifier, "{}", n) else null; | 355 | const name_tok = if (fn_name) |n| try appendToken(rp.c, .Identifier, "{}", n) else null; |
| 350 | const lparen_tok = try appendToken(c, .LParen, "("); | 356 | const lparen_tok = try appendToken(rp.c, .LParen, "("); |
| 351 | const var_args_tok = if (is_var_args) try appendToken(c, .Ellipsis3, "...") else null; | 357 | const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null; |
| 352 | const rparen_tok = try appendToken(c, .RParen, ")"); | 358 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); |
| 353 | | 359 | |
| 354 | const return_type_node = blk: { | 360 | const return_type_node = blk: { |
| 355 | if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) { | 361 | if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) { |
| 356 | break :blk try appendIdentifier(c, "noreturn"); | 362 | break :blk try appendIdentifier(rp.c, "noreturn"); |
| 357 | } else { | 363 | } else { |
| 358 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: non-noreturn FunctionProto return type"); | 364 | const return_qt = ZigClangFunctionType_getReturnType(fn_ty); |
| 359 | //proto_node->data.fn_proto.return_type = trans_qual_type(c, | 365 | if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) { |
| 360 | // ZigClangFunctionType_getReturnType(fn_ty), source_loc); | 366 | break :blk try appendIdentifier(rp.c, "void"); |
| 361 | //if (proto_node->data.fn_proto.return_type == nullptr) { | 367 | } else { |
| 362 | // emit_warning(c, source_loc, "unsupported function proto return type"); | 368 | break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) { |
| 363 | // return nullptr; | 369 | error.UnsupportedType => { |
| 364 | //} | 370 | try emitWarning(rp.c, source_loc, "unsupported function proto return type"); |
| 365 | //// convert c_void to actual void (only for return type) | 371 | return err; |
| 366 | //// we do want to look at the AstNode instead of ZigClangQualType, because | 372 | }, |
| 367 | //// if they do something like: | 373 | else => return err, |
| 368 | //// typedef Foo void; | 374 | }; |
| 369 | //// void foo(void) -> Foo; | 375 | } |
| 370 | //// we want to keep the return type AST node. | | |
| 371 | //if (is_c_void_type(proto_node->data.fn_proto.return_type)) { | | |
| 372 | // proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "void"); | | |
| 373 | //} | | |
| 374 | } | 376 | } |
| 375 | }; | 377 | }; |
| 376 | | 378 | |
| 377 | const fn_proto = try c.a().create(ast.Node.FnProto); | 379 | const fn_proto = try rp.c.a().create(ast.Node.FnProto); |
| 378 | fn_proto.* = ast.Node.FnProto{ | 380 | fn_proto.* = ast.Node.FnProto{ |
| 379 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | 381 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, |
| 380 | .doc_comments = null, | 382 | .doc_comments = null, |
| 381 | .visib_token = null, | 383 | .visib_token = null, |
| 382 | .fn_token = fn_tok, | 384 | .fn_token = fn_tok, |
| 383 | .name_token = name_tok, | 385 | .name_token = name_tok, |
| 384 | .params = ast.Node.FnProto.ParamList.init(c.a()), | 386 | .params = ast.Node.FnProto.ParamList.init(rp.c.a()), |
| 385 | .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node }, | 387 | .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node }, |
| 386 | .var_args_token = var_args_tok, | 388 | .var_args_token = var_args_tok, |
| 387 | .extern_export_inline_token = extern_export_inline_tok, | 389 | .extern_export_inline_token = extern_export_inline_tok, |
| ... | @@ -396,14 +398,14 @@ fn transFnProto( | ... | @@ -396,14 +398,14 @@ fn transFnProto( |
| 396 | } | 398 | } |
| 397 | | 399 | |
| 398 | fn revertAndWarn( | 400 | fn revertAndWarn( |
| 399 | restore_point: RestorePoint, | 401 | rp: RestorePoint, |
| 400 | err: var, | 402 | err: var, |
| 401 | source_loc: ZigClangSourceLocation, | 403 | source_loc: ZigClangSourceLocation, |
| 402 | comptime format: []const u8, | 404 | comptime format: []const u8, |
| 403 | args: ..., | 405 | args: ..., |
| 404 | ) (@typeOf(err) || error{OutOfMemory}) { | 406 | ) (@typeOf(err) || error{OutOfMemory}) { |
| 405 | restore_point.activate(); | 407 | rp.activate(); |
| 406 | try emitWarning(restore_point.context, source_loc, format, args); | 408 | try emitWarning(rp.c, source_loc, format, args); |
| 407 | return err; | 409 | return err; |
| 408 | } | 410 | } |
| 409 | | 411 | |