[clang] [Sema] Warning for _Float16 passed to format specifier '%f' (PR #74439)

Haocong Lu via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 5 01:30:25 PST 2023


https://github.com/Luhaocong created https://github.com/llvm/llvm-project/pull/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: https://github.com/llvm/llvm-project/issues/68538

>From 10c48f5c8c50617929cc72401721afc379131346 Mon Sep 17 00:00:00 2001
From: Lu Haocong <haocong.lu at evas.ai>
Date: Tue, 5 Dec 2023 16:45:22 +0800
Subject: [PATCH] [Sema] Warning for _Float16 passed to format specifier '%f'

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.
---
 clang/lib/AST/FormatString.cpp              |  1 -
 clang/test/AST/variadic-promotion.c         |  5 +++++
 clang/test/Sema/attr-format.c               |  7 +++++++
 clang/test/SemaCXX/attr-format.cpp          |  1 +
 clang/test/SemaCXX/format-strings-scanf.cpp | 16 ++++++++++------
 5 files changed, 23 insertions(+), 7 deletions(-)

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 at +1{{format specifies type 'int *' but the argument has type 'short *'}}
     scan("%hhi %i %li", &b.ss, &b.ss, &b.ss);
 
-    // expected-warning at +3{{format specifies type 'float *' but the argument has type '__fp16 *'}}
+    // expected-warning at +4{{format specifies type 'float *' but the argument has type '__fp16 *'}}
+    // expected-warning at +3{{format specifies type 'float *' but the argument has type '_Float16 *'}}
     // expected-warning at +2{{format specifies type 'float *' but the argument has type 'double *'}}
     // expected-warning at +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 at +3{{format specifies type 'double *' but the argument has type '__fp16 *'}}
+    // expected-warning at +4{{format specifies type 'double *' but the argument has type '__fp16 *'}}
+    // expected-warning at +3{{format specifies type 'double *' but the argument has type '_Float16 *'}}
     // expected-warning at +2{{format specifies type 'double *' but the argument has type 'float *'}}
     // expected-warning at +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 at +3{{format specifies type 'long double *' but the argument has type '__fp16 *'}}
+    // expected-warning at +4{{format specifies type 'long double *' but the argument has type '__fp16 *'}}
+    // expected-warning at +3{{format specifies type 'long double *' but the argument has type '_Float16 *'}}
     // expected-warning at +2{{format specifies type 'long double *' but the argument has type 'float *'}}
     // expected-warning at +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);
 }



More information about the cfe-commits mailing list