Index: include/clang/Basic/StmtNodes.td =================================================================== --- include/clang/Basic/StmtNodes.td (revision 152265) +++ include/clang/Basic/StmtNodes.td (working copy) @@ -133,7 +133,7 @@ // Obj-C Expressions. def ObjCStringLiteral : DStmt; -def ObjCNumericLiteral : DStmt; +def ObjCBoxedExpr : DStmt; def ObjCArrayLiteral : DStmt; def ObjCDictionaryLiteral : DStmt; def ObjCEncodeExpr : DStmt; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td (revision 152265) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -1489,6 +1489,12 @@ "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_objc_incomplete_boxed_expression_type : Error< + "incomplete 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< Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h (revision 152265) +++ include/clang/Sema/Sema.h (working copy) @@ -519,9 +519,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; @@ -3708,7 +3720,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); @@ -3716,6 +3728,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, Index: include/clang/AST/ASTImporter.h =================================================================== --- include/clang/AST/ASTImporter.h (revision 152265) +++ include/clang/AST/ASTImporter.h (working copy) @@ -271,7 +271,8 @@ /// \brief Determine whether the given types are structurally /// equivalent. - bool IsStructurallyEquivalent(QualType From, QualType To); + bool IsStructurallyEquivalent(QualType From, QualType To, + bool Complain = true); }; } Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h (revision 152265) +++ include/clang/AST/Type.h (working copy) @@ -1714,9 +1714,9 @@ friend class ASTWriter; }; -template <> inline const TypedefType *Type::getAs() const { - return dyn_cast(this); -} +/// \brief This will check for a TypedefType by removing any existing sugar +/// until it reaches a TypedefType or a non-sugared type. +template <> const TypedefType *Type::getAs() const; // We can do canonical leaf types faster, because we don't have to // worry about preserving child type decoration. Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h (revision 152265) +++ include/clang/AST/RecursiveASTVisitor.h (working copy) @@ -2106,7 +2106,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, { }) Index: include/clang/AST/ExprObjC.h =================================================================== --- include/clang/AST/ExprObjC.h (revision 152265) +++ include/clang/AST/ExprObjC.h (working copy) @@ -86,43 +86,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(Number); } - const Expr *getNumber() const { return cast(Number); } + Expr *getSubExpr() { return cast(SubExpr); } + const Expr *getSubExpr() const { return cast(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 { - 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; }; Index: include/clang/AST/NSAPI.h =================================================================== --- include/clang/AST/NSAPI.h (revision 152265) +++ include/clang/AST/NSAPI.h (working copy) @@ -125,10 +125,19 @@ /// \brief Determine the appropriate NSNumber factory method kind for a /// literal of the given type. - static llvm::Optional - getNSNumberFactoryMethodKind(QualType T); + llvm::Optional + getNSNumberFactoryMethodKind(QualType T) const; + /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. + bool isObjCBOOLType(QualType T) const; + /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. + bool isObjCNSIntegerType(QualType T) const; + /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. + bool isObjCNSUIntegerType(QualType T) const; + private: + bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; + ASTContext &Ctx; mutable IdentifierInfo *ClassIds[NumClassIds]; @@ -144,6 +153,8 @@ /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods]; mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods]; + + mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId; }; } // end namespace clang Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h (revision 152265) +++ include/clang/Parse/Parser.h (working copy) @@ -1497,6 +1497,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); Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h (revision 152265) +++ include/clang/Serialization/ASTBitCodes.h (working copy) @@ -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, Index: docs/LanguageExtensions.html =================================================================== --- docs/LanguageExtensions.html (revision 152265) +++ docs/LanguageExtensions.html (working copy) @@ -87,7 +87,7 @@
  • Related result types
  • Automatic reference counting
  • Enumerations with a fixed underlying type
  • - +
  • Function Overloading in C
  • Initializer lists for complex numbers in C
  • Index: tools/libclang/IndexBody.cpp =================================================================== --- tools/libclang/IndexBody.cpp (revision 152265) +++ tools/libclang/IndexBody.cpp (working copy) @@ -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(), Index: tools/libclang/CXCursor.cpp =================================================================== --- tools/libclang/CXCursor.cpp (revision 152265) +++ tools/libclang/CXCursor.cpp (working copy) @@ -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; Index: lib/Rewrite/RewriteModernObjC.cpp =================================================================== --- lib/Rewrite/RewriteModernObjC.cpp (revision 152265) +++ lib/Rewrite/RewriteModernObjC.cpp (working copy) @@ -309,6 +309,10 @@ Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); + Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp); + Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp); + Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp); + Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp); Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); void RewriteTryReturnStmts(Stmt *S); void RewriteSyncReturnStmts(Stmt *S, std::string buf); @@ -2587,6 +2591,435 @@ return cast; } +Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) { + unsigned IntSize = + static_cast(Context->getTypeSize(Context->IntTy)); + + Expr *FlagExp = IntegerLiteral::Create(*Context, + llvm::APInt(IntSize, Exp->getValue()), + Context->IntTy, Exp->getLocation()); + CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy, + CK_BitCast, FlagExp); + ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(), + cast); + ReplaceStmt(Exp, PE); + return PE; +} + +Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) { + // synthesize declaration of helper functions needed in this routine. + if (!SelGetUidFunctionDecl) + SynthSelGetUidFunctionDecl(); + // use objc_msgSend() for all. + if (!MsgSendFunctionDecl) + SynthMsgSendFunctionDecl(); + if (!GetClassFunctionDecl) + SynthGetClassFunctionDecl(); + + FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; + SourceLocation StartLoc = Exp->getLocStart(); + SourceLocation EndLoc = Exp->getLocEnd(); + + // Synthesize a call to objc_msgSend(). + SmallVector MsgExprs; + SmallVector ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + + // Create a call to objc_getClass(""). It will be the 1st argument. + ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod(); + ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface(); + + IdentifierInfo *clsName = BoxingClass->getIdentifier(); + ClsExprs.push_back(StringLiteral::Create(*Context, + clsName->getName(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(Cls); + + // Create a call to sel_registerName(":"), etc. + // it will be the 2nd argument. + SmallVector SelExprs; + SelExprs.push_back(StringLiteral::Create(*Context, + BoxingMethod->getSelector().getAsString(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, + &SelExprs[0], SelExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(SelExp); + + // User provided sub-expression is the 3rd, and last, argument. + Expr *subExpr = Exp->getSubExpr(); + if (ImplicitCastExpr *ICE = dyn_cast(subExpr)) { + QualType type = ICE->getType(); + const Expr *SubExpr = ICE->IgnoreParenImpCasts(); + CastKind CK = CK_BitCast; + if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType()) + CK = CK_IntegralToBoolean; + subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr); + } + MsgExprs.push_back(subExpr); + + SmallVector ArgTypes; + ArgTypes.push_back(Context->getObjCIdType()); + ArgTypes.push_back(Context->getObjCSelType()); + 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(); + + // Create a reference to the objc_msgSend() declaration. + DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, + VK_LValue, SourceLocation()); + + CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(Context->VoidTy), + CK_BitCast, DRE); + + // Now do the "normal" pointer to function cast. + QualType castType = + getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), + BoxingMethod->isVariadic()); + castType = Context->getPointerType(castType); + cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, + cast); + + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); + + const FunctionType *FT = msgSendType->getAs(); + CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], + MsgExprs.size(), + FT->getResultType(), VK_RValue, + EndLoc); + ReplaceStmt(Exp, CE); + return CE; +} + +Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { + // synthesize declaration of helper functions needed in this routine. + if (!SelGetUidFunctionDecl) + SynthSelGetUidFunctionDecl(); + // use objc_msgSend() for all. + if (!MsgSendFunctionDecl) + SynthMsgSendFunctionDecl(); + if (!GetClassFunctionDecl) + SynthGetClassFunctionDecl(); + + FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; + SourceLocation StartLoc = Exp->getLocStart(); + SourceLocation EndLoc = Exp->getLocEnd(); + + // Build the expression: __NSContainer_literal(int, ...).arr + QualType IntQT = Context->IntTy; + QualType NSArrayFType = + getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); + std::string NSArrayFName("__NSContainer_literal"); + FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName); + DeclRefExpr *NSArrayDRE = + new (Context) DeclRefExpr(NSArrayFD, NSArrayFType, VK_RValue, + SourceLocation()); + + SmallVector InitExprs; + unsigned NumElements = Exp->getNumElements(); + unsigned UnsignedIntSize = + static_cast(Context->getTypeSize(Context->UnsignedIntTy)); + Expr *count = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, SourceLocation()); + InitExprs.push_back(count); + for (unsigned i = 0; i < NumElements; i++) + InitExprs.push_back(Exp->getElement(i)); + Expr *NSArrayCallExpr = + new (Context) CallExpr(*Context, NSArrayDRE, &InitExprs[0], InitExprs.size(), + NSArrayFType, VK_LValue, SourceLocation()); + + FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), + &Context->Idents.get("arr"), + Context->getPointerType(Context->VoidPtrTy), 0, + /*BitWidth=*/0, /*Mutable=*/true, + /*HasInit=*/false); + MemberExpr *ArrayLiteralME = + new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD, + SourceLocation(), + ARRFD->getType(), VK_LValue, + OK_Ordinary); + QualType ConstIdT = Context->getObjCIdType().withConst(); + CStyleCastExpr * ArrayLiteralObjects = + NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(ConstIdT), + CK_BitCast, + ArrayLiteralME); + + // Synthesize a call to objc_msgSend(). + SmallVector MsgExprs; + SmallVector ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + QualType expType = Exp->getType(); + + // Create a call to objc_getClass("NSArray"). It will be th 1st argument. + ObjCInterfaceDecl *Class = + expType->getPointeeType()->getAs()->getInterface(); + + IdentifierInfo *clsName = Class->getIdentifier(); + ClsExprs.push_back(StringLiteral::Create(*Context, + clsName->getName(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(Cls); + + // Create a call to sel_registerName("arrayWithObjects:count:"). + // it will be the 2nd argument. + SmallVector SelExprs; + ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod(); + SelExprs.push_back(StringLiteral::Create(*Context, + ArrayMethod->getSelector().getAsString(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, + &SelExprs[0], SelExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(SelExp); + + // (const id [])objects + MsgExprs.push_back(ArrayLiteralObjects); + + // (NSUInteger)cnt + Expr *cnt = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, SourceLocation()); + MsgExprs.push_back(cnt); + + + SmallVector ArgTypes; + ArgTypes.push_back(Context->getObjCIdType()); + ArgTypes.push_back(Context->getObjCSelType()); + for (ObjCMethodDecl::param_iterator PI = ArrayMethod->param_begin(), + E = ArrayMethod->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(); + + // Create a reference to the objc_msgSend() declaration. + DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, + VK_LValue, SourceLocation()); + + CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(Context->VoidTy), + CK_BitCast, DRE); + + // Now do the "normal" pointer to function cast. + QualType castType = + getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), + ArrayMethod->isVariadic()); + castType = Context->getPointerType(castType); + cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, + cast); + + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); + + const FunctionType *FT = msgSendType->getAs(); + CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], + MsgExprs.size(), + FT->getResultType(), VK_RValue, + EndLoc); + ReplaceStmt(Exp, CE); + return CE; +} + +Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) { + // synthesize declaration of helper functions needed in this routine. + if (!SelGetUidFunctionDecl) + SynthSelGetUidFunctionDecl(); + // use objc_msgSend() for all. + if (!MsgSendFunctionDecl) + SynthMsgSendFunctionDecl(); + if (!GetClassFunctionDecl) + SynthGetClassFunctionDecl(); + + FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; + SourceLocation StartLoc = Exp->getLocStart(); + SourceLocation EndLoc = Exp->getLocEnd(); + + // Build the expression: __NSContainer_literal(int, ...).arr + QualType IntQT = Context->IntTy; + QualType NSDictFType = + getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); + std::string NSDictFName("__NSContainer_literal"); + FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName); + DeclRefExpr *NSDictDRE = + new (Context) DeclRefExpr(NSDictFD, NSDictFType, VK_RValue, + SourceLocation()); + + SmallVector KeyExprs; + SmallVector ValueExprs; + + unsigned NumElements = Exp->getNumElements(); + unsigned UnsignedIntSize = + static_cast(Context->getTypeSize(Context->UnsignedIntTy)); + Expr *count = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, SourceLocation()); + KeyExprs.push_back(count); + ValueExprs.push_back(count); + for (unsigned i = 0; i < NumElements; i++) { + ObjCDictionaryElement Element = Exp->getKeyValueElement(i); + KeyExprs.push_back(Element.Key); + ValueExprs.push_back(Element.Value); + } + + // (const id [])objects + Expr *NSValueCallExpr = + new (Context) CallExpr(*Context, NSDictDRE, &ValueExprs[0], ValueExprs.size(), + NSDictFType, VK_LValue, SourceLocation()); + + FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), + &Context->Idents.get("arr"), + Context->getPointerType(Context->VoidPtrTy), 0, + /*BitWidth=*/0, /*Mutable=*/true, + /*HasInit=*/false); + MemberExpr *DictLiteralValueME = + new (Context) MemberExpr(NSValueCallExpr, false, ARRFD, + SourceLocation(), + ARRFD->getType(), VK_LValue, + OK_Ordinary); + QualType ConstIdT = Context->getObjCIdType().withConst(); + CStyleCastExpr * DictValueObjects = + NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(ConstIdT), + CK_BitCast, + DictLiteralValueME); + // (const id [])keys + Expr *NSKeyCallExpr = + new (Context) CallExpr(*Context, NSDictDRE, &KeyExprs[0], KeyExprs.size(), + NSDictFType, VK_LValue, SourceLocation()); + + MemberExpr *DictLiteralKeyME = + new (Context) MemberExpr(NSKeyCallExpr, false, ARRFD, + SourceLocation(), + ARRFD->getType(), VK_LValue, + OK_Ordinary); + + CStyleCastExpr * DictKeyObjects = + NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(ConstIdT), + CK_BitCast, + DictLiteralKeyME); + + + + // Synthesize a call to objc_msgSend(). + SmallVector MsgExprs; + SmallVector ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + QualType expType = Exp->getType(); + + // Create a call to objc_getClass("NSArray"). It will be th 1st argument. + ObjCInterfaceDecl *Class = + expType->getPointeeType()->getAs()->getInterface(); + + IdentifierInfo *clsName = Class->getIdentifier(); + ClsExprs.push_back(StringLiteral::Create(*Context, + clsName->getName(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(Cls); + + // Create a call to sel_registerName("arrayWithObjects:count:"). + // it will be the 2nd argument. + SmallVector SelExprs; + ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod(); + SelExprs.push_back(StringLiteral::Create(*Context, + DictMethod->getSelector().getAsString(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, + &SelExprs[0], SelExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(SelExp); + + // (const id [])objects + MsgExprs.push_back(DictValueObjects); + + // (const id [])keys + MsgExprs.push_back(DictKeyObjects); + + // (NSUInteger)cnt + Expr *cnt = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, SourceLocation()); + MsgExprs.push_back(cnt); + + + SmallVector ArgTypes; + ArgTypes.push_back(Context->getObjCIdType()); + ArgTypes.push_back(Context->getObjCSelType()); + for (ObjCMethodDecl::param_iterator PI = DictMethod->param_begin(), + E = DictMethod->param_end(); PI != E; ++PI) { + QualType T = (*PI)->getType(); + if (const PointerType* PT = T->getAs()) { + QualType PointeeTy = PT->getPointeeType(); + convertToUnqualifiedObjCType(PointeeTy); + T = Context->getPointerType(PointeeTy); + } + ArgTypes.push_back(T); + } + + QualType returnType = Exp->getType(); + // Get the type, we will need to reference it in a couple spots. + QualType msgSendType = MsgSendFlavor->getType(); + + // Create a reference to the objc_msgSend() declaration. + DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, + VK_LValue, SourceLocation()); + + CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(Context->VoidTy), + CK_BitCast, DRE); + + // Now do the "normal" pointer to function cast. + QualType castType = + getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), + DictMethod->isVariadic()); + castType = Context->getPointerType(castType); + cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, + cast); + + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); + + const FunctionType *FT = msgSendType->getAs(); + CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], + MsgExprs.size(), + FT->getResultType(), VK_RValue, + EndLoc); + ReplaceStmt(Exp, CE); + return CE; +} + +// struct __rw_objc_super { +// struct objc_object *object; struct objc_object *superClass; +// }; // struct objc_super { struct objc_object *receiver; struct objc_class *super; }; QualType RewriteModernObjC::getSuperStructType() { if (!SuperStructDecl) { @@ -4801,6 +5234,19 @@ if (ObjCStringLiteral *AtString = dyn_cast(S)) return RewriteObjCStringLiteral(AtString); + + if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast(S)) + return RewriteObjCBoolLiteralExpr(BoolLitExpr); + + if (ObjCBoxedExpr *BoxedExpr = dyn_cast(S)) + return RewriteObjCBoxedExpr(BoxedExpr); + + if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast(S)) + return RewriteObjCArrayLiteralExpr(ArrayLitExpr); + + if (ObjCDictionaryLiteral *DictionaryLitExpr = + dyn_cast(S)) + return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr); if (ObjCMessageExpr *MessExpr = dyn_cast(S)) { #if 0 Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h (revision 152265) +++ lib/Sema/TreeTransform.h (working copy) @@ -2211,6 +2211,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. @@ -8298,8 +8306,16 @@ template ExprResult -TreeTransform::TransformObjCNumericLiteral(ObjCNumericLiteral *E) { - return SemaRef.MaybeBindToTemporary(E); +TreeTransform::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 Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp (revision 152265) +++ lib/Sema/SemaExprCXX.cpp (working copy) @@ -4469,8 +4469,8 @@ ObjCMethodDecl *D = 0; if (ObjCMessageExpr *Send = dyn_cast(E)) { D = Send->getMethodDecl(); - } else if (ObjCNumericLiteral *NumLit = dyn_cast(E)) { - D = NumLit->getObjCNumericLiteralMethod(); + } else if (ObjCBoxedExpr *BoxedExpr = dyn_cast(E)) { + D = BoxedExpr->getBoxingMethod(); } else if (ObjCArrayLiteral *ArrayLit = dyn_cast(E)) { D = ArrayLit->getArrayWithObjectsMethod(); } else if (ObjCDictionaryLiteral *DictLit @@ -4529,6 +4529,17 @@ if (RD->isInvalidDecl() || RD->isDependentContext()) return Owned(E); + if (!RD->getDefinition()) { + if (RD->hasExternalLexicalStorage()) { + ExternalASTSource *ext_source = RD->getASTContext().getExternalSource(); + if (ext_source) + ext_source->CompleteType(RD); + } + } + + if (!RD->getDefinition()) + return Owned(E); + bool IsDecltype = ExprEvalContexts.back().IsDecltype; CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD); Index: lib/Sema/SemaExceptionSpec.cpp =================================================================== --- lib/Sema/SemaExceptionSpec.cpp (revision 152265) +++ lib/Sema/SemaExceptionSpec.cpp (working copy) @@ -726,4 +726,4 @@ New->getLocation()); } -} // end namespace clang +} Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp (revision 152265) +++ lib/Sema/SemaChecking.cpp (working copy) @@ -4416,12 +4416,16 @@ // Don't consider sizes resulting from macro expansions or template argument // substitution to form C89 tail-padded arrays. - ConstantArrayTypeLoc TL = - cast(FD->getTypeSourceInfo()->getTypeLoc()); - const Expr *SizeExpr = dyn_cast(TL.getSizeExpr()); - if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) - return false; + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + if (TInfo) { + ConstantArrayTypeLoc TL = + cast(TInfo->getTypeLoc()); + const Expr *SizeExpr = dyn_cast(TL.getSizeExpr()); + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + } + const RecordDecl *RD = dyn_cast(FD->getDeclContext()); if (!RD) return false; if (RD->isUnion()) return false; Index: lib/Sema/SemaExprObjC.cpp =================================================================== --- lib/Sema/SemaExprObjC.cpp (revision 152265) +++ lib/Sema/SemaExprObjC.cpp (working copy) @@ -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(IF)) { @@ -143,41 +143,70 @@ /// \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 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]; 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); + if (S.getLangOptions().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. + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId, + Loc, Sema::LookupOrdinaryName); + S.NSNumberDecl = dyn_cast_or_null(IF); + if (!S.NSNumberDecl || !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.getLangOptions().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()); } @@ -202,29 +231,9 @@ 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(IF); - - if (!NSNumberDecl && getLangOptions().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(Number)) { @@ -249,29 +258,29 @@ } } - 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()); - + SourceRange NR(Number->getSourceRange()); + ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType, + true, NR); 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, - AA_Sending); + ParmVarDecl *ParamDecl = Method->param_begin()[0]; + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + ParamDecl); + ExprResult ConvertedNumber = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Number)); if (ConvertedNumber.isInvalid()) return ExprError(); Number = ConvertedNumber.get(); + // Use the effective source range of the literal, including the leading '@'. return MaybeBindToTemporary( - new (Context) ObjCNumericLiteral(Number, Ty, Method, AtLoc)); + new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method, + SourceRange(AtLoc, NR.getEnd()))); } ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, @@ -385,6 +394,154 @@ 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()); + if (const PointerType *PT = ValueType->getAs()) { + QualType PointeeType = PT->getPointeeType(); + if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) { + IdentifierInfo *NSStringId = + NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); + if (getLangOptions().DebuggerObjCLiteral) { + // Support boxed expressions in the debugger w/o NSString declaration. + NSStringDecl = ObjCInterfaceDecl::Create(Context, + Context.getTranslationUnitDecl(), + SourceLocation(), NSStringId, + 0, SourceLocation()); + } + else { + NamedDecl *Decl = LookupSingleName(TUScope, NSStringId, + SR.getBegin(), LookupOrdinaryName); + NSStringDecl = dyn_cast_or_null(Decl); + + if (!NSStringDecl || !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 && getLangOptions().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()); + StringWithUTF8StringMethod = M; + } + assert(StringWithUTF8StringMethod && + "StringWithUTF8StringMethod should not be NULL"); + } + + BoxingMethod = StringWithUTF8StringMethod; + BoxedType = NSStringPointer; + } + } else if (ValueType->isBuiltinType()) { + // 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 + // for more details. + + // Check for a top-level character literal. + if (const CharacterLiteral *Char = + dyn_cast(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; + + } else if (const EnumType *ET = ValueType->getAs()) { + if (!ET->getDecl()->isComplete()) { + Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type) + << ValueType << ValueExpr->getSourceRange(); + return ExprError(); + } + + BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), + ET->getDecl()->getIntegerType()); + 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. + ParmVarDecl *ParamDecl = BoxingMethod->param_begin()[0]; + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + ParamDecl); + ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(ValueExpr)); + 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, @@ -417,21 +574,22 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { // Look up the NSArray class, if we haven't done so already. if (!NSArrayDecl) { - NamedDecl *IF = LookupSingleName(TUScope, - NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), - SR.getBegin(), - LookupOrdinaryName); - NSArrayDecl = dyn_cast_or_null(IF); - if (!NSArrayDecl && getLangOptions().DebuggerObjCLiteral) + if (getLangOptions().DebuggerObjCLiteral) { NSArrayDecl = ObjCInterfaceDecl::Create (Context, Context.getTranslationUnitDecl(), SourceLocation(), NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), 0, SourceLocation()); - - if (!NSArrayDecl) { - Diag(SR.getBegin(), diag::err_undeclared_nsarray); - return ExprError(); + } else { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), + SR.getBegin(), + LookupOrdinaryName); + NSArrayDecl = dyn_cast_or_null(IF); + if (!NSArrayDecl) { + Diag(SR.getBegin(), diag::err_undeclared_nsarray); + return ExprError(); + } } } Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp (revision 152265) +++ lib/Sema/Sema.cpp (working copy) @@ -90,7 +90,9 @@ PackContext(0), MSStructPragmaOn(false), VisContext(0), ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0), IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0), - NSNumberDecl(0), NSArrayDecl(0), ArrayWithObjectsMethod(0), + NSNumberDecl(0), + NSStringDecl(0), StringWithUTF8StringMethod(0), + NSArrayDecl(0), ArrayWithObjectsMethod(0), NSDictionaryDecl(0), DictionaryWithObjectsMethod(0), GlobalNewDeleteDeclared(false), ObjCShouldCallSuperDealloc(false), Index: lib/AST/DeclObjC.cpp =================================================================== --- lib/AST/DeclObjC.cpp (revision 152265) +++ lib/AST/DeclObjC.cpp (working copy) @@ -330,6 +330,10 @@ LoadExternalDefinition(); while (ClassDecl != NULL) { + // FIXME: Should make sure no callers ever do this. + if (!ClassDecl->hasDefinition()) + return 0; + if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp (revision 152265) +++ lib/AST/ASTImporter.cpp (working copy) @@ -119,7 +119,8 @@ bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl &ToArgs); - bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord); + bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, + bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); @@ -201,12 +202,16 @@ /// \brief Whether we're being strict about the spelling of types when /// unifying two types. bool StrictTypeSpelling; - + + /// \brief Whether to complain about failures. + bool Complain; + StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2, llvm::DenseSet > &NonEquivalentDecls, - bool StrictTypeSpelling = false) + bool StrictTypeSpelling = false, + bool Complain = true) : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling) { } + StrictTypeSpelling(StrictTypeSpelling), Complain(Complain) { } /// \brief Determine whether the two declarations are structurally /// equivalent. @@ -223,10 +228,16 @@ public: DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) { + if (!Complain) + return DiagnosticBuilder(DiagnosticBuilder::Suppress); + return C1.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) { + if (!Complain) + return DiagnosticBuilder(DiagnosticBuilder::Suppress); + return C2.getDiagnostics().Report(Loc, DiagID); } }; @@ -2050,10 +2061,12 @@ } bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, - RecordDecl *ToRecord) { + RecordDecl *ToRecord, + bool Complain) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); + Importer.getNonEquivalentDecls(), + false, Complain); return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); } @@ -2333,7 +2346,7 @@ // We may already have a record of the same name; try to find and match it. RecordDecl *AdoptDecl = 0; - if (!DC->isFunctionOrMethod() && SearchName) { + if (!DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; llvm::SmallVector FoundDecls; DC->localUncachedLookup(SearchName, FoundDecls); @@ -2349,26 +2362,32 @@ if (RecordDecl *FoundRecord = dyn_cast(Found)) { if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { - if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { + if ((SearchName && !D->isCompleteDefinition()) || + (D->isCompleteDefinition() && + D->isAnonymousStructOrUnion() + == FoundDef->isAnonymousStructOrUnion() && + IsStructuralMatch(D, FoundDef, SearchName))) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. // FIXME: For C++, we should also merge methods here. return Importer.Imported(D, FoundDef); } - } else { + } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward // declaration rather than building a new one. AdoptDecl = FoundRecord; continue; - } + } else if (!SearchName) { + continue; + } } ConflictingDecls.push_back(FoundDecls[I]); } - if (!ConflictingDecls.empty()) { - Name = Importer.HandleNameConflict(Name, DC, IDNS, + if (!ConflictingDecls.empty() && SearchName) { + Name = Importer.HandleNameConflict(SearchName, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); } @@ -2393,6 +2412,8 @@ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); + if (D->isAnonymousStructOrUnion()) + D2->setAnonymousStructOrUnion(true); } Importer.Imported(D, D2); @@ -2631,12 +2652,17 @@ DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (FieldDecl *FoundField = dyn_cast(FoundDecls[I])) { - if (Importer.IsStructurallyEquivalent(D->getType(), - FoundField->getType())) { + if (Importer.IsStructurallyEquivalent(D->getType(), + FoundField->getType(), + Name)) { Importer.Imported(D, FoundField); return FoundField; } - + + // If there are more anonymous fields to check, continue. + if (!Name && I < N-1) + continue; + Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) @@ -4662,12 +4688,14 @@ return To; } -bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) { +bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, + bool Complain) { llvm::DenseMap::iterator Pos = ImportedTypes.find(From.getTypePtr()); if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To)) return true; - StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls); + StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, + false, Complain); return Ctx.IsStructurallyEquivalent(From, To); } Index: lib/AST/NSAPI.cpp =================================================================== --- lib/AST/NSAPI.cpp (revision 152265) +++ lib/AST/NSAPI.cpp (working copy) @@ -13,7 +13,7 @@ using namespace clang; NSAPI::NSAPI(ASTContext &ctx) - : Ctx(ctx), ClassIds() { + : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0) { } IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { @@ -250,11 +250,22 @@ } llvm::Optional -NSAPI::getNSNumberFactoryMethodKind(QualType T) { +NSAPI::getNSNumberFactoryMethodKind(QualType T) const { const BuiltinType *BT = T->getAs(); if (!BT) return llvm::Optional(); - + + const TypedefType *TDT = T->getAs(); + if (TDT) { + QualType TDTTy = QualType(TDT, 0); + if (isObjCBOOLType(TDTTy)) + return NSAPI::NSNumberWithBool; + if (isObjCNSIntegerType(TDTTy)) + return NSAPI::NSNumberWithInteger; + if (isObjCNSUIntegerType(TDTTy)) + return NSAPI::NSNumberWithUnsignedInteger; + } + switch (BT->getKind()) { case BuiltinType::Char_S: case BuiltinType::SChar: @@ -309,3 +320,35 @@ return llvm::Optional(); } + +/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. +bool NSAPI::isObjCBOOLType(QualType T) const { + return isObjCTypedef(T, "BOOL", BOOLId); +} +/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. +bool NSAPI::isObjCNSIntegerType(QualType T) const { + return isObjCTypedef(T, "NSInteger", NSIntegerId); +} +/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. +bool NSAPI::isObjCNSUIntegerType(QualType T) const { + return isObjCTypedef(T, "NSUInteger", NSUIntegerId); +} + +bool NSAPI::isObjCTypedef(QualType T, + StringRef name, IdentifierInfo *&II) const { + if (!Ctx.getLangOptions().ObjC1) + return false; + if (T.isNull()) + return false; + + if (!II) + II = &Ctx.Idents.get(name); + + while (const TypedefType *TDT = T->getAs()) { + if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II) + return true; + T = TDT->desugar(); + } + + return false; +} Index: lib/AST/DeclPrinter.cpp =================================================================== --- lib/AST/DeclPrinter.cpp (revision 152265) +++ lib/AST/DeclPrinter.cpp (working copy) @@ -114,6 +114,8 @@ BaseType = FTy->getResultType(); else if (const VectorType *VTy = BaseType->getAs()) BaseType = VTy->getElementType(); + else if (const ReferenceType *RTy = BaseType->getAs()) + BaseType = RTy->getPointeeType(); else llvm_unreachable("Unknown declarator!"); } Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp (revision 152265) +++ lib/AST/Type.cpp (working copy) @@ -288,6 +288,28 @@ return T; } +/// \brief This will check for a TypedefType by removing any existing sugar +/// until it reaches a TypedefType or a non-sugared type. +template <> const TypedefType *Type::getAs() const { + const Type *Cur = this; + + while (true) { + if (const TypedefType *TDT = dyn_cast(Cur)) + return TDT; + switch (Cur->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Parent) +#define TYPE(Class, Parent) \ + case Class: { \ + const Class##Type *Ty = cast(Cur); \ + if (!Ty->isSugared()) return 0; \ + Cur = Ty->desugar().getTypePtr(); \ + break; \ + } +#include "clang/AST/TypeNodes.def" + } + } +} + /// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic /// sugar off the given type. This should produce an object of the /// same dynamic type as the canonical type. Index: lib/AST/RecordLayoutBuilder.cpp =================================================================== --- lib/AST/RecordLayoutBuilder.cpp (revision 152265) +++ lib/AST/RecordLayoutBuilder.cpp (working copy) @@ -2313,6 +2313,8 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const { // Retrieve the definition + if (D->hasExternalLexicalStorage() && !D->getDefinition()) + getExternalSource()->CompleteType(const_cast(D)); D = D->getDefinition(); assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!"); Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp (revision 152265) +++ lib/AST/ExprConstant.cpp (working copy) @@ -3054,7 +3054,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); } @@ -4210,7 +4210,7 @@ /// character of a string literal. template static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) { - const Expr *E = LV.getLValueBase().dyn_cast(); + const Expr *E = LV.getLValueBase().template dyn_cast(); return E && isa(E) && LV.getLValueOffset().isZero(); } @@ -6259,7 +6259,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: Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp (revision 152265) +++ lib/AST/ItaniumMangle.cpp (working copy) @@ -2374,7 +2374,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: Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp (revision 152265) +++ lib/AST/StmtPrinter.cpp (working copy) @@ -1679,9 +1679,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) { Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp (revision 152265) +++ lib/AST/DeclBase.cpp (working copy) @@ -1153,14 +1153,14 @@ // If there's no external storage, just perform a normal lookup and copy // the results. - if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage()) { + if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) { lookup_result LookupResults = lookup(Name); Results.insert(Results.end(), LookupResults.first, LookupResults.second); return; } // If we have a lookup table, check there first. Maybe we'll get lucky. - if (LookupPtr) { + if (LookupPtr && Name) { StoredDeclsMap::iterator Pos = LookupPtr->find(Name); if (Pos != LookupPtr->end()) { Results.insert(Results.end(), Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp (revision 152265) +++ lib/AST/StmtProfile.cpp (working copy) @@ -982,7 +982,7 @@ VisitExpr(S); } -void StmtProfiler::VisitObjCNumericLiteral(const ObjCNumericLiteral *E) { +void StmtProfiler::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { VisitExpr(E); } Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp (revision 152265) +++ lib/AST/Expr.cpp (working copy) @@ -2100,7 +2100,7 @@ case ObjCArrayLiteralClass: case ObjCBoolLiteralExprClass: case ObjCDictionaryLiteralClass: - case ObjCNumericLiteralClass: + case ObjCBoxedExprClass: return CT_Can; // Many other things have subexpressions, so we have to test those. Index: lib/AST/ExprClassification.cpp =================================================================== --- lib/AST/ExprClassification.cpp (revision 152265) +++ lib/AST/ExprClassification.cpp (working copy) @@ -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: Index: lib/Lex/PPMacroExpansion.cpp =================================================================== --- lib/Lex/PPMacroExpansion.cpp (revision 152265) +++ lib/Lex/PPMacroExpansion.cpp (working copy) @@ -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) Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp (revision 152265) +++ lib/StaticAnalyzer/Core/ExprEngine.cpp (working copy) @@ -590,7 +590,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: Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp (revision 152265) +++ lib/CodeGen/CGExprScalar.cpp (working copy) @@ -531,8 +531,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); Index: lib/CodeGen/CGObjC.cpp =================================================================== --- lib/CodeGen/CGObjC.cpp (revision 152265) +++ lib/CodeGen/CGObjC.cpp (working copy) @@ -51,35 +51,36 @@ return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); } -/// EmitObjCNumericLiteral - This routine generates code for -/// the appropriate +[NSNumber numberWith:] method. +/// EmitObjCBoxedExpr - This routine generates code to call +/// the appropriate expression boxing method. This will either be +/// one of +[NSNumber numberWith:], or +[NSString stringWithUTF8String:]. /// -llvm::Value *CodeGenFunction::EmitObjCNumericLiteral(const ObjCNumericLiteral *E) { +llvm::Value * +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())); } Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp (revision 152265) +++ lib/CodeGen/CodeGenTypes.cpp (working copy) @@ -133,6 +133,14 @@ // when a class is translated, even though they aren't embedded by-value into // the class. if (const CXXRecordDecl *CRD = dyn_cast(RD)) { + if (!CRD->hasDefinition() && CRD->hasExternalLexicalStorage()) { + ExternalASTSource *EAS = CRD->getASTContext().getExternalSource(); + if (!EAS) + return false; + EAS->CompleteType(const_cast(CRD)); + if (!CRD->hasDefinition()) + return false; + } for (CXXRecordDecl::base_class_const_iterator I = CRD->bases_begin(), E = CRD->bases_end(); I != E; ++I) if (!isSafeToConvert(I->getType()->getAs()->getDecl(), Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h (revision 152265) +++ lib/CodeGen/CodeGenFunction.h (working copy) @@ -2238,7 +2238,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, Index: lib/Parse/ParseObjc.cpp =================================================================== --- lib/Parse/ParseObjc.cpp (revision 152265) +++ lib/Parse/ParseObjc.cpp (working copy) @@ -2067,6 +2067,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)); @@ -2581,6 +2585,31 @@ 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(); + + if (ValueExpr.isInvalid()) + 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. Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp (revision 152265) +++ lib/Serialization/ASTReaderStmt.cpp (working copy) @@ -823,12 +823,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(Record, Idx); - E->AtLoc = ReadSourceLocation(Record, Idx); + E->SubExpr = Reader.ReadSubStmt(); + E->BoxingMethod = ReadDeclAs(Record, Idx); + E->Range = ReadSourceRange(Record, Idx); } void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { @@ -1893,8 +1893,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, Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp (revision 152265) +++ lib/Serialization/ASTWriter.cpp (working copy) @@ -696,7 +696,7 @@ RECORD(EXPR_BLOCK_DECL_REF); 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); Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp (revision 152265) +++ lib/Serialization/ASTWriterStmt.cpp (working copy) @@ -783,12 +783,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) {