-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Sema] Warning for _Float16 passed to format specifier '%f' #74439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Haocong Lu (Luhaocong) ChangesAccording 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 Full diff: https://github.com/llvm/llvm-project/pull/74439.diff 5 Files Affected:
diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp
index e0c9e18cfe3a2..c5d14b4af7ff1 100644
--- a/clang/lib/AST/FormatString.cpp
+++ b/clang/lib/AST/FormatString.cpp
@@ -488,7 +488,6 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
return NoMatchPromotionTypeConfusion;
break;
case BuiltinType::Half:
- case BuiltinType::Float16:
case BuiltinType::Float:
if (T == C.DoubleTy)
return MatchPromotion;
diff --git a/clang/test/AST/variadic-promotion.c b/clang/test/AST/variadic-promotion.c
index 41c7fec8d7943..7cbadb832ca80 100644
--- a/clang/test/AST/variadic-promotion.c
+++ b/clang/test/AST/variadic-promotion.c
@@ -18,3 +18,8 @@ void test_floating_promotion(__fp16 *f16, float f32, double f64) {
// CHECK: ImplicitCastExpr {{.*}} 'double' <FloatingCast>
// CHECK-NEXT: 'float'
}
+
+void test_Float16_no_default_promotion(_Float16 f16) {
+ variadic(1, f16);
+// CHECK-NOT: ImplicitCastExpr {{.*}} 'double' <FloatingCast>
+}
diff --git a/clang/test/Sema/attr-format.c b/clang/test/Sema/attr-format.c
index 1f4c864d4f78b..bdfd8425c4e9a 100644
--- a/clang/test/Sema/attr-format.c
+++ b/clang/test/Sema/attr-format.c
@@ -16,6 +16,8 @@ typedef const char *xpto;
void j(xpto c, va_list list) __attribute__((format(printf, 1, 0))); // no-error
void k(xpto c) __attribute__((format(printf, 1, 0))); // no-error
+void l(char *a, _Float16 b) __attribute__((format(printf, 1, 2))); // expected-warning {{GCC requires a function with the 'format' attribute to be variadic}}
+
void y(char *str) __attribute__((format(strftime, 1, 0))); // no-error
void z(char *str, int c, ...) __attribute__((format(strftime, 1, 2))); // expected-error {{strftime format attribute requires 3rd parameter to be 0}}
@@ -93,6 +95,11 @@ void call_nonvariadic(void) {
d3("%s", 123); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
}
+void call_no_default_promotion(void) {
+ a("%f", (_Float16)1.0); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}}
+ l("%f", (_Float16)1.0); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}}
+}
+
__attribute__((format(printf, 1, 2)))
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}}
forward_fixed(fmt, b, i, j, k, l, m);
diff --git a/clang/test/SemaCXX/attr-format.cpp b/clang/test/SemaCXX/attr-format.cpp
index adc05fc46776c..4509c3a95e8ef 100644
--- a/clang/test/SemaCXX/attr-format.cpp
+++ b/clang/test/SemaCXX/attr-format.cpp
@@ -81,6 +81,7 @@ void do_format() {
format("%c %c %hhd %hd %d\n", (char)'a', 'a', 'a', (short)123, (int)123);
format("%f %f %f\n", (__fp16)123.f, 123.f, 123.);
+ format("%f", (_Float16)123.f);// expected-warning{{format specifies type 'double' but the argument has type '_Float16'}}
format("%Lf", (__fp16)123.f); // expected-warning{{format specifies type 'long double' but the argument has type '__fp16'}}
format("%Lf", 123.f); // expected-warning{{format specifies type 'long double' but the argument has type 'float'}}
format("%hhi %hhu %hi %hu %i %u", b, b, b, b, b, b);
diff --git a/clang/test/SemaCXX/format-strings-scanf.cpp b/clang/test/SemaCXX/format-strings-scanf.cpp
index 25fe5346791a0..406c2069e28ca 100644
--- a/clang/test/SemaCXX/format-strings-scanf.cpp
+++ b/clang/test/SemaCXX/format-strings-scanf.cpp
@@ -22,6 +22,7 @@ union bag {
unsigned long long ull;
signed long long sll;
__fp16 f16;
+ _Float16 Float16;
float ff;
double fd;
long double fl;
@@ -51,18 +52,21 @@ void test(void) {
// expected-warning@+1{{format specifies type 'int *' but the argument has type 'short *'}}
scan("%hhi %i %li", &b.ss, &b.ss, &b.ss);
- // expected-warning@+3{{format specifies type 'float *' but the argument has type '__fp16 *'}}
+ // expected-warning@+4{{format specifies type 'float *' but the argument has type '__fp16 *'}}
+ // expected-warning@+3{{format specifies type 'float *' but the argument has type '_Float16 *'}}
// expected-warning@+2{{format specifies type 'float *' but the argument has type 'double *'}}
// expected-warning@+1{{format specifies type 'float *' but the argument has type 'long double *'}}
- scan("%f %f %f", &b.f16, &b.fd, &b.fl);
+ scan("%f %f %f %f", &b.f16, &b.Float16, &b.fd, &b.fl);
- // expected-warning@+3{{format specifies type 'double *' but the argument has type '__fp16 *'}}
+ // expected-warning@+4{{format specifies type 'double *' but the argument has type '__fp16 *'}}
+ // expected-warning@+3{{format specifies type 'double *' but the argument has type '_Float16 *'}}
// expected-warning@+2{{format specifies type 'double *' but the argument has type 'float *'}}
// expected-warning@+1{{format specifies type 'double *' but the argument has type 'long double *'}}
- scan("%lf %lf %lf", &b.f16, &b.ff, &b.fl);
+ scan("%lf %lf %lf %lf", &b.f16, &b.Float16, &b.ff, &b.fl);
- // expected-warning@+3{{format specifies type 'long double *' but the argument has type '__fp16 *'}}
+ // expected-warning@+4{{format specifies type 'long double *' but the argument has type '__fp16 *'}}
+ // expected-warning@+3{{format specifies type 'long double *' but the argument has type '_Float16 *'}}
// expected-warning@+2{{format specifies type 'long double *' but the argument has type 'float *'}}
// expected-warning@+1{{format specifies type 'long double *' but the argument has type 'double *'}}
- scan("%Lf %Lf %Lf", &b.f16, &b.ff, &b.fd);
+ scan("%Lf %Lf %Lf %Lf", &b.f16, &b.Float16, &b.ff, &b.fd);
}
|
10c48f5
to
afb0d39
Compare
This patch improves implement 04e6178. Could you please help me review this patch @apple-fcloutier @AaronBallman |
Should this only apply in C23 mode? Standard behavior until C23 is that |
It seems clang never support default argument promotions for _Float16, as described in https://github.com/llvm/llvm-project/blob/main/clang/docs/LanguageExtensions.rst#half-precision-floating-point five years ago. Is there any demand to support this in old C/C++ standard? And I try case with -std=c99 (https://godbolt.org/z/xqx8e6oh5) and -std=c++11 (https://godbolt.org/z/Mrn779Tdq) , GCC give a warning at both. |
afb0d39
to
47ec170
Compare
CC @jcranmer-intel for additional opinions |
I can't find any reference in older versions of C or TS 18661-3 that suggests that
Which suggests that only |
N2844, as linked by OP, references the removed language that you are looking for. As Aaron said, it doesn't matter if clang never claimed conformance/never implemented default argument promotion for these types in the first place. |
Doing some more spelunking, no released version of the TS ever had default argument promotion. The change to the TS was done shortly before integration in C, in response to the C++ proposal for extended floating-point types, but WG14 objected to the change, so it was dropped in actual integration. See https://mailman.oakapple.net/pipermail/cfp-interest/2020-September/001782.html for the summary. |
47ec170
to
899e18d
Compare
Thanks for everyone's review. Do you have any other suggestions for this change, and can this pull request be accepted ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
The format diagnostics are new in Clang 18 and as such we do not need a release note. Correct?
clang/test/AST/variadic-promotion.c
Outdated
void test_Float16_no_default_promotion(_Float16 f16) { | ||
variadic(1, f16); | ||
// CHECK-NOT: ImplicitCastExpr {{.*}} 'double' <FloatingCast> | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test seems unrelated to the change, we should do that in a separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
According to https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2844.pdf, there are no default argument promotions for _FloatN types. 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.
899e18d
to
e86dc46
Compare
These format diagnostics are existent until 04e6178 was committed. Clang 17.0.1 gives a warning: https://godbolt.org/z/xMdK9cETY. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for confirming.
Do you need me to merge that for you?
It can't be better, thanks. |
This patch broke the Solaris/sparcv9 buildbot: the new/changed tests
|
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: llvm#68538
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