aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LanguageExtensions.html14
-rw-r--r--docs/ObjectiveCLiterals.html100
-rw-r--r--include/clang/AST/ExprObjC.h54
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h2
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--include/clang/Basic/StmtNodes.td2
-rw-r--r--include/clang/Parse/Parser.h1
-rw-r--r--include/clang/Sema/Sema.h21
-rw-r--r--include/clang/Serialization/ASTBitCodes.h2
-rw-r--r--lib/AST/ExprClassification.cpp2
-rw-r--r--lib/AST/ExprConstant.cpp4
-rw-r--r--lib/AST/ItaniumMangle.cpp2
-rw-r--r--lib/AST/StmtPrinter.cpp4
-rw-r--r--lib/AST/StmtProfile.cpp2
-rw-r--r--lib/CodeGen/CGExprScalar.cpp4
-rw-r--r--lib/CodeGen/CGObjC.cpp38
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
-rw-r--r--lib/Lex/PPMacroExpansion.cpp1
-rw-r--r--lib/Parse/ParseObjc.cpp26
-rw-r--r--lib/Rewrite/RewriteModernObjC.cpp46
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp2
-rw-r--r--lib/Sema/SemaExprCXX.cpp4
-rw-r--r--lib/Sema/SemaExprObjC.cpp247
-rw-r--r--lib/Sema/TreeTransform.h20
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp12
-rw-r--r--lib/Serialization/ASTWriter.cpp2
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp2
-rw-r--r--test/CodeGenObjC/objc-literal-debugger-test.m16
-rw-r--r--test/Parser/objc-boxing.m26
-rw-r--r--test/Rewriter/objc-modern-boxing.mm68
-rw-r--r--test/SemaObjC/boxing-illegal-types.m17
-rw-r--r--test/SemaTemplate/instantiate-objc-1.mm21
-rw-r--r--tools/libclang/CXCursor.cpp2
-rw-r--r--tools/libclang/IndexBody.cpp6
35 files changed, 624 insertions, 162 deletions
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 68f0afc1ff..9bae334f19 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -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 @@ in Objective-C++, and not in C++ with blocks, due to its use of
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>
diff --git a/docs/ObjectiveCLiterals.html b/docs/ObjectiveCLiterals.html
index 63b523c6df..dc2f2fff09 100644
--- a/docs/ObjectiveCLiterals.html
+++ b/docs/ObjectiveCLiterals.html
@@ -68,14 +68,15 @@ void main(int argc, const char *argv[]) {
<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 @@ The compiler implicitly converts <code>__objc_yes</code> and <code>__objc_no</co
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 @@ Objective-C now supports a new expression syntax for creating immutable array an
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 @@ Programs test for the new features by using clang's __has_feature checks. Here a
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>
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 4bfd12c069..d59662fd93 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -87,43 +87,45 @@ public:
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;
};
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index f1b5171021..a2f192ba83 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2209,7 +2209,7 @@ DEF_TRAVERSE_STMT(FloatingLiteral, { })
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, { })
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index a7c6ca3bbe..86d42bb72c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1518,6 +1518,10 @@ def err_undeclared_nsnumber : Error<
"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<
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index e7718cd80c..5abc50683c 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -134,7 +134,7 @@ def LambdaExpr : DStmt<Expr>;
// 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>;
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index de62ed2def..9d9a666c9c 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1503,6 +1503,7 @@ private:
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);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 8ac7c3ee01..e84a554505 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -523,9 +523,21 @@ public:
/// \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 @@ public:
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 @@ public:
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,
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index f9bb8928a3..f177b2fd59 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1066,7 +1066,7 @@ namespace clang {
/// \brief An ObjCStringLiteral record.
EXPR_OBJC_STRING_LITERAL,
- EXPR_OBJC_NUMERIC_LITERAL,
+ EXPR_OBJC_BOXED_EXPRESSION,
EXPR_OBJC_ARRAY_LITERAL,
EXPR_OBJC_DICTIONARY_LITERAL,
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index b091e19a8a..f958aded8d 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -158,7 +158,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
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 66a88b065c..818548127c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -3073,7 +3073,7 @@ public:
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 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
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 0d405f1f57..cf624f6d80 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2390,7 +2390,7 @@ recurse:
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 0d1066b7e3..af8e5c792a 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1727,9 +1727,9 @@ void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
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 e50523ae86..e6b378e16f 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -981,7 +981,7 @@ void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
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 18891f7492..734531f724 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -498,8 +498,8 @@ public:
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 d0aa0f5567..fc274a93a8 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -51,36 +51,36 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
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 83f1e2df9f..001a371002 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2264,7 +2264,7 @@ public:
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 fe7058570e..50388687dc 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -634,6 +634,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.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 789a8ae7a9..dd8259964c 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -2066,6 +2066,10 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
// 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 @@ ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
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 94fba64e17..b4da50583a 100644
--- a/lib/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Rewrite/RewriteModernObjC.cpp
@@ -317,7 +317,7 @@ namespace {
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 @@ Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {
return PE;