[cfe-commits] r155082 - in /cfe/trunk: docs/ include/clang/AST/ include/clang/Basic/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Lex/ lib/Parse/ lib/Rewrite/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/CodeGenObjC/ test/Parser/ test/Rewriter/ test/SemaObjC/ test/SemaTemplate/ tools/libclang/

Patrick Beard pcbeard at mac.com
Wed Apr 18 17:25:13 PDT 2012


Author: pcbeard
Date: Wed Apr 18 19:25:12 2012
New Revision: 155082

URL: http://llvm.org/viewvc/llvm-project?rev=155082&view=rev
Log:
Implements boxed expressions for Objective-C. <rdar://problem/10194391>

Added:
    cfe/trunk/test/Parser/objc-boxing.m
    cfe/trunk/test/Rewriter/objc-modern-boxing.mm
    cfe/trunk/test/SemaObjC/boxing-illegal-types.m
Modified:
    cfe/trunk/docs/LanguageExtensions.html
    cfe/trunk/docs/ObjectiveCLiterals.html
    cfe/trunk/include/clang/AST/ExprObjC.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/ExprClassification.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m
    cfe/trunk/test/SemaTemplate/instantiate-objc-1.mm
    cfe/trunk/tools/libclang/CXCursor.cpp
    cfe/trunk/tools/libclang/IndexBody.cpp

Modified: cfe/trunk/docs/LanguageExtensions.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.html?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.html (original)
+++ cfe/trunk/docs/LanguageExtensions.html Wed Apr 18 19:25:12 2012
@@ -91,7 +91,7 @@
     <li><a href="#objc_arc">Automatic reference counting</a></li>
     <li><a href="#objc_fixed_enum">Enumerations with a fixed underlying type</a></li>
     <li><a href="#objc_lambdas">Interoperability with C++11 lambdas</a></li>
-    <li><a href="#object-literals-subscripting">Object Literals and Subscripting</a></li>
+    <li><a href="#objc_object_literals_subscripting">Object Literals and Subscripting</a></li>
   </ul>
 </li>
 <li><a href="#overloading-in-c">Function Overloading in C</a></li>
@@ -1183,10 +1183,18 @@
 Objective-C memory management (autorelease).</p>
 
 <!-- ======================================================================= -->
-<h2 id="object-literals-subscripting">Object Literals and Subscripting</h2>
+<h2 id="objc_object_literals_subscripting">Object Literals and Subscripting</h2>
 <!-- ======================================================================= -->
 
-<p>Clang provides support for <a href="ObjectiveCLiterals.html">Object Literals and Subscripting</a> in Objective-C, which simplifies common Objective-C programming patterns, makes programs more concise, and improves the safety of container creation. There are several feature macros associated with object literals and subscripting: <code>__has_feature(objc_array_literals)</code> tests the availability of array literals; <code>__has_feature(objc_dictionary_literals)</code> tests the availability of dictionary literals; <code>__has_feature(objc_subscripting)</code> tests the availability of object subscripting.</p>
+<p>Clang provides support for <a href="ObjectiveCLiterals.html">Object Literals 
+and Subscripting</a> in Objective-C, which simplifies common Objective-C
+programming patterns, makes programs more concise, and improves the safety of
+container creation. There are several feature macros associated with object
+literals and subscripting: <code>__has_feature(objc_array_literals)</code>
+tests the availability of array literals;
+<code>__has_feature(objc_dictionary_literals)</code> tests the availability of
+dictionary literals; <code>__has_feature(objc_subscripting)</code> tests the
+availability of object subscripting.</p>
 
 <!-- ======================================================================= -->
 <h2 id="overloading-in-c">Function Overloading in C</h2>

Modified: cfe/trunk/docs/ObjectiveCLiterals.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ObjectiveCLiterals.html?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/docs/ObjectiveCLiterals.html (original)
+++ cfe/trunk/docs/ObjectiveCLiterals.html Wed Apr 18 19:25:12 2012
@@ -68,14 +68,15 @@
 
 <h3>Discussion</h3>
 
-NSNumber literals only support literal scalar values after the '@'. Consequently, @INT_MAX works, but @INT_MIN does not, because they are defined like this:<p>
+NSNumber literals only support literal scalar values after the <code>'@'</code>. Consequently, <code>@INT_MAX</code> works, but <code>@INT_MIN</code> does not, because they are defined like this:<p>
 
 <pre>
 #define INT_MAX   2147483647  /* max value for an int */
 #define INT_MIN   (-2147483647-1) /* min value for an int */
 </pre>
 
-The definition of INT_MIN is not a simple literal, but a parenthesized expression. This is by design, but may be improved in subsequent compiler releases.<p>
+The definition of <code>INT_MIN</code> is not a simple literal, but a parenthesized expression. Parenthesized
+expressions are supported using the <a href="#objc_boxed_expressions">boxed expression</a> syntax, which is described in the next section.<p>
 
 Because <code>NSNumber</code> does not currently support wrapping <code>long double</code> values, the use of a <code>long double NSNumber</code> literal (e.g. <code>@123.23L</code>) will be rejected by the compiler.<p>
 
@@ -95,6 +96,94 @@
 
 Objective-C++ also supports <code>@true</code> and <code>@false</code> expressions, which are equivalent to <code>@YES</code> and <code>@NO</code>.
 
+<!-- ======================================================================= -->
+<h2 id="objc_boxed_expressions">Boxed Expressions</h2>
+<!-- ======================================================================= -->
+
+<p>Objective-C provides a new syntax for boxing C expressions:</p>
+
+<pre>
+<code>@( <em>expression</em> )</code>
+</pre>
+
+<p>Expressions of scalar (numeric, enumerated, BOOL) and C string pointer types
+are supported:</p>
+
+<pre>
+// numbers.
+NSNumber *smallestInt = @(-INT_MAX - 1);
+NSNumber *piOverTwo = @(M_PI / 2);
+
+// enumerated types.
+typedef enum { Red, Green, Blue } Color;
+NSNumber *favoriteColor = @(Green);
+
+// strings.
+NSString *path = @(getenv("PATH"));
+NSArray *pathComponents = [path componentsSeparatedByString:@":"];
+</pre>
+
+<h3>Boxed Enums</h3>
+
+<p>
+Cocoa frameworks frequently define constant values using <em>enums.</em> Although enum values are integral, they may not be used directly as boxed literals (this avoids conflicts with future <code>'@'</code>-prefixed Objective-C keywords). Instead, an enum value must be placed inside a boxed expression. The following example demonstrates configuring an <code>AVAudioRecorder</code> using a dictionary that contains a boxed enumeration value:
+</p>
+
+<pre>
+enum {
+  AVAudioQualityMin = 0,
+  AVAudioQualityLow = 0x20,
+  AVAudioQualityMedium = 0x40,
+  AVAudioQualityHigh = 0x60,
+  AVAudioQualityMax = 0x7F
+};
+
+- (AVAudioRecorder *)recordToFile:(NSURL *)fileURL {
+  NSDictionary *settings = @{ AVEncoderAudioQualityKey : @(AVAudioQualityMax) };
+  return [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:NULL];
+}
+</pre>
+
+<p>
+The expression <code>@(AVAudioQualityMax)</code> converts <code>AVAudioQualityMax</code> to an integer type, and boxes the value accordingly. If the enum has a <a href="http://clang.llvm.org/docs/LanguageExtensions.html#objc_fixed_enum">fixed underlying type</a> as in:
+</p>
+
+<pre>
+typedef enum : unsigned char { Red, Green, Blue } Color;
+NSNumber *red = @(Red), *green = @(Green), *blue = @(Blue); // => [NSNumber numberWithUnsignedChar:]
+</pre>
+
+<p>
+then the fixed underlying type will be used to select the correct <code>NSNumber</code> creation method.
+</p>
+
+<h3>Boxed C Strings</h3>
+
+<p>
+A C string literal prefixed by the <code>'@'</code> token denotes an <code>NSString</code> literal in the same way a numeric literal prefixed by the <code>'@'</code> token denotes an <code>NSNumber</code> literal. When the type of the parenthesized expression is <code>(char *)</code> or <code>(const char *)</code>, the result of the boxed expression is a pointer to an <code>NSString</code> object containing equivalent character data. The following example converts C-style command line arguments into <code>NSString</code> objects.
+</p>
+
+<pre>
+// Partition command line arguments into positional and option arguments.
+NSMutableArray *args = [NSMutableArray new];
+NSMutableDictionary *options = [NSMutableArray new];
+while (--argc) {
+    const char *arg = *++argv;
+    if (strncmp(arg, "--", 2) == 0) {
+        options[@(arg + 2)] = @(*++argv);   // --key value
+    } else {
+        [args addObject:@(arg)];            // positional argument
+    }
+}
+</pre>
+
+<p>
+As with all C pointers, character pointer expressions can involve arbitrary pointer arithmetic, therefore programmers must ensure that the character data is valid. Passing <code>NULL</code> as the character pointer will raise an exception at runtime. When possible, the compiler will reject <code>NULL</code> character pointers used in boxed expressions.
+</p>
+
+<h3>Availability</h3>
+
+<p>This feature will be available in clang 3.2. It is not currently available in any Apple compiler.</p>
 
 <h2>Container Literals</h2>
 
@@ -104,9 +193,11 @@
 
 Immutable array expression:<p>
  
- <pre>
+<blockquote>
+<pre>
 NSArray *array = @[ @"Hello", NSApp, [NSNumber numberWithInt:42] ];
 </pre>
+</blockquote>
 
 This creates an <code>NSArray</code> with 3 elements. The comma-separated sub-expressions of an array literal can be any Objective-C object pointer typed expression.<p>
 
@@ -309,6 +400,9 @@
 
 Code can use also <code>__has_feature(objc_bool)</code> to check for the availability of numeric literals support. This checks for the new <code>__objc_yes / __objc_no</code> keywords, which enable the use of <code>@YES / @NO</code> literals.<p>
 
+<p>To check whether boxed expressions are supported, use
+<code>__has_feature(objc_boxed_expressions)</code> feature macro.</p>
+
 </div>
 </body>
 </html>

Modified: cfe/trunk/include/clang/AST/ExprObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Wed Apr 18 19:25:12 2012
@@ -87,43 +87,45 @@
   child_range children() { return child_range(); }
 };
 
-/// ObjCNumericLiteral - used for objective-c numeric literals;
-/// as in: @42 or @true (c++/objc++) or @__yes (c/objc)
-class ObjCNumericLiteral : public Expr {
-  /// Number - expression AST node for the numeric literal
-  Stmt *Number;
-  ObjCMethodDecl *ObjCNumericLiteralMethod;
-  SourceLocation AtLoc;
+/// ObjCBoxedExpr - used for generalized expression boxing.
+/// as in: @(strdup("hello world")) or @(random())
+/// Also used for boxing non-parenthesized numeric literals;
+/// as in: @42 or @true (c++/objc++) or @__yes (c/objc).
+class ObjCBoxedExpr : public Expr {
+  Stmt *SubExpr;
+  ObjCMethodDecl *BoxingMethod;
+  SourceRange Range;
 public:
-  ObjCNumericLiteral(Stmt *NL, QualType T, ObjCMethodDecl *method,
-                     SourceLocation L)
-  : Expr(ObjCNumericLiteralClass, T, VK_RValue, OK_Ordinary, 
-         false, false, false, false), Number(NL), 
-    ObjCNumericLiteralMethod(method), AtLoc(L) {}
-  explicit ObjCNumericLiteral(EmptyShell Empty)
-  : Expr(ObjCNumericLiteralClass, Empty) {}
+  ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
+                     SourceRange R)
+  : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary, 
+         E->isTypeDependent(), E->isValueDependent(), 
+         E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), 
+         SubExpr(E), BoxingMethod(method), Range(R) {}
+  explicit ObjCBoxedExpr(EmptyShell Empty)
+  : Expr(ObjCBoxedExprClass, Empty) {}
   
-  Expr *getNumber() { return cast<Expr>(Number); }
-  const Expr *getNumber() const { return cast<Expr>(Number); }
+  Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
   
-  ObjCMethodDecl *getObjCNumericLiteralMethod() const {
-    return ObjCNumericLiteralMethod; 
+  ObjCMethodDecl *getBoxingMethod() const {
+    return BoxingMethod; 
   }
-    
-  SourceLocation getAtLoc() const { return AtLoc; }
+  
+  SourceLocation getAtLoc() const { return Range.getBegin(); }
   
   SourceRange getSourceRange() const LLVM_READONLY {
-    return SourceRange(AtLoc, Number->getSourceRange().getEnd());
+    return Range;
   }
-
+  
   static bool classof(const Stmt *T) {
-      return T->getStmtClass() == ObjCNumericLiteralClass;
+    return T->getStmtClass() == ObjCBoxedExprClass;
   }
-  static bool classof(const ObjCNumericLiteral *) { return true; }
+  static bool classof(const ObjCBoxedExpr *) { return true; }
   
   // Iterators
-  child_range children() { return child_range(&Number, &Number+1); }
-    
+  child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+  
   friend class ASTStmtReader;
 };
 

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Apr 18 19:25:12 2012
@@ -2209,7 +2209,7 @@
 DEF_TRAVERSE_STMT(ImaginaryLiteral, { })
 DEF_TRAVERSE_STMT(StringLiteral, { })
 DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
-DEF_TRAVERSE_STMT(ObjCNumericLiteral, { })
+DEF_TRAVERSE_STMT(ObjCBoxedExpr, { })
 DEF_TRAVERSE_STMT(ObjCArrayLiteral, { })
 DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
   

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 18 19:25:12 2012
@@ -1518,6 +1518,10 @@
   "NSNumber must be available to use Objective-C literals">;
 def err_invalid_nsnumber_type : Error<
   "%0 is not a valid literal type for NSNumber">;
+def err_undeclared_nsstring : Error<
+  "cannot box a string value because NSString has not been declared">;
+def err_objc_illegal_boxed_expression_type : Error<
+  "Illegal type %0 used in a boxed expression">;
 def err_undeclared_nsarray : Error<
   "NSArray must be available to use Objective-C array literals">;
 def err_undeclared_nsdictionary : Error<

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Wed Apr 18 19:25:12 2012
@@ -134,7 +134,7 @@
 
 // Obj-C Expressions.
 def ObjCStringLiteral : DStmt<Expr>;
-def ObjCNumericLiteral : DStmt<Expr>;
+def ObjCBoxedExpr : DStmt<Expr>;
 def ObjCArrayLiteral : DStmt<Expr>;
 def ObjCDictionaryLiteral : DStmt<Expr>;
 def ObjCEncodeExpr : DStmt<Expr>;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Apr 18 19:25:12 2012
@@ -1503,6 +1503,7 @@
   ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue);
   ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc);
   ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
+  ExprResult ParseObjCBoxedExpr(SourceLocation AtLoc);
   ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
   ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
   ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 18 19:25:12 2012
@@ -523,9 +523,21 @@
   /// \brief The declaration of the Objective-C NSNumber class.
   ObjCInterfaceDecl *NSNumberDecl;
   
+  /// \brief Pointer to NSNumber type (NSNumber *).
+  QualType NSNumberPointer;
+  
   /// \brief The Objective-C NSNumber methods used to create NSNumber literals.
   ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
   
+  /// \brief The declaration of the Objective-C NSString class.
+  ObjCInterfaceDecl *NSStringDecl;
+
+  /// \brief Pointer to NSString type (NSString *).
+  QualType NSStringPointer;
+  
+  /// \brief The declaration of the stringWithUTF8String: method.
+  ObjCMethodDecl *StringWithUTF8StringMethod;
+
   /// \brief The declaration of the Objective-C NSArray class.
   ObjCInterfaceDecl *NSArrayDecl;
 
@@ -3848,7 +3860,7 @@
     
   ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
   
-  /// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
+  /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
   /// numeric literal expression. Type of the expression will be "NSNumber *"
   /// or "id" if NSNumber is unavailable.
   ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number);
@@ -3856,6 +3868,13 @@
                                   bool Value);
   ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements);
   
+  // BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the
+  // '@' prefixed parenthesized expression. The type of the expression will
+  // either be "NSNumber *" or "NSString *" depending on the type of
+  // ValueType, which is allowed to be a built-in numeric type or
+  // "char *" or "const char *".
+  ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr);
+  
   ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
                                           Expr *IndexExpr,
                                           ObjCMethodDecl *getterMethod,

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed Apr 18 19:25:12 2012
@@ -1066,7 +1066,7 @@
       /// \brief An ObjCStringLiteral record.
       EXPR_OBJC_STRING_LITERAL,
 
-      EXPR_OBJC_NUMERIC_LITERAL,
+      EXPR_OBJC_BOXED_EXPRESSION,
       EXPR_OBJC_ARRAY_LITERAL,
       EXPR_OBJC_DICTIONARY_LITERAL,
 

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Wed Apr 18 19:25:12 2012
@@ -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:

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Apr 18 19:25:12 2012
@@ -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:

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Apr 18 19:25:12 2012
@@ -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:

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Apr 18 19:25:12 2012
@@ -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) {

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Wed Apr 18 19:25:12 2012
@@ -981,7 +981,7 @@
   VisitExpr(S);
 }
 
-void StmtProfiler::VisitObjCNumericLiteral(const ObjCNumericLiteral *E) {
+void StmtProfiler::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
   VisitExpr(E);
 }
 

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed Apr 18 19:25:12 2012
@@ -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);

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Wed Apr 18 19:25:12 2012
@@ -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()));
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Apr 18 19:25:12 2012
@@ -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,

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Apr 18 19:25:12 2012
@@ -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)

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Wed Apr 18 19:25:12 2012
@@ -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.

Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Wed Apr 18 19:25:12 2012
@@ -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);

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Wed Apr 18 19:25:12 2012
@@ -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.

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Apr 18 19:25:12 2012
@@ -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

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Apr 18 19:25:12 2012
@@ -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);
-    
-    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();
-    }
-  }
-  
+  // compute the effective range of the literal, including the leading '@'.
+  SourceRange SR(AtLoc, Number->getSourceRange().getEnd());
+    
   // 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,

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Apr 18 19:25:12 2012
@@ -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>

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Apr 18 19:25:12 2012
@@ -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,

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Apr 18 19:25:12 2012
@@ -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);

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Apr 18 19:25:12 2012
@@ -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) {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Apr 18 19:25:12 2012
@@ -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:

Modified: cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m (original)
+++ cfe/trunk/test/CodeGenObjC/objc-literal-debugger-test.m Wed Apr 18 19:25:12 2012
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-objc-literal -emit-llvm -o - %s | FileCheck %s
 
 int main() {
-  id l = @'a';
+  // object literals.
+  id l;
   l = @'a';
   l = @42;
   l = @-42;
@@ -11,6 +12,19 @@
   l = @__objc_no;
   l = @{ @"name":@666 };
   l = @[ @"foo", @"bar" ];
+
+#if __has_feature(objc_boxed_expressions)
+  // boxed expressions.
+  id b;
+  b = @('a');
+  b = @(42);
+  b = @(-42);
+  b = @(42u);
+  b = @(3.141592654f);
+  b = @(__objc_yes);
+  b = @(__objc_no);
+  b = @("hello");
+#endif
 }
 
 // CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind

Added: cfe/trunk/test/Parser/objc-boxing.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objc-boxing.m?rev=155082&view=auto
==============================================================================
--- cfe/trunk/test/Parser/objc-boxing.m (added)
+++ cfe/trunk/test/Parser/objc-boxing.m Wed Apr 18 19:25:12 2012
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+ at interface NSString @end
+
+ at interface NSString (NSStringExtensionMethods)
++ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
+ at end
+
+extern char *strdup(const char *str);
+
+id constant_string() {
+    return @("boxed constant string.");
+}
+
+id dynamic_string() {
+    return @(strdup("boxed dynamic string"));
+}
+
+id const_char_pointer() {
+    return @((const char *)"constant character pointer");
+}
+
+id missing_parentheses() {
+    return @(5;             // expected-error {{expected ')'}} \
+                            // expected-note {{to match this '('}}
+}

Added: cfe/trunk/test/Rewriter/objc-modern-boxing.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/objc-modern-boxing.mm?rev=155082&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/objc-modern-boxing.mm (added)
+++ cfe/trunk/test/Rewriter/objc-modern-boxing.mm Wed Apr 18 19:25:12 2012
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -E %s -o %t.mm
+// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -o - | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -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 -Wno-attributes -Werror
+
+extern char *strdup(const char *str);
+extern "C" void *sel_registerName(const char *);
+
+typedef signed char BOOL;
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+
+#if __has_feature(objc_bool)
+#define YES             __objc_yes
+#define NO              __objc_no
+#else
+#define YES             ((BOOL)1)
+#define NO              ((BOOL)0)
+#endif
+
+ at interface NSNumber
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
++ (NSNumber *)numberWithShort:(short)value;
++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
++ (NSNumber *)numberWithInt:(int)value;
++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
++ (NSNumber *)numberWithLong:(long)value;
++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
++ (NSNumber *)numberWithLongLong:(long long)value;
++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
++ (NSNumber *)numberWithFloat:(float)value;
++ (NSNumber *)numberWithDouble:(double)value;
++ (NSNumber *)numberWithBool:(BOOL)value;
++ (NSNumber *)numberWithInteger:(NSInteger)value ;
++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ;
+ at end
+
+ at interface NSString
++ (id)stringWithUTF8String:(const char *)str;
+ at end
+
+int main(int argc, const char *argv[]) {
+  // character.
+  NSNumber *theLetterZ = @('Z');          // equivalent to [NSNumber numberWithChar:('Z')]
+
+  // integral.
+  NSNumber *fortyTwo = @(42);             // equivalent to [NSNumber numberWithInt:(42)]
+  NSNumber *fortyTwoUnsigned = @(42U);    // equivalent to [NSNumber numberWithUnsignedInt:(42U)]
+  NSNumber *fortyTwoLong = @(42L);        // equivalent to [NSNumber numberWithLong:(42L)]
+  NSNumber *fortyTwoLongLong = @(42LL);   // equivalent to [NSNumber numberWithLongLong:(42LL)]
+
+  // floating point.
+  NSNumber *piFloat = @(3.141592654F);    // equivalent to [NSNumber numberWithFloat:(3.141592654F)]
+  NSNumber *piDouble = @(3.1415926535);   // equivalent to [NSNumber numberWithDouble:(3.1415926535)]
+
+  // Strings.
+  NSString *duplicateString = @(strdup("Hello"));
+}
+
+// CHECK:  NSNumber *theLetterZ = ((NSNumber *(*)(id, SEL, char))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithChar:"), ('Z'));
+// CHECK:  NSNumber *fortyTwo = ((NSNumber *(*)(id, SEL, int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), (42));
+// CHECK:  NSNumber *fortyTwoUnsigned = ((NSNumber *(*)(id, SEL, unsigned int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithUnsignedInt:"), (42U));
+// CHECK:  NSNumber *fortyTwoLong = ((NSNumber *(*)(id, SEL, long))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithLong:"), (42L));
+// CHECK:  NSNumber *fortyTwoLongLong = ((NSNumber *(*)(id, SEL, long long))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithLongLong:"), (42LL));
+// CHECK:  NSNumber *piFloat = ((NSNumber *(*)(id, SEL, float))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithFloat:"), (3.1415927));
+// CHECK:  NSNumber *piDouble = ((NSNumber *(*)(id, SEL, double))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithDouble:"), (3.1415926535));
+// CHECK:  NSString *duplicateString = ((NSString *(*)(id, SEL, const char *))(void *)objc_msgSend)(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), (const char *)(strdup("Hello")));

Added: cfe/trunk/test/SemaObjC/boxing-illegal-types.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/boxing-illegal-types.m?rev=155082&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/boxing-illegal-types.m (added)
+++ cfe/trunk/test/SemaObjC/boxing-illegal-types.m Wed Apr 18 19:25:12 2012
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+
+typedef struct {
+    int x, y, z;
+} point;
+
+void testStruct() {
+    point p = { 0, 0, 0 };
+    id boxed = @(p);    // expected-error {{Illegal type 'point' used in a boxed expression}}
+}
+
+void testPointers() {
+    void *null = 0;
+    id boxed_null = @(null);        // expected-error {{Illegal type 'void *' used in a boxed expression}}
+    int numbers[] = { 0, 1, 2 };
+    id boxed_numbers = @(numbers);  // expected-error {{Illegal type 'int *' used in a boxed expression}}
+}

Modified: cfe/trunk/test/SemaTemplate/instantiate-objc-1.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-objc-1.mm?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-objc-1.mm (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-objc-1.mm Wed Apr 18 19:25:12 2012
@@ -46,3 +46,24 @@
 template struct EncodeTest<int>;
 template struct EncodeTest<double>;
 template struct EncodeTest<wchar_t>;
+
+// @() boxing expressions.
+template <typename T> struct BoxingTest {
+  static id box(T value) {
+    return @(value);                     // expected-error {{Illegal type 'int *' used in a boxed expression}} \
+                                         // expected-error {{Illegal type 'long double' used in a boxed expression}}
+  }
+};
+
+ at interface NSNumber
++ (NSNumber *)numberWithInt:(int)value;
+ at end
+
+ at interface NSString
++ (id)stringWithUTF8String:(const char *)str;
+ at end
+
+template struct BoxingTest<int>;
+template struct BoxingTest<const char *>;
+template struct BoxingTest<int *>;        // expected-note {{in instantiation of member function 'BoxingTest<int *>::box' requested here}}
+template struct BoxingTest<long double>;  // expected-note {{in instantiation of member function 'BoxingTest<long double>::box' requested here}}

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Wed Apr 18 19:25:12 2012
@@ -229,7 +229,7 @@
   case Stmt::VAArgExprClass:
   case Stmt::ObjCArrayLiteralClass:
   case Stmt::ObjCDictionaryLiteralClass:
-  case Stmt::ObjCNumericLiteralClass:
+  case Stmt::ObjCBoxedExprClass:
   case Stmt::ObjCSubscriptRefExprClass:
     K = CXCursor_UnexposedExpr;
     break;

Modified: cfe/trunk/tools/libclang/IndexBody.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=155082&r1=155081&r2=155082&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/IndexBody.cpp (original)
+++ cfe/trunk/tools/libclang/IndexBody.cpp Wed Apr 18 19:25:12 2012
@@ -90,13 +90,13 @@
     return true;
   }
 
-  bool VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
-    if (ObjCMethodDecl *MD = E->getObjCNumericLiteralMethod())
+  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+    if (ObjCMethodDecl *MD = E->getBoxingMethod())
       IndexCtx.handleReference(MD, E->getLocStart(),
                                Parent, ParentDC, E, CXIdxEntityRef_Implicit);
     return true;
   }
-
+  
   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
       IndexCtx.handleReference(MD, E->getLocStart(),





More information about the cfe-commits mailing list