diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 48 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 5 |
9 files changed, 70 insertions, 10 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 2fad5a18ba6..26d62021380 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -329,6 +329,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_auto_type: case TST_bool: case TST_char: + case TST_char8: case TST_char16: case TST_char32: case TST_class: @@ -499,6 +500,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_void: return "void"; case DeclSpec::TST_char: return "char"; case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; + case DeclSpec::TST_char8: return "char8_t"; case DeclSpec::TST_char16: return "char16_t"; case DeclSpec::TST_char32: return "char32_t"; case DeclSpec::TST_int: return "int"; @@ -1202,7 +1204,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { StorageClassSpec == SCS_auto) S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class) << FixItHint::CreateRemoval(StorageClassSpecLoc); - if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) + if (TypeSpecType == TST_char8) + S.Diag(TSTLoc, diag::warn_cxx17_compat_unicode_type); + else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type) << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); if (Constexpr_specified) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 58676101d82..732853de48c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -148,6 +148,9 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw_decltype: return getLangOpts().CPlusPlus; + case tok::kw_char8_t: + return getLangOpts().Char8; + default: break; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2cf16221f75..4339c9a8de1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13187,6 +13187,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) || Context.hasSameType(ParamType, Context.CharTy) || Context.hasSameType(ParamType, Context.WideCharTy) || + Context.hasSameType(ParamType, Context.Char8Ty) || Context.hasSameType(ParamType, Context.Char16Ty) || Context.hasSameType(ParamType, Context.Char32Ty)) { } else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) { @@ -13247,10 +13248,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { } QualType InnerType = PointeeType.getUnqualifiedType(); - // Only const char *, const wchar_t*, const char16_t*, and const char32_t* - // are allowed as the first parameter to a two-parameter function + // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and + // const char32_t* are allowed as the first parameter to a two-parameter + // function if (!(Context.hasSameType(InnerType, Context.CharTy) || Context.hasSameType(InnerType, Context.WideCharTy) || + Context.hasSameType(InnerType, Context.Char8Ty) || Context.hasSameType(InnerType, Context.Char16Ty) || Context.hasSameType(InnerType, Context.Char32Ty))) { Diag((*Param)->getSourceRange().getBegin(), diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b1ecbfad4c3..58e70a4ceaa 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1535,6 +1535,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { CharTy = Context.getWideCharType(); Kind = StringLiteral::Wide; } else if (Literal.isUTF8()) { + if (getLangOpts().Char8) + CharTy = Context.Char8Ty; Kind = StringLiteral::UTF8; } else if (Literal.isUTF16()) { CharTy = Context.Char16Ty; @@ -3094,6 +3096,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { QualType Ty; if (Literal.isWide()) Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++. + else if (Literal.isUTF8() && getLangOpts().Char8) + Ty = Context.Char8Ty; // u8'x' -> char8_t when it exists. else if (Literal.isUTF16()) Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11. else if (Literal.isUTF32()) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e44eaa5162a..be33326cd42 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -49,6 +49,8 @@ enum StringInitFailureKind { SIF_NarrowStringIntoWideChar, SIF_WideStringIntoChar, SIF_IncompatWideStringIntoWideChar, + SIF_UTF8StringIntoPlainChar, + SIF_PlainStringIntoUTF8Char, SIF_Other }; @@ -77,12 +79,21 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, Context.getCanonicalType(AT->getElementType()).getUnqualifiedType(); switch (SL->getKind()) { - case StringLiteral::Ascii: case StringLiteral::UTF8: + // char8_t array can be initialized with a UTF-8 string. + if (ElemTy->isChar8Type()) + return SIF_None; + LLVM_FALLTHROUGH; + case StringLiteral::Ascii: // char array can be initialized with a narrow string. // Only allow char x[] = "foo"; not char x[] = L"foo"; if (ElemTy->isCharType()) - return SIF_None; + return (SL->getKind() == StringLiteral::UTF8 && + Context.getLangOpts().Char8) + ? SIF_UTF8StringIntoPlainChar + : SIF_None; + if (ElemTy->isChar8Type()) + return SIF_PlainStringIntoUTF8Char; if (IsWideCharCompatible(ElemTy, Context)) return SIF_NarrowStringIntoWideChar; return SIF_Other; @@ -94,7 +105,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, case StringLiteral::UTF16: if (Context.typesAreCompatible(Context.Char16Ty, ElemTy)) return SIF_None; - if (ElemTy->isCharType()) + if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; @@ -102,7 +113,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, case StringLiteral::UTF32: if (Context.typesAreCompatible(Context.Char32Ty, ElemTy)) return SIF_None; - if (ElemTy->isCharType()) + if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; @@ -110,7 +121,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, case StringLiteral::Wide: if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy)) return SIF_None; - if (ElemTy->isCharType()) + if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; @@ -3185,6 +3196,8 @@ bool InitializationSequence::isAmbiguous() const { case FK_NarrowStringIntoWideCharArray: case FK_WideStringIntoCharArray: case FK_IncompatWideStringIntoWideChar: + case FK_PlainStringIntoUTF8Char: + case FK_UTF8StringIntoPlainChar: case FK_AddressOfOverloadFailed: // FIXME: Could do better case FK_NonConstLValueReferenceBindingToTemporary: case FK_NonConstLValueReferenceBindingToBitfield: @@ -5362,6 +5375,12 @@ void InitializationSequence::InitializeFrom(Sema &S, case SIF_IncompatWideStringIntoWideChar: SetFailed(FK_IncompatWideStringIntoWideChar); return; + case SIF_PlainStringIntoUTF8Char: + SetFailed(FK_PlainStringIntoUTF8Char); + return; + case SIF_UTF8StringIntoPlainChar: + SetFailed(FK_UTF8StringIntoPlainChar); + return; case SIF_Other: break; } @@ -7591,6 +7610,17 @@ bool InitializationSequence::Diagnose(Sema &S, S.Diag(Kind.getLocation(), diag::err_array_init_incompat_wide_string_into_wchar); break; + case FK_PlainStringIntoUTF8Char: + S.Diag(Kind.getLocation(), + diag::err_array_init_plain_string_into_char8_t); + S.Diag(Args.front()->getLocStart(), + diag::note_array_init_plain_string_into_char8_t) + << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8"); + break; + case FK_UTF8StringIntoPlainChar: + S.Diag(Kind.getLocation(), + diag::err_array_init_utf8_string_into_char); + break; case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: S.Diag(Kind.getLocation(), @@ -8000,6 +8030,14 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "incompatible wide string into wide char array"; break; + case FK_PlainStringIntoUTF8Char: + OS << "plain string literal into char8_t array"; + break; + + case FK_UTF8StringIntoPlainChar: + OS << "u8 string literal into char array"; + break; + case FK_ArrayTypeMismatch: OS << "array type mismatch"; break; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 64cd52c1f65..4b5898883b3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -7707,6 +7707,8 @@ class BuiltinOperatorOverloadBuilder { ArithmeticTypes.push_back(S.Context.BoolTy); ArithmeticTypes.push_back(S.Context.CharTy); ArithmeticTypes.push_back(S.Context.WCharTy); + if (S.Context.getLangOpts().Char8) + ArithmeticTypes.push_back(S.Context.Char8Ty); ArithmeticTypes.push_back(S.Context.Char16Ty); ArithmeticTypes.push_back(S.Context.Char32Ty); ArithmeticTypes.push_back(S.Context.SignedCharTy); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d98176ad2e5..04fdfaea75f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6771,11 +6771,11 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, Expr *E; if (T->isAnyCharacterType()) { - // This does not need to handle u8 character literals because those are - // of type char, and so can also be covered by an ASCII character literal. CharacterLiteral::CharacterKind Kind; if (T->isWideCharType()) Kind = CharacterLiteral::Wide; + else if (T->isChar8Type() && getLangOpts().Char8) + Kind = CharacterLiteral::UTF8; else if (T->isChar16Type()) Kind = CharacterLiteral::UTF16; else if (T->isChar32Type()) diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 7aa0e317df0..37a9c260034 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -822,6 +822,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_void: case TST_char: case TST_wchar: + case TST_char8: case TST_char16: case TST_char32: case TST_int: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 0e71047f00e..a6491e56acd 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1277,6 +1277,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.getUnsignedWCharType(); } break; + case DeclSpec::TST_char8: + assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && + "Unknown TSS value"); + Result = Context.Char8Ty; + break; case DeclSpec::TST_char16: assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && "Unknown TSS value"); |