]> granicus.if.org Git - clang/commitdiff
Implement rewrite rules for ObjC string constants.
authorSteve Naroff <snaroff@apple.com>
Sat, 3 Nov 2007 11:27:19 +0000 (11:27 +0000)
committerSteve Naroff <snaroff@apple.com>
Sat, 3 Nov 2007 11:27:19 +0000 (11:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43665 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
Driver/RewriteTest.cpp
Parse/ParseObjc.cpp
Sema/Sema.h
Sema/SemaExpr.cpp
include/clang/AST/ASTContext.h
include/clang/AST/Expr.h
include/clang/Parse/Action.h
include/clang/Parse/Parser.h

index a8900c12a63e1b209894ae51e92fc5219fc733ec..f0b179bf397628aefa34a01eb8228887e849d614 100644 (file)
@@ -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);
index 7bbd7afdb522dc2ab3b43a236beb690b88deae03..b4d2fdf4a7bfce13c1fbfdff1415961bd494785e 100644 (file)
@@ -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(),
index 23d5f0e4192e1089702e7b6a0c815438fd4d339b..6464ca18c9a1ff3c4af64cbf66c3fd136926df0b 100644 (file)
@@ -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:
index 3ab5516e896d9e281bc4e2aa78262f0422b67d17..f6aa5b18dcc79e33ce95c4b2f3f0093d93612ed9 100644 (file)
@@ -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,
index 1eacd48f3d05133c8f064c8c99153576ea16fe72..30aa7b3001914e4cc3d5d54b4c95a1df425f4902 100644 (file)
@@ -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,
index 2dc904453077ae051e4ce770c23d27612be0ce05..a994d66fa99ce524d4de9a80ef0e76e286894065 100644 (file)
@@ -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.
index d19abe303480ac05e851279e31c7e37b376f4c73..f4d2af485f63ba626eb61bc0f3205ee695a5b351 100644 (file)
@@ -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) { 
index f7f58a80cd8d4b052d3444f84bb21d15bbc76928..c198e74d67d96095590f193d0ff63a2b87e10c9e 100644 (file)
@@ -612,7 +612,8 @@ public:
                                                
                                                
   //===----------------------- Obj-C Expressions --------------------------===//
-  virtual ExprResult ParseObjCStringLiteral(ExprTy *string) {
+  virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc, 
+                                            ExprTy *string) {
     return 0;
   }
 
index aeffdc69a41448553635d6c66cec3b1234ac56aa..95473d3c98bd3bd5290d4c3623dde2480b1e85ed 100644 (file)
@@ -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);