https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/88265
>From 40e533e6f58acbe832b3fa4e14ca9fd600cf77cf Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@gmail.com> Date: Wed, 10 Apr 2024 14:36:23 +0200 Subject: [PATCH 1/5] [Clang] Allow raw string literals in C as an extension --- clang/docs/ReleaseNotes.rst | 3 +++ clang/include/clang/Basic/LangOptions.def | 2 ++ clang/include/clang/Basic/LangStandard.h | 6 ++++++ clang/include/clang/Driver/Options.td | 6 ++++++ clang/lib/Basic/LangOptions.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 2 ++ clang/lib/Format/Format.cpp | 1 + clang/lib/Lex/Lexer.cpp | 10 +++++----- clang/test/Lexer/raw-string-ext.c | 18 ++++++++++++++++++ 9 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 clang/test/Lexer/raw-string-ext.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f96cebbde3d82..20d14130fb62b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -43,6 +43,9 @@ code bases. C/C++ Language Potentially Breaking Changes ------------------------------------------- +- Clang now supports raw string literals in ``-std=gnuXY`` mode as an extension in + C. This behaviour can also be overridden using ``-f[no-]raw-string-literals``. + C++ Specific Potentially Breaking Changes ----------------------------------------- - Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template<class T> void T();``. diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 8ef6700ecdc78..96bd339bb1851 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -454,6 +454,8 @@ LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type") LANGOPT(CXXAssumptions, 1, 1, "Enable or disable codegen and compile-time checks for C++23's [[assume]] attribute") +LANGOPT(RawStringLiterals, 1, 0, "Enable or disable raw string literals") + ENUM_LANGOPT(StrictFlexArraysLevel, StrictFlexArraysLevelKind, 2, StrictFlexArraysLevelKind::Default, "Rely on strict definition of flexible arrays") diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h index 8e25afc833661..0a308b93ada74 100644 --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -130,6 +130,12 @@ struct LangStandard { /// hasDigraphs - Language supports digraphs. bool hasDigraphs() const { return Flags & Digraphs; } + /// hasRawStringLiterals - Language supports R"()" raw string literals. + bool hasRawStringLiterals() const { + // GCC supports raw string literals in C, but not in C++ before C++11. + return isCPlusPlus11() || (!isCPlusPlus() && isGNUMode()); + } + /// isGNUMode - Language includes GNU extensions. bool isGNUMode() const { return Flags & GNUMode; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f745e573eb268..32e6c10e1251b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4142,6 +4142,12 @@ def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>, HelpText<"Enable matrix data type and related builtin functions">, MarshallingInfoFlag<LangOpts<"MatrixTypes">>; +defm raw_string_literals : BoolFOption<"raw-string-literals", + LangOpts<"RawStringLiterals">, Default<std#".hasRawStringLiterals()">, + PosFlag<SetTrue, [], [], "Enable">, + NegFlag<SetFalse, [], [], "Disable">, + BothFlags<[], [ClangOption, CC1Option], " raw string literals">>; + def fzero_call_used_regs_EQ : Joined<["-"], "fzero-call-used-regs=">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index a0adfbf61840e..c34f0ed5ed717 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -124,6 +124,7 @@ void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang, Opts.HexFloats = Std.hasHexFloats(); Opts.WChar = Std.isCPlusPlus(); Opts.Digraphs = Std.hasDigraphs(); + Opts.RawStringLiterals = Std.hasRawStringLiterals(); Opts.HLSL = Lang == Language::HLSL; if (Opts.HLSL && Opts.IncludeDefaultHeader) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 766a9b91e3c0a..c99bfe4efc413 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6536,6 +6536,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs); Args.AddLastArg(CmdArgs, options::OPT_fzero_call_used_regs_EQ); + Args.AddLastArg(CmdArgs, options::OPT_fraw_string_literals, + options::OPT_fno_raw_string_literals); if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, Triple.hasDefaultEmulatedTLS())) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 89e6c19b0af45..71865bb061f57 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3850,6 +3850,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { // the sequence "<::" will be unconditionally treated as "[:". // Cf. Lexer::LexTokenInternal. LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; + LangOpts.RawStringLiterals = LexingStd >= FormatStyle::LS_Cpp11; LangOpts.LineComment = 1; bool AlternativeOperators = Style.isCpp(); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index c98645993abe0..67d75c1140b23 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -3867,7 +3867,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { tok::utf16_char_constant); // UTF-16 raw string literal - if (Char == 'R' && LangOpts.CPlusPlus11 && + if (Char == 'R' && LangOpts.RawStringLiterals && getCharAndSize(CurPtr + SizeTmp, SizeTmp2) == '"') return LexRawStringLiteral(Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), @@ -3889,7 +3889,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { SizeTmp2, Result), tok::utf8_char_constant); - if (Char2 == 'R' && LangOpts.CPlusPlus11) { + if (Char2 == 'R' && LangOpts.RawStringLiterals) { unsigned SizeTmp3; char Char3 = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3); // UTF-8 raw string literal @@ -3925,7 +3925,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { tok::utf32_char_constant); // UTF-32 raw string literal - if (Char == 'R' && LangOpts.CPlusPlus11 && + if (Char == 'R' && LangOpts.RawStringLiterals && getCharAndSize(CurPtr + SizeTmp, SizeTmp2) == '"') return LexRawStringLiteral(Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), @@ -3940,7 +3940,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { // Notify MIOpt that we read a non-whitespace/non-comment token. MIOpt.ReadToken(); - if (LangOpts.CPlusPlus11) { + if (LangOpts.RawStringLiterals) { Char = getCharAndSize(CurPtr, SizeTmp); if (Char == '"') @@ -3963,7 +3963,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { tok::wide_string_literal); // Wide raw string literal. - if (LangOpts.CPlusPlus11 && Char == 'R' && + if (LangOpts.RawStringLiterals && Char == 'R' && getCharAndSize(CurPtr + SizeTmp, SizeTmp2) == '"') return LexRawStringLiteral(Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), diff --git a/clang/test/Lexer/raw-string-ext.c b/clang/test/Lexer/raw-string-ext.c new file mode 100644 index 0000000000000..45e3990cadf3d --- /dev/null +++ b/clang/test/Lexer/raw-string-ext.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -verify=gnu -DGNU %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -fraw-string-literals -verify=gnu -DGNU %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify=std %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -fno-raw-string-literals -verify=std %s + +void f() { + (void) R"foo()foo"; // std-error {{use of undeclared identifier 'R'}} + (void) LR"foo()foo"; // std-error {{use of undeclared identifier 'LR'}} + (void) uR"foo()foo"; // std-error {{use of undeclared identifier 'uR'}} + (void) u8R"foo()foo"; // std-error {{use of undeclared identifier 'u8R'}} + (void) UR"foo()foo"; // std-error {{use of undeclared identifier 'UR'}} +} + +// gnu-error@* {{missing terminating delimiter}} +// gnu-error@* {{expected expression}} +// gnu-error@* {{expected ';' after top level declarator}} +#define R "bar" +const char* s = R"foo("; >From f4f2294e6050168223d52a03e97f512ddab54764 Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@gmail.com> Date: Mon, 22 Apr 2024 20:13:03 +0200 Subject: [PATCH 2/5] [Clang] Ignore '-f[no-]raw-string-literals' in C++ mode --- clang/docs/ReleaseNotes.rst | 3 +- .../clang/Basic/DiagnosticDriverKinds.td | 2 + clang/include/clang/Basic/LangStandard.h | 5 ++- clang/lib/Frontend/CompilerInvocation.cpp | 9 ++++ .../test/Driver/fraw-string-literals-cxx.cpp | 11 +++++ clang/test/Lexer/raw-string-ext.c | 45 ++++++++++++++----- 6 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 clang/test/Driver/fraw-string-literals-cxx.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 20d14130fb62b..e98c0cde2e6b3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -44,7 +44,8 @@ C/C++ Language Potentially Breaking Changes ------------------------------------------- - Clang now supports raw string literals in ``-std=gnuXY`` mode as an extension in - C. This behaviour can also be overridden using ``-f[no-]raw-string-literals``. + C99 and later. This behaviour can also be overridden using ``-f[no-]raw-string-literals``. + Support of raw string literals in C++ is not affected. Fixes (#GH85703). C++ Specific Potentially Breaking Changes ----------------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index ed3fd9b1c4a55..6185dd4691d8a 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -375,6 +375,8 @@ def err_drv_negative_columns : Error< "invalid value '%1' in '%0', value must be 'none' or a positive integer">; def err_drv_small_columns : Error< "invalid value '%1' in '%0', value must be '%2' or greater">; +def warn_drv_fraw_string_literals_in_cxx : Warning< + "ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C">; def err_drv_invalid_malign_branch_EQ : Error< "invalid argument '%0' to -malign-branch=; each element must be one of: %1">; diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h index 0a308b93ada74..49594a49e9f37 100644 --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -132,8 +132,9 @@ struct LangStandard { /// hasRawStringLiterals - Language supports R"()" raw string literals. bool hasRawStringLiterals() const { - // GCC supports raw string literals in C, but not in C++ before C++11. - return isCPlusPlus11() || (!isCPlusPlus() && isGNUMode()); + // GCC supports raw string literals in C99 and later, but not in C++ + // before C++11. + return isCPlusPlus11() || (!isCPlusPlus() && isC99() && isGNUMode()); } /// isGNUMode - Language includes GNU extensions. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 1f1f5440ddd75..963f1d1bc34f5 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -610,6 +610,15 @@ static bool FixupInvocation(CompilerInvocation &Invocation, LangOpts.NewAlignOverride = 0; } + // The -f[no-]raw-string-literals option is only valid in C. + if ((Args.hasArg(OPT_fraw_string_literals) || + Args.hasArg(OPT_fno_raw_string_literals)) && + LangOpts.CPlusPlus) { + Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx) + << bool(LangOpts.RawStringLiterals); + LangOpts.RawStringLiterals = LangOpts.CPlusPlus11; + } + // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host. if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost) Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device" diff --git a/clang/test/Driver/fraw-string-literals-cxx.cpp b/clang/test/Driver/fraw-string-literals-cxx.cpp new file mode 100644 index 0000000000000..cb1133711a030 --- /dev/null +++ b/clang/test/Driver/fraw-string-literals-cxx.cpp @@ -0,0 +1,11 @@ +// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++11 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++11 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++11 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++11 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s + +// CHECK-POS: ignoring '-fraw-string-literals', which is only valid for C +// CHECK-NEG: ignoring '-fno-raw-string-literals', which is only valid for C diff --git a/clang/test/Lexer/raw-string-ext.c b/clang/test/Lexer/raw-string-ext.c index 45e3990cadf3d..feac8d0c4beaf 100644 --- a/clang/test/Lexer/raw-string-ext.c +++ b/clang/test/Lexer/raw-string-ext.c @@ -1,18 +1,39 @@ -// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -verify=gnu -DGNU %s -// RUN: %clang_cc1 -fsyntax-only -std=c11 -fraw-string-literals -verify=gnu -DGNU %s -// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify=std %s -// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -fno-raw-string-literals -verify=std %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -verify=supported %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -fraw-string-literals -verify=supported %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu89 -verify=unsupported %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify=unsupported %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -fno-raw-string-literals -verify=unsupported %s + +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -verify=unsupported,cxx-unsupported %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -verify=unsupported,cxx-unsupported %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -fraw-string-literals -verify=unsupported,cxx-unsupported,yes %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -fraw-string-literals -verify=unsupported,cxx-unsupported,yes %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -verify=supported,cxx %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -verify=supported,cxx %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -fno-raw-string-literals -verify=supported,no %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -fno-raw-string-literals -verify=supported,no %s + +// GCC supports raw string literals in C99 and later in '-std=gnuXY' mode; we +// additionally provide '-f[no-]raw-string-literals' to enable/disable them +// explicitly in C. +// +// We do not allow disabling or enabling raw string literals in C++ mode if +// they’re not already enabled by the language standard. + +// Driver warnings. +// yes-warning@* {{ignoring '-fraw-string-literals', which is only valid for C}} +// no-warning@* {{ignoring '-fno-raw-string-literals', which is only valid for C}} void f() { - (void) R"foo()foo"; // std-error {{use of undeclared identifier 'R'}} - (void) LR"foo()foo"; // std-error {{use of undeclared identifier 'LR'}} - (void) uR"foo()foo"; // std-error {{use of undeclared identifier 'uR'}} - (void) u8R"foo()foo"; // std-error {{use of undeclared identifier 'u8R'}} - (void) UR"foo()foo"; // std-error {{use of undeclared identifier 'UR'}} + (void) R"foo()foo"; // unsupported-error {{use of undeclared identifier 'R'}} cxx-unsupported-error {{expected ';' after expression}} + (void) LR"foo()foo"; // unsupported-error {{use of undeclared identifier 'LR'}} cxx-unsupported-error {{expected ';' after expression}} + (void) uR"foo()foo"; // unsupported-error {{use of undeclared identifier 'uR'}} cxx-unsupported-error {{expected ';' after expression}} + (void) u8R"foo()foo"; // unsupported-error {{use of undeclared identifier 'u8R'}} cxx-unsupported-error {{expected ';' after expression}} + (void) UR"foo()foo"; // unsupported-error {{use of undeclared identifier 'UR'}} cxx-unsupported-error {{expected ';' after expression}} } -// gnu-error@* {{missing terminating delimiter}} -// gnu-error@* {{expected expression}} -// gnu-error@* {{expected ';' after top level declarator}} +// supported-error@* {{missing terminating delimiter}} +// supported-error@* {{expected expression}} +// supported-error@* {{expected ';' after top level declarator}} #define R "bar" const char* s = R"foo("; >From a660165aca3db6cbda965a2f7cef976e76975f0e Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@gmail.com> Date: Mon, 20 May 2024 18:20:01 +0200 Subject: [PATCH 3/5] [Clang] Address review feedback --- .../clang/Basic/DiagnosticDriverKinds.td | 5 +++-- clang/include/clang/Basic/LangOptions.def | 2 +- clang/lib/Format/Format.cpp | 1 - clang/lib/Frontend/CompilerInvocation.cpp | 10 ++++++---- clang/test/Driver/fraw-string-literals-cxx.cpp | 18 ++++++++++++------ clang/test/Lexer/raw-string-ext.c | 4 ++-- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 6185dd4691d8a..395ddb4a117a2 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -375,8 +375,9 @@ def err_drv_negative_columns : Error< "invalid value '%1' in '%0', value must be 'none' or a positive integer">; def err_drv_small_columns : Error< "invalid value '%1' in '%0', value must be '%2' or greater">; -def warn_drv_fraw_string_literals_in_cxx : Warning< - "ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C">; +def warn_drv_fraw_string_literals_in_cxx11 : Warning< + "ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C and C++ standards before C++11">, + InGroup<UnusedCommandLineArgument>; def err_drv_invalid_malign_branch_EQ : Error< "invalid argument '%0' to -malign-branch=; each element must be one of: %1">; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 96bd339bb1851..6037a41104e69 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -454,7 +454,7 @@ LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type") LANGOPT(CXXAssumptions, 1, 1, "Enable or disable codegen and compile-time checks for C++23's [[assume]] attribute") -LANGOPT(RawStringLiterals, 1, 0, "Enable or disable raw string literals") +LANGOPT(RawStringLiterals, 1, 1, "Enable or disable raw string literals") ENUM_LANGOPT(StrictFlexArraysLevel, StrictFlexArraysLevelKind, 2, StrictFlexArraysLevelKind::Default, diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 71865bb061f57..89e6c19b0af45 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3850,7 +3850,6 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { // the sequence "<::" will be unconditionally treated as "[:". // Cf. Lexer::LexTokenInternal. LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; - LangOpts.RawStringLiterals = LexingStd >= FormatStyle::LS_Cpp11; LangOpts.LineComment = 1; bool AlternativeOperators = Style.isCpp(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 963f1d1bc34f5..67f9d8294b1e5 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -610,13 +610,15 @@ static bool FixupInvocation(CompilerInvocation &Invocation, LangOpts.NewAlignOverride = 0; } - // The -f[no-]raw-string-literals option is only valid in C. + // The -f[no-]raw-string-literals option is only valid in C and C++ standards + // before C++11. if ((Args.hasArg(OPT_fraw_string_literals) || Args.hasArg(OPT_fno_raw_string_literals)) && - LangOpts.CPlusPlus) { - Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx) + LangOpts.CPlusPlus11) { + Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11) << bool(LangOpts.RawStringLiterals); - LangOpts.RawStringLiterals = LangOpts.CPlusPlus11; + // Do not allow disabling raw string literals in C++11 or later. + LangOpts.RawStringLiterals = true; } // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host. diff --git a/clang/test/Driver/fraw-string-literals-cxx.cpp b/clang/test/Driver/fraw-string-literals-cxx.cpp index cb1133711a030..20692e77839de 100644 --- a/clang/test/Driver/fraw-string-literals-cxx.cpp +++ b/clang/test/Driver/fraw-string-literals-cxx.cpp @@ -1,11 +1,17 @@ -// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s -// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s -// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s -// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 %s // RUN: %clang -fraw-string-literals -fsyntax-only -std=c++11 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s // RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++11 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s // RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++11 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s // RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++11 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++20 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s +// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++20 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++20 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s +// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++20 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s -// CHECK-POS: ignoring '-fraw-string-literals', which is only valid for C -// CHECK-NEG: ignoring '-fno-raw-string-literals', which is only valid for C +// CHECK-PRE-CXX11-NOT: ignoring '-fraw-string-literals' +// CHECK-PRE-CXX11-NOT: ignoring '-fno-raw-string-literals' +// CHECK-POS: ignoring '-fraw-string-literals', which is only valid for C and C++ standards before C++11 +// CHECK-NEG: ignoring '-fno-raw-string-literals', which is only valid for C and C++ standards before C++11 diff --git a/clang/test/Lexer/raw-string-ext.c b/clang/test/Lexer/raw-string-ext.c index feac8d0c4beaf..f6ab1144c2b7a 100644 --- a/clang/test/Lexer/raw-string-ext.c +++ b/clang/test/Lexer/raw-string-ext.c @@ -6,8 +6,8 @@ // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -verify=unsupported,cxx-unsupported %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -verify=unsupported,cxx-unsupported %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -fraw-string-literals -verify=unsupported,cxx-unsupported,yes %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -fraw-string-literals -verify=unsupported,cxx-unsupported,yes %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -fraw-string-literals -verify=supported %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -fraw-string-literals -verify=supported %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -verify=supported,cxx %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -verify=supported,cxx %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -fno-raw-string-literals -verify=supported,no %s >From 83065acfdb04be60ae1dff3ab74574b7a8ea0074 Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@gmail.com> Date: Mon, 20 May 2024 19:09:59 +0200 Subject: [PATCH 4/5] [Driver] WIP: Allow fraw-string-literals in C++<11 --- clang/lib/Frontend/CompilerInvocation.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index fa3038a9271f2..3d89a54305076 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -610,13 +610,13 @@ static bool FixupInvocation(CompilerInvocation &Invocation, LangOpts.NewAlignOverride = 0; } - // The -f[no-]raw-string-literals option is only valid in C and C++ standards - // before C++11. - if ((Args.hasArg(OPT_fraw_string_literals) || - Args.hasArg(OPT_fno_raw_string_literals)) && - LangOpts.CPlusPlus11) { + // The -f[no-]raw-string-literals option is only valid in C and C++ + // standards before C++11. + if (LangOpts.CPlusPlus11) { + Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals); Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11) << bool(LangOpts.RawStringLiterals); + // Do not allow disabling raw string literals in C++11 or later. LangOpts.RawStringLiterals = true; } >From 21f41bcea0536f33d9f6bb5ebb95bd9950c35b06 Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@gmail.com> Date: Wed, 19 Jun 2024 16:50:41 +0200 Subject: [PATCH 5/5] Fix spurious diagnostic --- clang/lib/Frontend/CompilerInvocation.cpp | 10 +++++---- clang/test/Lexer/raw-string-ext.c | 27 ++++++++++++++--------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 62640da8a4fb7..d4a682e71b0a7 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -610,12 +610,14 @@ static bool FixupInvocation(CompilerInvocation &Invocation, LangOpts.NewAlignOverride = 0; } - // The -f[no-]raw-string-literals option is only valid in C and C++ + // The -f[no-]raw-string-literals option is only valid in C and in C++ // standards before C++11. if (LangOpts.CPlusPlus11) { - Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals); - Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11) - << bool(LangOpts.RawStringLiterals); + if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) { + Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals); + Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11) + << bool(LangOpts.RawStringLiterals); + } // Do not allow disabling raw string literals in C++11 or later. LangOpts.RawStringLiterals = true; diff --git a/clang/test/Lexer/raw-string-ext.c b/clang/test/Lexer/raw-string-ext.c index f6ab1144c2b7a..de318b616df70 100644 --- a/clang/test/Lexer/raw-string-ext.c +++ b/clang/test/Lexer/raw-string-ext.c @@ -1,35 +1,40 @@ // RUN: %clang_cc1 -fsyntax-only -std=gnu11 -verify=supported %s -// RUN: %clang_cc1 -fsyntax-only -std=c11 -fraw-string-literals -verify=supported %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -DUNICODE -fraw-string-literals -verify=supported %s // RUN: %clang_cc1 -fsyntax-only -std=gnu89 -verify=unsupported %s -// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify=unsupported %s -// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -fno-raw-string-literals -verify=unsupported %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -DUNICODE -verify=unsupported %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -DUNICODE -fno-raw-string-literals -verify=unsupported %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -verify=unsupported,cxx-unsupported %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -verify=unsupported,cxx-unsupported %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -fraw-string-literals -verify=supported %s // RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -fraw-string-literals -verify=supported %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -verify=supported,cxx %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -verify=supported,cxx %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -fno-raw-string-literals -verify=supported,no %s -// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -fno-raw-string-literals -verify=supported,no %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -DUNICODE -verify=supported,cxx %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -DUNICODE -verify=supported,cxx %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -DUNICODE -fraw-string-literals -verify=supported,yes %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -DUNICODE -fraw-string-literals -verify=supported,yes %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -DUNICODE -fno-raw-string-literals -verify=supported,no %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -DUNICODE -fno-raw-string-literals -verify=supported,no %s // GCC supports raw string literals in C99 and later in '-std=gnuXY' mode; we // additionally provide '-f[no-]raw-string-literals' to enable/disable them // explicitly in C. // -// We do not allow disabling or enabling raw string literals in C++ mode if -// they’re not already enabled by the language standard. +// We do not allow disabling raw string literals in C++ mode if they’re enabled +// by the language standard, i.e. in C++11 or later. // Driver warnings. -// yes-warning@* {{ignoring '-fraw-string-literals', which is only valid for C}} -// no-warning@* {{ignoring '-fno-raw-string-literals', which is only valid for C}} +// yes-warning@* {{ignoring '-fraw-string-literals'}} +// no-warning@* {{ignoring '-fno-raw-string-literals'}} void f() { (void) R"foo()foo"; // unsupported-error {{use of undeclared identifier 'R'}} cxx-unsupported-error {{expected ';' after expression}} (void) LR"foo()foo"; // unsupported-error {{use of undeclared identifier 'LR'}} cxx-unsupported-error {{expected ';' after expression}} + +#ifdef UNICODE (void) uR"foo()foo"; // unsupported-error {{use of undeclared identifier 'uR'}} cxx-unsupported-error {{expected ';' after expression}} (void) u8R"foo()foo"; // unsupported-error {{use of undeclared identifier 'u8R'}} cxx-unsupported-error {{expected ';' after expression}} (void) UR"foo()foo"; // unsupported-error {{use of undeclared identifier 'UR'}} cxx-unsupported-error {{expected ';' after expression}} +#endif } // supported-error@* {{missing terminating delimiter}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits