diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp index 0674f8f116..878a94c1f1 100644 --- a/Driver/RewriteObjC.cpp +++ b/Driver/RewriteObjC.cpp @@ -1736,7 +1736,7 @@ Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); Expr *Replacement = new (Context) StringLiteral(*Context,StrEncoding.c_str(), StrEncoding.length(), false, StrType, - SourceLocation(), SourceLocation()); + SourceLocation()); ReplaceStmt(Exp, Replacement); // Replace this subexpr in the parent. @@ -1754,8 +1754,7 @@ Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { SelExprs.push_back(new (Context) StringLiteral((*Context), Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().size(), - false, argType, SourceLocation(), - SourceLocation())); + false, argType, SourceLocation())); CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, &SelExprs[0], SelExprs.size()); ReplaceStmt(Exp, SelExp); @@ -2293,8 +2292,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { ClsExprs.push_back(new (Context) StringLiteral(*Context, SuperDecl->getIdentifier()->getName(), SuperDecl->getIdentifier()->getLength(), - false, argType, SourceLocation(), - SourceLocation())); + false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, &ClsExprs[0], ClsExprs.size()); @@ -2346,8 +2344,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { ClsExprs.push_back(new (Context) StringLiteral(*Context, clsName->getName(), clsName->getLength(), - false, argType, SourceLocation(), - SourceLocation())); + false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, &ClsExprs[0], ClsExprs.size()); @@ -2377,8 +2374,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { ClsExprs.push_back(new (Context) StringLiteral(*Context, SuperDecl->getIdentifier()->getName(), SuperDecl->getIdentifier()->getLength(), - false, argType, SourceLocation(), - SourceLocation())); + false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, &ClsExprs[0], ClsExprs.size()); @@ -2436,8 +2432,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { SelExprs.push_back(new (Context) StringLiteral(*Context, Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().size(), - false, argType, SourceLocation(), - SourceLocation())); + false, argType, SourceLocation())); CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, &SelExprs[0], SelExprs.size()); MsgExprs.push_back(SelExp); @@ -2605,8 +2600,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { StringLiteral(*Context, Exp->getProtocol()->getNameAsCString(), strlen(Exp->getProtocol()->getNameAsCString()), - false, argType, SourceLocation(), - SourceLocation())); + false, argType, SourceLocation())); CallExpr *ProtoExp = SynthesizeCallToFunctionDecl(GetProtocolFunctionDecl, &ProtoExprs[0], ProtoExprs.size()); diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index cb1400c079..8bd0c9d759 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -480,22 +480,33 @@ class StringLiteral : public Expr { const char *StrData; unsigned ByteLength; bool IsWide; - // if the StringLiteral was composed using token pasting, both locations + // If the StringLiteral was composed using token pasting, both locations // are needed. If not (the common case), firstTokLoc == lastTokLoc. - // FIXME: if space becomes an issue, we should create a sub-class. - SourceLocation firstTokLoc, lastTokLoc; + unsigned NumConcatenated; + SourceLocation TokLocs[1]; public: - StringLiteral(ASTContext& C, const char *strData, unsigned byteLength, - bool Wide, QualType t, SourceLocation b, SourceLocation e); + StringLiteral(ASTContext &C, const char *StrData, unsigned ByteLength, + bool Wide, QualType t, SourceLocation Loc); + StringLiteral(ASTContext &C, const char *StrData, unsigned ByteLength, + bool Wide, QualType t, SourceLocation *Loc, unsigned NumStrs); - void Destroy(ASTContext& C); + void Destroy(ASTContext &C); const char *getStrData() const { return StrData; } unsigned getByteLength() const { return ByteLength; } bool isWide() const { return IsWide; } + + /// getNumConcatenated - Get the number of string literal tokens that were + /// concatenated in translation phase #6 to form this string literal. + unsigned getNumConcatenated() const { return NumConcatenated; } + + SourceLocation getStrTokenLoc(unsigned TokNum) const { + assert(TokNum < NumConcatenated && "Invalid tok number"); + return TokLocs[TokNum]; + } virtual SourceRange getSourceRange() const { - return SourceRange(firstTokLoc,lastTokLoc); + return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); } static bool classof(const Stmt *T) { return T->getStmtClass() == StringLiteralClass; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 0cd68ce3b8..81da44407b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -39,20 +39,36 @@ double FloatingLiteral::getValueAsApproximateDouble() const { StringLiteral::StringLiteral(ASTContext& C, const char *strData, - unsigned byteLength, bool Wide, QualType t, - SourceLocation firstLoc, - SourceLocation lastLoc) : - Expr(StringLiteralClass, t) { + unsigned byteLength, bool Wide, QualType Ty, + SourceLocation Loc) : + Expr(StringLiteralClass, Ty) { // OPTIMIZE: could allocate this appended to the StringLiteral. char *AStrData = new (C, 1) char[byteLength]; memcpy(AStrData, strData, byteLength); StrData = AStrData; ByteLength = byteLength; IsWide = Wide; - firstTokLoc = firstLoc; - lastTokLoc = lastLoc; + TokLocs[0] = Loc; + NumConcatenated = 1; } +StringLiteral::StringLiteral(ASTContext &C, const char *strData, + unsigned byteLength, bool Wide, QualType Ty, + SourceLocation *Loc, unsigned NumStrs) : + Expr(StringLiteralClass, Ty) { + // OPTIMIZE: could allocate this appended to the StringLiteral. + char *AStrData = new (C, 1) char[byteLength]; + memcpy(AStrData, strData, byteLength); + StrData = AStrData; + ByteLength = byteLength; + IsWide = Wide; + TokLocs[0] = Loc[0]; + NumConcatenated = NumStrs; + if (NumStrs != 1) + memcpy(&TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1)); +} + + void StringLiteral::Destroy(ASTContext &C) { C.Deallocate(const_cast(StrData)); this->~StringLiteral(); diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index 22ce8183fd..074969e9de 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/lib/AST/StmtSerialization.cpp @@ -955,8 +955,7 @@ VAArgExpr* VAArgExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { void StringLiteral::EmitImpl(Serializer& S) const { S.Emit(getType()); - S.Emit(firstTokLoc); - S.Emit(lastTokLoc); + assert(0 && "Unimpl loc serialization"); S.EmitBool(isWide()); S.Emit(getByteLength()); @@ -966,13 +965,14 @@ void StringLiteral::EmitImpl(Serializer& S) const { StringLiteral* StringLiteral::CreateImpl(Deserializer& D, ASTContext& C) { QualType t = QualType::ReadVal(D); - SourceLocation firstTokLoc = SourceLocation::ReadVal(D); - SourceLocation lastTokLoc = SourceLocation::ReadVal(D); + assert(0 && "Unimpl loc serialization"); + //SourceLocation firstTokLoc = SourceLocation::ReadVal(D); + //SourceLocation lastTokLoc = SourceLocation::ReadVal(D); bool isWide = D.ReadBool(); unsigned ByteLength = D.ReadInt(); StringLiteral* sl = new (C, llvm::alignof()) - StringLiteral(C, NULL, 0, isWide, t, firstTokLoc, lastTokLoc); + StringLiteral(C, NULL, 0, isWide, t, SourceLocation()); char* StrData = new (C, llvm::alignof()) char[ByteLength]; for (unsigned i = 0; i < ByteLength; ++i) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4eb29c4f94..c0b61bf8d7 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -352,13 +352,17 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Literal.GetStringLength()+1), ArrayType::Normal, 0); - + // Allocate enough space for the StringLiteral plus an array of locations for + // any concatenated strings. + void *Mem = Context.Allocate(sizeof(StringLiteral)+ + sizeof(SourceLocation)*(NumStringToks-1)); + // Pass &StringTokLocs[0], StringTokLocs.size() to factory! - return Owned(new (Context) StringLiteral(Context, Literal.GetString(), - Literal.GetStringLength(), - Literal.AnyWide, StrTy, - StringToks[0].getLocation(), - StringToks[NumStringToks-1].getLocation())); + return Owned(new (Mem) StringLiteral(Context, Literal.GetString(), + Literal.GetStringLength(), + Literal.AnyWide, StrTy, + &StringTokLocs[0], + StringTokLocs.size())); } /// ShouldSnapshotBlockValueReference - Return true if a reference inside of diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 3e99482772..b0b5367790 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -29,10 +29,12 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, unsigned Length = 0; for (unsigned i = 0; i < NumStrings; i++) Length += static_cast(Strings[i])->getByteLength(); - char *strBuf = new char [Length]; + + // FIXME: This should not be allocated by SEMA! + char *strBuf = new char[Length]; char *p = strBuf; bool isWide = false; - for (unsigned i = 0; i < NumStrings; i++) { + for (unsigned i = 0; i != NumStrings; ++i) { S = static_cast(Strings[i]); if (S->isWide()) isWide = true; @@ -40,9 +42,10 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, p += S->getByteLength(); S->Destroy(Context); } - S = new (Context, 8) StringLiteral(Context, strBuf, Length, isWide, - Context.getPointerType(Context.CharTy), - AtLoc, EndLoc); + // FIXME: PASS LOCATIONS PROPERLY. + S = new (Context) StringLiteral(Context, strBuf, Length, isWide, + Context.getPointerType(Context.CharTy), + AtLoc); } if (CheckBuiltinCFStringArgument(S))