r346892 - [c++20] Implement P0482R6: enable -fchar8_t by default in C++20 mode.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 14 13:04:34 PST 2018


Author: rsmith
Date: Wed Nov 14 13:04:34 2018
New Revision: 346892

URL: http://llvm.org/viewvc/llvm-project?rev=346892&view=rev
Log:
[c++20] Implement P0482R6: enable -fchar8_t by default in C++20 mode.

This unfortunately results in a substantial breaking change when
switching to C++20, but it's not yet clear what / how much we should
do about that. We may want to add a compatibility conversion from
u8 string literals to const char*, similar to how C++98 provided a
compatibility conversion from string literals to non-const char*,
but that's not handled by this patch.

The feature can be disabled in C++20 mode with -fno-char8_t.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/lib/Driver/ToolChains/Clang.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Frontend/InitPreprocessor.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Lexer/cxx-features.cpp
    cfe/trunk/test/SemaCXX/char8_t.cpp
    cfe/trunk/test/SemaCXX/cxx2a-compat.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Nov 14 13:04:34 2018
@@ -5809,8 +5809,14 @@ def err_array_init_plain_string_into_cha
 def note_array_init_plain_string_into_char8_t : Note<
   "add 'u8' prefix to form a 'char8_t' string literal">;
 def err_array_init_utf8_string_into_char : Error<
-  "initialization of char array with UTF-8 string literal is not permitted "
-  "by '-fchar8_t'">;
+  "%select{|ISO C++20 does not permit }0initialization of char array with "
+  "UTF-8 string literal%select{ is not permitted by '-fchar8_t'|}0">;
+def warn_cxx2a_compat_utf8_string : Warning<
+  "type of UTF-8 string literal will change from array of const char to "
+  "array of const char8_t in C++2a">, InGroup<CXX2aCompat>, DefaultIgnore;
+def note_cxx2a_compat_utf8_string_remove_u8 : Note<
+  "remove 'u8' prefix to avoid a change of behavior; "
+  "Clang encodes unprefixed narrow string literals as UTF-8">;
 def err_array_init_different_type : Error<
   "cannot initialize array %diff{of type $ with array of type $|"
   "with different type of array}0,1">;

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Wed Nov 14 13:04:34 2018
@@ -1600,7 +1600,7 @@ def fshort_enums : Flag<["-"], "fshort-e
   HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
 def fchar8__t : Flag<["-"], "fchar8_t">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Enable C++ builtin type char8_t">;
-def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>,
+def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Disable C++ builtin type char8_t">;
 def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>,
   HelpText<"Force wchar_t to be a short unsigned int">;

Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Clang.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Wed Nov 14 13:04:34 2018
@@ -2772,8 +2772,10 @@ static void RenderCharacterOptions(const
     CmdArgs.push_back("-fno-signed-char");
   }
 
-  if (Args.hasFlag(options::OPT_fchar8__t, options::OPT_fno_char8__t, false))
-    CmdArgs.push_back("-fchar8_t");
+  // The default depends on the language standard.
+  if (const Arg *A =
+          Args.getLastArg(options::OPT_fchar8__t, options::OPT_fno_char8__t))
+    A->render(Args, CmdArgs);
 
   if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
                                      options::OPT_fno_short_wchar)) {

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Wed Nov 14 13:04:34 2018
@@ -2475,7 +2475,7 @@ static void ParseLangArgs(LangOptions &O
   Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules);
   Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
   Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
-  Opts.Char8 = Args.hasArg(OPT_fchar8__t);
+  Opts.Char8 = Args.hasFlag(OPT_fchar8__t, OPT_fno_char8__t, Opts.CPlusPlus2a);
   if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) {
     Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue())
                          .Case("char", 1)

Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitPreprocessor.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original)
+++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Wed Nov 14 13:04:34 2018
@@ -558,15 +558,15 @@ static void InitializeCPlusPlusFeatureTe
   if (LangOpts.RelaxedTemplateTemplateArgs)
     Builder.defineMacro("__cpp_template_template_args", "201611L");
 
+  // C++20 features.
+  if (LangOpts.Char8)
+    Builder.defineMacro("__cpp_char8_t", "201811L");
+
   // TS features.
   if (LangOpts.ConceptsTS)
     Builder.defineMacro("__cpp_experimental_concepts", "1L");
   if (LangOpts.CoroutinesTS)
     Builder.defineMacro("__cpp_coroutines", "201703L");
-
-  // Potential future breaking changes.
-  if (LangOpts.Char8)
-    Builder.defineMacro("__cpp_char8_t", "201803L");
 }
 
 static void InitializePredefinedMacros(const TargetInfo &TI,

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Nov 14 13:04:34 2018
@@ -1559,6 +1559,32 @@ Sema::ActOnStringLiteral(ArrayRef<Token>
     CharTy = Context.UnsignedCharTy;
   }
 
+  // Warn on initializing an array of char from a u8 string literal; this
+  // becomes ill-formed in C++2a.
+  if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus2a &&
+      !getLangOpts().Char8 && Kind == StringLiteral::UTF8) {
+    Diag(StringTokLocs.front(), diag::warn_cxx2a_compat_utf8_string);
+
+    // Create removals for all 'u8' prefixes in the string literal(s). This
+    // ensures C++2a compatibility (but may change the program behavior when
+    // built by non-Clang compilers for which the execution character set is
+    // not always UTF-8).
+    auto RemovalDiag = PDiag(diag::note_cxx2a_compat_utf8_string_remove_u8);
+    SourceLocation RemovalDiagLoc;
+    for (const Token &Tok : StringToks) {
+      if (Tok.getKind() == tok::utf8_string_literal) {
+        if (RemovalDiagLoc.isInvalid())
+          RemovalDiagLoc = Tok.getLocation();
+        RemovalDiag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+            Tok.getLocation(),
+            Lexer::AdvanceToTokenCharacter(Tok.getLocation(), 2,
+                                           getSourceManager(), getLangOpts())));
+      }
+    }
+    Diag(RemovalDiagLoc, RemovalDiag);
+  }
+
+
   QualType CharTyConst = CharTy;
   // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
   if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Nov 14 13:04:34 2018
@@ -8268,7 +8268,8 @@ bool InitializationSequence::Diagnose(Se
     break;
   case FK_UTF8StringIntoPlainChar:
     S.Diag(Kind.getLocation(),
-           diag::err_array_init_utf8_string_into_char);
+           diag::err_array_init_utf8_string_into_char)
+      << S.getLangOpts().CPlusPlus2a;
     break;
   case FK_ArrayTypeMismatch:
   case FK_NonConstantArrayInit:

Modified: cfe/trunk/test/Lexer/cxx-features.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/cxx-features.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/test/Lexer/cxx-features.cpp (original)
+++ cfe/trunk/test/Lexer/cxx-features.cpp Wed Nov 14 13:04:34 2018
@@ -9,53 +9,64 @@
 // RUN: %clang_cc1 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS -fsized-deallocation
 // RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify -fsized-deallocation %s
 // RUN: %clang_cc1 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify -fsized-deallocation %s
+// RUN: %clang_cc1 -std=c++2a -fno-char8_t -DNO_EXCEPTIONS -DNO_CHAR8_T -verify -fsized-deallocation %s
 
 // expected-no-diagnostics
 
 // FIXME using `defined` in a macro has undefined behavior.
 #if __cplusplus < 201103L
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98)
 #elif __cplusplus < 201402L
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
-#elif __cplusplus < 201406L
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11)
+#elif __cplusplus < 201703L
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14)
+#elif __cplusplus <= 201703L
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx17 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx17)
 #else
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx17 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx17
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx20 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx20)
+#endif
+
+// --- C++20 features ---
+
+#if defined(CHAR8_T) ? check(char8_t, 201811, 201811, 201811, 201811, 201811) : \
+    defined(NO_CHAR8_T) ? check(char8_t, 0, 0, 0, 0, 0) : \
+    check(char8_t, 0, 0, 0, 0, 201811)
+#error "wrong value for __cpp_char8_t"
 #endif
 
 // --- C++17 features ---
 
-#if check(hex_float, 0, 0, 0, 201603)
+#if check(hex_float, 0, 0, 0, 201603, 201603)
 #error "wrong value for __cpp_hex_float"
 #endif
 
-#if check(inline_variables, 0, 0, 0, 201606)
+#if check(inline_variables, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_inline_variables"
 #endif
 
-#if check(aligned_new, 0, 0, 0, 201606)
+#if check(aligned_new, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_aligned_new"
 #endif
 
-#if check(guaranteed_copy_elision, 0, 0, 0, 201606)
+#if check(guaranteed_copy_elision, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_guaranteed_copy_elision"
 #endif
 
-#if check(noexcept_function_type, 0, 0, 0, 201510)
+#if check(noexcept_function_type, 0, 0, 0, 201510, 201510)
 #error "wrong value for __cpp_noexcept_function_type"
 #endif
 
-#if check(fold_expressions, 0, 0, 0, 201603)
+#if check(fold_expressions, 0, 0, 0, 201603, 201603)
 #error "wrong value for __cpp_fold_expressions"
 #endif
 
-#if check(capture_star_this, 0, 0, 0, 201603)
+#if check(capture_star_this, 0, 0, 0, 201603, 201603)
 #error "wrong value for __cpp_capture_star_this"
 #endif
 
 // constexpr checked below
 
-#if check(if_constexpr, 0, 0, 0, 201606)
+#if check(if_constexpr, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_if_constexpr"
 #endif
 
@@ -63,204 +74,199 @@
 
 // static_assert checked below
 
-#if check(deduction_guides, 0, 0, 0, 201703)
+#if check(deduction_guides, 0, 0, 0, 201703, 201703)
 #error "wrong value for __cpp_deduction_guides"
 #endif
 
-#if check(nontype_template_parameter_auto, 0, 0, 0, 201606)
+#if check(nontype_template_parameter_auto, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_nontype_template_parameter_auto"
 #endif
 
 // This is the old name (from P0096R4) for
 // __cpp_nontype_template_parameter_auto
-#if check(template_auto, 0, 0, 0, 201606)
+#if check(template_auto, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_template_auto"
 #endif
 
-#if check(namespace_attributes, 0, 0, 0, 201411)
+#if check(namespace_attributes, 0, 0, 0, 201411, 201411)
 // FIXME: allowed without warning in C++14 and C++11
 #error "wrong value for __cpp_namespace_attributes"
 #endif
 
-#if check(enumerator_attributes, 0, 0, 0, 201411)
+#if check(enumerator_attributes, 0, 0, 0, 201411, 201411)
 // FIXME: allowed without warning in C++14 and C++11
 #error "wrong value for __cpp_enumerator_attributes"
 #endif
 
 // This is an old name (from P0096R4), now removed from SD-6.
-#if check(nested_namespace_definitions, 0, 0, 0, 201411)
+#if check(nested_namespace_definitions, 0, 0, 0, 201411, 201411)
 #error "wrong value for __cpp_nested_namespace_definitions"
 #endif
 
 // inheriting_constructors checked below
 
-#if check(variadic_using, 0, 0, 0, 201611)
+#if check(variadic_using, 0, 0, 0, 201611, 201611)
 #error "wrong value for __cpp_variadic_using"
 #endif
 
-#if check(aggregate_bases, 0, 0, 0, 201603)
+#if check(aggregate_bases, 0, 0, 0, 201603, 201603)
 #error "wrong value for __cpp_aggregate_bases"
 #endif
 
-#if check(structured_bindings, 0, 0, 0, 201606)
+#if check(structured_bindings, 0, 0, 0, 201606, 201606)
 #error "wrong value for __cpp_structured_bindings"
 #endif
 
-#if check(nontype_template_args, 0, 0, 0, 201411)
+#if check(nontype_template_args, 0, 0, 0, 201411, 201411)
 #error "wrong value for __cpp_nontype_template_args"
 #endif
 
 #if defined(RELAXED_TEMPLATE_TEMPLATE_ARGS) \
-    ? check(template_template_args, 0, 0, 0, 201611) \
-    : check(template_template_args, 0, 0, 0, 0)
+    ? check(template_template_args, 0, 0, 0, 201611, 201611) \
+    : check(template_template_args, 0, 0, 0, 0, 0)
 #error "wrong value for __cpp_template_template_args"
 #endif
 
 // --- C++14 features ---
 
-#if check(binary_literals, 0, 0, 201304, 201304)
+#if check(binary_literals, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_binary_literals"
 #endif
 
 // (Removed from SD-6.)
-#if check(digit_separators, 0, 0, 201309, 201309)
+#if check(digit_separators, 0, 0, 201309, 201309, 201309)
 #error "wrong value for __cpp_digit_separators"
 #endif
 
-#if check(init_captures, 0, 0, 201304, 201304)
+#if check(init_captures, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_init_captures"
 #endif
 
-#if check(generic_lambdas, 0, 0, 201304, 201304)
+#if check(generic_lambdas, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_generic_lambdas"
 #endif
 
-#if check(sized_deallocation, 0, 0, 201309, 201309)
+#if check(sized_deallocation, 0, 0, 201309, 201309, 201309)
 #error "wrong value for __cpp_sized_deallocation"
 #endif
 
 // constexpr checked below
 
-#if check(decltype_auto, 0, 0, 201304, 201304)
+#if check(decltype_auto, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_decltype_auto"
 #endif
 
-#if check(return_type_deduction, 0, 0, 201304, 201304)
+#if check(return_type_deduction, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_return_type_deduction"
 #endif
 
-#if check(runtime_arrays, 0, 0, 0, 0)
+#if check(runtime_arrays, 0, 0, 0, 0, 0)
 #error "wrong value for __cpp_runtime_arrays"
 #endif
 
-#if check(aggregate_nsdmi, 0, 0, 201304, 201304)
+#if check(aggregate_nsdmi, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_aggregate_nsdmi"
 #endif
 
-#if check(variable_templates, 0, 0, 201304, 201304)
+#if check(variable_templates, 0, 0, 201304, 201304, 201304)
 #error "wrong value for __cpp_variable_templates"
 #endif
 
 // --- C++11 features ---
 
-#if check(unicode_characters, 0, 200704, 200704, 200704)
+#if check(unicode_characters, 0, 200704, 200704, 200704, 200704)
 #error "wrong value for __cpp_unicode_characters"
 #endif
 
-#if check(raw_strings, 0, 200710, 200710, 200710)
+#if check(raw_strings, 0, 200710, 200710, 200710, 200710)
 #error "wrong value for __cpp_raw_strings"
 #endif
 
-#if check(unicode_literals, 0, 200710, 200710, 200710)
+#if check(unicode_literals, 0, 200710, 200710, 200710, 200710)
 #error "wrong value for __cpp_unicode_literals"
 #endif
 
-#if check(user_defined_literals, 0, 200809, 200809, 200809)
+#if check(user_defined_literals, 0, 200809, 200809, 200809, 200809)
 #error "wrong value for __cpp_user_defined_literals"
 #endif
 
-#if defined(NO_THREADSAFE_STATICS) ? check(threadsafe_static_init, 0, 0, 0, 0) : check(threadsafe_static_init, 200806, 200806, 200806, 200806)
+#if defined(NO_THREADSAFE_STATICS) ? check(threadsafe_static_init, 0, 0, 0, 0, 0) : \
+                                     check(threadsafe_static_init, 200806, 200806, 200806, 200806, 200806)
 #error "wrong value for __cpp_threadsafe_static_init"
 #endif
 
-#if check(lambdas, 0, 200907, 200907, 200907)
+#if check(lambdas, 0, 200907, 200907, 200907, 200907)
 #error "wrong value for __cpp_lambdas"
 #endif
 
-#if check(constexpr, 0, 200704, 201304, 201603)
+#if check(constexpr, 0, 200704, 201304, 201603, 201603)
 #error "wrong value for __cpp_constexpr"
 #endif
 
-#if check(range_based_for, 0, 200907, 200907, 201603)
+#if check(range_based_for, 0, 200907, 200907, 201603, 201603)
 #error "wrong value for __cpp_range_based_for"
 #endif
 
-#if check(static_assert, 0, 200410, 200410, 201411)
+#if check(static_assert, 0, 200410, 200410, 201411, 201411)
 #error "wrong value for __cpp_static_assert"
 #endif
 
-#if check(decltype, 0, 200707, 200707, 200707)
+#if check(decltype, 0, 200707, 200707, 200707, 200707)
 #error "wrong value for __cpp_decltype"
 #endif
 
-#if check(attributes, 0, 200809, 200809, 200809)
+#if check(attributes, 0, 200809, 200809, 200809, 200809)
 #error "wrong value for __cpp_attributes"
 #endif
 
-#if check(rvalue_references, 0, 200610, 200610, 200610)
+#if check(rvalue_references, 0, 200610, 200610, 200610, 200610)
 #error "wrong value for __cpp_rvalue_references"
 #endif
 
-#if check(variadic_templates, 0, 200704, 200704, 200704)
+#if check(variadic_templates, 0, 200704, 200704, 200704, 200704)
 #error "wrong value for __cpp_variadic_templates"
 #endif
 
-#if check(initializer_lists, 0, 200806, 200806, 200806)
+#if check(initializer_lists, 0, 200806, 200806, 200806, 200806)
 #error "wrong value for __cpp_initializer_lists"
 #endif
 
-#if check(delegating_constructors, 0, 200604, 200604, 200604)
+#if check(delegating_constructors, 0, 200604, 200604, 200604, 200604)
 #error "wrong value for __cpp_delegating_constructors"
 #endif
 
-#if check(nsdmi, 0, 200809, 200809, 200809)
+#if check(nsdmi, 0, 200809, 200809, 200809, 200809)
 #error "wrong value for __cpp_nsdmi"
 #endif
 
-#if check(inheriting_constructors, 0, 201511, 201511, 201511)
+#if check(inheriting_constructors, 0, 201511, 201511, 201511, 201511)
 #error "wrong value for __cpp_inheriting_constructors"
 #endif
 
-#if check(ref_qualifiers, 0, 200710, 200710, 200710)
+#if check(ref_qualifiers, 0, 200710, 200710, 200710, 200710)
 #error "wrong value for __cpp_ref_qualifiers"
 #endif
 
-#if check(alias_templates, 0, 200704, 200704, 200704)
+#if check(alias_templates, 0, 200704, 200704, 200704, 200704)
 #error "wrong value for __cpp_alias_templates"
 #endif
 
 // --- C++98 features ---
 
-#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711)
+#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711, 199711)
 #error "wrong value for __cpp_rtti"
 #endif
 
-#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711)
+#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711, 199711)
 #error "wrong value for __cpp_exceptions"
 #endif
 
 // --- TS features --
 
-#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS)
+#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS, CONCEPTS_TS)
 #error "wrong value for __cpp_experimental_concepts"
 #endif
 
-#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0)
+#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0, 0)
 #error "wrong value for __cpp_coroutines"
 #endif
-
-// --- not-yet-standard features --
-
-#if defined(CHAR8_T) ? check(char8_t, 201803, 201803, 201803, 201803) : check(char8_t, 0, 0, 0, 0)
-#error "wrong value for __cpp_char8_t"
-#endif

Modified: cfe/trunk/test/SemaCXX/char8_t.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/char8_t.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/char8_t.cpp (original)
+++ cfe/trunk/test/SemaCXX/char8_t.cpp Wed Nov 14 13:04:34 2018
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fchar8_t -std=c++2a -verify %s
+// RUN: %clang_cc1 -fchar8_t -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++2a -verify %s
 
 char8_t a = u8'a';
 char8_t b[] = u8"foo";
@@ -6,7 +7,12 @@ char8_t c = 'a';
 char8_t d[] = "foo"; // expected-error {{initializing 'char8_t' array with plain string literal}} expected-note {{add 'u8' prefix}}
 
 char e = u8'a';
-char f[] = u8"foo"; // expected-error {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}}
+char f[] = u8"foo";
+#if __cplusplus <= 201703L
+// expected-error at -2 {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}}
+#else
+// expected-error at -4 {{ISO C++20 does not permit initialization of char array with UTF-8 string literal}}
+#endif
 char g = 'a';
 char h[] = "foo";
 

Modified: cfe/trunk/test/SemaCXX/cxx2a-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-compat.cpp?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx2a-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx2a-compat.cpp Wed Nov 14 13:04:34 2018
@@ -21,3 +21,19 @@ B b2 = {1, 2, 3, 4};
 #else
   // expected-error at -4 2{{no viable conversion from 'int' to 'A'}}
 #endif
+
+// Essentially any use of a u8 string literal in C++<=17 is broken by C++20.
+// Just warn on all such string literals.
+struct string { string(const char*); }; // expected-note 0+{{candidate}}
+char u8arr[] = u8"hello";
+const char *u8ptr = "wo" u8"rld";
+string u8str = u8"test" u8"test";
+#if __cplusplus <= 201703L
+// expected-warning at -4 {{type of UTF-8 string literal will change}} expected-note at -4 {{remove 'u8' prefix}}
+// expected-warning at -4 {{type of UTF-8 string literal will change}} expected-note at -4 {{remove 'u8' prefix}}
+// expected-warning at -4 {{type of UTF-8 string literal will change}} expected-note at -4 {{remove 'u8' prefix}}
+#else
+// expected-error at -8 {{ISO C++20 does not permit initialization of char array with UTF-8 string literal}}
+// expected-error at -8 {{cannot initialize a variable of type 'const char *' with an lvalue of type 'const char8_t [6]'}}
+// expected-error at -8 {{no viable conversion from 'const char8_t [9]' to 'string'}}
+#endif

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=346892&r1=346891&r2=346892&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Wed Nov 14 13:04:34 2018
@@ -996,7 +996,7 @@ as the draft C++2a standard evolves.
     <tr>
       <td><tt>char8_t</tt></td>
       <td><a href="http://wg21.link/p0482r6">P0482R6</a></td>
-      <td class="none" align="center">No</td>
+      <td class="full" align="center">Clang 7 <a href="#p0482">(11)</a></td>
     </tr>
     <tr>
       <td>Immediate functions (<tt>consteval</tt>)</td>
@@ -1014,6 +1014,12 @@ as the draft C++2a standard evolves.
       <td class="svn" align="center">SVN</td>
     </tr>
 </table>
+
+<p>
+<span id="p0482">(11): Prior to Clang 8, this feature is not enabled by
+<tt>-std=c++2a</tt>, but can be enabled with <tt>-fchar8_t</tt>.
+</span>
+</p>
 </details>
 
 <h2 id="dr">Defect reports</h2>




More information about the cfe-commits mailing list