diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/InitPreprocessor.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 3 |
5 files changed, 37 insertions, 8 deletions
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5120d4ae554..5f1eb2ce174 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2772,8 +2772,10 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, 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)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 4a3195c69c3..1ea3df4303d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2475,7 +2475,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, 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) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index db707f46b84..b8d808f2d38 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -558,15 +558,15 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, 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, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c549514da83..980dbf9921f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1559,6 +1559,32 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { 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) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 438e90414d6..5249986ac03 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8268,7 +8268,8 @@ bool InitializationSequence::Diagnose(Sema &S, 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: |