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