translate-c-2 function calls

This commit is contained in:
Vexu 2019-12-18 23:56:39 +02:00
parent c2666c48a4
commit d54c288bd3
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
3 changed files with 112 additions and 18 deletions

View File

@ -839,6 +839,7 @@ pub extern fn ZigClangFunctionType_getReturnType(self: *const ZigClangFunctionTy
pub extern fn ZigClangFunctionProtoType_isVariadic(self: *const struct_ZigClangFunctionProtoType) bool;
pub extern fn ZigClangFunctionProtoType_getNumParams(self: *const struct_ZigClangFunctionProtoType) c_uint;
pub extern fn ZigClangFunctionProtoType_getParamType(self: *const struct_ZigClangFunctionProtoType, i: c_uint) ZigClangQualType;
pub extern fn ZigClangFunctionProtoType_getReturnType(self: *const ZigClangFunctionProtoType) ZigClangQualType;
pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
pub const ZigClangQualType = struct_ZigClangQualType;
@ -993,6 +994,7 @@ pub extern fn ZigClangIncompleteArrayType_getElementType(*const ZigClangIncomple
pub extern fn ZigClangConstantArrayType_getElementType(self: *const struct_ZigClangConstantArrayType) ZigClangQualType;
pub extern fn ZigClangConstantArrayType_getSize(self: *const struct_ZigClangConstantArrayType) *const struct_ZigClangAPInt;
pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl;
pub extern fn ZigClangDeclRefExpr_getFoundDecl(*const ZigClangDeclRefExpr) *const ZigClangNamedDecl;
pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
@ -1105,3 +1107,7 @@ pub extern fn ZigClangMemberExpr_getMemberDecl(*const ZigClangMemberExpr) *const
pub extern fn ZigClangArraySubscriptExpr_getBase(*const ZigClangArraySubscriptExpr) *const ZigClangExpr;
pub extern fn ZigClangArraySubscriptExpr_getIdx(*const ZigClangArraySubscriptExpr) *const ZigClangExpr;
pub extern fn ZigClangCallExpr_getCallee(*const ZigClangCallExpr) *const ZigClangExpr;
pub extern fn ZigClangCallExpr_getNumArgs(*const ZigClangCallExpr) c_uint;
pub extern fn ZigClangCallExpr_getArgs(*const ZigClangCallExpr) [*]const *const ZigClangExpr;

View File

@ -851,6 +851,7 @@ fn transStmt(
.StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used),
.MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const ZigClangMemberExpr, stmt), result_used),
.ArraySubscriptExprClass => return transArrayAccess(rp, scope, @ptrCast(*const ZigClangArraySubscriptExpr, stmt), result_used),
.CallExprClass => return transCallExpr(rp, scope, @ptrCast(*const ZigClangCallExpr, stmt), result_used),
else => {
return revertAndWarn(
rp,
@ -2004,6 +2005,73 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArrayS
return maybeSuppressResult(rp, scope, result_used, &node.base);
}
fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCallExpr, result_used: ResultUsed) TransError!*ast.Node {
const callee = ZigClangCallExpr_getCallee(stmt);
var raw_fn_expr = try transExpr(rp, scope, callee, .used, .r_value);
var is_ptr = false;
const fn_ty = qualTypeGetFnProto(ZigClangExpr_getType(callee), &is_ptr);
const fn_expr = if (is_ptr and fn_ty != null) blk: {
if (ZigClangExpr_getStmtClass(callee) == .ImplicitCastExprClass) {
const implicit_cast = @ptrCast(*const ZigClangImplicitCastExpr, callee);
if (ZigClangImplicitCastExpr_getCastKind(implicit_cast) == .FunctionToPointerDecay) {
const subexpr = ZigClangImplicitCastExpr_getSubExpr(implicit_cast);
if (ZigClangExpr_getStmtClass(subexpr) == .DeclRefExprClass) {
const decl_ref = @ptrCast(*const ZigClangDeclRefExpr, subexpr);
const named_decl = ZigClangDeclRefExpr_getFoundDecl(decl_ref);
if (ZigClangDecl_getKind(@ptrCast(*const ZigClangDecl, named_decl)) == .Function) {
break :blk raw_fn_expr;
}
}
}
}
break :blk try transCreateNodeUnwrapNull(rp.c, raw_fn_expr);
} else
raw_fn_expr;
const node = try transCreateNodeFnCall(rp.c, fn_expr);
const num_args = ZigClangCallExpr_getNumArgs(stmt);
const args = ZigClangCallExpr_getArgs(stmt);
var i: usize = 0;
while (i < num_args) : (i+=1) {
if (i != 0) {
_ = try appendToken(rp.c, .Comma, ",");
}
const arg = try transExpr(rp, scope, args[i], .used, .r_value);
try node.op.Call.params.push(arg);
}
node.rtoken = try appendToken(rp.c, .RParen, ")");
if (fn_ty) |ty| {
const canon = ZigClangQualType_getCanonicalType(ZigClangFunctionProtoType_getReturnType(ty));
const ret_ty = ZigClangQualType_getTypePtr(canon);
if (ZigClangType_isVoidType(ret_ty)) {
_ = try appendToken(rp.c, .Semicolon, ";");
return &node.base;
}
}
return maybeSuppressResult(rp, scope, result_used, &node.base);
}
fn qualTypeGetFnProto(qt: ZigClangQualType, is_ptr: *bool) ?*const ZigClangFunctionProtoType {
const canon = ZigClangQualType_getCanonicalType(qt);
var ty = ZigClangQualType_getTypePtr(canon);
is_ptr.* = false;
if (ZigClangType_getTypeClass(ty) == .Pointer) {
is_ptr.* = true;
const child_qt = ZigClangType_getPointeeType(ty);
ty = ZigClangQualType_getTypePtr(child_qt);
}
if (ZigClangType_getTypeClass(ty) == .FunctionProto) {
return @ptrCast(*const ZigClangFunctionProtoType, ty);
}
return null;
}
fn transCPtrCast(
rp: RestorePoint,
loc: ZigClangSourceLocation,
@ -3947,6 +4015,22 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
if (it.next().?.id != .RBrace)
return error.ParseError;
},
.LParen => {
const call_node = try transCreateNodeFnCall(rp.c, node);
while (true) {
const arg = try parseCExpr(rp, it, source_loc, scope);
try call_node.op.Call.params.push(arg);
const next = it.next().?;
if (next.id == .Comma)
_ = try appendToken(rp.c, .Comma, ",")
else if (next.id == .RParen)
break
else
return error.ParseError;
}
call_node.rtoken = try appendToken(rp.c, .RParen, ")");
node = &call_node.base;
},
else => {
_ = it.prev();
return node;

View File

@ -702,6 +702,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
cases.addC_both("function call",
\\static void bar(void) { }
\\void foo(int *(baz)(void)) {
\\ bar();
\\ baz();
\\}
, &[_][]const u8{
\\pub fn bar() void {}
\\pub export fn foo(baz: ?extern fn () [*c]c_int) void {
\\ bar();
\\ _ = baz.?();
\\}
});
/////////////// Cases that pass for only stage2 ////////////////
cases.add_2("Parameterless function prototypes",
@ -1538,6 +1552,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const ACCESS = array[2];
});
cases.add_2("macro call",
\\#define CALL(arg) bar(arg)
, &[_][]const u8{
\\pub inline fn CALL(arg: var) @TypeOf(bar(arg)) {
\\ return bar(arg);
\\}
});
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
cases.addAllowWarnings("simple data types",
@ -1728,24 +1750,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
cases.addC("function call",
\\static void bar(void) { }
\\static int baz(void) { return 0; }
\\void foo(void) {
\\ bar();
\\ baz();
\\}
, &[_][]const u8{
\\pub fn bar() void {}
\\pub fn baz() c_int {
\\ return 0;
\\}
\\pub export fn foo() void {
\\ bar();
\\ _ = baz();
\\}
});
cases.addC("sizeof",
\\#include <stddef.h>
\\size_t size_of(void) {