Skip to content

Commit b2315a1

Browse files
committed
Update the support for escape sequences
1 parent ab37a01 commit b2315a1

File tree

5 files changed

+49
-26
lines changed

5 files changed

+49
-26
lines changed

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,14 @@ def ext_mathematical_notation : ExtWarn<
148148
InGroup<DiagGroup<"mathematical-notation-identifier-extension">>;
149149

150150
def ext_delimited_escape_sequence : Extension<
151-
"%select{delimited|named}0 escape sequences are a "
152-
"%select{Clang|C++23}1 extension">,
153-
InGroup<DiagGroup<"delimited-escape-sequence-extension">>;
154-
151+
"%select{delimited|named}0 escape sequences are a %select{C++23|C2y}1 "
152+
"extension">, InGroup<DiagGroup<"delimited-escape-sequence-extension">>;
155153
def warn_cxx23_delimited_escape_sequence : Warning<
156-
"%select{delimited|named}0 escape sequences are "
157-
"incompatible with C++ standards before C++23">,
158-
InGroup<CXXPre23Compat>, DefaultIgnore;
154+
"%select{delimited|named}0 escape sequences are incompatible with C++ "
155+
"standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
156+
def warn_c2y_delimited_escape_sequence : Warning<
157+
"delimited escape sequences are incompatible with C standards before C2y">,
158+
InGroup<CPre2yCompat>, DefaultIgnore;
159159

160160
def err_delimited_escape_empty : Error<
161161
"delimited escape sequence cannot be empty">;

clang/include/clang/Lex/Lexer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,12 @@ class Lexer : public PreprocessorLexer {
582582
/// sequence.
583583
static bool isNewLineEscaped(const char *BufferStart, const char *Str);
584584

585+
/// Diagnose use of a delimited or named escape sequence.
586+
static void DiagnoseDelimitedOrNamedEscapeSequence(SourceLocation Loc,
587+
bool Named,
588+
const LangOptions &Opts,
589+
DiagnosticsEngine &Diags);
590+
585591
/// Represents a char and the number of bytes parsed to produce it.
586592
struct SizedChar {
587593
char Char;

clang/lib/Lex/Lexer.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3405,6 +3405,24 @@ bool Lexer::isCodeCompletionPoint(const char *CurPtr) const {
34053405
return false;
34063406
}
34073407

3408+
void Lexer::DiagnoseDelimitedOrNamedEscapeSequence(SourceLocation Loc,
3409+
bool Named,
3410+
const LangOptions &Opts,
3411+
DiagnosticsEngine &Diags) {
3412+
unsigned DiagId;
3413+
if (Opts.CPlusPlus23)
3414+
DiagId = diag::warn_cxx23_delimited_escape_sequence;
3415+
else if (Opts.C2y)
3416+
DiagId = diag::warn_c2y_delimited_escape_sequence;
3417+
else
3418+
DiagId = diag::ext_delimited_escape_sequence;
3419+
3420+
// The trailing arguments are only used by the extension warning; either this
3421+
// is a C2y extension or a C++23 extension.
3422+
Diags.Report(Loc, DiagId) << Named << !Opts.CPlusPlus;
3423+
}
3424+
3425+
34083426
std::optional<uint32_t> Lexer::tryReadNumericUCN(const char *&StartPtr,
34093427
const char *SlashLoc,
34103428
Token *Result) {
@@ -3496,12 +3514,10 @@ std::optional<uint32_t> Lexer::tryReadNumericUCN(const char *&StartPtr,
34963514
return std::nullopt;
34973515
}
34983516

3499-
if (Delimited && PP) {
3500-
Diag(SlashLoc, PP->getLangOpts().CPlusPlus23
3501-
? diag::warn_cxx23_delimited_escape_sequence
3502-
: diag::ext_delimited_escape_sequence)
3503-
<< /*delimited*/ 0 << (PP->getLangOpts().CPlusPlus ? 1 : 0);
3504-
}
3517+
if (Delimited && PP)
3518+
DiagnoseDelimitedOrNamedEscapeSequence(getSourceLocation(SlashLoc), false,
3519+
PP->getLangOpts(),
3520+
PP->getDiagnostics());
35053521

35063522
if (Result) {
35073523
Result->setFlag(Token::HasUCN);
@@ -3585,10 +3601,9 @@ std::optional<uint32_t> Lexer::tryReadNamedUCN(const char *&StartPtr,
35853601
}
35863602

35873603
if (Diagnose && Match)
3588-
Diag(SlashLoc, PP->getLangOpts().CPlusPlus23
3589-
? diag::warn_cxx23_delimited_escape_sequence
3590-
: diag::ext_delimited_escape_sequence)
3591-
<< /*named*/ 1 << (PP->getLangOpts().CPlusPlus ? 1 : 0);
3604+
DiagnoseDelimitedOrNamedEscapeSequence(getSourceLocation(SlashLoc), true,
3605+
PP->getLangOpts(),
3606+
PP->getDiagnostics());
35923607

35933608
// If no diagnostic has been emitted yet, likely because we are doing a
35943609
// tentative lexing, we do not want to recover here to make sure the token

clang/lib/Lex/LiteralSupport.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,8 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
354354
diag::err_expected)
355355
<< tok::r_brace;
356356
else if (!HadError) {
357-
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
358-
Features.CPlusPlus23 ? diag::warn_cxx23_delimited_escape_sequence
359-
: diag::ext_delimited_escape_sequence)
360-
<< /*delimited*/ 0 << (Features.CPlusPlus ? 1 : 0);
357+
Lexer::DiagnoseDelimitedOrNamedEscapeSequence(Loc, false, Features,
358+
*Diags);
361359
}
362360
}
363361

@@ -710,11 +708,8 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
710708
diag::warn_ucn_not_valid_in_c89_literal);
711709

712710
if ((IsDelimitedEscapeSequence || IsNamedEscapeSequence) && Diags)
713-
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
714-
Features.CPlusPlus23 ? diag::warn_cxx23_delimited_escape_sequence
715-
: diag::ext_delimited_escape_sequence)
716-
<< (IsNamedEscapeSequence ? 1 : 0) << (Features.CPlusPlus ? 1 : 0);
717-
711+
Lexer::DiagnoseDelimitedOrNamedEscapeSequence(Loc, IsNamedEscapeSequence,
712+
Features, *Diags);
718713
return true;
719714
}
720715

clang/test/C/C2y/n3353.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ int r = M; /* compat-warning {{octal integer literals are incompatible with sta
9292
cpp-warning {{octal integer literals are a Clang extension}}
9393
*/
9494

95+
// Also, test delimited escape sequences. Note, this paper added a delimited
96+
// escape sequence for octal *and* hex.
97+
auto a = "\x{12}\o{12}"; /* compat-warning 2 {{delimited escape sequences are incompatible with C standards before C2y}}
98+
ext-warning 2 {{delimited escape sequences are a C2y extension}}
99+
cpp-warning 2 {{delimited escape sequences are a C++23 extension}}
100+
*/
101+
95102
#ifdef __cplusplus
96103
template <unsigned N>
97104
struct S {

0 commit comments

Comments
 (0)