Skip to content

Commit

Permalink
[clang][NFC] Refactor StringLiteral::StringKind
Browse files Browse the repository at this point in the history
This patch converts `StringLiteral::StringKind` to a scoped enum in namespace scope. This enabled forward-declarations of this enum where necessary, e.g. for `preferred_type` annotation for bit-fields.
  • Loading branch information
Endilll committed Nov 5, 2023
1 parent c0a7391 commit 3e6ce58
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 76 deletions.
36 changes: 23 additions & 13 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 };

This comment has been minimized.

Copy link
@topperc

topperc Nov 5, 2023

Collaborator

Should this be removed?

This comment has been minimized.

Copy link
@Endilll

Endilll Nov 5, 2023

Author Contributor

Nice catch, thank you!


private:
unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; }
Expand All @@ -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);

Expand All @@ -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) {
Expand All @@ -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);
}
Expand Down Expand Up @@ -1918,16 +1928,16 @@ class StringLiteral final
unsigned getLength() const { return *getTrailingObjects<unsigned>(); }
unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; }

StringKind getKind() const {
return static_cast<StringKind>(StringLiteralBits.Kind);
StringLiteralKind getKind() const {
return static_cast<StringLiteralKind>(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 {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
56 changes: 32 additions & 24 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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);
Expand Down Expand Up @@ -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<unsigned, SourceLocation, char>(
1, NumConcatenated, Str.size()),
Expand All @@ -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";
Expand All @@ -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);
Expand All @@ -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";
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
};
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/Rewrite/RewriteObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
};
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }

Expand Down
20 changes: 10 additions & 10 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1969,7 +1969,7 @@ ExprResult Sema::ActOnUnevaluatedStringLiteral(ArrayRef<Token> 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()) {
Expand Down Expand Up @@ -2055,28 +2055,28 @@ Sema::ActOnStringLiteral(ArrayRef<Token> 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;
}

// 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
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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);
}
Expand Down
28 changes: 14 additions & 14 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExprObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down

0 comments on commit 3e6ce58

Please sign in to comment.