Implements boxed expressions for Objective-C. <rdar://problem/10194391>


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155082 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index b091e19..f958ade 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -158,7 +158,7 @@
   case Expr::ObjCSelectorExprClass:
   case Expr::ObjCProtocolExprClass:
   case Expr::ObjCStringLiteralClass:
-  case Expr::ObjCNumericLiteralClass:
+  case Expr::ObjCBoxedExprClass:
   case Expr::ObjCArrayLiteralClass:
   case Expr::ObjCDictionaryLiteralClass:
   case Expr::ObjCBoolLiteralExprClass:
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 66a88b0..8185481 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -3073,7 +3073,7 @@
   bool VisitUnaryAddrOf(const UnaryOperator *E);
   bool VisitObjCStringLiteral(const ObjCStringLiteral *E)
       { return Success(E); }
-  bool VisitObjCNumericLiteral(const ObjCNumericLiteral *E)
+  bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E)
       { return Success(E); }    
   bool VisitAddrLabelExpr(const AddrLabelExpr *E)
       { return Success(E); }
@@ -6501,7 +6501,7 @@
   case Expr::CXXDependentScopeMemberExprClass:
   case Expr::UnresolvedMemberExprClass:
   case Expr::ObjCStringLiteralClass:
-  case Expr::ObjCNumericLiteralClass:
+  case Expr::ObjCBoxedExprClass:
   case Expr::ObjCArrayLiteralClass:
   case Expr::ObjCDictionaryLiteralClass:
   case Expr::ObjCEncodeExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 0d405f1..cf624f6 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2390,7 +2390,7 @@
   case Expr::ObjCProtocolExprClass:
   case Expr::ObjCSelectorExprClass:
   case Expr::ObjCStringLiteralClass:
-  case Expr::ObjCNumericLiteralClass:
+  case Expr::ObjCBoxedExprClass:
   case Expr::ObjCArrayLiteralClass:
   case Expr::ObjCDictionaryLiteralClass:
   case Expr::ObjCSubscriptRefExprClass:
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 0d1066b..af8e5c7 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1727,9 +1727,9 @@
   VisitStringLiteral(Node->getString());
 }
 
-void StmtPrinter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
+void StmtPrinter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
   OS << "@";
-  Visit(E->getNumber());
+  Visit(E->getSubExpr());
 }
 
 void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index e50523a..e6b378e 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -981,7 +981,7 @@
   VisitExpr(S);
 }
 
-void StmtProfiler::VisitObjCNumericLiteral(const ObjCNumericLiteral *E) {
+void StmtProfiler::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
   VisitExpr(E);
 }
 
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 18891f7..734531f 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -498,8 +498,8 @@
   Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
     return CGF.EmitObjCStringLiteral(E);
   }
-  Value *VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
-    return CGF.EmitObjCNumericLiteral(E);
+  Value *VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+    return CGF.EmitObjCBoxedExpr(E);
   }
   Value *VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
     return CGF.EmitObjCArrayLiteral(E);
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index d0aa0f5..fc274a9 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -51,36 +51,36 @@
   return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
 }
 
-/// EmitObjCNumericLiteral - This routine generates code for
-/// the appropriate +[NSNumber numberWith<Type>:] method.
+/// EmitObjCBoxedExpr - This routine generates code to call
+/// the appropriate expression boxing method. This will either be
+/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:].
 ///
 llvm::Value *
-CodeGenFunction::EmitObjCNumericLiteral(const ObjCNumericLiteral *E) {
+CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
   // Generate the correct selector for this literal's concrete type.
-  const Expr *NL = E->getNumber();
+  const Expr *SubExpr = E->getSubExpr();
   // Get the method.
-  const ObjCMethodDecl *Method = E->getObjCNumericLiteralMethod();
-  assert(Method && "NSNumber method is null");
-  Selector Sel = Method->getSelector();
+  const ObjCMethodDecl *BoxingMethod = E->getBoxingMethod();
+  assert(BoxingMethod && "BoxingMethod is null");
+  assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method");
+  Selector Sel = BoxingMethod->getSelector();
   
   // Generate a reference to the class pointer, which will be the receiver.
-  QualType ResultType = E->getType(); // should be NSNumber *
-  const ObjCObjectPointerType *InterfacePointerType = 
-    ResultType->getAsObjCInterfacePointerType();
-  ObjCInterfaceDecl *NSNumberDecl = 
-    InterfacePointerType->getObjectType()->getInterface();
+  // Assumes that the method was introduced in the class that should be
+  // messaged (avoids pulling it out of the result type).
   CGObjCRuntime &Runtime = CGM.getObjCRuntime();
-  llvm::Value *Receiver = Runtime.GetClass(Builder, NSNumberDecl);
-
-  const ParmVarDecl *argDecl = *Method->param_begin();
+  const ObjCInterfaceDecl *ClassDecl = BoxingMethod->getClassInterface();
+  llvm::Value *Receiver = Runtime.GetClass(Builder, ClassDecl);
+  
+  const ParmVarDecl *argDecl = *BoxingMethod->param_begin();
   QualType ArgQT = argDecl->getType().getUnqualifiedType();
-  RValue RV = EmitAnyExpr(NL);
+  RValue RV = EmitAnyExpr(SubExpr);
   CallArgList Args;
   Args.add(RV, ArgQT);
-
+  
   RValue result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), 
-                                              ResultType, Sel, Receiver, Args, 
-                                              NSNumberDecl, Method);
+                                              BoxingMethod->getResultType(), Sel, Receiver, Args, 
+                                              ClassDecl, BoxingMethod);
   return Builder.CreateBitCast(result.getScalarVal(), 
                                ConvertType(E->getType()));
 }
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 83f1e2d..001a371 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2264,7 +2264,7 @@
 
   llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
   llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
-  llvm::Value *EmitObjCNumericLiteral(const ObjCNumericLiteral *E);
+  llvm::Value *EmitObjCBoxedExpr(const ObjCBoxedExpr *E);
   llvm::Value *EmitObjCArrayLiteral(const ObjCArrayLiteral *E);
   llvm::Value *EmitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E);
   llvm::Value *EmitObjCCollectionLiteral(const Expr *E,
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index fe70585..5038868 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -634,6 +634,7 @@
            .Case("objc_subscripting", LangOpts.ObjCNonFragileABI)
            .Case("objc_array_literals", LangOpts.ObjC2)
            .Case("objc_dictionary_literals", LangOpts.ObjC2)
+           .Case("objc_boxed_expressions", LangOpts.ObjC2)
            .Case("arc_cf_code_audited", true)
            // C11 features
            .Case("c_alignas", LangOpts.C11)
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 789a8ae..dd82599 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -2066,6 +2066,10 @@
     // Objective-C dictionary literal
     return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
           
+  case tok::l_paren:
+    // Objective-C boxed expression
+    return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
+          
   default:
     if (Tok.getIdentifierInfo() == 0)
       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
@@ -2580,6 +2584,28 @@
   return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()));
 }
 
+/// ParseObjCBoxedExpr -
+/// objc-box-expression:
+///       @( assignment-expression )
+ExprResult
+Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
+  if (Tok.isNot(tok::l_paren))
+    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");
+
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  T.consumeOpen();
+  ExprResult ValueExpr(ParseAssignmentExpression());
+  if (T.consumeClose())
+    return ExprError();
+  
+  // Wrap the sub-expression in a parenthesized expression, to distinguish
+  // a boxed expression from a literal.
+  SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
+  ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take());
+  return Owned(Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
+                                          ValueExpr.take()));
+}
+
 ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
   ExprVector ElementExprs(Actions);                   // array elements.
   ConsumeBracket(); // consume the l_square.
diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp
index 94fba64..b4da505 100644
--- a/lib/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Rewrite/RewriteModernObjC.cpp
@@ -317,7 +317,7 @@
     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
     Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
-    Stmt *RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp);
+    Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);
     Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);
     Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);
     Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
@@ -2471,7 +2471,7 @@
   return PE;
 }
 
-Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp) {
+Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
   // synthesize declaration of helper functions needed in this routine.
   if (!SelGetUidFunctionDecl)
     SynthSelGetUidFunctionDecl();
@@ -2489,13 +2489,12 @@
   SmallVector<Expr*, 4> MsgExprs;
   SmallVector<Expr*, 4> ClsExprs;
   QualType argType = Context->getPointerType(Context->CharTy);
-  QualType expType = Exp->getType();
   
-  // Create a call to objc_getClass("NSNumber"). It will be th 1st argument.
-  ObjCInterfaceDecl *Class = 
-    expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface();
+  // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.
+  ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();
+  ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();
   
-  IdentifierInfo *clsName = Class->getIdentifier();
+  IdentifierInfo *clsName = BoxingClass->getIdentifier();
   ClsExprs.push_back(StringLiteral::Create(*Context,
                                            clsName->getName(),
                                            StringLiteral::Ascii, false,
@@ -2506,12 +2505,11 @@
                                                StartLoc, EndLoc);
   MsgExprs.push_back(Cls);
   
-  // Create a call to sel_registerName("numberWithBool:"), etc.
+  // Create a call to sel_registerName("<BoxingMethod>:"), etc.
   // it will be the 2nd argument.
   SmallVector<Expr*, 4> SelExprs;
-  ObjCMethodDecl *NumericMethod = Exp->getObjCNumericLiteralMethod();
   SelExprs.push_back(StringLiteral::Create(*Context,
-                                           NumericMethod->getSelector().getAsString(),
+                                           BoxingMethod->getSelector().getAsString(),
                                            StringLiteral::Ascii, false,
                                            argType, SourceLocation()));
   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
@@ -2519,25 +2517,25 @@
                                                   StartLoc, EndLoc);
   MsgExprs.push_back(SelExp);
   
-  // User provided numeric literal is the 3rd, and last, argument.
-  Expr *userExpr  = Exp->getNumber();
-  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
+  // User provided sub-expression is the 3rd, and last, argument.
+  Expr *subExpr  = Exp->getSubExpr();
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {
     QualType type = ICE->getType();
     const Expr *SubExpr = ICE->IgnoreParenImpCasts();
     CastKind CK = CK_BitCast;
     if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())
       CK = CK_IntegralToBoolean;
-    userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
+    subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);
   }
-  MsgExprs.push_back(userExpr);
+  MsgExprs.push_back(subExpr);
   
   SmallVector<QualType, 4> ArgTypes;
   ArgTypes.push_back(Context->getObjCIdType());
   ArgTypes.push_back(Context->getObjCSelType());
-  for (ObjCMethodDecl::param_iterator PI = NumericMethod->param_begin(),
-       E = NumericMethod->param_end(); PI != E; ++PI)
+  for (ObjCMethodDecl::param_iterator PI = BoxingMethod->param_begin(),
+       E = BoxingMethod->param_end(); PI != E; ++PI)
     ArgTypes.push_back((*PI)->getType());
-    
+  
   QualType returnType = Exp->getType();
   // Get the type, we will need to reference it in a couple spots.
   QualType msgSendType = MsgSendFlavor->getType();
@@ -2547,13 +2545,13 @@
                                                VK_LValue, SourceLocation());
   
   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
-                                  Context->getPointerType(Context->VoidTy),
-                                  CK_BitCast, DRE);
+                                            Context->getPointerType(Context->VoidTy),
+                                            CK_BitCast, DRE);
   
   // Now do the "normal" pointer to function cast.
   QualType castType =
-    getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
-                          NumericMethod->isVariadic());
+  getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
+                        BoxingMethod->isVariadic());
   castType = Context->getPointerType(castType);
   cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
                                   cast);
@@ -5214,8 +5212,8 @@
   if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
     return RewriteObjCBoolLiteralExpr(BoolLitExpr);
   
-  if (ObjCNumericLiteral *NumericLitExpr = dyn_cast<ObjCNumericLiteral>(S))
-    return RewriteObjCNumericLiteralExpr(NumericLitExpr);
+  if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
+    return RewriteObjCBoxedExpr(BoxedExpr);
   
   if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
     return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 14b2434..ec33f0a 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -964,7 +964,7 @@
     // possibility.
   case Expr::ObjCArrayLiteralClass:
   case Expr::ObjCDictionaryLiteralClass:
-  case Expr::ObjCNumericLiteralClass:
+  case Expr::ObjCBoxedExprClass:
     return CT_Can;
 
     // Many other things have subexpressions, so we have to test those.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index af86cb2..af0f971 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4522,8 +4522,8 @@
       ObjCMethodDecl *D = 0;
       if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
         D = Send->getMethodDecl();
-      } else if (ObjCNumericLiteral *NumLit = dyn_cast<ObjCNumericLiteral>(E)) {
-        D = NumLit->getObjCNumericLiteralMethod();
+      } else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
+        D = BoxedExpr->getBoxingMethod();
       } else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) {
         D = ArrayLit->getArrayWithObjectsMethod();
       } else if (ObjCDictionaryLiteral *DictLit
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b62d56e..41fd112 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -111,7 +111,7 @@
       Ty = Context.getObjCIdType();
     }
   } else {
-    IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
+    IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
     NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
                                      LookupOrdinaryName);
     if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
@@ -143,17 +143,20 @@
 /// \brief Retrieve the NSNumber factory method that should be used to create
 /// an Objective-C literal for the given type.
 static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
-                                                QualType T, QualType ReturnType,
-                                                SourceRange Range) {
+                                                QualType NumberType,
+                                                bool isLiteral = false,
+                                                SourceRange R = SourceRange()) {
   llvm::Optional<NSAPI::NSNumberLiteralMethodKind> Kind 
-    = S.NSAPIObj->getNSNumberFactoryMethodKind(T);
+    = S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);
   
   if (!Kind) {
-    S.Diag(Loc, diag::err_invalid_nsnumber_type)
-      << T << Range;
+    if (isLiteral) {
+      S.Diag(Loc, diag::err_invalid_nsnumber_type)
+        << NumberType << R;
+    }
     return 0;
   }
-    
+  
   // If we already looked up this method, we're done.
   if (S.NSNumberLiteralMethods[*Kind])
     return S.NSNumberLiteralMethods[*Kind];
@@ -161,23 +164,52 @@
   Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,
                                                         /*Instance=*/false);
   
+  ASTContext &CX = S.Context;
+  
+  // Look up the NSNumber class, if we haven't done so already. It's cached
+  // in the Sema instance.
+  if (!S.NSNumberDecl) {
+    IdentifierInfo *NSNumberId = S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber);
+    NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId,
+                                       Loc, Sema::LookupOrdinaryName);
+    S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+    if (!S.NSNumberDecl) {
+      if (S.getLangOpts().DebuggerObjCLiteral) {
+        // Create a stub definition of NSNumber.
+        S.NSNumberDecl =  ObjCInterfaceDecl::Create (CX,
+                                                     CX.getTranslationUnitDecl(),
+                                                     SourceLocation(),  NSNumberId,
+                                                     0, SourceLocation());
+      } else {
+        // Otherwise, require a declaration of NSNumber.
+        S.Diag(Loc, diag::err_undeclared_nsnumber);
+        return 0;
+      }
+    } else if (!S.NSNumberDecl->hasDefinition()) {
+      S.Diag(Loc, diag::err_undeclared_nsnumber);
+      return 0;
+    }
+    
+    // generate the pointer to NSNumber type.
+    S.NSNumberPointer = CX.getObjCObjectPointerType(CX.getObjCInterfaceType(S.NSNumberDecl));
+  }
+  
   // Look for the appropriate method within NSNumber.
   ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);;
   if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
+    // create a stub definition this NSNumber factory method.
     TypeSourceInfo *ResultTInfo = 0;
-    Method = ObjCMethodDecl::Create(S.Context, SourceLocation(), SourceLocation(), Sel,
-                           ReturnType,
-                           ResultTInfo,
-                           S.Context.getTranslationUnitDecl(),
-                           false /*Instance*/, false/*isVariadic*/,
-                           /*isSynthesized=*/false,
-                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
-                           ObjCMethodDecl::Required,
-                           false);
+    Method = ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
+                                    S.NSNumberPointer, ResultTInfo, S.NSNumberDecl,
+                                    /*isInstance=*/false, /*isVariadic=*/false,
+                                    /*isSynthesized=*/false,
+                                    /*isImplicitlyDeclared=*/true,
+                                    /*isDefined=*/false, ObjCMethodDecl::Required,
+                                    /*HasRelatedResultType=*/false);
     ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
                                              SourceLocation(), SourceLocation(),
-                                             &S.Context.Idents.get("value"),
-                                             T, /*TInfo=*/0, SC_None, SC_None, 0);
+                                             &CX.Idents.get("value"),
+                                             NumberType, /*TInfo=*/0, SC_None, SC_None, 0);
     Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>());
   }
 
@@ -202,29 +234,12 @@
   return Method;
 }
 
-/// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
-/// numeric literal expression. Type of the expression will be "NSNumber *"
-/// or "id" if NSNumber is unavailable.
+/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
+/// numeric literal expression. Type of the expression will be "NSNumber *".
 ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
-  // Look up the NSNumber class, if we haven't done so already.
-  if (!NSNumberDecl) {
-    NamedDecl *IF = LookupSingleName(TUScope,
-                                NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
-                                AtLoc, LookupOrdinaryName);
-    NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+  // compute the effective range of the literal, including the leading '@'.
+  SourceRange SR(AtLoc, Number->getSourceRange().getEnd());
     
-    if (!NSNumberDecl && getLangOpts().DebuggerObjCLiteral)
-      NSNumberDecl =  ObjCInterfaceDecl::Create (Context,
-                        Context.getTranslationUnitDecl(),
-                        SourceLocation(), 
-                        NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
-                        0, SourceLocation());
-    if (!NSNumberDecl) {
-      Diag(AtLoc, diag::err_undeclared_nsnumber);
-      return ExprError();
-    }
-  }
-  
   // Determine the type of the literal.
   QualType NumberType = Number->getType();
   if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {
@@ -249,29 +264,23 @@
     }
   }
   
-  ObjCMethodDecl *Method = 0;
   // Look for the appropriate method within NSNumber.
   // Construct the literal.
-  QualType Ty
-    = Context.getObjCObjectPointerType(
-                                    Context.getObjCInterfaceType(NSNumberDecl));
-  Method  = getNSNumberFactoryMethod(*this, AtLoc, 
-                                     NumberType, Ty, 
-                                     Number->getSourceRange());
-
+  ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType,
+                                                    true, Number->getSourceRange());
   if (!Method)
     return ExprError();
 
   // Convert the number to the type that the parameter expects.
-  QualType ElementT = Method->param_begin()[0]->getType();
-  ExprResult ConvertedNumber = PerformImplicitConversion(Number, ElementT,
+  QualType ArgType = Method->param_begin()[0]->getType();
+  ExprResult ConvertedNumber = PerformImplicitConversion(Number, ArgType,
                                                          AA_Sending);
   if (ConvertedNumber.isInvalid())
     return ExprError();
   Number = ConvertedNumber.get();
   
   return MaybeBindToTemporary(
-           new (Context) ObjCNumericLiteral(Number, Ty, Method, AtLoc));
+           new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method, SR));
 }
 
 ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, 
@@ -385,6 +394,144 @@
            Element->getLocStart(), Element);
 }
 
+ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
+  if (ValueExpr->isTypeDependent()) {
+    ObjCBoxedExpr *BoxedExpr = 
+      new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR);
+    return Owned(BoxedExpr);
+  }
+  ObjCMethodDecl *BoxingMethod = NULL;
+  QualType BoxedType;
+  // Convert the expression to an RValue, so we can check for pointer types...
+  ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr);
+  if (RValue.isInvalid()) {
+    return ExprError();
+  }
+  ValueExpr = RValue.get();
+  QualType ValueType(ValueExpr->getType().getCanonicalType());
+  if (const PointerType *PT = ValueType->getAs<PointerType>()) {
+    QualType PointeeType = PT->getPointeeType();
+    if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {
+
+      if (!NSStringDecl) {
+        IdentifierInfo *NSStringId =
+          NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
+        NamedDecl *Decl = LookupSingleName(TUScope, NSStringId,
+                                           SR.getBegin(), LookupOrdinaryName);
+        NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
+        if (!NSStringDecl) {
+          if (getLangOpts().DebuggerObjCLiteral) {
+            // Support boxed expressions in the debugger w/o NSString declaration.
+            NSStringDecl = ObjCInterfaceDecl::Create(Context,
+                                                     Context.getTranslationUnitDecl(),
+                                                     SourceLocation(), NSStringId,
+                                                     0, SourceLocation());
+          } else {
+            Diag(SR.getBegin(), diag::err_undeclared_nsstring);
+            return ExprError();
+          }
+        } else if (!NSStringDecl->hasDefinition()) {
+          Diag(SR.getBegin(), diag::err_undeclared_nsstring);
+          return ExprError();
+        }
+        assert(NSStringDecl && "NSStringDecl should not be NULL");
+        NSStringPointer =
+          Context.getObjCObjectPointerType(Context.getObjCInterfaceType(NSStringDecl));
+      }
+      
+      if (!StringWithUTF8StringMethod) {
+        IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");
+        Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);
+
+        // Look for the appropriate method within NSString.
+        StringWithUTF8StringMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
+        if (!StringWithUTF8StringMethod && getLangOpts().DebuggerObjCLiteral) {
+          // Debugger needs to work even if NSString hasn't been defined.
+          TypeSourceInfo *ResultTInfo = 0;
+          ObjCMethodDecl *M =
+            ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
+                                   stringWithUTF8String, NSStringPointer,
+                                   ResultTInfo, NSStringDecl,
+                                   /*isInstance=*/false, /*isVariadic=*/false,
+                                   /*isSynthesized=*/false,
+                                   /*isImplicitlyDeclared=*/true,
+                                   /*isDefined=*/false,
+                                   ObjCMethodDecl::Required,
+                                   /*HasRelatedResultType=*/false);
+          ParmVarDecl *value =
+            ParmVarDecl::Create(Context, M,
+                                SourceLocation(), SourceLocation(),
+                                &Context.Idents.get("value"),
+                                Context.getPointerType(Context.CharTy.withConst()),
+                                /*TInfo=*/0,
+                                SC_None, SC_None, 0);
+          M->setMethodParams(Context, value, ArrayRef<SourceLocation>());
+          StringWithUTF8StringMethod = M;
+        }
+        assert(StringWithUTF8StringMethod &&
+               "StringWithUTF8StringMethod should not be NULL");
+      }
+      
+      BoxingMethod = StringWithUTF8StringMethod;
+      BoxedType = NSStringPointer;
+    }
+  } else if (isa<BuiltinType>(ValueType)) {
+    // The other types we support are numeric, char and BOOL/bool. We could also
+    // provide limited support for structure types, such as NSRange, NSRect, and
+    // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>
+    // for more details.
+
+    // Check for a top-level character literal.
+    if (const CharacterLiteral *Char =
+        dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) {
+      // In C, character literals have type 'int'. That's not the type we want
+      // to use to determine the Objective-c literal kind.
+      switch (Char->getKind()) {
+      case CharacterLiteral::Ascii:
+        ValueType = Context.CharTy;
+        break;
+        
+      case CharacterLiteral::Wide:
+        ValueType = Context.getWCharType();
+        break;
+        
+      case CharacterLiteral::UTF16:
+        ValueType = Context.Char16Ty;
+        break;
+        
+      case CharacterLiteral::UTF32:
+        ValueType = Context.Char32Ty;
+        break;
+      }
+    }
+    
+    // FIXME:  Do I need to do anything special with BoolTy expressions?
+    
+    // Look for the appropriate method within NSNumber.
+    BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
+    BoxedType = NSNumberPointer;
+  }
+
+  if (!BoxingMethod) {
+    Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type)
+      << ValueType << ValueExpr->getSourceRange();
+    return ExprError();
+  }
+  
+  // Convert the expression to the type that the parameter requires.
+  QualType ArgType = BoxingMethod->param_begin()[0]->getType();
+  ExprResult ConvertedValueExpr = PerformImplicitConversion(ValueExpr, ArgType,
+                                                            AA_Sending);
+  if (ConvertedValueExpr.isInvalid())
+    return ExprError();
+  ValueExpr = ConvertedValueExpr.get();
+  
+  ObjCBoxedExpr *BoxedExpr = 
+    new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,
+                                      BoxingMethod, SR);
+  return MaybeBindToTemporary(BoxedExpr);
+}
+
 ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
                                         Expr *IndexExpr,
                                         ObjCMethodDecl *getterMethod,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index a66378e..7387eac 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2225,6 +2225,14 @@
                                                 RParenLoc);
   }
 
+  /// \brief Build a new Objective-C boxed expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
+    return getSema().BuildObjCBoxedExpr(SR, ValueExpr);
+  }
+  
   /// \brief Build a new Objective-C array literal.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -8352,8 +8360,16 @@
 
 template<typename Derived>
 ExprResult
-TreeTransform<Derived>::TransformObjCNumericLiteral(ObjCNumericLiteral *E) {
-  return SemaRef.MaybeBindToTemporary(E);
+TreeTransform<Derived>::TransformObjCBoxedExpr(ObjCBoxedExpr *E) {
+  ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildObjCBoxedExpr(E->getSourceRange(), SubExpr.get());
 }
 
 template<typename Derived>
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 007ecee..73b5ab7 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -816,12 +816,12 @@
   E->setAtLoc(ReadSourceLocation(Record, Idx));
 }
 
-void ASTStmtReader::VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
+void ASTStmtReader::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
   VisitExpr(E);
   // could be one of several IntegerLiteral, FloatLiteral, etc.
-  E->Number = Reader.ReadSubStmt();
-  E->ObjCNumericLiteralMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
-  E->AtLoc = ReadSourceLocation(Record, Idx);
+  E->SubExpr = Reader.ReadSubStmt();
+  E->BoxingMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
+  E->Range = ReadSourceRange(Record, Idx);
 }
 
 void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
@@ -1888,8 +1888,8 @@
     case EXPR_OBJC_STRING_LITERAL:
       S = new (Context) ObjCStringLiteral(Empty);
       break;
-    case EXPR_OBJC_NUMERIC_LITERAL:
-      S = new (Context) ObjCNumericLiteral(Empty);
+    case EXPR_OBJC_BOXED_EXPRESSION:
+      S = new (Context) ObjCBoxedExpr(Empty);
       break;
     case EXPR_OBJC_ARRAY_LITERAL:
       S = ObjCArrayLiteral::CreateEmpty(Context,
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 81c0a9d..e9c0596 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -696,7 +696,7 @@
   RECORD(EXPR_BLOCK);
   RECORD(EXPR_GENERIC_SELECTION);
   RECORD(EXPR_OBJC_STRING_LITERAL);
-  RECORD(EXPR_OBJC_NUMERIC_LITERAL);
+  RECORD(EXPR_OBJC_BOXED_EXPRESSION);
   RECORD(EXPR_OBJC_ARRAY_LITERAL);
   RECORD(EXPR_OBJC_DICTIONARY_LITERAL);
   RECORD(EXPR_OBJC_ENCODE);
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 1e31211..8943615 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -777,12 +777,12 @@
   Code = serialization::EXPR_OBJC_STRING_LITERAL;
 }
 
-void ASTStmtWriter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
+void ASTStmtWriter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
   VisitExpr(E);
-  Writer.AddStmt(E->getNumber());
-  Writer.AddDeclRef(E->getObjCNumericLiteralMethod(), Record);
-  Writer.AddSourceLocation(E->getAtLoc(), Record);
-  Code = serialization::EXPR_OBJC_NUMERIC_LITERAL;
+  Writer.AddStmt(E->getSubExpr());
+  Writer.AddDeclRef(E->getBoxingMethod(), Record);
+  Writer.AddSourceRange(E->getSourceRange(), Record);
+  Code = serialization::EXPR_OBJC_BOXED_EXPRESSION;
 }
 
 void ASTStmtWriter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 1fd9068..abc6316 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -592,7 +592,7 @@
     case Stmt::ObjCIsaExprClass:
     case Stmt::ObjCProtocolExprClass:
     case Stmt::ObjCSelectorExprClass:
-    case Expr::ObjCNumericLiteralClass:
+    case Expr::ObjCBoxedExprClass:
     case Stmt::ParenListExprClass:
     case Stmt::PredefinedExprClass:
     case Stmt::ShuffleVectorExprClass: