| ... | ... | @@ -272,7 +272,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 272 | 272 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { |
| 273 | 273 | .FunctionProto => blk: { |
| 274 | 274 | const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type); |
| 275 | | break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) { |
| 275 | break :blk transFnProto(rp, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) { |
| 276 | 276 | error.UnsupportedType => { |
| 277 | 277 | return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function", .{}); |
| 278 | 278 | }, |
| ... | ... | @@ -1178,11 +1178,11 @@ fn transCreateNodePtrType( |
| 1178 | 1178 | break :blk lbracket; |
| 1179 | 1179 | }, |
| 1180 | 1180 | .Identifier => blk: { |
| 1181 | | _ = try appendToken(c, .LBracket, "["); |
| 1181 | const lbracket = try appendToken(c, .LBracket, "["); // Rendering checks if this token + 2 == .Identifier, so needs to return this token |
| 1182 | 1182 | _ = try appendToken(c, .Asterisk, "*"); |
| 1183 | | const c_ident = try appendToken(c, .Identifier, "c"); |
| 1183 | _ = try appendToken(c, .Identifier, "c"); |
| 1184 | 1184 | _ = try appendToken(c, .RBracket, "]"); |
| 1185 | | break :blk c_ident; |
| 1185 | break :blk lbracket; |
| 1186 | 1186 | }, |
| 1187 | 1187 | .Asterisk => try appendToken(c, .Asterisk, "*"), |
| 1188 | 1188 | else => unreachable, |
| ... | ... | @@ -1281,7 +1281,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1281 | 1281 | }, |
| 1282 | 1282 | .FunctionProto => { |
| 1283 | 1283 | const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty); |
| 1284 | | const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, false); |
| 1284 | const fn_proto = try transFnProto(rp, null, fn_proto_ty, source_loc, null, false); |
| 1285 | 1285 | return &fn_proto.base; |
| 1286 | 1286 | }, |
| 1287 | 1287 | .Paren => { |
| ... | ... | @@ -1352,6 +1352,7 @@ fn transCC( |
| 1352 | 1352 | |
| 1353 | 1353 | fn transFnProto( |
| 1354 | 1354 | rp: RestorePoint, |
| 1355 | fn_decl: ?*const ZigClangFunctionDecl, |
| 1355 | 1356 | fn_proto_ty: *const ZigClangFunctionProtoType, |
| 1356 | 1357 | source_loc: ZigClangSourceLocation, |
| 1357 | 1358 | fn_decl_context: ?FnDeclContext, |
| ... | ... | @@ -1360,19 +1361,7 @@ fn transFnProto( |
| 1360 | 1361 | const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty); |
| 1361 | 1362 | const cc = try transCC(rp, fn_ty, source_loc); |
| 1362 | 1363 | const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty); |
| 1363 | | const param_count: usize = ZigClangFunctionProtoType_getNumParams(fn_proto_ty); |
| 1364 | | var i: usize = 0; |
| 1365 | | while (i < param_count) : (i += 1) { |
| 1366 | | return revertAndWarn( |
| 1367 | | rp, |
| 1368 | | error.UnsupportedType, |
| 1369 | | source_loc, |
| 1370 | | "TODO: implement parameters for FunctionProto in transType", |
| 1371 | | .{}, |
| 1372 | | ); |
| 1373 | | } |
| 1374 | | |
| 1375 | | return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 1364 | return finishTransFnProto(rp, fn_decl, fn_proto_ty, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 1376 | 1365 | } |
| 1377 | 1366 | |
| 1378 | 1367 | fn transFnNoProto( |
| ... | ... | @@ -1384,11 +1373,13 @@ fn transFnNoProto( |
| 1384 | 1373 | ) !*ast.Node.FnProto { |
| 1385 | 1374 | const cc = try transCC(rp, fn_ty, source_loc); |
| 1386 | 1375 | const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true; |
| 1387 | | return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 1376 | return finishTransFnProto(rp, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); |
| 1388 | 1377 | } |
| 1389 | 1378 | |
| 1390 | 1379 | fn finishTransFnProto( |
| 1391 | 1380 | rp: RestorePoint, |
| 1381 | fn_decl: ?*const ZigClangFunctionDecl, |
| 1382 | fn_proto_ty: ?*const ZigClangFunctionProtoType, |
| 1392 | 1383 | fn_ty: *const ZigClangFunctionType, |
| 1393 | 1384 | source_loc: ZigClangSourceLocation, |
| 1394 | 1385 | fn_decl_context: ?FnDeclContext, |
| ... | ... | @@ -1414,7 +1405,67 @@ fn finishTransFnProto( |
| 1414 | 1405 | const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn"); |
| 1415 | 1406 | const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null; |
| 1416 | 1407 | const lparen_tok = try appendToken(rp.c, .LParen, "("); |
| 1417 | | const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null; |
| 1408 | |
| 1409 | var fn_params = ast.Node.FnProto.ParamList.init(rp.c.a()); |
| 1410 | const param_count: usize = if (fn_proto_ty != null) ZigClangFunctionProtoType_getNumParams(fn_proto_ty.?) else 0; |
| 1411 | |
| 1412 | var i: usize = 0; |
| 1413 | while (i < param_count) : (i += 1) { |
| 1414 | const param_qt = ZigClangFunctionProtoType_getParamType(fn_proto_ty.?, @intCast(c_uint, i)); |
| 1415 | |
| 1416 | const noalias_tok = if (ZigClangQualType_isRestrictQualified(param_qt)) try appendToken(rp.c, .Keyword_noalias, "noalias") else null; |
| 1417 | |
| 1418 | const param_name_tok: ?ast.TokenIndex = blk: { |
| 1419 | if (fn_decl != null) { |
| 1420 | const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i)); |
| 1421 | const param_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param))); |
| 1422 | if (param_name.len > 0) { |
| 1423 | // TODO: If len == 0, auto-generate arg1, arg2, etc? Or leave the name blank? |
| 1424 | const result = try appendToken(rp.c, .Identifier, param_name); |
| 1425 | _ = try appendToken(rp.c, .Colon, ":"); |
| 1426 | break :blk result; |
| 1427 | } |
| 1428 | } |
| 1429 | break :blk null; |
| 1430 | }; |
| 1431 | |
| 1432 | const type_node = try transQualType(rp, param_qt, source_loc); |
| 1433 | |
| 1434 | const param_node = try rp.c.a().create(ast.Node.ParamDecl); |
| 1435 | param_node.* = ast.Node.ParamDecl{ |
| 1436 | .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, |
| 1437 | .doc_comments = null, |
| 1438 | .comptime_token = null, |
| 1439 | .noalias_token = noalias_tok, |
| 1440 | .name_token = param_name_tok, |
| 1441 | .type_node = type_node, |
| 1442 | .var_args_token = null, |
| 1443 | }; |
| 1444 | try fn_params.push(&param_node.base); |
| 1445 | |
| 1446 | if (i + 1 < param_count) { |
| 1447 | _ = try appendToken(rp.c, .Comma, ","); |
| 1448 | } |
| 1449 | } |
| 1450 | |
| 1451 | if (is_var_args) { |
| 1452 | if (param_count > 0) { |
| 1453 | _ = try appendToken(rp.c, .Comma, ","); |
| 1454 | } |
| 1455 | |
| 1456 | const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl); |
| 1457 | var_arg_node.* = ast.Node.ParamDecl{ |
| 1458 | .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, |
| 1459 | .doc_comments = null, |
| 1460 | .comptime_token = null, |
| 1461 | .noalias_token = null, |
| 1462 | .name_token = null, |
| 1463 | .type_node = undefined, // Note: Accessing this causes an access violation. Need to check .var_args_token first before trying this field |
| 1464 | .var_args_token = try appendToken(rp.c, .Ellipsis3, "..."), |
| 1465 | }; |
| 1466 | try fn_params.push(&var_arg_node.base); |
| 1467 | } |
| 1468 | |
| 1418 | 1469 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); |
| 1419 | 1470 | |
| 1420 | 1471 | const return_type_node = blk: { |
| ... | ... | @@ -1443,7 +1494,7 @@ fn finishTransFnProto( |
| 1443 | 1494 | .visib_token = pub_tok, |
| 1444 | 1495 | .fn_token = fn_tok, |
| 1445 | 1496 | .name_token = name_tok, |
| 1446 | | .params = ast.Node.FnProto.ParamList.init(rp.c.a()), |
| 1497 | .params = fn_params, |
| 1447 | 1498 | .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node }, |
| 1448 | 1499 | .var_args_token = null, // TODO this field is broken in the AST data model |
| 1449 | 1500 | .extern_export_inline_token = extern_export_inline_tok, |
| ... | ... | @@ -1453,19 +1504,6 @@ fn finishTransFnProto( |
| 1453 | 1504 | .align_expr = null, |
| 1454 | 1505 | .section_expr = null, |
| 1455 | 1506 | }; |
| 1456 | | if (is_var_args) { |
| 1457 | | const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl); |
| 1458 | | var_arg_node.* = ast.Node.ParamDecl{ |
| 1459 | | .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, |
| 1460 | | .doc_comments = null, |
| 1461 | | .comptime_token = null, |
| 1462 | | .noalias_token = null, |
| 1463 | | .name_token = null, |
| 1464 | | .type_node = undefined, |
| 1465 | | .var_args_token = var_args_tok, |
| 1466 | | }; |
| 1467 | | try fn_proto.params.push(&var_arg_node.base); |
| 1468 | | } |
| 1469 | 1507 | return fn_proto; |
| 1470 | 1508 | } |
| 1471 | 1509 | |