aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
19 files changed, 309 insertions, 121 deletions
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;
}
-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 @@ Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp)
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 @@ Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp)
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 @@ Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp)
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 @@ Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp)
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 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
return RewriteObjCBoolLiteralExpr(BoolLitExpr);
- if (ObjCNumericLiteral *NumericLitExpr = dyn_cast<ObjCNumericLiteral>(S))
- return RewriteObjCNumericLiteralExpr(NumericLitExpr);
+ if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
+ return RewriteObjCBoxedExpr(BoxedExpr);
if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 14b24341d0..ec33f0ac8e 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -964,7 +964,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// possibility.
case Expr::ObjCArrayLiteralClass:
case Expr::ObjCDictionaryLiteralClass:
- case Expr::ObjCNumericLiteralClass:
+ case Expr::ObjCBoxedExprClass:
return CT_Can;
// Many other things have subexpressions, so we have to test those.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index af86cb2c43..af0f971c1c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4522,8 +4522,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
ObjCMethodDecl *D = 0;
if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
D = Send->getMethodDecl();
- } else if (ObjCNumericLiteral *NumLit = dyn_cast<ObjCNumericLiteral>(E)) {
- D = NumLit->getObjCNumericLiteralMethod();
+ } else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
+ D = BoxedExpr->getBoxingMethod();
} else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) {
D = ArrayLit->getArrayWithObjectsMethod();
} else if (ObjCDictionaryLiteral *DictLit
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b62d56efda..41fd112c71 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -111,7 +111,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
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 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
/// \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 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
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 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
return Method;
}
-/// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
-/// numeric literal expression. Type of the expression will be "NSNumber *"
-/// or "id" if NSNumber is unavailable.
+/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
+/// numeric literal expression. Type of the expression will be "NSNumber *".
ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
- // Look up the NSNumber class, if we haven't done so already.
- if (!NSNumberDecl) {
- NamedDecl *IF = LookupSingleName(TUScope,
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
- AtLoc, LookupOrdinaryName);
- NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ // compute the effective range of the literal, including the leading '@'.
+ SourceRange SR(AtLoc, Number->getSourceRange().getEnd());
- if (!NSNumberDecl && getLangOpts().DebuggerObjCLiteral)
- NSNumberDecl = ObjCInterfaceDecl::Create (Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
- 0, SourceLocation());
- if (!NSNumberDecl) {
- Diag(AtLoc, diag::err_undeclared_nsnumber);
- return ExprError();
- }
- }
-
// Determine the type of the literal.
QualType NumberType = Number->getType();
if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {
@@ -249,29 +264,23 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
}
}
- 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 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
Element->getLocStart(), Element);
}
+ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
+ if (ValueExpr->isTypeDependent()) {
+ ObjCBoxedExpr *BoxedExpr =
+ new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR);
+ return Owned(BoxedExpr);
+ }
+ ObjCMethodDecl *BoxingMethod = NULL;
+ QualType BoxedType;
+ // Convert the expression to an RValue, so we can check for pointer types...
+ ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr);
+ if (RValue.isInvalid()) {
+ return ExprError();
+ }
+ ValueExpr = RValue.get();
+ QualType ValueType(ValueExpr->getType().getCanonicalType());
+ if (const PointerType *PT = ValueType->getAs<PointerType>()) {
+ QualType PointeeType = PT->getPointeeType();
+ if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {
+
+ if (!NSStringDecl) {
+ IdentifierInfo *NSStringId =
+ NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
+ NamedDecl *Decl = LookupSingleName(TUScope, NSStringId,
+ SR.getBegin(), LookupOrdinaryName);
+ NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
+ if (!NSStringDecl) {
+ if (getLangOpts().DebuggerObjCLiteral) {
+ // Support boxed expressions in the debugger w/o NSString declaration.
+ NSStringDecl = ObjCInterfaceDecl::Create(Context,
+ Context.getTranslationUnitDecl(),
+ SourceLocation(), NSStringId,
+ 0, SourceLocation());
+ } else {
+ Diag(SR.getBegin(), diag::err_undeclared_nsstring);
+ return ExprError();
+ }
+ } else if (!NSStringDecl->hasDefinition()) {
+ Diag(SR.getBegin(), diag::err_undeclared_nsstring);
+ return ExprError();
+ }
+ assert(NSStringDecl && "NSStringDecl should not be NULL");
+ NSStringPointer =
+ Context.getObjCObjectPointerType(Context.getObjCInterfaceType(NSStringDecl));
+ }
+
+ if (!StringWithUTF8StringMethod) {
+ IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");
+ Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);
+
+ // Look for the appropriate method within NSString.
+ StringWithUTF8StringMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
+ if (!StringWithUTF8StringMethod && getLangOpts().DebuggerObjCLiteral) {
+ // Debugger needs to work even if NSString hasn't been defined.
+ TypeSourceInfo *ResultTInfo = 0;
+ ObjCMethodDecl *M =
+ ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
+ stringWithUTF8String, NSStringPointer,
+ ResultTInfo, NSStringDecl,
+ /*isInstance=*/false, /*isVariadic=*/false,
+ /*isSynthesized=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false,
+ ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
+ ParmVarDecl *value =
+ ParmVarDecl::Create(Context, M,
+ SourceLocation(), SourceLocation(),
+ &Context.Idents.get("value"),
+ Context.getPointerType(Context.CharTy.withConst()),
+ /*TInfo=*/0,
+ SC_None, SC_None, 0);
+ M->setMethodParams(Context, value, ArrayRef<SourceLocation>());
+ StringWithUTF8StringMethod = M;
+ }
+ assert(StringWithUTF8StringMethod &&
+ "StringWithUTF8StringMethod should not be NULL");
+ }
+
+ BoxingMethod = StringWithUTF8StringMethod;
+ BoxedType = NSStringPointer;
+ }
+ } else if (isa<BuiltinType>(ValueType)) {
+ // The other types we support are numeric, char and BOOL/bool. We could also
+ // provide limited support for structure types, such as NSRange, NSRect, and
+ // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>
+ // for more details.
+
+ // Check for a top-level character literal.
+ if (const CharacterLiteral *Char =
+ dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) {
+ // In C, character literals have type 'int'. That's not the type we want
+ // to use to determine the Objective-c literal kind.
+ switch (Char->getKind()) {
+ case CharacterLiteral::Ascii:
+ ValueType = Context.CharTy;
+ break;
+
+ case CharacterLiteral::Wide:
+ ValueType = Context.getWCharType();
+ break;
+
+ case CharacterLiteral::UTF16:
+ ValueType = Context.Char16Ty;
+ break;
+
+ case CharacterLiteral::UTF32:
+ ValueType = Context.Char32Ty;
+ break;
+ }
+ }
+
+ // FIXME: Do I need to do anything special with BoolTy expressions?
+
+ // Look for the appropriate method within NSNumber.
+ BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
+ BoxedType = NSNumberPointer;
+ }
+
+ if (!BoxingMethod) {
+ Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type)
+ << ValueType << ValueExpr->getSourceRange();
+ return ExprError();
+ }
+
+ // Convert the expression to the type that the parameter requires.
+ QualType ArgType = BoxingMethod->param_begin()[0]->getType();
+ ExprResult ConvertedValueExpr = PerformImplicitConversion(ValueExpr, ArgType,
+ AA_Sending);
+ if (ConvertedValueExpr.isInvalid())
+ return ExprError();
+ ValueExpr = ConvertedValueExpr.get();
+
+ ObjCBoxedExpr *BoxedExpr =
+ new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,
+ BoxingMethod, SR);
+ return MaybeBindToTemporary(BoxedExpr);
+}
+
ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
Expr *IndexExpr,
ObjCMethodDecl *getterMethod,
diff --git a/lib/Sema/TreeTransform.h