aboutsummaryrefslogtreecommitdiff
path: root/Driver/RewriteTest.cpp
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-11-03 11:27:19 +0000
committerSteve Naroff <snaroff@apple.com>2007-11-03 11:27:19 +0000
commitbeaf299a2701c5559a4e5d76b0c40f805afb8e6a (patch)
tree6307897552c0d0a3eaf3e522980fa209a582e190 /Driver/RewriteTest.cpp
parent31e6c7ddfeeefe05b67220bc87fa23d4338d1056 (diff)
Implement rewrite rules for ObjC string constants.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43665 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Driver/RewriteTest.cpp')
-rw-r--r--Driver/RewriteTest.cpp85
1 files changed, 75 insertions, 10 deletions
diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp
index 7bbd7afdb5..b4d2fdf4a7 100644
--- a/Driver/RewriteTest.cpp
+++ b/Driver/RewriteTest.cpp
@@ -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(),