[cfe-commits] r159445 - in /cfe/trunk: lib/Rewrite/RewriteModernObjC.cpp test/Rewriter/objc-modern-StretAPI.mm test/Rewriter/objc-modern-container-subscript.mm

Fariborz Jahanian fjahanian at apple.com
Fri Jun 29 11:27:08 PDT 2012


Author: fjahanian
Date: Fri Jun 29 13:27:08 2012
New Revision: 159445

URL: http://llvm.org/viewvc/llvm-project?rev=159445&view=rev
Log:
objective-c modern translator: Translation into objc_msgSend_stret
entry point which requires nil check before calling objc_msgSend_stret.
// rdar://11359268 - wip.

Added:
    cfe/trunk/test/Rewriter/objc-modern-StretAPI.mm
Modified:
    cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp
    cfe/trunk/test/Rewriter/objc-modern-container-subscript.mm

Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=159445&r1=159444&r2=159445&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Fri Jun 29 13:27:08 2012
@@ -367,6 +367,13 @@
                                            Expr **args, unsigned nargs,
                                            SourceLocation StartLoc=SourceLocation(),
                                            SourceLocation EndLoc=SourceLocation());
+    
+    Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
+                                        QualType msgSendType, 
+                                        QualType returnType, 
+                                        SmallVectorImpl<QualType> &ArgTypes,
+                                        SmallVectorImpl<Expr*> &MsgExprs,
+                                        ObjCMethodDecl *Method);
 
     Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
                            SourceLocation StartLoc=SourceLocation(),
@@ -3055,6 +3062,107 @@
   return Context->getTagDeclType(ConstantStringDecl);
 }
 
+/// getFunctionSourceLocation - returns start location of a function
+/// definition. Complication arises when function has declared as
+/// extern "C" or extern "C" {...}
+static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
+                                                 FunctionDecl *FD) {
+  if (FD->isExternC()  && !FD->isMain()) {
+    const DeclContext *DC = FD->getDeclContext();
+    if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
+      // if it is extern "C" {...}, return function decl's own location.
+      if (!LSD->getRBraceLoc().isValid())
+        return LSD->getExternLoc();
+  }
+  if (FD->getStorageClassAsWritten() != SC_None)
+    R.RewriteBlockLiteralFunctionDecl(FD);
+  return FD->getTypeSpecStartLoc();
+}
+
+/// SynthMsgSendStretCallExpr - This routine translates message expression
+/// into a call to objc_msgSend_stret() entry point. Tricky part is that
+/// nil check on receiver must be performed before calling objc_msgSend_stret.
+/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)
+/// msgSendType - function type of objc_msgSend_stret(...)
+/// returnType - Result type of the method being synthesized.
+/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
+/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret, 
+/// starting with receiver.
+/// Method - Method being rewritten.
+Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
+                                                 QualType msgSendType, 
+                                                 QualType returnType, 
+                                                 SmallVectorImpl<QualType> &ArgTypes,
+                                                 SmallVectorImpl<Expr*> &MsgExprs,
+                                                 ObjCMethodDecl *Method) {
+  // Now do the "normal" pointer to function cast.
+  QualType castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
+                                            Method ? Method->isVariadic() : false);
+  castType = Context->getPointerType(castType);
+  
+  // build type for containing the objc_msgSend_stret object.
+  static unsigned stretCount=0;
+  std::string name = "__Stret"; name += utostr(stretCount);
+  std::string str = "struct "; str += name;
+  str += " {\n\t";
+  str += name;
+  str += "(id receiver, SEL sel";
+  for (unsigned i = 2; i < ArgTypes.size(); i++) {
+    str += ", "; str += ArgTypes[i].getAsString(Context->getPrintingPolicy());
+    str += " arg"; str += utostr(i);
+  }
+  // could be vararg.
+  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
+    str += ", "; str += MsgExprs[i]->getType().getAsString(Context->getPrintingPolicy());
+    str += " arg"; str += utostr(i);
+  }
+  
+  str += ") {\n";
+  str += "\t  if (receiver == 0)\n";
+  str += "\t    memset((void*)&s, 0, sizeof(s));\n";
+  str += "\t  else\n";
+  str += "\t    s = (("; str += castType.getAsString(Context->getPrintingPolicy());
+  str += ")(void *)objc_msgSend_stret)(receiver, sel";
+  for (unsigned i = 2; i < ArgTypes.size(); i++) {
+    str += ", arg"; str += utostr(i);
+  }
+  // could be vararg.
+  for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
+    str += ", arg"; str += utostr(i);
+  }
+  
+  str += ");\n";
+  str += "\t}\n";
+  str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
+  str += " s;\n";
+  str += "};\n\n";
+  SourceLocation FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
+  InsertText(FunLocStart, str);
+  ++stretCount;
+  
+  // AST for __Stretn(receiver, args).s;
+  IdentifierInfo *ID = &Context->Idents.get(name);
+  FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
+                                          SourceLocation(), ID, castType, 0, SC_Extern,
+                                          SC_None, false, false);
+  DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
+                                               SourceLocation());
+  CallExpr *STCE = new (Context) CallExpr(*Context, DRE, &MsgExprs[0], MsgExprs.size(),
+                                          castType, VK_LValue, SourceLocation());
+  
+  FieldDecl *FieldD = FieldDecl::Create(*Context, 0, SourceLocation(),
+                                    SourceLocation(),
+                                    &Context->Idents.get("s"),
+                                    returnType, 0,
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    ICIS_NoInit);
+  MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(),
+                                            FieldD->getType(), VK_LValue,
+                                            OK_Ordinary);
+
+  return ME;
+}
+
 Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
                                     SourceLocation StartLoc,
                                     SourceLocation EndLoc) {
@@ -3443,29 +3551,10 @@
     // expression which dictate which one to envoke depending on size of
     // method's return type.
 
-    // Create a reference to the objc_msgSend_stret() declaration.
-    DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor,
-                                                   false, msgSendType,
-                                                   VK_LValue, SourceLocation());
-    // Need to cast objc_msgSend_stret to "void *" (see above comment).
-    cast = NoTypeInfoCStyleCastExpr(Context,
-                                    Context->getPointerType(Context->VoidTy),
-                                    CK_BitCast, STDRE);
-    // Now do the "normal" pointer to function cast.
-    castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
-      Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
-    castType = Context->getPointerType(castType);
-    cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
-                                    cast);
-
-    // Don't forget the parens to enforce the proper binding.
-    PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
-
-    FT = msgSendType->getAs<FunctionType>();
-    CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
-                                            MsgExprs.size(),
-                                            FT->getResultType(), VK_RValue,
-                                            SourceLocation());
+    Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, 
+                                           msgSendType, returnType, 
+                                           ArgTypes, MsgExprs,
+                                           Exp->getMethodDecl());
 
     // Build sizeof(returnType)
     UnaryExprOrTypeTraitExpr *sizeofExpr =
@@ -4152,23 +4241,6 @@
   return S;
 }
 
-/// getFunctionSourceLocation - returns start location of a function
-/// definition. Complication arises when function has declared as
-/// extern "C" or extern "C" {...}
-static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
-                                                 FunctionDecl *FD) {
-  if (FD->isExternC()  && !FD->isMain()) {
-    const DeclContext *DC = FD->getDeclContext();
-    if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
-      // if it is extern "C" {...}, return function decl's own location.
-      if (!LSD->getRBraceLoc().isValid())
-        return LSD->getExternLoc();
-  }
-  if (FD->getStorageClassAsWritten() != SC_None)
-    R.RewriteBlockLiteralFunctionDecl(FD);
-  return FD->getTypeSpecStartLoc();
-}
-
 void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
                                           StringRef FunName) {
   bool RewriteSC = (GlobalVarDecl &&
@@ -5885,6 +5957,9 @@
     Preamble += "#define __weak\n";
   }
   
+  // needed for use of memset.
+  Preamble += "\n#include <string.h>\n";
+  
   // Declarations required for modern objective-c array and dictionary literals.
   Preamble += "\n#include <stdarg.h>\n";
   Preamble += "struct __NSContainer_literal {\n";

Added: cfe/trunk/test/Rewriter/objc-modern-StretAPI.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/objc-modern-StretAPI.mm?rev=159445&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/objc-modern-StretAPI.mm (added)
+++ cfe/trunk/test/Rewriter/objc-modern-StretAPI.mm Fri Jun 29 13:27:08 2012
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// rdar://11359268
+
+extern "C" void *sel_registerName(const char *);
+
+union U {
+  double d1;
+  char filler[32];
+};
+
+struct S {
+  char filler[128];
+};
+
+ at interface I
+- (struct S) Meth : (int) arg1 : (id) arg2;
+- (struct S) Meth1;
+- (union U) Meth2 : (double)d;
+- (struct S) VAMeth : (int)anchor, ...;
+ at end
+
+I* PI();
+
+extern "C" {
+
+struct S foo () {
+  struct S s = [PI() Meth : 1 : (id)0];
+
+  U u = [PI() Meth2 : 3.14];
+
+  S s1 = [PI() VAMeth : 12, 13.4, 1000, "hello"];
+
+  S s2 = [PI() VAMeth : 12];
+
+  S s3 = [PI() VAMeth : 0, "hello", "there"];
+
+  return [PI() Meth1];
+}
+
+}
+

Modified: cfe/trunk/test/Rewriter/objc-modern-container-subscript.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/objc-modern-container-subscript.mm?rev=159445&r1=159444&r2=159445&view=diff
==============================================================================
--- cfe/trunk/test/Rewriter/objc-modern-container-subscript.mm (original)
+++ cfe/trunk/test/Rewriter/objc-modern-container-subscript.mm Fri Jun 29 13:27:08 2012
@@ -2,9 +2,10 @@
 // RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
 // rdar://11203853
 
+#include <string.h>
+
 void *sel_registerName(const char *);
 
-typedef unsigned int size_t;
 @protocol P @end
 
 @interface NSMutableArray





More information about the cfe-commits mailing list