-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[C2y] Add octal prefixes, deprecate unprefixed octals #131626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f3c0bc1
ab37a01
b2315a1
91a043c
5ad8f34
6ae2e2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -582,6 +582,12 @@ class Lexer : public PreprocessorLexer { | |
/// sequence. | ||
static bool isNewLineEscaped(const char *BufferStart, const char *Str); | ||
|
||
/// Diagnose use of a delimited or named escape sequence. | ||
static void DiagnoseDelimitedOrNamedEscapeSequence(SourceLocation Loc, | ||
bool Named, | ||
const LangOptions &Opts, | ||
DiagnosticsEngine &Diags); | ||
|
||
Comment on lines
+585
to
+590
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could just be a non-member static function Lexer.cpp There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's called from LiteralSupport.cpp, so it could be a non-member function, but I think it's a bit cleaner to scope it to the |
||
/// Represents a char and the number of bytes parsed to produce it. | ||
struct SizedChar { | ||
char Char; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// 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}} | ||
AaronBallman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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}} | ||
AaronBallman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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; | ||
|
||
// 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}} | ||
*/ | ||
AaronBallman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 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}} |
Uh oh!
There was an error while loading. Please reload this page.