change the StringLiteral AST node to track all of the SourceLocations of

the various PPTokens that are pasted together to make it.  In the course
of working on this, I discovered ParseObjCStringLiteral which needs some
work.  I'll tackle it next.

llvm-svn: 64892
This commit is contained in:
Chris Lattner 2009-02-18 05:49:11 +00:00
parent 2af1f85f1f
commit 630970ddb8
6 changed files with 70 additions and 42 deletions

View File

@ -1736,7 +1736,7 @@ Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
Expr *Replacement = new (Context) StringLiteral(*Context,StrEncoding.c_str(), Expr *Replacement = new (Context) StringLiteral(*Context,StrEncoding.c_str(),
StrEncoding.length(), false, StrType, StrEncoding.length(), false, StrType,
SourceLocation(), SourceLocation()); SourceLocation());
ReplaceStmt(Exp, Replacement); ReplaceStmt(Exp, Replacement);
// Replace this subexpr in the parent. // Replace this subexpr in the parent.
@ -1754,8 +1754,7 @@ Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
SelExprs.push_back(new (Context) StringLiteral((*Context), SelExprs.push_back(new (Context) StringLiteral((*Context),
Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().c_str(),
Exp->getSelector().getAsString().size(), Exp->getSelector().getAsString().size(),
false, argType, SourceLocation(), false, argType, SourceLocation()));
SourceLocation()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
&SelExprs[0], SelExprs.size()); &SelExprs[0], SelExprs.size());
ReplaceStmt(Exp, SelExp); ReplaceStmt(Exp, SelExp);
@ -2293,8 +2292,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
ClsExprs.push_back(new (Context) StringLiteral(*Context, ClsExprs.push_back(new (Context) StringLiteral(*Context,
SuperDecl->getIdentifier()->getName(), SuperDecl->getIdentifier()->getName(),
SuperDecl->getIdentifier()->getLength(), SuperDecl->getIdentifier()->getLength(),
false, argType, SourceLocation(), false, argType, SourceLocation()));
SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
&ClsExprs[0], &ClsExprs[0],
ClsExprs.size()); ClsExprs.size());
@ -2346,8 +2344,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
ClsExprs.push_back(new (Context) StringLiteral(*Context, ClsExprs.push_back(new (Context) StringLiteral(*Context,
clsName->getName(), clsName->getName(),
clsName->getLength(), clsName->getLength(),
false, argType, SourceLocation(), false, argType, SourceLocation()));
SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
&ClsExprs[0], &ClsExprs[0],
ClsExprs.size()); ClsExprs.size());
@ -2377,8 +2374,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
ClsExprs.push_back(new (Context) StringLiteral(*Context, ClsExprs.push_back(new (Context) StringLiteral(*Context,
SuperDecl->getIdentifier()->getName(), SuperDecl->getIdentifier()->getName(),
SuperDecl->getIdentifier()->getLength(), SuperDecl->getIdentifier()->getLength(),
false, argType, SourceLocation(), false, argType, SourceLocation()));
SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
&ClsExprs[0], &ClsExprs[0],
ClsExprs.size()); ClsExprs.size());
@ -2436,8 +2432,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
SelExprs.push_back(new (Context) StringLiteral(*Context, SelExprs.push_back(new (Context) StringLiteral(*Context,
Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().c_str(),
Exp->getSelector().getAsString().size(), Exp->getSelector().getAsString().size(),
false, argType, SourceLocation(), false, argType, SourceLocation()));
SourceLocation()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
&SelExprs[0], SelExprs.size()); &SelExprs[0], SelExprs.size());
MsgExprs.push_back(SelExp); MsgExprs.push_back(SelExp);
@ -2605,8 +2600,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
StringLiteral(*Context, StringLiteral(*Context,
Exp->getProtocol()->getNameAsCString(), Exp->getProtocol()->getNameAsCString(),
strlen(Exp->getProtocol()->getNameAsCString()), strlen(Exp->getProtocol()->getNameAsCString()),
false, argType, SourceLocation(), false, argType, SourceLocation()));
SourceLocation()));
CallExpr *ProtoExp = SynthesizeCallToFunctionDecl(GetProtocolFunctionDecl, CallExpr *ProtoExp = SynthesizeCallToFunctionDecl(GetProtocolFunctionDecl,
&ProtoExprs[0], &ProtoExprs[0],
ProtoExprs.size()); ProtoExprs.size());

View File

@ -480,22 +480,33 @@ class StringLiteral : public Expr {
const char *StrData; const char *StrData;
unsigned ByteLength; unsigned ByteLength;
bool IsWide; 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. // are needed. If not (the common case), firstTokLoc == lastTokLoc.
// FIXME: if space becomes an issue, we should create a sub-class. unsigned NumConcatenated;
SourceLocation firstTokLoc, lastTokLoc; SourceLocation TokLocs[1];
public: public:
StringLiteral(ASTContext& C, const char *strData, unsigned byteLength, StringLiteral(ASTContext &C, const char *StrData, unsigned ByteLength,
bool Wide, QualType t, SourceLocation b, SourceLocation e); 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; } const char *getStrData() const { return StrData; }
unsigned getByteLength() const { return ByteLength; } unsigned getByteLength() const { return ByteLength; }
bool isWide() const { return IsWide; } 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 { virtual SourceRange getSourceRange() const {
return SourceRange(firstTokLoc,lastTokLoc); return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
} }
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == StringLiteralClass; return T->getStmtClass() == StringLiteralClass;

View File

@ -39,20 +39,36 @@ double FloatingLiteral::getValueAsApproximateDouble() const {
StringLiteral::StringLiteral(ASTContext& C, const char *strData, StringLiteral::StringLiteral(ASTContext& C, const char *strData,
unsigned byteLength, bool Wide, QualType t, unsigned byteLength, bool Wide, QualType Ty,
SourceLocation firstLoc, SourceLocation Loc) :
SourceLocation lastLoc) : Expr(StringLiteralClass, Ty) {
Expr(StringLiteralClass, t) {
// OPTIMIZE: could allocate this appended to the StringLiteral. // OPTIMIZE: could allocate this appended to the StringLiteral.
char *AStrData = new (C, 1) char[byteLength]; char *AStrData = new (C, 1) char[byteLength];
memcpy(AStrData, strData, byteLength); memcpy(AStrData, strData, byteLength);
StrData = AStrData; StrData = AStrData;
ByteLength = byteLength; ByteLength = byteLength;
IsWide = Wide; IsWide = Wide;
firstTokLoc = firstLoc; TokLocs[0] = Loc;
lastTokLoc = lastLoc; 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) { void StringLiteral::Destroy(ASTContext &C) {
C.Deallocate(const_cast<char*>(StrData)); C.Deallocate(const_cast<char*>(StrData));
this->~StringLiteral(); this->~StringLiteral();

View File

@ -955,8 +955,7 @@ VAArgExpr* VAArgExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
void StringLiteral::EmitImpl(Serializer& S) const { void StringLiteral::EmitImpl(Serializer& S) const {
S.Emit(getType()); S.Emit(getType());
S.Emit(firstTokLoc); assert(0 && "Unimpl loc serialization");
S.Emit(lastTokLoc);
S.EmitBool(isWide()); S.EmitBool(isWide());
S.Emit(getByteLength()); S.Emit(getByteLength());
@ -966,13 +965,14 @@ void StringLiteral::EmitImpl(Serializer& S) const {
StringLiteral* StringLiteral::CreateImpl(Deserializer& D, ASTContext& C) { StringLiteral* StringLiteral::CreateImpl(Deserializer& D, ASTContext& C) {
QualType t = QualType::ReadVal(D); QualType t = QualType::ReadVal(D);
SourceLocation firstTokLoc = SourceLocation::ReadVal(D); assert(0 && "Unimpl loc serialization");
SourceLocation lastTokLoc = SourceLocation::ReadVal(D); //SourceLocation firstTokLoc = SourceLocation::ReadVal(D);
//SourceLocation lastTokLoc = SourceLocation::ReadVal(D);
bool isWide = D.ReadBool(); bool isWide = D.ReadBool();
unsigned ByteLength = D.ReadInt(); unsigned ByteLength = D.ReadInt();
StringLiteral* sl = new (C, llvm::alignof<StringLiteral>()) StringLiteral* sl = new (C, llvm::alignof<StringLiteral>())
StringLiteral(C, NULL, 0, isWide, t, firstTokLoc, lastTokLoc); StringLiteral(C, NULL, 0, isWide, t, SourceLocation());
char* StrData = new (C, llvm::alignof<char>()) char[ByteLength]; char* StrData = new (C, llvm::alignof<char>()) char[ByteLength];
for (unsigned i = 0; i < ByteLength; ++i) for (unsigned i = 0; i < ByteLength; ++i)

View File

@ -352,13 +352,17 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
StrTy = Context.getConstantArrayType(StrTy, StrTy = Context.getConstantArrayType(StrTy,
llvm::APInt(32, Literal.GetStringLength()+1), llvm::APInt(32, Literal.GetStringLength()+1),
ArrayType::Normal, 0); 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! // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
return Owned(new (Context) StringLiteral(Context, Literal.GetString(), return Owned(new (Mem) StringLiteral(Context, Literal.GetString(),
Literal.GetStringLength(), Literal.GetStringLength(),
Literal.AnyWide, StrTy, Literal.AnyWide, StrTy,
StringToks[0].getLocation(), &StringTokLocs[0],
StringToks[NumStringToks-1].getLocation())); StringTokLocs.size()));
} }
/// ShouldSnapshotBlockValueReference - Return true if a reference inside of /// ShouldSnapshotBlockValueReference - Return true if a reference inside of

View File

@ -29,10 +29,12 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
unsigned Length = 0; unsigned Length = 0;
for (unsigned i = 0; i < NumStrings; i++) for (unsigned i = 0; i < NumStrings; i++)
Length += static_cast<StringLiteral *>(Strings[i])->getByteLength(); Length += static_cast<StringLiteral *>(Strings[i])->getByteLength();
char *strBuf = new char [Length];
// FIXME: This should not be allocated by SEMA!
char *strBuf = new char[Length];
char *p = strBuf; char *p = strBuf;
bool isWide = false; bool isWide = false;
for (unsigned i = 0; i < NumStrings; i++) { for (unsigned i = 0; i != NumStrings; ++i) {
S = static_cast<StringLiteral *>(Strings[i]); S = static_cast<StringLiteral *>(Strings[i]);
if (S->isWide()) if (S->isWide())
isWide = true; isWide = true;
@ -40,9 +42,10 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
p += S->getByteLength(); p += S->getByteLength();
S->Destroy(Context); S->Destroy(Context);
} }
S = new (Context, 8) StringLiteral(Context, strBuf, Length, isWide, // FIXME: PASS LOCATIONS PROPERLY.
S = new (Context) StringLiteral(Context, strBuf, Length, isWide,
Context.getPointerType(Context.CharTy), Context.getPointerType(Context.CharTy),
AtLoc, EndLoc); AtLoc);
} }
if (CheckBuiltinCFStringArgument(S)) if (CheckBuiltinCFStringArgument(S))