[clang] [C2y] Add test coverage for N3298 (PR #112033)

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 14 05:11:13 PDT 2024


https://github.com/AaronBallman updated https://github.com/llvm/llvm-project/pull/112033

>From 411744a7a98081f03f0b9e928924dd8ef178a609 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Fri, 11 Oct 2024 14:51:46 -0400
Subject: [PATCH 1/3] [C2y] Add test coverage for N3298

This paper adds 'i' and 'j' as suffixes for forming a _Complex
constant. This feature has been supported in Clang since at least
Clang 3.0, so only test coverage is needed.

It does remove -Wgnu-imaginary-constant in C mode (still used in C++
mode) because the feature is now a C2y feature rather than a GNU one.
---
 clang/test/C/C2y/n3298.c     | 104 +++++++++++++++++++++++++++++++++++
 clang/test/Lexer/gnu-flags.c |  12 +---
 clang/test/Sema/builtins.c   |   2 +-
 clang/test/Sema/exprs.c      |   8 +--
 clang/www/c_status.html      |   2 +-
 5 files changed, 112 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/C/C2y/n3298.c

diff --git a/clang/test/C/C2y/n3298.c b/clang/test/C/C2y/n3298.c
new file mode 100644
index 00000000000000..b39d0528963514
--- /dev/null
+++ b/clang/test/C/C2y/n3298.c
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -verify=ped -std=c23 -Wall -pedantic %s
+// RUN: %clang_cc1 -verify=yay -std=c2y -Wall -pedantic %s
+// RUN: %clang_cc1 -verify=pre -std=c2y -Wpre-c2y-compat -Wall -pedantic %s
+// RUN: %clang_cc1 -verify=gnu -Wall -Wgnu -x c++ %s
+// RUN: %clang_cc1 -verify=yay -Wall -Wgnu -Wno-gnu-imaginary-constant -x c++ %s
+
+
+/* WG14 N3298: Yes
+ * Introduce complex literals v. 2
+ *
+ * This introduces two suffixes for making complex literals: i and j (and I and
+ * J), which can be combined in any order with the other floating literal
+ * suffixes.
+ *
+ * We support these suffixes in older language modes as a conforming extension.
+ * It used to be a GNU extension, but now it's a C2y extension.
+ */
+
+// yay-no-diagnostics
+
+static_assert(_Generic(12.0i, _Complex double : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0fi, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0li, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0if, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0il, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+
+static_assert(_Generic(12.0I, _Complex double : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0fI, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0lI, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0If, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0Il, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+
+static_assert(_Generic(12.0j, _Complex double : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0fj, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0lj, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0jf, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0jl, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+
+static_assert(_Generic(12.0J, _Complex double : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0fJ, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0lJ, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0Jf, _Complex float : 1, default : 0));       /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+static_assert(_Generic(12.0Jl, _Complex long double : 1, default : 0)); /* gnu-warning {{imaginary constants are a GNU extension}}
+                                                                           ped-warning {{imaginary constants are a C2y extension}}
+                                                                           pre-warning {{imaginary constants are incompatible with C standards before C2y}}
+                                                                         */
+
diff --git a/clang/test/Lexer/gnu-flags.c b/clang/test/Lexer/gnu-flags.c
index 4d6d216b101f4a..6c7bf9405ddf0a 100644
--- a/clang/test/Lexer/gnu-flags.c
+++ b/clang/test/Lexer/gnu-flags.c
@@ -2,13 +2,12 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL \
 // RUN:   -Wgnu-zero-variadic-macro-arguments \
-// RUN:   -Wgnu-imaginary-constant -Wgnu-zero-line-directive
+// RUN:   -Wgnu-zero-line-directive
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wgnu \
 // RUN:   -Wno-gnu-zero-variadic-macro-arguments \
-// RUN:   -Wno-gnu-imaginary-constant -Wno-gnu-zero-line-directive
+// RUN:   -Wno-gnu-zero-line-directive
 // Additional disabled tests:
 // %clang_cc1 -fsyntax-only -verify %s -DZEROARGS -Wgnu-zero-variadic-macro-arguments
-// %clang_cc1 -fsyntax-only -verify %s -DIMAGINARYCONST -Wgnu-imaginary-constant
 // %clang_cc1 -fsyntax-only -verify %s -DLINE0 -Wgnu-zero-line-directive
 
 #if NONE
@@ -28,13 +27,6 @@ void foo( const char* c )
 }
 
 
-#if ALL || IMAGINARYCONST
-// expected-warning at +3 {{imaginary constants are a GNU extension}}
-#endif
-
-float _Complex c = 1.if;
-
-
 // This case is handled differently because lit has a bug whereby #line 0 is reported to be on line 4294967295
 // http://llvm.org/bugs/show_bug.cgi?id=16952
 #if ALL || LINE0
diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c
index d176dec9e9b3a3..b669ee68cdd954 100644
--- a/clang/test/Sema/builtins.c
+++ b/clang/test/Sema/builtins.c
@@ -40,7 +40,7 @@ void test9(short v) {
 
   old = __sync_fetch_and_add();  // expected-error {{too few arguments to function call}}
   old = __sync_fetch_and_add(&old);  // expected-error {{too few arguments to function call}}
-  old = __sync_fetch_and_add((unsigned*)0, 42i); // expected-warning {{imaginary constants are a GNU extension}}
+  old = __sync_fetch_and_add((unsigned*)0, 42i); // expected-warning {{imaginary constants are a C2y extension}}
 
   // PR7600: Pointers are implicitly casted to integers and back.
   void *old_ptr = __sync_val_compare_and_swap((void**)0, 0, 0);
diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c
index 3203d961dd0a49..caf173a9aa5011 100644
--- a/clang/test/Sema/exprs.c
+++ b/clang/test/Sema/exprs.c
@@ -40,7 +40,7 @@ _Complex double test1(void) {
 }
 
 _Complex double test2(void) {
-  return 1.0if;    // expected-warning {{imaginary constants are a GNU extension}}
+  return 1.0if;    // expected-warning {{imaginary constants are a C2y extension}}
 }
 
 void test3(void) {
@@ -57,7 +57,7 @@ void test4(void) {
 
       var =+5;  // no warning when the subexpr of the unary op has no space before it.
       var =-5;
-  
+
 #define FIVE 5
       var=-FIVE;  // no warning with macros.
       var=-FIVE;
@@ -152,7 +152,7 @@ void test17(int x) {
   x = x % 0;  // expected-warning {{remainder by zero is undefined}}
   x /= 0;  // expected-warning {{division by zero is undefined}}
   x %= 0;  // expected-warning {{remainder by zero is undefined}}
-  
+
   x = sizeof(x/0);  // no warning.
 }
 
@@ -205,7 +205,7 @@ int test20(int x) {
                  // expected-note {{remove constant to silence this warning}}
 
   return x && sizeof(int) == 4;  // no warning, RHS is logical op.
-  
+
   // no warning, this is an idiom for "true" in old C style.
   return x && (signed char)1;
 
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 2535651be12043..c896b6124b6ab2 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -216,7 +216,7 @@ <h2 id="c2y">C2y implementation status</h2>
     <tr>
       <td>Introduce complex literals v. 2</td>
       <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3298.htm">N3298</a></td>
-      <td class="unknown" align="center">Unknown</td>
+      <td class="full" align="center">Yes</td>
     </tr>
     <tr>
       <td>Allow zero length operations on null pointers</td>

>From 306b0c8095e08f57c566e4b3fe954879484c0118 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Mon, 14 Oct 2024 07:57:42 -0400
Subject: [PATCH 2/3] Add changes which were dropped by a bad git stash pop

---
 clang/lib/Sema/SemaExpr.cpp | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 531e7f6933d6d3..48f4029d873b94 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4096,7 +4096,15 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
     Res = new (Context) ImaginaryLiteral(Res,
                                         Context.getComplexType(Res->getType()));
 
-    Diag(Tok.getLocation(), diag::ext_imaginary_constant);
+    // In C++, this is a GNU extension. In C, it's a C2y extension.
+    unsigned DiagId;
+    if (getLangOpts().CPlusPlus)
+      DiagId = diag::ext_gnu_imaginary_constant;
+    else if (getLangOpts().C2y)
+      DiagId = diag::warn_c23_compat_imaginary_constant;
+    else
+      DiagId = diag::ext_c2y_imaginary_constant;
+    Diag(Tok.getLocation(), DiagId);
   }
   return Res;
 }

>From cdb9796a852e8e3a8e67fe545dbdcbd8bf0ae31f Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Mon, 14 Oct 2024 08:10:37 -0400
Subject: [PATCH 3/3] More dropped changes; git stash pop defeats me

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3c62a017005e59..fa7d97cdc2cf86 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -250,7 +250,12 @@ def ext_designated_init_brace_elision : ExtWarn<
 // Declarations.
 def ext_plain_complex : ExtWarn<
   "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
-def ext_imaginary_constant : Extension<
+def warn_c23_compat_imaginary_constant : Warning<
+  "imaginary constants are incompatible with C standards before C2y">,
+  DefaultIgnore, InGroup<CPre2yCompat>;
+def ext_c2y_imaginary_constant : Extension<
+  "imaginary constants are a C2y extension">, InGroup<C2y>;
+def ext_gnu_imaginary_constant : Extension<
   "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
 def ext_integer_complex : Extension<
   "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;



More information about the cfe-commits mailing list