Do not implicitly convert enums to ordinal in formatting functions.

This commit is contained in:
Christoffer Lerno
2025-03-25 12:27:51 +01:00
parent 439349ceb8
commit fa707db078
7 changed files with 17 additions and 13 deletions

View File

@@ -46,7 +46,7 @@ macro Char16[] @char16(String $string) @builtin
@param [in] fmt : `The formatting string`
*>
fn ZString tformat_zstr(String fmt, args...)
fn ZString tformat_zstr(String fmt, args...) @format(0)
{
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);
@@ -59,7 +59,7 @@ fn ZString tformat_zstr(String fmt, args...)
@param [inout] allocator : `The allocator to use`
@param [in] fmt : `The formatting string`
*>
fn String format(Allocator allocator, String fmt, args...) => @pool()
fn String format(Allocator allocator, String fmt, args...) @format(1) => @pool()
{
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);
@@ -71,7 +71,7 @@ fn String format(Allocator allocator, String fmt, args...) => @pool()
@param [in] fmt : `The formatting string`
*>
fn String tformat(String fmt, args...)
fn String tformat(String fmt, args...) @format(0)
{
DString str = dstring::temp_with_capacity(fmt.len + args.len * 8);
str.appendf(fmt, ...args);

View File

@@ -339,7 +339,7 @@ macro usz? @wrap_bad(Formatter* f, #action)
case INTERNAL_BUFFER_EXCEEDED:
return f.first_err(err)?;
default:
err = f.first_err(INVALID_ARGUMENT);
err = f.first_err(INVALID_ARGUMENT);
f.out_substr("<INVALID>")!;
return err?;
}

View File

@@ -43,7 +43,6 @@ fn uint128? int_from_any(any arg, bool *is_neg) @private
*is_neg = false;
return (uint128)(uptr)*(void**)arg.ptr;
case TypeKind.DISTINCT:
case TypeKind.ENUM:
return int_from_any(arg.as_inner(), is_neg);
default:
break;

View File

@@ -45,18 +45,18 @@ fn String format(Allocator allocator, DateTimeFormat type, TzDateTime dt)
return string::format(allocator, "%s, %02d %s %d %02d:%02d:%02d %s", dt.weekday.abbrev, dt.day, dt.month.abbrev, dt.year, dt.hour, dt.min, dt.sec, temp_numeric_tzsuffix(dt.gmt_offset));
case RFC3339:
dt = dt.to_gmt_offset(0);
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02dZ", dt.year, dt.month + 1, dt.day, dt.hour, dt.min, dt.sec);
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02dZ", dt.year, dt.month.ordinal + 1, dt.day, dt.hour, dt.min, dt.sec);
case RFC3339Z:
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02d%s", dt.year, dt.month + 1, dt.day, dt.hour, dt.min, dt.sec, temp_numeric_tzsuffix_colon(dt.gmt_offset));
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02d%s", dt.year, dt.month.ordinal + 1, dt.day, dt.hour, dt.min, dt.sec, temp_numeric_tzsuffix_colon(dt.gmt_offset));
case RFC3339MS:
dt = dt.to_gmt_offset(0);
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02d.%dZ", dt.year, dt.month + 1, dt.day, dt.hour, dt.min, dt.sec, dt.usec);
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02d.%dZ", dt.year, dt.month.ordinal + 1, dt.day, dt.hour, dt.min, dt.sec, dt.usec);
case RFC3339ZMS:
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02d.%d%s", dt.year, dt.month + 1, dt.day, dt.hour, dt.min, dt.sec, dt.usec, temp_numeric_tzsuffix_colon(dt.gmt_offset));
return string::format(allocator, "%04d-%02d-%02dT%02d:%02d:%02d.%d%s", dt.year, dt.month.ordinal + 1, dt.day, dt.hour, dt.min, dt.sec, dt.usec, temp_numeric_tzsuffix_colon(dt.gmt_offset));
case DATETIME:
return string::format(allocator, "%04d-%02d-%02d %02d:%02d:%02d", dt.year, dt.month + 1, dt.day, dt.hour, dt.min, dt.sec);
return string::format(allocator, "%04d-%02d-%02d %02d:%02d:%02d", dt.year, dt.month.ordinal + 1, dt.day, dt.hour, dt.min, dt.sec);
case DATEONLY:
return string::format(allocator, "%04d-%02d-%02d", dt.year, dt.month + 1, dt.day);
return string::format(allocator, "%04d-%02d-%02d", dt.year, dt.month.ordinal + 1, dt.day);
case TIMEONLY:
return string::format(allocator, "%02d:%02d:%02d", dt.hour, dt.min, dt.sec);
}

View File

@@ -44,6 +44,7 @@
- `tmem` is now a variable.
- Compile test and benchmark functions when invoking `--lsp` #2058.
- Added `@format` attribute for compile time printf validation #2057.
- Formatter no longer implicitly converts enums to ordinals.
### Fixes
- Fix address sanitizer to work on MachO targets (e.g. MacOS).

View File

@@ -1869,6 +1869,10 @@ CHECK_FORMAT:;
case 'G':
if (!type_is_number_or_bool(type))
{
if (type->type_kind == TYPE_ENUM)
{
RETURN_SEMA_ERROR(vaargs[idx], "An enum cannot directly be turned into a number. Use '.ordinal' to convert it to its value.", type_quoted_error_string(type));
}
RETURN_SEMA_ERROR(vaargs[idx], "Expected a number here, but was %s", type_quoted_error_string(type));
}
goto NEXT;

View File

@@ -107,10 +107,10 @@ fn void printf_enum()
assert(s == "ENUMB", "got '%s'; want 'ENUMB'", s);
free(s);
s = string::format(mem, "%d", PrintfTest.ENUMA);
s = string::format(mem, "%d", PrintfTest.ENUMA.ordinal);
assert(s == "0", "got '%s'; want '0'", s);
free(s);
s = string::format(mem, "%d", PrintfTest.ENUMB);
s = string::format(mem, "%d", PrintfTest.ENUMB.ordinal);
assert(s == "1", "got '%s'; want '1'", s);
free(s);
}