Skip to content

Commit 5034994

Browse files
authored
[Sema] Warning for _Float16 passed to format specifier '%f' (#74439)
According to https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2844.pdf, default argument promotions for _FloatN types has been removed. A warning is needed to notice user to promote _Float16 to double explicitly, and then pass it to format specifier '%f', which is consistent with GCC. Fixes: #68538
1 parent d6aef86 commit 5034994

File tree

4 files changed

+18
-7
lines changed

4 files changed

+18
-7
lines changed

clang/lib/AST/FormatString.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,6 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
488488
return NoMatchPromotionTypeConfusion;
489489
break;
490490
case BuiltinType::Half:
491-
case BuiltinType::Float16:
492491
case BuiltinType::Float:
493492
if (T == C.DoubleTy)
494493
return MatchPromotion;

clang/test/Sema/attr-format.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ typedef const char *xpto;
1616
void j(xpto c, va_list list) __attribute__((format(printf, 1, 0))); // no-error
1717
void k(xpto c) __attribute__((format(printf, 1, 0))); // no-error
1818

19+
void l(char *a, _Float16 b) __attribute__((format(printf, 1, 2))); // expected-warning {{GCC requires a function with the 'format' attribute to be variadic}}
20+
1921
void y(char *str) __attribute__((format(strftime, 1, 0))); // no-error
2022
void z(char *str, int c, ...) __attribute__((format(strftime, 1, 2))); // expected-error {{strftime format attribute requires 3rd parameter to be 0}}
2123

@@ -93,6 +95,11 @@ void call_nonvariadic(void) {
9395
d3("%s", 123); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
9496
}
9597

98+
void call_no_default_promotion(void) {
99+
a("%f", (_Float16)1.0); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}}
100+
l("%f", (_Float16)1.0); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}}
101+
}
102+
96103
__attribute__((format(printf, 1, 2)))
97104
void forward_fixed(const char *fmt, _Bool b, char i, short j, int k, float l, double m) { // expected-warning{{GCC requires a function with the 'format' attribute to be variadic}}
98105
forward_fixed(fmt, b, i, j, k, l, m);

clang/test/SemaCXX/attr-format.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ void do_format() {
8181

8282
format("%c %c %hhd %hd %d\n", (char)'a', 'a', 'a', (short)123, (int)123);
8383
format("%f %f %f\n", (__fp16)123.f, 123.f, 123.);
84+
format("%f", (_Float16)123.f);// expected-warning{{format specifies type 'double' but the argument has type '_Float16'}}
8485
format("%Lf", (__fp16)123.f); // expected-warning{{format specifies type 'long double' but the argument has type '__fp16'}}
8586
format("%Lf", 123.f); // expected-warning{{format specifies type 'long double' but the argument has type 'float'}}
8687
format("%hhi %hhu %hi %hu %i %u", b, b, b, b, b, b);

clang/test/SemaCXX/format-strings-scanf.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ union bag {
2222
unsigned long long ull;
2323
signed long long sll;
2424
__fp16 f16;
25+
_Float16 Float16;
2526
float ff;
2627
double fd;
2728
long double fl;
@@ -51,18 +52,21 @@ void test(void) {
5152
// expected-warning@+1{{format specifies type 'int *' but the argument has type 'short *'}}
5253
scan("%hhi %i %li", &b.ss, &b.ss, &b.ss);
5354

54-
// expected-warning@+3{{format specifies type 'float *' but the argument has type '__fp16 *'}}
55+
// expected-warning@+4{{format specifies type 'float *' but the argument has type '__fp16 *'}}
56+
// expected-warning@+3{{format specifies type 'float *' but the argument has type '_Float16 *'}}
5557
// expected-warning@+2{{format specifies type 'float *' but the argument has type 'double *'}}
5658
// expected-warning@+1{{format specifies type 'float *' but the argument has type 'long double *'}}
57-
scan("%f %f %f", &b.f16, &b.fd, &b.fl);
59+
scan("%f %f %f %f", &b.f16, &b.Float16, &b.fd, &b.fl);
5860

59-
// expected-warning@+3{{format specifies type 'double *' but the argument has type '__fp16 *'}}
61+
// expected-warning@+4{{format specifies type 'double *' but the argument has type '__fp16 *'}}
62+
// expected-warning@+3{{format specifies type 'double *' but the argument has type '_Float16 *'}}
6063
// expected-warning@+2{{format specifies type 'double *' but the argument has type 'float *'}}
6164
// expected-warning@+1{{format specifies type 'double *' but the argument has type 'long double *'}}
62-
scan("%lf %lf %lf", &b.f16, &b.ff, &b.fl);
65+
scan("%lf %lf %lf %lf", &b.f16, &b.Float16, &b.ff, &b.fl);
6366

64-
// expected-warning@+3{{format specifies type 'long double *' but the argument has type '__fp16 *'}}
67+
// expected-warning@+4{{format specifies type 'long double *' but the argument has type '__fp16 *'}}
68+
// expected-warning@+3{{format specifies type 'long double *' but the argument has type '_Float16 *'}}
6569
// expected-warning@+2{{format specifies type 'long double *' but the argument has type 'float *'}}
6670
// expected-warning@+1{{format specifies type 'long double *' but the argument has type 'double *'}}
67-
scan("%Lf %Lf %Lf", &b.f16, &b.ff, &b.fd);
71+
scan("%Lf %Lf %Lf %Lf", &b.f16, &b.Float16, &b.ff, &b.fd);
6872
}

0 commit comments

Comments
 (0)