
Fixes #149669; the old check compared with the end of the literal, but we can just check that after parsing digits, we're pointing to one character past the token start. (cherry picked from commit 8366dc207a2e6b50cb8afe2d98fca68bd78bd0fa)
171 lines
9.5 KiB
C
171 lines
9.5 KiB
C
// 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 k1 = 0;
|
|
unsigned int k2 = 0u;
|
|
long k3 = 0l;
|
|
unsigned long k4 = 0ul;
|
|
long long k5 = 0ll;
|
|
unsigned long long k6 = 0ull;
|
|
|
|
// 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}}
|
|
*/
|
|
|
|
// 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}}
|
|
*/
|
|
// 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}}
|
|
*/
|
|
|
|
// Show that floating-point suffixes on octal literals are rejected.
|
|
auto f1 = 0o0.; /* expected-error {{invalid suffix '.' on integer 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}}
|
|
*/
|
|
auto f2 = 0o0.1; /* expected-error {{invalid suffix '.1' on integer 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}}
|
|
*/
|
|
auto f3 = 0o0e1; /* expected-error {{invalid suffix 'e1' on integer 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}}
|
|
*/
|
|
auto f4 = 0o0E1; /* expected-error {{invalid suffix 'E1' on integer 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}}
|
|
*/
|
|
|
|
// Show that valid floating-point literals with a leading 0 do not produce octal-related warnings.
|
|
auto f5 = 0.;
|
|
auto f7 = 00.;
|
|
auto f8 = 01.;
|
|
auto f9 = 0e1;
|
|
auto f10 = 0E1;
|
|
auto f11 = 00e1;
|
|
auto f12 = 00E1;
|
|
|
|
// 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}}
|
|
*/
|
|
|
|
#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}}
|