diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3c62a017005e598..fa7d97cdc2cf86e 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; +def ext_c2y_imaginary_constant : Extension< + "imaginary constants are a C2y extension">, InGroup; +def ext_gnu_imaginary_constant : Extension< "imaginary constants are a GNU extension">, InGroup; def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 531e7f6933d6d33..48f4029d873b940 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; } diff --git a/clang/test/C/C2y/n3298.c b/clang/test/C/C2y/n3298.c new file mode 100644 index 000000000000000..b39d0528963514c --- /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 4d6d216b101f4a6..6c7bf9405ddf0a6 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@+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 d176dec9e9b3a3c..b669ee68cdd9540 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 3203d961dd0a49a..caf173a9aa50115 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 2535651be12043b..c896b6124b6ab2e 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -216,7 +216,7 @@

C2y implementation status

Introduce complex literals v. 2 N3298 - Unknown + Yes Allow zero length operations on null pointers