| author | |
| committer | |
| log | 1b86a628acef7bc180ea6cbe6e4930710e5dff97 |
| tree | 36d24de2b50eabdb9588c8c82f03f84448f6ac49 |
| parent | b0cd24f90ef159cc60c9607e9cc37af8b5bd147a |
| parent | 81443fcde84879782f38fde33510e56d2faaaa21 |
| signature |
Sema: add error for recursive inline call9 files changed, 130 insertions(+), 60 deletions(-)
doc/langref.html.in+41-22| ... | @@ -12062,24 +12062,24 @@ ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerFiel | ... | @@ -12062,24 +12062,24 @@ ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerFiel |
| 12062 | 12062 | ||
| 12063 | ContainerDeclarations | 12063 | ContainerDeclarations |
| 12064 | <- TestDecl ContainerDeclarations | 12064 | <- TestDecl ContainerDeclarations |
| 12065 | / TopLevelComptime ContainerDeclarations | 12065 | / ComptimeDecl ContainerDeclarations |
| 12066 | / doc_comment? KEYWORD_pub? TopLevelDecl ContainerDeclarations | 12066 | / doc_comment? KEYWORD_pub? Decl ContainerDeclarations |
| 12067 | / | 12067 | / |
| 12068 | 12068 | ||
| 12069 | TestDecl <- doc_comment? KEYWORD_test STRINGLITERALSINGLE? Block | 12069 | TestDecl <- KEYWORD_test STRINGLITERALSINGLE? Block |
| 12070 | 12070 | ||
| 12071 | TopLevelComptime <- doc_comment? KEYWORD_comptime BlockExpr | 12071 | ComptimeDecl <- KEYWORD_comptime Block |
| 12072 | 12072 | ||
| 12073 | TopLevelDecl | 12073 | Decl |
| 12074 | <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) | 12074 | <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) |
| 12075 | / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl | 12075 | / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl |
| 12076 | / KEYWORD_usingnamespace Expr SEMICOLON | 12076 | / KEYWORD_usingnamespace Expr SEMICOLON |
| 12077 | 12077 | ||
| 12078 | FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr | 12078 | FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr |
| 12079 | 12079 | ||
| 12080 | VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON | 12080 | VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON |
| 12081 | 12081 | ||
| 12082 | ContainerField <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON (KEYWORD_anytype / TypeExpr) ByteAlign?)? (EQUAL Expr)? | 12082 | ContainerField <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? |
| 12083 | 12083 | ||
| 12084 | # *** Block Level *** | 12084 | # *** Block Level *** |
| 12085 | Statement | 12085 | Statement |
| ... | @@ -12240,6 +12240,8 @@ WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN | ... | @@ -12240,6 +12240,8 @@ WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN |
| 12240 | 12240 | ||
| 12241 | LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN | 12241 | LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN |
| 12242 | 12242 | ||
| 12243 | AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN | ||
| 12244 | |||
| 12243 | # Fn specific | 12245 | # Fn specific |
| 12244 | CallConv <- KEYWORD_callconv LPAREN Expr RPAREN | 12246 | CallConv <- KEYWORD_callconv LPAREN Expr RPAREN |
| 12245 | 12247 | ||
| ... | @@ -12267,7 +12269,7 @@ PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE | ... | @@ -12267,7 +12269,7 @@ PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE |
| 12267 | 12269 | ||
| 12268 | 12270 | ||
| 12269 | # Switch specific | 12271 | # Switch specific |
| 12270 | SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr | 12272 | SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr |
| 12271 | 12273 | ||
| 12272 | SwitchCase | 12274 | SwitchCase |
| 12273 | <- SwitchItem (COMMA SwitchItem)* COMMA? | 12275 | <- SwitchItem (COMMA SwitchItem)* COMMA? |
| ... | @@ -12278,11 +12280,15 @@ SwitchItem <- Expr (DOT3 Expr)? | ... | @@ -12278,11 +12280,15 @@ SwitchItem <- Expr (DOT3 Expr)? |
| 12278 | # Operators | 12280 | # Operators |
| 12279 | AssignOp | 12281 | AssignOp |
| 12280 | <- ASTERISKEQUAL | 12282 | <- ASTERISKEQUAL |
| 12283 | / ASTERISKPIPEEQUAL | ||
| 12281 | / SLASHEQUAL | 12284 | / SLASHEQUAL |
| 12282 | / PERCENTEQUAL | 12285 | / PERCENTEQUAL |
| 12283 | / PLUSEQUAL | 12286 | / PLUSEQUAL |
| 12287 | / PLUSPIPEEQUAL | ||
| 12284 | / MINUSEQUAL | 12288 | / MINUSEQUAL |
| 12289 | / MINUSPIPEEQUAL | ||
| 12285 | / LARROW2EQUAL | 12290 | / LARROW2EQUAL |
| 12291 | / LARROW2PIPEEQUAL | ||
| 12286 | / RARROW2EQUAL | 12292 | / RARROW2EQUAL |
| 12287 | / AMPERSANDEQUAL | 12293 | / AMPERSANDEQUAL |
| 12288 | / CARETEQUAL | 12294 | / CARETEQUAL |
| ... | @@ -12310,6 +12316,7 @@ BitwiseOp | ... | @@ -12310,6 +12316,7 @@ BitwiseOp |
| 12310 | BitShiftOp | 12316 | BitShiftOp |
| 12311 | <- LARROW2 | 12317 | <- LARROW2 |
| 12312 | / RARROW2 | 12318 | / RARROW2 |
| 12319 | / LARROW2PIPE | ||
| 12313 | 12320 | ||
| 12314 | AdditionOp | 12321 | AdditionOp |
| 12315 | <- PLUS | 12322 | <- PLUS |
| ... | @@ -12317,6 +12324,8 @@ AdditionOp | ... | @@ -12317,6 +12324,8 @@ AdditionOp |
| 12317 | / PLUS2 | 12324 | / PLUS2 |
| 12318 | / PLUSPERCENT | 12325 | / PLUSPERCENT |
| 12319 | / MINUSPERCENT | 12326 | / MINUSPERCENT |
| 12327 | / PLUSPIPE | ||
| 12328 | / MINUSPIPE | ||
| 12320 | 12329 | ||
| 12321 | MultiplyOp | 12330 | MultiplyOp |
| 12322 | <- PIPE2 | 12331 | <- PIPE2 |
| ... | @@ -12325,6 +12334,7 @@ MultiplyOp | ... | @@ -12325,6 +12334,7 @@ MultiplyOp |
| 12325 | / PERCENT | 12334 | / PERCENT |
| 12326 | / ASTERISK2 | 12335 | / ASTERISK2 |
| 12327 | / ASTERISKPERCENT | 12336 | / ASTERISKPERCENT |
| 12337 | / ASTERISKPIPE | ||
| 12328 | 12338 | ||
| 12329 | PrefixOp | 12339 | PrefixOp |
| 12330 | <- EXCLAMATIONMARK | 12340 | <- EXCLAMATIONMARK |
| ... | @@ -12338,8 +12348,8 @@ PrefixOp | ... | @@ -12338,8 +12348,8 @@ PrefixOp |
| 12338 | PrefixTypeOp | 12348 | PrefixTypeOp |
| 12339 | <- QUESTIONMARK | 12349 | <- QUESTIONMARK |
| 12340 | / KEYWORD_anyframe MINUSRARROW | 12350 | / KEYWORD_anyframe MINUSRARROW |
| 12341 | / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 12351 | / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 12342 | / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 12352 | / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 12343 | / ArrayTypeStart | 12353 | / ArrayTypeStart |
| 12344 | 12354 | ||
| 12345 | SuffixOp | 12355 | SuffixOp |
| ... | @@ -12364,7 +12374,7 @@ ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET | ... | @@ -12364,7 +12374,7 @@ ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET |
| 12364 | ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE | 12374 | ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE |
| 12365 | 12375 | ||
| 12366 | ContainerDeclType | 12376 | ContainerDeclType |
| 12367 | <- KEYWORD_struct | 12377 | <- KEYWORD_struct (LPAREN Expr RPAREN)? |
| 12368 | / KEYWORD_opaque | 12378 | / KEYWORD_opaque |
| 12369 | / KEYWORD_enum (LPAREN Expr RPAREN)? | 12379 | / KEYWORD_enum (LPAREN Expr RPAREN)? |
| 12370 | / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? | 12380 | / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| ... | @@ -12455,7 +12465,7 @@ string_char | ... | @@ -12455,7 +12465,7 @@ string_char |
| 12455 | / [^\\"\n] | 12465 | / [^\\"\n] |
| 12456 | 12466 | ||
| 12457 | container_doc_comment <- ('//!' [^\n]* [ \n]*)+ | 12467 | container_doc_comment <- ('//!' [^\n]* [ \n]*)+ |
| 12458 | doc_comment <- ('///' [^\n]* [ \n]*)+ | 12468 | doc_comment <- ('///' [^\n]* [ \n]*)+ skip |
| 12459 | line_comment <- '//' ![!/][^\n]* / '////' [^\n]* | 12469 | line_comment <- '//' ![!/][^\n]* / '////' [^\n]* |
| 12460 | line_string <- ("\\\\" [^\n]* [ \n]*)+ | 12470 | line_string <- ("\\\\" [^\n]* [ \n]*)+ |
| 12461 | skip <- ([ \n] / line_comment)* | 12471 | skip <- ([ \n] / line_comment)* |
| ... | @@ -12483,11 +12493,13 @@ BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip | ... | @@ -12483,11 +12493,13 @@ BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip |
| 12483 | 12493 | ||
| 12484 | AMPERSAND <- '&' ![=] skip | 12494 | AMPERSAND <- '&' ![=] skip |
| 12485 | AMPERSANDEQUAL <- '&=' skip | 12495 | AMPERSANDEQUAL <- '&=' skip |
| 12486 | ASTERISK <- '*' ![*%=] skip | 12496 | ASTERISK <- '*' ![*%=|] skip |
| 12487 | ASTERISK2 <- '**' skip | 12497 | ASTERISK2 <- '**' skip |
| 12488 | ASTERISKEQUAL <- '*=' skip | 12498 | ASTERISKEQUAL <- '*=' skip |
| 12489 | ASTERISKPERCENT <- '*%' ![=] skip | 12499 | ASTERISKPERCENT <- '*%' ![=] skip |
| 12490 | ASTERISKPERCENTEQUAL <- '*%=' skip | 12500 | ASTERISKPERCENTEQUAL <- '*%=' skip |
| 12501 | ASTERISKPIPE <- '*|' ![=] skip | ||
| 12502 | ASTERISKPIPEEQUAL <- '*|=' skip | ||
| 12491 | CARET <- '^' ![=] skip | 12503 | CARET <- '^' ![=] skip |
| 12492 | CARETEQUAL <- '^=' skip | 12504 | CARETEQUAL <- '^=' skip |
| 12493 | COLON <- ':' skip | 12505 | COLON <- ':' skip |
| ... | @@ -12503,27 +12515,33 @@ EQUALRARROW <- '=>' skip | ... | @@ -12503,27 +12515,33 @@ EQUALRARROW <- '=>' skip |
| 12503 | EXCLAMATIONMARK <- '!' ![=] skip | 12515 | EXCLAMATIONMARK <- '!' ![=] skip |
| 12504 | EXCLAMATIONMARKEQUAL <- '!=' skip | 12516 | EXCLAMATIONMARKEQUAL <- '!=' skip |
| 12505 | LARROW <- '<' ![<=] skip | 12517 | LARROW <- '<' ![<=] skip |
| 12506 | LARROW2 <- '<<' ![=] skip | 12518 | LARROW2 <- '<<' ![=|] skip |
| 12507 | LARROW2EQUAL <- '<<=' skip | 12519 | LARROW2EQUAL <- '<<=' skip |
| 12520 | LARROW2PIPE <- '<<|' ![=] skip | ||
| 12521 | LARROW2PIPEEQUAL <- '<<|=' skip | ||
| 12508 | LARROWEQUAL <- '<=' skip | 12522 | LARROWEQUAL <- '<=' skip |
| 12509 | LBRACE <- '{' skip | 12523 | LBRACE <- '{' skip |
| 12510 | LBRACKET <- '[' skip | 12524 | LBRACKET <- '[' skip |
| 12511 | LPAREN <- '(' skip | 12525 | LPAREN <- '(' skip |
| 12512 | MINUS <- '-' ![%=>] skip | 12526 | MINUS <- '-' ![%=>|] skip |
| 12513 | MINUSEQUAL <- '-=' skip | 12527 | MINUSEQUAL <- '-=' skip |
| 12514 | MINUSPERCENT <- '-%' ![=] skip | 12528 | MINUSPERCENT <- '-%' ![=] skip |
| 12515 | MINUSPERCENTEQUAL <- '-%=' skip | 12529 | MINUSPERCENTEQUAL <- '-%=' skip |
| 12530 | MINUSPIPE <- '-|' ![=] skip | ||
| 12531 | MINUSPIPEEQUAL <- '-|=' skip | ||
| 12516 | MINUSRARROW <- '->' skip | 12532 | MINUSRARROW <- '->' skip |
| 12517 | PERCENT <- '%' ![=] skip | 12533 | PERCENT <- '%' ![=] skip |
| 12518 | PERCENTEQUAL <- '%=' skip | 12534 | PERCENTEQUAL <- '%=' skip |
| 12519 | PIPE <- '|' ![|=] skip | 12535 | PIPE <- '|' ![|=] skip |
| 12520 | PIPE2 <- '||' skip | 12536 | PIPE2 <- '||' skip |
| 12521 | PIPEEQUAL <- '|=' skip | 12537 | PIPEEQUAL <- '|=' skip |
| 12522 | PLUS <- '+' ![%+=] skip | 12538 | PLUS <- '+' ![%+=|] skip |
| 12523 | PLUS2 <- '++' skip | 12539 | PLUS2 <- '++' skip |
| 12524 | PLUSEQUAL <- '+=' skip | 12540 | PLUSEQUAL <- '+=' skip |
| 12525 | PLUSPERCENT <- '+%' ![=] skip | 12541 | PLUSPERCENT <- '+%' ![=] skip |
| 12526 | PLUSPERCENTEQUAL <- '+%=' skip | 12542 | PLUSPERCENTEQUAL <- '+%=' skip |
| 12543 | PLUSPIPE <- '+|' ![=] skip | ||
| 12544 | PLUSPIPEEQUAL <- '+|=' skip | ||
| 12527 | LETTERC <- 'c' skip | 12545 | LETTERC <- 'c' skip |
| 12528 | QUESTIONMARK <- '?' skip | 12546 | QUESTIONMARK <- '?' skip |
| 12529 | RARROW <- '>' ![>=] skip | 12547 | RARROW <- '>' ![>=] skip |
| ... | @@ -12539,6 +12557,7 @@ SLASHEQUAL <- '/=' skip | ... | @@ -12539,6 +12557,7 @@ SLASHEQUAL <- '/=' skip |
| 12539 | TILDE <- '~' skip | 12557 | TILDE <- '~' skip |
| 12540 | 12558 | ||
| 12541 | end_of_word <- ![a-zA-Z0-9_] skip | 12559 | end_of_word <- ![a-zA-Z0-9_] skip |
| 12560 | KEYWORD_addrspace <- 'addrspace' end_of_word | ||
| 12542 | KEYWORD_align <- 'align' end_of_word | 12561 | KEYWORD_align <- 'align' end_of_word |
| 12543 | KEYWORD_allowzero <- 'allowzero' end_of_word | 12562 | KEYWORD_allowzero <- 'allowzero' end_of_word |
| 12544 | KEYWORD_and <- 'and' end_of_word | 12563 | KEYWORD_and <- 'and' end_of_word |
| ... | @@ -12588,11 +12607,11 @@ KEYWORD_var <- 'var' end_of_word | ... | @@ -12588,11 +12607,11 @@ KEYWORD_var <- 'var' end_of_word |
| 12588 | KEYWORD_volatile <- 'volatile' end_of_word | 12607 | KEYWORD_volatile <- 'volatile' end_of_word |
| 12589 | KEYWORD_while <- 'while' end_of_word | 12608 | KEYWORD_while <- 'while' end_of_word |
| 12590 | 12609 | ||
| 12591 | keyword <- KEYWORD_align / KEYWORD_allowzero / KEYWORD_and / KEYWORD_anyframe | 12610 | keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and |
| 12592 | / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async / KEYWORD_await | 12611 | / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async |
| 12593 | / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch / KEYWORD_comptime | 12612 | / KEYWORD_await / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch |
| 12594 | / KEYWORD_const / KEYWORD_continue / KEYWORD_defer / KEYWORD_else | 12613 | / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer |
| 12595 | / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export | 12614 | / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export |
| 12596 | / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if | 12615 | / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if |
| 12597 | / KEYWORD_inline / KEYWORD_noalias / KEYWORD_nosuspend / KEYWORD_noinline | 12616 | / KEYWORD_inline / KEYWORD_noalias / KEYWORD_nosuspend / KEYWORD_noinline |
| 12598 | / KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed | 12617 | / KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed |
lib/std/zig/parse.zig+4-4| ... | @@ -240,10 +240,10 @@ const Parser = struct { | ... | @@ -240,10 +240,10 @@ const Parser = struct { |
| 240 | /// ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerField / ContainerDeclarations) | 240 | /// ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerField / ContainerDeclarations) |
| 241 | /// ContainerDeclarations | 241 | /// ContainerDeclarations |
| 242 | /// <- TestDecl ContainerDeclarations | 242 | /// <- TestDecl ContainerDeclarations |
| 243 | /// / TopLevelComptime ContainerDeclarations | 243 | /// / ComptimeDecl ContainerDeclarations |
| 244 | /// / KEYWORD_pub? TopLevelDecl ContainerDeclarations | 244 | /// / doc_comment? KEYWORD_pub? Decl ContainerDeclarations |
| 245 | /// / | 245 | /// / |
| 246 | /// TopLevelComptime <- KEYWORD_comptime Block | 246 | /// ComptimeDecl <- KEYWORD_comptime Block |
| 247 | fn parseContainerMembers(p: *Parser) !Members { | 247 | fn parseContainerMembers(p: *Parser) !Members { |
| 248 | const scratch_top = p.scratch.items.len; | 248 | const scratch_top = p.scratch.items.len; |
| 249 | defer p.scratch.shrinkRetainingCapacity(scratch_top); | 249 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| ... | @@ -622,7 +622,7 @@ const Parser = struct { | ... | @@ -622,7 +622,7 @@ const Parser = struct { |
| 622 | }; | 622 | }; |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | /// TopLevelDecl | 625 | /// Decl |
| 626 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) | 626 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) |
| 627 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl | 627 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl |
| 628 | /// / KEYWORD_usingnamespace Expr SEMICOLON | 628 | /// / KEYWORD_usingnamespace Expr SEMICOLON |
src/Sema.zig+33-15| ... | @@ -335,6 +335,7 @@ pub const Block = struct { | ... | @@ -335,6 +335,7 @@ pub const Block = struct { |
| 335 | /// It is shared among all the blocks in an inline or comptime called | 335 | /// It is shared among all the blocks in an inline or comptime called |
| 336 | /// function. | 336 | /// function. |
| 337 | pub const Inlining = struct { | 337 | pub const Inlining = struct { |
| 338 | func: ?*Module.Fn, | ||
| 338 | comptime_result: Air.Inst.Ref, | 339 | comptime_result: Air.Inst.Ref, |
| 339 | merges: Merges, | 340 | merges: Merges, |
| 340 | }; | 341 | }; |
| ... | @@ -6428,7 +6429,6 @@ fn analyzeCall( | ... | @@ -6428,7 +6429,6 @@ fn analyzeCall( |
| 6428 | }), | 6429 | }), |
| 6429 | else => unreachable, | 6430 | else => unreachable, |
| 6430 | }; | 6431 | }; |
| 6431 | if (!is_comptime_call and module_fn.state == .sema_failure) return error.AnalysisFail; | ||
| 6432 | if (func_ty_info.is_var_args) { | 6432 | if (func_ty_info.is_var_args) { |
| 6433 | return sema.fail(block, call_src, "{s} call of variadic function", .{ | 6433 | return sema.fail(block, call_src, "{s} call of variadic function", .{ |
| 6434 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | 6434 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), |
| ... | @@ -6448,6 +6448,7 @@ fn analyzeCall( | ... | @@ -6448,6 +6448,7 @@ fn analyzeCall( |
| 6448 | // This one is shared among sub-blocks within the same callee, but not | 6448 | // This one is shared among sub-blocks within the same callee, but not |
| 6449 | // shared among the entire inline/comptime call stack. | 6449 | // shared among the entire inline/comptime call stack. |
| 6450 | var inlining: Block.Inlining = .{ | 6450 | var inlining: Block.Inlining = .{ |
| 6451 | .func = null, | ||
| 6451 | .comptime_result = undefined, | 6452 | .comptime_result = undefined, |
| 6452 | .merges = .{ | 6453 | .merges = .{ |
| 6453 | .results = .{}, | 6454 | .results = .{}, |
| ... | @@ -6534,6 +6535,7 @@ fn analyzeCall( | ... | @@ -6534,6 +6535,7 @@ fn analyzeCall( |
| 6534 | const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst); | 6535 | const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst); |
| 6535 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body); | 6536 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body); |
| 6536 | 6537 | ||
| 6538 | var has_comptime_args = false; | ||
| 6537 | var arg_i: usize = 0; | 6539 | var arg_i: usize = 0; |
| 6538 | for (fn_info.param_body) |inst| { | 6540 | for (fn_info.param_body) |inst| { |
| 6539 | sema.analyzeInlineCallArg( | 6541 | sema.analyzeInlineCallArg( |
| ... | @@ -6549,6 +6551,7 @@ fn analyzeCall( | ... | @@ -6549,6 +6551,7 @@ fn analyzeCall( |
| 6549 | memoized_call_key, | 6551 | memoized_call_key, |
| 6550 | func_ty_info.param_types, | 6552 | func_ty_info.param_types, |
| 6551 | func, | 6553 | func, |
| 6554 | &has_comptime_args, | ||
| 6552 | ) catch |err| switch (err) { | 6555 | ) catch |err| switch (err) { |
| 6553 | error.NeededSourceLocation => { | 6556 | error.NeededSourceLocation => { |
| 6554 | _ = sema.inst_map.remove(inst); | 6557 | _ = sema.inst_map.remove(inst); |
| ... | @@ -6566,6 +6569,7 @@ fn analyzeCall( | ... | @@ -6566,6 +6569,7 @@ fn analyzeCall( |
| 6566 | memoized_call_key, | 6569 | memoized_call_key, |
| 6567 | func_ty_info.param_types, | 6570 | func_ty_info.param_types, |
| 6568 | func, | 6571 | func, |
| 6572 | &has_comptime_args, | ||
| 6569 | ); | 6573 | ); |
| 6570 | unreachable; | 6574 | unreachable; |
| 6571 | }, | 6575 | }, |
| ... | @@ -6573,6 +6577,19 @@ fn analyzeCall( | ... | @@ -6573,6 +6577,19 @@ fn analyzeCall( |
| 6573 | }; | 6577 | }; |
| 6574 | } | 6578 | } |
| 6575 | 6579 | ||
| 6580 | if (!has_comptime_args and module_fn.state == .sema_failure) return error.AnalysisFail; | ||
| 6581 | |||
| 6582 | const recursive_msg = "inline call is recursive"; | ||
| 6583 | var head = if (!has_comptime_args) block else null; | ||
| 6584 | while (head) |some| { | ||
| 6585 | const parent_inlining = some.inlining orelse break; | ||
| 6586 | if (parent_inlining.func == module_fn) { | ||
| 6587 | return sema.fail(block, call_src, recursive_msg, .{}); | ||
| 6588 | } | ||
| 6589 | head = some.parent; | ||
| 6590 | } | ||
| 6591 | if (!has_comptime_args) inlining.func = module_fn; | ||
| 6592 | |||
| 6576 | // In case it is a generic function with an expression for the return type that depends | 6593 | // In case it is a generic function with an expression for the return type that depends |
| 6577 | // on parameters, we must now do the same for the return type as we just did with | 6594 | // on parameters, we must now do the same for the return type as we just did with |
| 6578 | // each of the parameters, resolving the return type and providing it to the child | 6595 | // each of the parameters, resolving the return type and providing it to the child |
| ... | @@ -6657,6 +6674,7 @@ fn analyzeCall( | ... | @@ -6657,6 +6674,7 @@ fn analyzeCall( |
| 6657 | error.ComptimeReturn => break :result inlining.comptime_result, | 6674 | error.ComptimeReturn => break :result inlining.comptime_result, |
| 6658 | error.AnalysisFail => { | 6675 | error.AnalysisFail => { |
| 6659 | const err_msg = sema.err orelse return err; | 6676 | const err_msg = sema.err orelse return err; |
| 6677 | if (std.mem.eql(u8, err_msg.msg, recursive_msg)) return err; | ||
| 6660 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); | 6678 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); |
| 6661 | err_msg.clearTrace(sema.gpa); | 6679 | err_msg.clearTrace(sema.gpa); |
| 6662 | return err; | 6680 | return err; |
| ... | @@ -6814,8 +6832,13 @@ fn analyzeInlineCallArg( | ... | @@ -6814,8 +6832,13 @@ fn analyzeInlineCallArg( |
| 6814 | memoized_call_key: Module.MemoizedCall.Key, | 6832 | memoized_call_key: Module.MemoizedCall.Key, |
| 6815 | raw_param_types: []const Type, | 6833 | raw_param_types: []const Type, |
| 6816 | func_inst: Air.Inst.Ref, | 6834 | func_inst: Air.Inst.Ref, |
| 6835 | has_comptime_args: *bool, | ||
| 6817 | ) !void { | 6836 | ) !void { |
| 6818 | const zir_tags = sema.code.instructions.items(.tag); | 6837 | const zir_tags = sema.code.instructions.items(.tag); |
| 6838 | switch (zir_tags[inst]) { | ||
| 6839 | .param_comptime, .param_anytype_comptime => has_comptime_args.* = true, | ||
| 6840 | else => {}, | ||
| 6841 | } | ||
| 6819 | switch (zir_tags[inst]) { | 6842 | switch (zir_tags[inst]) { |
| 6820 | .param, .param_comptime => { | 6843 | .param, .param_comptime => { |
| 6821 | // Evaluate the parameter type expression now that previous ones have | 6844 | // Evaluate the parameter type expression now that previous ones have |
| ... | @@ -6870,23 +6893,20 @@ fn analyzeInlineCallArg( | ... | @@ -6870,23 +6893,20 @@ fn analyzeInlineCallArg( |
| 6870 | .ty = param_ty, | 6893 | .ty = param_ty, |
| 6871 | .val = arg_val, | 6894 | .val = arg_val, |
| 6872 | }; | 6895 | }; |
| 6873 | } else if (zir_tags[inst] == .param_comptime or try sema.typeRequiresComptime(param_ty)) { | ||
| 6874 | sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); | ||
| 6875 | } else if (try sema.resolveMaybeUndefVal(casted_arg)) |val| { | ||
| 6876 | // We have a comptime value but we need a runtime value to preserve inlining semantics, | ||
| 6877 | const wrapped = try sema.addConstant(param_ty, try Value.Tag.runtime_value.create(sema.arena, val)); | ||
| 6878 | sema.inst_map.putAssumeCapacityNoClobber(inst, wrapped); | ||
| 6879 | } else { | 6896 | } else { |
| 6880 | sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); | 6897 | sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); |
| 6881 | } | 6898 | } |
| 6882 | 6899 | ||
| 6900 | if (try sema.resolveMaybeUndefVal(casted_arg)) |_| { | ||
| 6901 | has_comptime_args.* = true; | ||
| 6902 | } | ||
| 6903 | |||
| 6883 | arg_i.* += 1; | 6904 | arg_i.* += 1; |
| 6884 | }, | 6905 | }, |
| 6885 | .param_anytype, .param_anytype_comptime => { | 6906 | .param_anytype, .param_anytype_comptime => { |
| 6886 | // No coercion needed. | 6907 | // No coercion needed. |
| 6887 | const uncasted_arg = uncasted_args[arg_i.*]; | 6908 | const uncasted_arg = uncasted_args[arg_i.*]; |
| 6888 | new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg); | 6909 | new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg); |
| 6889 | const param_ty = sema.typeOf(uncasted_arg); | ||
| 6890 | 6910 | ||
| 6891 | if (is_comptime_call) { | 6911 | if (is_comptime_call) { |
| 6892 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); | 6912 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); |
| ... | @@ -6912,16 +6932,14 @@ fn analyzeInlineCallArg( | ... | @@ -6912,16 +6932,14 @@ fn analyzeInlineCallArg( |
| 6912 | .ty = sema.typeOf(uncasted_arg), | 6932 | .ty = sema.typeOf(uncasted_arg), |
| 6913 | .val = arg_val, | 6933 | .val = arg_val, |
| 6914 | }; | 6934 | }; |
| 6915 | } else if (zir_tags[inst] == .param_anytype_comptime or try sema.typeRequiresComptime(param_ty)) { | ||
| 6916 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); | ||
| 6917 | } else if (try sema.resolveMaybeUndefVal(uncasted_arg)) |val| { | ||
| 6918 | // We have a comptime value but we need a runtime value to preserve inlining semantics, | ||
| 6919 | const wrapped = try sema.addConstant(param_ty, try Value.Tag.runtime_value.create(sema.arena, val)); | ||
| 6920 | sema.inst_map.putAssumeCapacityNoClobber(inst, wrapped); | ||
| 6921 | } else { | 6935 | } else { |
| 6922 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); | 6936 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); |
| 6923 | } | 6937 | } |
| 6924 | 6938 | ||
| 6939 | if (try sema.resolveMaybeUndefVal(uncasted_arg)) |_| { | ||
| 6940 | has_comptime_args.* = true; | ||
| 6941 | } | ||
| 6942 | |||
| 6925 | arg_i.* += 1; | 6943 | arg_i.* += 1; |
| 6926 | }, | 6944 | }, |
| 6927 | else => {}, | 6945 | else => {}, |
| ... | @@ -33075,7 +33093,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { | ... | @@ -33075,7 +33093,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { |
| 33075 | host_size: u16 = 0, | 33093 | host_size: u16 = 0, |
| 33076 | alignment: u32 = 0, | 33094 | alignment: u32 = 0, |
| 33077 | vector_index: VI = .none, | 33095 | vector_index: VI = .none, |
| 33078 | } = if (parent_ty.tag() == .vector) blk: { | 33096 | } = if (parent_ty.tag() == .vector and ptr_info.size == .One) blk: { |
| 33079 | const elem_bits = elem_ty.bitSize(target); | 33097 | const elem_bits = elem_ty.bitSize(target); |
| 33080 | if (elem_bits == 0) break :blk .{}; | 33098 | if (elem_bits == 0) break :blk .{}; |
| 33081 | const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits); | 33099 | const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits); |
src/codegen/llvm.zig+4| ... | @@ -3361,6 +3361,10 @@ pub const DeclGen = struct { | ... | @@ -3361,6 +3361,10 @@ pub const DeclGen = struct { |
| 3361 | const llvm_type = try dg.lowerType(tv.ty); | 3361 | const llvm_type = try dg.lowerType(tv.ty); |
| 3362 | return llvm_type.constNull(); | 3362 | return llvm_type.constNull(); |
| 3363 | }, | 3363 | }, |
| 3364 | .opt_payload => { | ||
| 3365 | const payload = tv.val.castTag(.opt_payload).?.data; | ||
| 3366 | return dg.lowerParentPtr(payload, tv.ty); | ||
| 3367 | }, | ||
| 3364 | else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ | 3368 | else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ |
| 3365 | tv.ty.fmtDebug(), tag, | 3369 | tv.ty.fmtDebug(), tag, |
| 3366 | }), | 3370 | }), |
test/behavior.zig-1| ... | @@ -133,7 +133,6 @@ test { | ... | @@ -133,7 +133,6 @@ test { |
| 133 | _ = @import("behavior/bugs/13113.zig"); | 133 | _ = @import("behavior/bugs/13113.zig"); |
| 134 | _ = @import("behavior/bugs/13128.zig"); | 134 | _ = @import("behavior/bugs/13128.zig"); |
| 135 | _ = @import("behavior/bugs/13159.zig"); | 135 | _ = @import("behavior/bugs/13159.zig"); |
| 136 | _ = @import("behavior/bugs/13164.zig"); | ||
| 137 | _ = @import("behavior/bugs/13171.zig"); | 136 | _ = @import("behavior/bugs/13171.zig"); |
| 138 | _ = @import("behavior/bugs/13209.zig"); | 137 | _ = @import("behavior/bugs/13209.zig"); |
| 139 | _ = @import("behavior/bugs/13285.zig"); | 138 | _ = @import("behavior/bugs/13285.zig"); |
test/behavior/bugs/13164.zig deleted-18| ... | @@ -1,18 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | inline fn setLimits(min: ?u32, max: ?u32) !void { | ||
| 5 | if (min != null and max != null) { | ||
| 6 | try std.testing.expect(min.? <= max.?); | ||
| 7 | } | ||
| 8 | } | ||
| 9 | |||
| 10 | test { | ||
| 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 12 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 13 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 14 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 15 | |||
| 16 | var x: u32 = 42; | ||
| 17 | try setLimits(x, null); | ||
| 18 | } | ||
test/behavior/call.zig+14| ... | @@ -381,3 +381,17 @@ test "generic function with generic function parameter" { | ... | @@ -381,3 +381,17 @@ test "generic function with generic function parameter" { |
| 381 | }; | 381 | }; |
| 382 | try S.f(S.g, 123); | 382 | try S.f(S.g, 123); |
| 383 | } | 383 | } |
| 384 | |||
| 385 | test "recursive inline call with comptime known argument" { | ||
| 386 | const S = struct { | ||
| 387 | inline fn foo(x: i32) i32 { | ||
| 388 | if (x <= 0) { | ||
| 389 | return 0; | ||
| 390 | } else { | ||
| 391 | return x * 2 + foo(x - 1); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | }; | ||
| 395 | |||
| 396 | try expect(S.foo(4) == 20); | ||
| 397 | } |
test/behavior/vector.zig+16| ... | @@ -1261,3 +1261,19 @@ test "store packed vector element" { | ... | @@ -1261,3 +1261,19 @@ test "store packed vector element" { |
| 1261 | v[0] = 0; | 1261 | v[0] = 0; |
| 1262 | try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v); | 1262 | try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v); |
| 1263 | } | 1263 | } |
| 1264 | |||
| 1265 | test "store to vector in slice" { | ||
| 1266 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1267 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1268 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1269 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1270 | |||
| 1271 | var v = [_]@Vector(3, f32){ | ||
| 1272 | .{ 1, 1, 1 }, | ||
| 1273 | .{ 0, 0, 0 }, | ||
| 1274 | }; | ||
| 1275 | var s: []@Vector(3, f32) = &v; | ||
| 1276 | var i: usize = 1; | ||
| 1277 | s[i] = s[0]; | ||
| 1278 | try expectEqual(v[1], v[0]); | ||
| 1279 | } |
test/cases/compile_errors/recursive_inline_fn.zig created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | inline fn foo(x: i32) i32 { | ||
| 2 | if (x <= 0) { | ||
| 3 | return 0; | ||
| 4 | } else { | ||
| 5 | return x * 2 + foo(x - 1); | ||
| 6 | } | ||
| 7 | } | ||
| 8 | |||
| 9 | pub export fn entry() void { | ||
| 10 | var x: i32 = 4; | ||
| 11 | _ = foo(x) == 20; | ||
| 12 | } | ||
| 13 | |||
| 14 | // error | ||
| 15 | // backend=stage2 | ||
| 16 | // target=native | ||
| 17 | // | ||
| 18 | // :5:27: error: inline call is recursive | ||