diff options
author | Steve Naroff <snaroff@apple.com> | 2007-11-03 11:27:19 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2007-11-03 11:27:19 +0000 |
commit | beaf299a2701c5559a4e5d76b0c40f805afb8e6a (patch) | |
tree | 6307897552c0d0a3eaf3e522980fa209a582e190 | |
parent | 31e6c7ddfeeefe05b67220bc87fa23d4338d1056 (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
-rw-r--r-- | AST/ASTContext.cpp | 15 | ||||
-rw-r--r-- | Driver/RewriteTest.cpp | 85 | ||||
-rw-r--r-- | Parse/ParseObjc.cpp | 6 | ||||
-rw-r--r-- | Sema/Sema.h | 3 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | include/clang/AST/ASTContext.h | 4 | ||||
-rw-r--r-- | include/clang/AST/Expr.h | 7 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 3 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 2 |
9 files changed, 98 insertions, 32 deletions
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index a8900c12a6..f0b179bf39 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -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); 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(), diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index 23d5f0e419..6464ca18c9 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -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: diff --git a/Sema/Sema.h b/Sema/Sema.h index 3ab5516e89..f6aa5b18dc 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -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, diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 1eacd48f3d..30aa7b3001 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -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, diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2dc9044530..a994d66fa9 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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. diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d19abe3034..f4d2af485f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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) { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index f7f58a80cd..c198e74d67 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -612,7 +612,8 @@ public: //===----------------------- Obj-C Expressions --------------------------===// - virtual ExprResult ParseObjCStringLiteral(ExprTy *string) { + virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc, + ExprTy *string) { return 0; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index aeffdc69a4..95473d3c98 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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); |