forked from OSchip/llvm-project
Implement rewrite rules for ObjC string constants.
llvm-svn: 43665
This commit is contained in:
parent
dfcc3f26ae
commit
a397efd915
|
@ -861,23 +861,20 @@ QualType ASTContext::maxIntegerType(QualType lhs, QualType rhs) {
|
|||
QualType ASTContext::getCFConstantStringType() {
|
||||
if (!CFConstantStringTypeDecl) {
|
||||
CFConstantStringTypeDecl = new RecordDecl(Decl::Struct, SourceLocation(),
|
||||
&Idents.get("__builtin_CFString"),
|
||||
&Idents.get("NSConstantString"),
|
||||
0);
|
||||
|
||||
QualType FieldTypes[4];
|
||||
QualType FieldTypes[3];
|
||||
|
||||
// const int *isa;
|
||||
FieldTypes[0] = getPointerType(IntTy.getQualifiedType(QualType::Const));
|
||||
// int flags;
|
||||
FieldTypes[1] = IntTy;
|
||||
// const char *str;
|
||||
FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));
|
||||
FieldTypes[1] = getPointerType(CharTy.getQualifiedType(QualType::Const));
|
||||
// long length;
|
||||
FieldTypes[3] = LongTy;
|
||||
FieldTypes[2] = LongTy;
|
||||
// Create fields
|
||||
FieldDecl *FieldDecls[4];
|
||||
FieldDecl *FieldDecls[3];
|
||||
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
FieldDecls[i] = new FieldDecl(SourceLocation(), 0, FieldTypes[i]);
|
||||
|
||||
CFConstantStringTypeDecl->defineBody(FieldDecls, 4);
|
||||
|
|
|
@ -39,6 +39,10 @@ namespace {
|
|||
FunctionDecl *GetClassFunctionDecl;
|
||||
FunctionDecl *SelGetUidFunctionDecl;
|
||||
|
||||
// ObjC string constant support.
|
||||
FileVarDecl *ConstantStringClassReference;
|
||||
RecordDecl *NSStringRecord;
|
||||
|
||||
static const int OBJC_ABI_VERSION =7 ;
|
||||
public:
|
||||
void Initialize(ASTContext &context, unsigned mainFileID) {
|
||||
|
@ -48,6 +52,8 @@ namespace {
|
|||
MsgSendFunctionDecl = 0;
|
||||
GetClassFunctionDecl = 0;
|
||||
SelGetUidFunctionDecl = 0;
|
||||
ConstantStringClassReference = 0;
|
||||
NSStringRecord = 0;
|
||||
Rewrite.setSourceMgr(Context->SourceMgr);
|
||||
}
|
||||
|
||||
|
@ -73,12 +79,14 @@ namespace {
|
|||
Stmt *RewriteFunctionBody(Stmt *S);
|
||||
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
|
||||
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
|
||||
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
|
||||
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
|
||||
Expr **args, unsigned nargs);
|
||||
void SynthMsgSendFunctionDecl();
|
||||
void SynthGetClassFunctionDecl();
|
||||
|
||||
// Metadata emission.
|
||||
void HandleObjcMetaDataEmission();
|
||||
void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
|
||||
std::string &Result);
|
||||
|
||||
|
@ -125,6 +133,12 @@ void RewriteTest::HandleTopLevelDecl(Decl *D) {
|
|||
// Look for built-in declarations that we need to refer during the rewrite.
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
RewriteFunctionDecl(FD);
|
||||
} else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
|
||||
// declared in <Foundation/NSString.h>
|
||||
if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
|
||||
ConstantStringClassReference = FVD;
|
||||
return;
|
||||
}
|
||||
} else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
|
||||
RewriteInterfaceDecl(MD);
|
||||
} else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
|
||||
|
@ -161,17 +175,11 @@ RewriteTest::~RewriteTest() {
|
|||
// Get the top-level buffer that this corresponds to.
|
||||
RewriteTabs();
|
||||
|
||||
// Rewrite Objective-c meta data*
|
||||
std::string ResultStr;
|
||||
WriteObjcMetaData(ResultStr);
|
||||
// For now just print the string out.
|
||||
printf("%s", ResultStr.c_str());
|
||||
|
||||
// Get the buffer corresponding to MainFileID. If we haven't changed it, then
|
||||
// we are done.
|
||||
if (const RewriteBuffer *RewriteBuf =
|
||||
Rewrite.getRewriteBufferFor(MainFileID)) {
|
||||
printf("Changed:\n");
|
||||
//printf("Changed:\n");
|
||||
std::string S(RewriteBuf->begin(), RewriteBuf->end());
|
||||
printf("%s\n", S.c_str());
|
||||
} else {
|
||||
|
@ -180,6 +188,16 @@ RewriteTest::~RewriteTest() {
|
|||
|
||||
}
|
||||
|
||||
/// HandleObjcMetaDataEmission - main routine to generate objective-c's
|
||||
/// metadata.
|
||||
void RewriteTest::HandleObjcMetaDataEmission() {
|
||||
// Rewrite Objective-c meta data*
|
||||
std::string ResultStr;
|
||||
WriteObjcMetaData(ResultStr);
|
||||
// For now just print the string out.
|
||||
printf("%s", ResultStr.c_str());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Syntactic (non-AST) Rewriting Code
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -364,6 +382,9 @@ Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
|
|||
// Handle specific things.
|
||||
if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
|
||||
return RewriteAtEncode(AtEncode);
|
||||
|
||||
if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
|
||||
return RewriteObjCStringLiteral(AtString);
|
||||
|
||||
if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
|
||||
// Before we rewrite it, put the original message expression in a comment.
|
||||
|
@ -492,7 +513,7 @@ void RewriteTest::RewriteObjcQualifiedInterfaceTypes(
|
|||
|
||||
void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
|
||||
// declared in <objc/objc.h>
|
||||
if (strcmp(FD->getName(), "sel_getUid") == 0) {
|
||||
if (strcmp(FD->getName(), "sel_registerName") == 0) {
|
||||
SelGetUidFunctionDecl = FD;
|
||||
return;
|
||||
}
|
||||
|
@ -536,8 +557,52 @@ void RewriteTest::SynthGetClassFunctionDecl() {
|
|||
FunctionDecl::Extern, false, 0);
|
||||
}
|
||||
|
||||
Stmt *RewriteTest::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
|
||||
assert(ConstantStringClassReference && "Can't find constant string reference");
|
||||
llvm::SmallVector<Expr*, 4> InitExprs;
|
||||
|
||||
// Synthesize "(Class)&_NSConstantStringClassReference"
|
||||
DeclRefExpr *ClsRef = new DeclRefExpr(ConstantStringClassReference,
|
||||
ConstantStringClassReference->getType(),
|
||||
SourceLocation());
|
||||
QualType expType = Context->getPointerType(ClsRef->getType());
|
||||
UnaryOperator *Unop = new UnaryOperator(ClsRef, UnaryOperator::AddrOf,
|
||||
expType, SourceLocation());
|
||||
CastExpr *cast = new CastExpr(Context->getObjcClassType(), Unop,
|
||||
SourceLocation());
|
||||
InitExprs.push_back(cast); // set the 'isa'.
|
||||
InitExprs.push_back(Exp->getString()); // set "char *bytes".
|
||||
unsigned IntSize = static_cast<unsigned>(
|
||||
Context->getTypeSize(Context->IntTy, Exp->getLocStart()));
|
||||
llvm::APInt IntVal(IntSize, Exp->getString()->getByteLength());
|
||||
IntegerLiteral *len = new IntegerLiteral(IntVal, Context->IntTy,
|
||||
Exp->getLocStart());
|
||||
InitExprs.push_back(len); // set "int numBytes".
|
||||
|
||||
// struct NSConstantString
|
||||
QualType CFConstantStrType = Context->getCFConstantStringType();
|
||||
// (struct NSConstantString) { <exprs from above> }
|
||||
InitListExpr *ILE = new InitListExpr(SourceLocation(),
|
||||
&InitExprs[0], InitExprs.size(),
|
||||
SourceLocation());
|
||||
CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, ILE);
|
||||
// struct NSConstantString *
|
||||
expType = Context->getPointerType(StrRep->getType());
|
||||
Unop = new UnaryOperator(StrRep, UnaryOperator::AddrOf, expType,
|
||||
SourceLocation());
|
||||
// struct NSString *
|
||||
if (!NSStringRecord)
|
||||
NSStringRecord = new RecordDecl(Decl::Struct, SourceLocation(),
|
||||
&Context->Idents.get("NSString"), 0);
|
||||
expType = Context->getPointerType(Context->getTagDeclType(NSStringRecord));
|
||||
cast = new CastExpr(expType, Unop, SourceLocation());
|
||||
Rewrite.ReplaceStmt(Exp, cast);
|
||||
delete Exp;
|
||||
return StrRep;
|
||||
}
|
||||
|
||||
Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
|
||||
assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
|
||||
assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
|
||||
if (!MsgSendFunctionDecl)
|
||||
SynthMsgSendFunctionDecl();
|
||||
if (!GetClassFunctionDecl)
|
||||
|
@ -561,7 +626,7 @@ Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
|
|||
} else // instance message.
|
||||
MsgExprs.push_back(Exp->getReceiver());
|
||||
|
||||
// Create a call to sel_getUid("selName"), it will be the 2nd argument.
|
||||
// Create a call to sel_registerName("selName"), it will be the 2nd argument.
|
||||
llvm::SmallVector<Expr*, 8> SelExprs;
|
||||
QualType argType = Context->getPointerType(Context->CharTy);
|
||||
SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
|
||||
|
|
|
@ -1155,7 +1155,7 @@ Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
|
|||
switch (Tok.getKind()) {
|
||||
case tok::string_literal: // primary-expression: string-literal
|
||||
case tok::wide_string_literal:
|
||||
return ParsePostfixExpressionSuffix(ParseObjCStringLiteral());
|
||||
return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1285,12 +1285,12 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() {
|
|||
&KeyExprs[0]);
|
||||
}
|
||||
|
||||
Parser::ExprResult Parser::ParseObjCStringLiteral() {
|
||||
Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
|
||||
ExprResult Res = ParseStringLiteralExpression();
|
||||
|
||||
if (Res.isInvalid) return Res;
|
||||
|
||||
return Actions.ParseObjCStringLiteral(Res.Val);
|
||||
return Actions.ParseObjCStringLiteral(AtLoc, Res.Val);
|
||||
}
|
||||
|
||||
/// objc-encode-expression:
|
||||
|
|
|
@ -454,7 +454,8 @@ public:
|
|||
tok::TokenKind Kind);
|
||||
|
||||
// ParseObjCStringLiteral - Parse Objective-C string literals.
|
||||
virtual ExprResult ParseObjCStringLiteral(ExprTy *string);
|
||||
virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc,
|
||||
ExprTy *string);
|
||||
virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
|
||||
SourceLocation EncodeLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
|
|
@ -1929,7 +1929,8 @@ Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
|
|||
}
|
||||
|
||||
// TODO: Move this to SemaObjC.cpp
|
||||
Sema::ExprResult Sema::ParseObjCStringLiteral(ExprTy *string) {
|
||||
Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation AtLoc,
|
||||
ExprTy *string) {
|
||||
StringLiteral* S = static_cast<StringLiteral *>(string);
|
||||
|
||||
if (CheckBuiltinCFStringArgument(S))
|
||||
|
@ -1949,7 +1950,7 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(ExprTy *string) {
|
|||
}
|
||||
QualType t = Context.getObjcConstantStringInterface();
|
||||
t = Context.getPointerType(t);
|
||||
return new ObjCStringLiteral(S, t);
|
||||
return new ObjCStringLiteral(S, t, AtLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
|
||||
|
|
|
@ -178,8 +178,8 @@ public:
|
|||
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
|
||||
QualType getPointerDiffType() const;
|
||||
|
||||
// getCFConstantStringType - Return the type used for constant CFStrings.
|
||||
// CURRENTLY UNUSED (10/15/07). ObjCStringLiteral now uses the hook below.
|
||||
// getCFConstantStringType - Return the C structure type used to represent
|
||||
// constant CFStrings.
|
||||
QualType getCFConstantStringType();
|
||||
|
||||
// This setter/getter represents the ObjC type for an NSConstantString.
|
||||
|
|
|
@ -1062,16 +1062,17 @@ public:
|
|||
/// i.e. @"foo".
|
||||
class ObjCStringLiteral : public Expr {
|
||||
StringLiteral *String;
|
||||
SourceLocation AtLoc;
|
||||
public:
|
||||
ObjCStringLiteral(StringLiteral *SL, QualType T)
|
||||
: Expr(ObjCStringLiteralClass, T), String(SL) {}
|
||||
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
|
||||
: Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {}
|
||||
|
||||
StringLiteral* getString() { return String; }
|
||||
|
||||
const StringLiteral* getString() const { return String; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return String->getSourceRange();
|
||||
return SourceRange(AtLoc, String->getLocEnd());
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
|
|
|
@ -612,7 +612,8 @@ public:
|
|||
|
||||
|
||||
//===----------------------- Obj-C Expressions --------------------------===//
|
||||
virtual ExprResult ParseObjCStringLiteral(ExprTy *string) {
|
||||
virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc,
|
||||
ExprTy *string) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -362,7 +362,7 @@ private:
|
|||
//===--------------------------------------------------------------------===//
|
||||
// Objective-C Expressions
|
||||
ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
|
||||
ExprResult ParseObjCStringLiteral();
|
||||
ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
|
||||
ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
|
||||
ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
|
||||
ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
|
||||
|
|
Loading…
Reference in New Issue