blob: a616228f1bad0cf2e7af9895cb7546075eeb0022 [file] [log] [blame] [edit]
// RUN: %clang_cc1 -verify=expected,c2y,c -pedantic -std=c2y %s
// RUN: %clang_cc1 -verify=expected,c2y,compat -Wpre-c2y-compat -std=c2y %s
// RUN: %clang_cc1 -verify=expected,ext,c -pedantic -std=c23 %s
// RUN: %clang_cc1 -verify=expected,cpp -pedantic -x c++ -Wno-c11-extensions %s
/* WG14 N3353: Clang 21
* Obsolete implicitly octal literals and add delimited escape sequences
*/
constexpr int i = 0234; // c2y-warning {{octal literals without a '0o' prefix are deprecated}}
constexpr int j = 0o234; /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
static_assert(i == 156);
static_assert(j == 156);
// Show that 0O is the same as Oo (tested above)
static_assert(0O1234 == 0o1234); /* ext-warning 2 {{octal integer literals are a C2y extension}}
cpp-warning 2 {{octal integer literals are a Clang extension}}
compat-warning 2 {{octal integer literals are incompatible with standards before C2y}}
*/
// Show that you can use them with the usual integer literal suffixes.
static_assert(0o234ull == 156); /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
// And it's still a valid null pointer constant.
static const void *ptr = 0o0; /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
// Demonstrate that it works fine in the preprocessor.
#if 0o123 != 0x53 /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
#error "oh no, math stopped working!"
#endif
// 0 by itself is not deprecated, of course.
int k = 0;
// Test a preprocessor use of 0 by itself, which is also not deprecated.
#if 0
#endif
// Make sure there are no surprises with auto and type deduction. Promotion
// turns this into an 'int', and 'constexpr' implies 'const'.
constexpr auto l = 0o1234567; /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
static_assert(l == 0x53977);
static_assert(__extension__ _Generic(typeof(0o1), typeof(01) : 1, default : 0)); /* c2y-warning {{octal literals without a '0o' prefix are deprecated}}
compat-warning {{passing a type argument as the first operand to '_Generic' is incompatible with C standards before C2y}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
static_assert(__extension__ _Generic(typeof(l), const int : 1, default : 0)); // compat-warning {{passing a type argument as the first operand to '_Generic' is incompatible with C standards before C2y}}
// Note that 0o by itself is an invalid literal.
int m = 0o; /* expected-error {{invalid suffix 'o' on integer constant}}
c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
// Ensure negation works as expected.
static_assert(-0o1234 == -668); /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
// FIXME: it would be better to not diagnose the compat and ext warnings when
// the octal literal is invalid.
// We expect diagnostics for non-octal digits.
int n = 0o18; /* expected-error {{invalid digit '8' in octal constant}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
*/
int o1 = 0o8; /* expected-error {{invalid suffix 'o8' on integer constant}}
c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
// FIXME: however, it matches the behavior for hex literals in terms of the
// error reported. Unfortunately, we then go on to think 0 is an octal literal
// without a prefix, which is again a bit confusing.
int o2 = 0xG; /* expected-error {{invalid suffix 'xG' on integer constant}}
c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
// Ensure digit separators work as expected.
constexpr int p = 0o0'1'2'3'4'5'6'7; /* compat-warning {{octal integer literals are incompatible with standards before C2y}}
ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
*/
static_assert(p == 01234567); // c2y-warning {{octal literals without a '0o' prefix are deprecated}}
int q = 0o'0'1; /* expected-error {{invalid suffix 'o'0'1' on integer constant}}
c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
#define M 0o123
int r = M; /* compat-warning {{octal integer literals are incompatible with standards before C2y}}
ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
*/
// Also, test delimited escape sequences. Note, this paper added a delimited
// escape sequence for octal *and* hex.
auto a = "\x{12}\o{12}\N{SPARKLES}"; /* compat-warning 2 {{delimited escape sequences are incompatible with C standards before C2y}}
ext-warning 2 {{delimited escape sequences are a C2y extension}}
cpp-warning 2 {{delimited escape sequences are a C++23 extension}}
cpp-warning {{named escape sequences are a C++23 extension}}
c-warning {{named escape sequences are a Clang extension}}
*/
#ifdef __cplusplus
template <unsigned N>
struct S {
static_assert(N == 0o567); /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
};
void foo() {
S<0o567> s; /* ext-warning {{octal integer literals are a C2y extension}}
cpp-warning {{octal integer literals are a Clang extension}}
compat-warning {{octal integer literals are incompatible with standards before C2y}}
*/
}
#endif
#line 0123 // expected-warning {{#line directive interprets number as decimal, not octal}}
#line 0o123 // expected-error {{#line directive requires a simple digit sequence}}