@@ -254,11 +254,20 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
254
254
const fn_qt = ZigClangFunctionDecl_getType (fn_decl );
255
255
const fn_type = ZigClangQualType_getTypePtr (fn_qt );
256
256
var scope = & c .global_scope .base ;
257
+ const has_body = ZigClangFunctionDecl_hasBody (fn_decl );
258
+ const storage_class = ZigClangFunctionDecl_getStorageClass (fn_decl );
257
259
const decl_ctx = FnDeclContext {
258
260
.fn_name = fn_name ,
259
- .has_body = ZigClangFunctionDecl_hasBody ( fn_decl ) ,
260
- .storage_class = ZigClangFunctionDecl_getStorageClass ( fn_decl ) ,
261
+ .has_body = has_body ,
262
+ .storage_class = storage_class ,
261
263
.scope = & scope ,
264
+ .is_export = switch (storage_class ) {
265
+ .None = > has_body ,
266
+ .Extern , .Static = > false ,
267
+ .PrivateExtern = > return failDecl (c , fn_decl_loc , fn_name , "unsupported storage class: private extern" ),
268
+ .Auto = > unreachable , // Not legal on functions
269
+ .Register = > unreachable , // Not legal on functions
270
+ },
262
271
};
263
272
const proto_node = switch (ZigClangType_getTypeClass (fn_type )) {
264
273
.FunctionProto = > blk : {
@@ -270,7 +279,15 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
270
279
error .OutOfMemory = > return error .OutOfMemory ,
271
280
};
272
281
},
273
- .FunctionNoProto = > return failDecl (c , fn_decl_loc , fn_name , "TODO support functions with no prototype" ),
282
+ .FunctionNoProto = > blk : {
283
+ const fn_no_proto_type = @ptrCast (* const ZigClangFunctionType , fn_type );
284
+ break :blk transFnNoProto (rp , fn_no_proto_type , fn_decl_loc , decl_ctx ) catch | err | switch (err ) {
285
+ error .UnsupportedType = > {
286
+ return failDecl (c , fn_decl_loc , fn_name , "unable to resolve prototype of function" );
287
+ },
288
+ error .OutOfMemory = > return error .OutOfMemory ,
289
+ };
290
+ },
274
291
else = > unreachable ,
275
292
};
276
293
@@ -432,61 +449,67 @@ const FnDeclContext = struct {
432
449
has_body : bool ,
433
450
storage_class : ZigClangStorageClass ,
434
451
scope : ** Scope ,
452
+ is_export : bool ,
435
453
};
436
454
455
+ fn transCC (
456
+ rp : RestorePoint ,
457
+ fn_ty : * const ZigClangFunctionType ,
458
+ source_loc : ZigClangSourceLocation ,
459
+ ) ! CallingConvention {
460
+ const clang_cc = ZigClangFunctionType_getCallConv (fn_ty );
461
+ switch (clang_cc ) {
462
+ .C = > return CallingConvention .C ,
463
+ .X86StdCall = > return CallingConvention .Stdcall ,
464
+ else = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: {}" , @tagName (clang_cc )),
465
+ }
466
+ }
467
+
437
468
fn transFnProto (
438
469
rp : RestorePoint ,
439
470
fn_proto_ty : * const ZigClangFunctionProtoType ,
440
471
source_loc : ZigClangSourceLocation ,
441
472
fn_decl_context : ? FnDeclContext ,
442
473
) ! * ast.Node.FnProto {
443
474
const fn_ty = @ptrCast (* const ZigClangFunctionType , fn_proto_ty );
444
- const cc = switch (ZigClangFunctionType_getCallConv (fn_ty )) {
445
- .C = > CallingConvention .C ,
446
- .X86StdCall = > CallingConvention .Stdcall ,
447
- .X86FastCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 fastcall" ),
448
- .X86ThisCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 thiscall" ),
449
- .X86VectorCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 vectorcall" ),
450
- .X86Pascal = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 pascal" ),
451
- .Win64 = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: win64" ),
452
- .X86_64SysV = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 64sysv" ),
453
- .X86RegCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 reg" ),
454
- .AAPCS = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: aapcs" ),
455
- .AAPCS_VFP = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: aapcs-vfp" ),
456
- .IntelOclBicc = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: intel_ocl_bicc" ),
457
- .SpirFunction = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: SPIR function" ),
458
- .OpenCLKernel = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: OpenCLKernel" ),
459
- .Swift = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: Swift" ),
460
- .PreserveMost = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: PreserveMost" ),
461
- .PreserveAll = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: PreserveAll" ),
462
- .AArch64VectorCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: AArch64VectorCall" ),
463
- };
464
-
475
+ const cc = try transCC (rp , fn_ty , source_loc );
465
476
const is_var_args = ZigClangFunctionProtoType_isVariadic (fn_proto_ty );
466
477
const param_count : usize = ZigClangFunctionProtoType_getNumParams (fn_proto_ty );
467
478
var i : usize = 0 ;
468
479
while (i < param_count ) : (i += 1 ) {
469
480
return revertAndWarn (rp , error .UnsupportedType , source_loc , "TODO: implement parameters for FunctionProto in transType" );
470
481
}
482
+
483
+ return finishTransFnProto (rp , fn_ty , source_loc , fn_decl_context , is_var_args , cc );
484
+ }
485
+
486
+ fn transFnNoProto (
487
+ rp : RestorePoint ,
488
+ fn_ty : * const ZigClangFunctionType ,
489
+ source_loc : ZigClangSourceLocation ,
490
+ fn_decl_context : ? FnDeclContext ,
491
+ ) ! * ast.Node.FnProto {
492
+ const cc = try transCC (rp , fn_ty , source_loc );
493
+ const is_var_args = if (fn_decl_context ) | ctx | ! ctx .is_export else true ;
494
+ return finishTransFnProto (rp , fn_ty , source_loc , fn_decl_context , is_var_args , cc );
495
+ }
496
+
497
+ fn finishTransFnProto (
498
+ rp : RestorePoint ,
499
+ fn_ty : * const ZigClangFunctionType ,
500
+ source_loc : ZigClangSourceLocation ,
501
+ fn_decl_context : ? FnDeclContext ,
502
+ is_var_args : bool ,
503
+ cc : CallingConvention ,
504
+ ) ! * ast.Node.FnProto {
505
+ const is_export = if (fn_decl_context ) | ctx | ctx .is_export else false ;
506
+
471
507
// TODO check for always_inline attribute
472
508
// TODO check for align attribute
473
509
474
510
// pub extern fn name(...) T
475
511
const pub_tok = try appendToken (rp .c , .Keyword_pub , "pub" );
476
512
const cc_tok = if (cc == .Stdcall ) try appendToken (rp .c , .Keyword_stdcallcc , "stdcallcc" ) else null ;
477
- const is_export = exp : {
478
- const decl_ctx = fn_decl_context orelse break :exp false ;
479
- break :exp switch (decl_ctx .storage_class ) {
480
- .None = > switch (rp .c .mode ) {
481
- .import = > false ,
482
- .translate = > decl_ctx .has_body ,
483
- },
484
- .Extern , .Static = > false ,
485
- .PrivateExtern = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported storage class: private extern" ),
486
- .Auto = > unreachable , // Not legal on functions
487
- .Register = > unreachable , // Not legal on functions
488
- };
489
- };
490
513
const extern_export_inline_tok = if (is_export )
491
514
try appendToken (rp .c , .Keyword_export , "export" )
492
515
else if (cc == .C )
@@ -527,7 +550,7 @@ fn transFnProto(
527
550
.name_token = name_tok ,
528
551
.params = ast .Node .FnProto .ParamList .init (rp .c .a ()),
529
552
.return_type = ast.Node.FnProto.ReturnType { .Explicit = return_type_node },
530
- .var_args_token = var_args_tok ,
553
+ .var_args_token = null , // TODO this field is broken in the AST data model
531
554
.extern_export_inline_token = extern_export_inline_tok ,
532
555
.cc_token = cc_tok ,
533
556
.async_attr = null ,
@@ -536,6 +559,19 @@ fn transFnProto(
536
559
.align_expr = null ,
537
560
.section_expr = null ,
538
561
};
562
+ if (is_var_args ) {
563
+ const var_arg_node = try rp .c .a ().create (ast .Node .ParamDecl );
564
+ var_arg_node .* = ast.Node.ParamDecl {
565
+ .base = ast.Node { .id = ast .Node .Id .ParamDecl },
566
+ .doc_comments = null ,
567
+ .comptime_token = null ,
568
+ .noalias_token = null ,
569
+ .name_token = null ,
570
+ .type_node = undefined ,
571
+ .var_args_token = var_args_tok ,
572
+ };
573
+ try fn_proto .params .push (& var_arg_node .base );
574
+ }
539
575
return fn_proto ;
540
576
}
541
577
0 commit comments