diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 37821982000ea..1baaf06d96d86 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1786,6 +1786,15 @@ class ImaginaryLiteral : public Expr { } }; +enum class StringLiteralKind { + Ordinary, + Wide, + UTF8, + UTF16, + UTF32, + Unevaluated +}; + /// StringLiteral - This represents a string literal expression, e.g. "foo" /// or L"bar" (wide strings). The actual string data can be obtained with /// getBytes() and is NOT null-terminated. The length of the string data is @@ -1825,7 +1834,7 @@ class StringLiteral final /// * An array of getByteLength() char used to store the string data. public: - enum StringKind { Ordinary, Wide, UTF8, UTF16, UTF32, Unevaluated }; + // enum StringKind { Ordinary, Wide, UTF8, UTF16, UTF32, Unevaluated }; private: unsigned numTrailingObjects(OverloadToken) const { return 1; } @@ -1849,7 +1858,7 @@ class StringLiteral final } /// Build a string literal. - StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind, + StringLiteral(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated); @@ -1858,7 +1867,8 @@ class StringLiteral final unsigned CharByteWidth); /// Map a target and string kind to the appropriate character width. - static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK); + static unsigned mapCharByteWidth(TargetInfo const &Target, + StringLiteralKind SK); /// Set one of the string literal token. void setStrTokenLoc(unsigned TokNum, SourceLocation L) { @@ -1870,13 +1880,13 @@ class StringLiteral final /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, + StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated); /// Simple constructor for string literals made from one token. static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, + StringLiteralKind Kind, bool Pascal, QualType Ty, SourceLocation Loc) { return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1); } @@ -1918,16 +1928,16 @@ class StringLiteral final unsigned getLength() const { return *getTrailingObjects(); } unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; } - StringKind getKind() const { - return static_cast(StringLiteralBits.Kind); + StringLiteralKind getKind() const { + return static_cast(StringLiteralBits.Kind); } - bool isOrdinary() const { return getKind() == Ordinary; } - bool isWide() const { return getKind() == Wide; } - bool isUTF8() const { return getKind() == UTF8; } - bool isUTF16() const { return getKind() == UTF16; } - bool isUTF32() const { return getKind() == UTF32; } - bool isUnevaluated() const { return getKind() == Unevaluated; } + bool isOrdinary() const { return getKind() == StringLiteralKind::Ordinary; } + bool isWide() const { return getKind() == StringLiteralKind::Wide; } + bool isUTF8() const { return getKind() == StringLiteralKind::UTF8; } + bool isUTF16() const { return getKind() == StringLiteralKind::UTF16; } + bool isUTF32() const { return getKind() == StringLiteralKind::UTF32; } + bool isUnevaluated() const { return getKind() == StringLiteralKind::Unevaluated; } bool isPascal() const { return StringLiteralBits.IsPascal; } bool containsNonAscii() const { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index da90136752210..6329864b45b1a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -12221,7 +12221,7 @@ ASTContext::getPredefinedStringLiteralFromCache(StringRef Key) const { StringLiteral *&Result = StringLiteralCache[Key]; if (!Result) Result = StringLiteral::Create( - *this, Key, StringLiteral::Ordinary, + *this, Key, StringLiteralKind::Ordinary, /*Pascal*/ false, getStringLiteralArrayType(CharTy, Key.size()), SourceLocation()); return Result; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 084ef514293c5..15a64cc71b79f 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1060,23 +1060,23 @@ double FloatingLiteral::getValueAsApproximateDouble() const { } unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target, - StringKind SK) { + StringLiteralKind SK) { unsigned CharByteWidth = 0; switch (SK) { - case Ordinary: - case UTF8: + case StringLiteralKind::Ordinary: + case StringLiteralKind::UTF8: CharByteWidth = Target.getCharWidth(); break; - case Wide: + case StringLiteralKind::Wide: CharByteWidth = Target.getWCharWidth(); break; - case UTF16: + case StringLiteralKind::UTF16: CharByteWidth = Target.getChar16Width(); break; - case UTF32: + case StringLiteralKind::UTF32: CharByteWidth = Target.getChar32Width(); break; - case Unevaluated: + case StringLiteralKind::Unevaluated: return sizeof(char); // Host; } assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple"); @@ -1087,17 +1087,17 @@ unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target, } StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, + StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated) : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary) { unsigned Length = Str.size(); - StringLiteralBits.Kind = Kind; + StringLiteralBits.Kind = llvm::to_underlying(Kind); StringLiteralBits.NumConcatenated = NumConcatenated; - if (Kind != StringKind::Unevaluated) { + if (Kind != StringLiteralKind::Unevaluated) { assert(Ctx.getAsConstantArrayType(Ty) && "StringLiteral must be of constant array type!"); unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind); @@ -1152,8 +1152,8 @@ StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated, } StringLiteral *StringLiteral::Create(const ASTContext &Ctx, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, - const SourceLocation *Loc, + StringLiteralKind Kind, bool Pascal, + QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated) { void *Mem = Ctx.Allocate(totalSizeToAlloc( 1, NumConcatenated, Str.size()), @@ -1175,13 +1175,21 @@ StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx, void StringLiteral::outputString(raw_ostream &OS) const { switch (getKind()) { - case Unevaluated: - case Ordinary: + case StringLiteralKind::Unevaluated: + case StringLiteralKind::Ordinary: break; // no prefix. - case Wide: OS << 'L'; break; - case UTF8: OS << "u8"; break; - case UTF16: OS << 'u'; break; - case UTF32: OS << 'U'; break; + case StringLiteralKind::Wide: + OS << 'L'; + break; + case StringLiteralKind::UTF8: + OS << "u8"; + break; + case StringLiteralKind::UTF16: + OS << 'u'; + break; + case StringLiteralKind::UTF32: + OS << 'U'; + break; } OS << '"'; static const char Hex[] = "0123456789ABCDEF"; @@ -1195,8 +1203,8 @@ void StringLiteral::outputString(raw_ostream &OS) const { // Convert UTF-16 surrogate pairs back to codepoints before rendering. // Leave invalid surrogates alone; we'll use \x for those. - if (getKind() == UTF16 && I != N - 1 && Char >= 0xd800 && - Char <= 0xdbff) { + if (getKind() == StringLiteralKind::UTF16 && I != N - 1 && + Char >= 0xd800 && Char <= 0xdbff) { uint32_t Trail = getCodeUnit(I + 1); if (Trail >= 0xdc00 && Trail <= 0xdfff) { Char = 0x10000 + ((Char - 0xd800) << 10) + (Trail - 0xdc00); @@ -1208,7 +1216,7 @@ void StringLiteral::outputString(raw_ostream &OS) const { // If this is a wide string, output characters over 0xff using \x // escapes. Otherwise, this is a UTF-16 or UTF-32 string, and Char is a // codepoint: use \x escapes for invalid codepoints. - if (getKind() == Wide || + if (getKind() == StringLiteralKind::Wide || (Char >= 0xd800 && Char <= 0xdfff) || Char >= 0x110000) { // FIXME: Is this the best way to print wchar_t? OS << "\\x"; @@ -1285,9 +1293,9 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken, unsigned *StartTokenByteOffset) const { - assert((getKind() == StringLiteral::Ordinary || - getKind() == StringLiteral::UTF8 || - getKind() == StringLiteral::Unevaluated) && + assert((getKind() == StringLiteralKind::Ordinary || + getKind() == StringLiteralKind::UTF8 || + getKind() == StringLiteralKind::Unevaluated) && "Only narrow string literals are currently supported"); // Loop over all of the tokens in this string until we find the one that diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index b6b1e6617dffa..e16fec6109e74 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9043,7 +9043,7 @@ class PointerExprEvaluator CharTy, Size, nullptr, ArraySizeModifier::Normal, 0); StringLiteral *SL = - StringLiteral::Create(Info.Ctx, ResultStr, StringLiteral::Ordinary, + StringLiteral::Create(Info.Ctx, ResultStr, StringLiteralKind::Ordinary, /*Pascal*/ false, ArrayTy, E->getLocation()); evaluateLValue(SL, Result); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 22b6855b0fff2..c4f524142ba63 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1371,7 +1371,7 @@ void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) { void StmtProfiler::VisitStringLiteral(const StringLiteral *S) { VisitExpr(S); ID.AddString(S->getBytes()); - ID.AddInteger(S->getKind()); + ID.AddInteger(llvm::to_underlying(S->getKind())); } void StmtProfiler::VisitParenExpr(const ParenExpr *S) { diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index c458700837f4e..1f40db785981d 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -601,7 +601,7 @@ namespace { QualType StrType = Context->getConstantArrayType( Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr, ArraySizeModifier::Normal, 0); - return StringLiteral::Create(*Context, Str, StringLiteral::Ordinary, + return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary, /*Pascal=*/false, StrType, SourceLocation()); } }; diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index 71d0e95f9bf37..bf5176a2b6fb2 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -500,7 +500,7 @@ namespace { QualType StrType = Context->getConstantArrayType( Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr, ArraySizeModifier::Normal, 0); - return StringLiteral::Create(*Context, Str, StringLiteral::Ordinary, + return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary, /*Pascal=*/false, StrType, SourceLocation()); } }; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 12915a32d02ea..efad202ba67d3 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10130,7 +10130,7 @@ class FormatStringLiteral { unsigned getLength() const { return FExpr->getLength() - Offset; } unsigned getCharByteWidth() const { return FExpr->getCharByteWidth(); } - StringLiteral::StringKind getKind() const { return FExpr->getKind(); } + StringLiteralKind getKind() const { return FExpr->getKind(); } QualType getType() const { return FExpr->getType(); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2bdc5d50c14d1..60e6b6d1e7c6e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1969,7 +1969,7 @@ ExprResult Sema::ActOnUnevaluatedStringLiteral(ArrayRef StringToks) { StringTokLocs.push_back(Tok.getLocation()); StringLiteral *Lit = StringLiteral::Create( - Context, Literal.GetString(), StringLiteral::Unevaluated, false, {}, + Context, Literal.GetString(), StringLiteralKind::Unevaluated, false, {}, &StringTokLocs[0], StringTokLocs.size()); if (!Literal.getUDSuffix().empty()) { @@ -2055,20 +2055,20 @@ Sema::ActOnStringLiteral(ArrayRef StringToks, Scope *UDLScope) { StringTokLocs.push_back(Tok.getLocation()); QualType CharTy = Context.CharTy; - StringLiteral::StringKind Kind = StringLiteral::Ordinary; + StringLiteralKind Kind = StringLiteralKind::Ordinary; if (Literal.isWide()) { CharTy = Context.getWideCharType(); - Kind = StringLiteral::Wide; + Kind = StringLiteralKind::Wide; } else if (Literal.isUTF8()) { if (getLangOpts().Char8) CharTy = Context.Char8Ty; - Kind = StringLiteral::UTF8; + Kind = StringLiteralKind::UTF8; } else if (Literal.isUTF16()) { CharTy = Context.Char16Ty; - Kind = StringLiteral::UTF16; + Kind = StringLiteralKind::UTF16; } else if (Literal.isUTF32()) { CharTy = Context.Char32Ty; - Kind = StringLiteral::UTF32; + Kind = StringLiteralKind::UTF32; } else if (Literal.isPascal()) { CharTy = Context.UnsignedCharTy; } @@ -2076,7 +2076,7 @@ Sema::ActOnStringLiteral(ArrayRef StringToks, Scope *UDLScope) { // Warn on initializing an array of char from a u8 string literal; this // becomes ill-formed in C++2a. if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus20 && - !getLangOpts().Char8 && Kind == StringLiteral::UTF8) { + !getLangOpts().Char8 && Kind == StringLiteralKind::UTF8) { Diag(StringTokLocs.front(), diag::warn_cxx20_compat_utf8_string); // Create removals for all 'u8' prefixes in the string literal(s). This @@ -3743,14 +3743,14 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, ResTy = Context.getConstantArrayType(ResTy, LengthI, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals*/ 0); - SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide, + SL = StringLiteral::Create(Context, RawChars, StringLiteralKind::Wide, /*Pascal*/ false, ResTy, Loc); } else { ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst()); ResTy = Context.getConstantArrayType(ResTy, LengthI, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals*/ 0); - SL = StringLiteral::Create(Context, Str, StringLiteral::Ordinary, + SL = StringLiteral::Create(Context, Str, StringLiteralKind::Ordinary, /*Pascal*/ false, ResTy, Loc); } } @@ -4006,7 +4006,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { llvm::APInt(32, Length + 1), nullptr, ArraySizeModifier::Normal, 0); Expr *Lit = StringLiteral::Create(Context, StringRef(TokSpelling.data(), Length), - StringLiteral::Ordinary, + StringLiteralKind::Ordinary, /*Pascal*/ false, StrTy, &TokLoc, 1); return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 16a04d303c12c..db3be4816a211 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4105,20 +4105,20 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { // explicit appropriate pointer target type (C++ 4.2p2). if (!ToPtrType->getPointeeType().hasQualifiers()) { switch (StrLit->getKind()) { - case StringLiteral::UTF8: - case StringLiteral::UTF16: - case StringLiteral::UTF32: - // We don't allow UTF literals to be implicitly converted - break; - case StringLiteral::Ordinary: - return (ToPointeeType->getKind() == BuiltinType::Char_U || - ToPointeeType->getKind() == BuiltinType::Char_S); - case StringLiteral::Wide: - return Context.typesAreCompatible(Context.getWideCharType(), - QualType(ToPointeeType, 0)); - case StringLiteral::Unevaluated: - assert(false && "Unevaluated string literal in expression"); - break; + case StringLiteralKind::UTF8: + case StringLiteralKind::UTF16: + case StringLiteralKind::UTF32: + // We don't allow UTF literals to be implicitly converted + break; + case StringLiteralKind::Ordinary: + return (ToPointeeType->getKind() == BuiltinType::Char_U || + ToPointeeType->getKind() == BuiltinType::Char_S); + case StringLiteralKind::Wide: + return Context.typesAreCompatible(Context.getWideCharType(), + QualType(ToPointeeType, 0)); + case StringLiteralKind::Unevaluated: + assert(false && "Unevaluated string literal in expression"); + break; } } } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 172a3d7fee2fb..4e72899551d32 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -71,7 +71,7 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, QualType StrTy = Context.getConstantArrayType( CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), nullptr, CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers()); - S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ordinary, + S = StringLiteral::Create(Context, StrBuf, StringLiteralKind::Ordinary, /*Pascal=*/false, StrTy, &StrLocs[0], StrLocs.size()); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index ed02d3580f34f..7bec15c895c7a 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -93,7 +93,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, }; switch (SL->getKind()) { - case StringLiteral::UTF8: + case StringLiteralKind::UTF8: // char8_t array can be initialized with a UTF-8 string. // - C++20 [dcl.init.string] (DR) // Additionally, an array of char or unsigned char may be initialized @@ -103,11 +103,11 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, IsCharOrUnsignedChar(ElemTy.getCanonicalType()))) return SIF_None; [[fallthrough]]; - case StringLiteral::Ordinary: + case StringLiteralKind::Ordinary: // char array can be initialized with a narrow string. // Only allow char x[] = "foo"; not char x[] = L"foo"; if (ElemTy->isCharType()) - return (SL->getKind() == StringLiteral::UTF8 && + return (SL->getKind() == StringLiteralKind::UTF8 && Context.getLangOpts().Char8) ? SIF_UTF8StringIntoPlainChar : SIF_None; @@ -121,7 +121,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, // version of wchar_t, char16_t, or char32_t may be initialized by a wide // string literal with the corresponding encoding prefix (L, u, or U, // respectively), optionally enclosed in braces. - case StringLiteral::UTF16: + case StringLiteralKind::UTF16: if (Context.typesAreCompatible(Context.Char16Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) @@ -129,7 +129,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; - case StringLiteral::UTF32: + case StringLiteralKind::UTF32: if (Context.typesAreCompatible(Context.Char32Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) @@ -137,7 +137,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; - case StringLiteral::Wide: + case StringLiteralKind::Wide: if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) @@ -145,7 +145,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; - case StringLiteral::Unevaluated: + case StringLiteralKind::Unevaluated: assert(false && "Unevaluated string literal in initialization"); break; } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index edfa3fab6cd45..be258130b97de 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -687,7 +687,7 @@ void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) { Record.push_back(E->getNumConcatenated()); Record.push_back(E->getLength()); Record.push_back(E->getCharByteWidth()); - Record.push_back(E->getKind()); + Record.push_back(llvm::to_underlying(E->getKind())); Record.push_back(E->isPascal()); // Store the trailing array of SourceLocation.