diff --git a/releasenotes.md b/releasenotes.md index 85d71bb2f..0f041a9b2 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -27,6 +27,7 @@ - Compiler segfault when modifying variable using an inline assembly block inside defer #2450. - Compile time switch over type would not correctly compare function pointer types. - Regression: Compiler segfault when assigning struct literal with too few members #2483 +- Fix compile time format check when the formatting string is a constant slice. ### Stdlib changes - Added generic `InterfaceList` to store a list of values that implement a specific interface diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index a90daf4e7..29a6a2ffb 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2180,6 +2180,10 @@ CHECK_FORMAT:; // Check Expr *expr = actual_args[format_index]; if (!sema_cast_const(expr) || call->call_expr.va_is_splat) return true; + if (!expr_is_const_string(expr)) + { + RETURN_SEMA_ERROR(expr, "The format string must be a constant string."); + } assert(expr_is_const_string(expr)); const char *data = expr->const_expr.bytes.ptr; size_t len = expr->const_expr.bytes.len; diff --git a/test/test_suite/attributes/format_check_error.c3 b/test/test_suite/attributes/format_check_error.c3 new file mode 100644 index 000000000..98be46c40 --- /dev/null +++ b/test/test_suite/attributes/format_check_error.c3 @@ -0,0 +1,51 @@ +import std; + +const VERSION = "2.0"; +enum Subcommand : (String name, String desc, String[] args) +{ + FOO = {"oekfe", "foek", { "foke", "foekfe"}}, + BAR = {"foek", "foek", { "foekf", "foekfe"}}, + BAZ = {"Foekfef", "foek", { "foke", "foekfe" }} +} +macro void help (String program_name, bool to_stderr = false) +{ + var printfn = to_stderr ? &io::printfn : &io::eprintfn; + var printf = to_stderr ? &io::printfn : &io::eprintfn; + + @pool() + { + printfn("mu2d version " +++ VERSION); + printfn(""); + (void) printfn("Usage: %s [flags] [options] ...", program_name.file_tbasename()); + printfn(""); + printfn("Subcommands:"); + var $ident = " "; + $foreach $subcommand : Subcommand.values: + var $line = $ident +++ $subcommand.name; + $foreach $arg : $subcommand.args: + $line = $line +++ " " +++ $arg; + $endforeach + printfn($line); + + var $row_counter = 0; + $foreach $c : $subcommand.desc: + $if $row_counter == 0: + $row_counter += $ident.len * 2; + printf($ident + $ident); // #error: Cannot do the addition 'String' + 'String' + $endif + + $if $row_counter + 1 >= 80 &&& $c == ' ': + printf("\n"); + $row_counter = 0; + $else + printf((String) { $c }); // #error: The format string must be a constant + $row_counter += 1; + $endif + $endforeach + $endforeach + }; +} +fn void main() +{ + help("aaa", true); +} \ No newline at end of file