aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/Expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r--clang/lib/AST/Expr.cpp132
1 files changed, 67 insertions, 65 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 37575e7..b811b22 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -912,42 +912,80 @@ unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target,
return CharByteWidth;
}
-StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
- StringKind Kind, bool Pascal, QualType Ty,
- const SourceLocation *Loc,
- unsigned NumStrs) {
- assert(C.getAsConstantArrayType(Ty) &&
+StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
+ const SourceLocation *Loc,
+ unsigned NumConcatenated)
+ : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
+ false) {
+ assert(Ctx.getAsConstantArrayType(Ty) &&
"StringLiteral must be of constant array type!");
+ unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind);
+ unsigned ByteLength = Str.size();
+ assert((ByteLength % CharByteWidth == 0) &&
+ "The size of the data must be a multiple of CharByteWidth!");
+
+ // Avoid the expensive division. The compiler should be able to figure it
+ // out by itself. However as of clang 7, even with the appropriate
+ // llvm_unreachable added just here, it is not able to do so.
+ unsigned Length;
+ switch (CharByteWidth) {
+ case 1:
+ Length = ByteLength;
+ break;
+ case 2:
+ Length = ByteLength / 2;
+ break;
+ case 4:
+ Length = ByteLength / 4;
+ break;
+ default:
+ llvm_unreachable("Unsupported character width!");
+ }
- // Allocate enough space for the StringLiteral plus an array of locations for
- // any concatenated string tokens.
- void *Mem =
- C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
- alignof(StringLiteral));
- StringLiteral *SL = new (Mem) StringLiteral(Ty);
+ StringLiteralBits.Kind = Kind;
+ StringLiteralBits.CharByteWidth = CharByteWidth;
+ StringLiteralBits.IsPascal = Pascal;
+ StringLiteralBits.NumConcatenated = NumConcatenated;
+ *getTrailingObjects<unsigned>() = Length;
- // OPTIMIZE: could allocate this appended to the StringLiteral.
- SL->setString(C,Str,Kind,Pascal);
+ // Initialize the trailing array of SourceLocation.
+ // This is safe since SourceLocation is POD-like.
+ std::memcpy(getTrailingObjects<SourceLocation>(), Loc,
+ NumConcatenated * sizeof(SourceLocation));
- SL->TokLocs[0] = Loc[0];
- SL->NumConcatenated = NumStrs;
+ // Initialize the trailing array of char holding the string data.
+ std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength);
+}
- if (NumStrs != 1)
- memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1));
- return SL;
+StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated,
+ unsigned Length, unsigned CharByteWidth)
+ : Expr(StringLiteralClass, Empty) {
+ StringLiteralBits.CharByteWidth = CharByteWidth;
+ StringLiteralBits.NumConcatenated = NumConcatenated;
+ *getTrailingObjects<unsigned>() = Length;
}
-StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C,
- unsigned NumStrs) {
- void *Mem =
- C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
- alignof(StringLiteral));
- StringLiteral *SL =
- new (Mem) StringLiteral(C.adjustStringLiteralBaseType(QualType()));
- SL->CharByteWidth = 0;
- SL->Length = 0;
- SL->NumConcatenated = NumStrs;
- return SL;
+StringLiteral *StringLiteral::Create(const ASTContext &Ctx, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
+ const SourceLocation *Loc,
+ unsigned NumConcatenated) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>(
+ 1, NumConcatenated, Str.size()),
+ alignof(StringLiteral));
+ return new (Mem)
+ StringLiteral(Ctx, Str, Kind, Pascal, Ty, Loc, NumConcatenated);
+}
+
+StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumConcatenated,
+ unsigned Length,
+ unsigned CharByteWidth) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>(
+ 1, NumConcatenated, Length * CharByteWidth),
+ alignof(StringLiteral));
+ return new (Mem)
+ StringLiteral(EmptyShell(), NumConcatenated, Length, CharByteWidth);
}
void StringLiteral::outputString(raw_ostream &OS) const {
@@ -1046,42 +1084,6 @@ void StringLiteral::outputString(raw_ostream &OS) const {
OS << '"';
}
-void StringLiteral::setString(const ASTContext &C, StringRef Str,
- StringKind Kind, bool IsPascal) {
- //FIXME: we assume that the string data comes from a target that uses the same
- // code unit size and endianness for the type of string.
- this->Kind = Kind;
- this->IsPascal = IsPascal;
-
- CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind);
- assert((Str.size()%CharByteWidth == 0)
- && "size of data must be multiple of CharByteWidth");
- Length = Str.size()/CharByteWidth;
-
- switch(CharByteWidth) {
- case 1: {
- char *AStrData = new (C) char[Length];
- std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
- StrData.asChar = AStrData;
- break;
- }
- case 2: {
- uint16_t *AStrData = new (C) uint16_t[Length];
- std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
- StrData.asUInt16 = AStrData;
- break;
- }
- case 4: {
- uint32_t *AStrData = new (C) uint32_t[Length];
- std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
- StrData.asUInt32 = AStrData;
- break;
- }
- default:
- llvm_unreachable("unsupported CharByteWidth");
- }
-}
-
/// getLocationOfByte - Return a source location that points to the specified
/// byte of this string literal.
///