From 4407880666f657ba1535eec4408488c596f68842 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Thu, 17 May 2012 23:29:56 +0000 Subject: [PATCH] I have updated Clang to include support for Objective-C boxed expressions returning numbers and strings. I also added boxed expressions to our testcases, and enabled boxed expressions when libarclite is linked into the inferior. llvm-svn: 157026 --- lldb/scripts/clang.amalgamated.diff | 1723 ++++++++++++++++++++ .../clang.check-definition-for-superclasses.diff | 15 - .../scripts/clang.complete-type-getObjCLayout.diff | 13 - .../clang.complete-type-isSafeToConvert.diff | 19 - .../scripts/clang.decl-printer-reference-type.diff | 13 - lldb/scripts/clang.tail-padded-arrays.diff | 26 - lldb/scripts/clang.template-keyword-fixes.diff | 13 - .../ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp | 4 +- .../lang/objc/objc-new-syntax/TestObjCNewSyntax.py | 14 +- 9 files changed, 1735 insertions(+), 105 deletions(-) create mode 100644 lldb/scripts/clang.amalgamated.diff delete mode 100644 lldb/scripts/clang.check-definition-for-superclasses.diff delete mode 100644 lldb/scripts/clang.complete-type-getObjCLayout.diff delete mode 100644 lldb/scripts/clang.complete-type-isSafeToConvert.diff delete mode 100644 lldb/scripts/clang.decl-printer-reference-type.diff delete mode 100644 lldb/scripts/clang.tail-padded-arrays.diff delete mode 100644 lldb/scripts/clang.template-keyword-fixes.diff diff --git a/lldb/scripts/clang.amalgamated.diff b/lldb/scripts/clang.amalgamated.diff new file mode 100644 index 0000000..b42cdac --- /dev/null +++ b/lldb/scripts/clang.amalgamated.diff @@ -0,0 +1,1723 @@ +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/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 +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/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/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) { diff --git a/lldb/scripts/clang.check-definition-for-superclasses.diff b/lldb/scripts/clang.check-definition-for-superclasses.diff deleted file mode 100644 index 566c518..0000000 --- a/lldb/scripts/clang.check-definition-for-superclasses.diff +++ /dev/null @@ -1,15 +0,0 @@ -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; - diff --git a/lldb/scripts/clang.complete-type-getObjCLayout.diff b/lldb/scripts/clang.complete-type-getObjCLayout.diff deleted file mode 100644 index 2360957..0000000 --- a/lldb/scripts/clang.complete-type-getObjCLayout.diff +++ /dev/null @@ -1,13 +0,0 @@ -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!"); - diff --git a/lldb/scripts/clang.complete-type-isSafeToConvert.diff b/lldb/scripts/clang.complete-type-isSafeToConvert.diff deleted file mode 100644 index b874e42..0000000 --- a/lldb/scripts/clang.complete-type-isSafeToConvert.diff +++ /dev/null @@ -1,19 +0,0 @@ -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(), diff --git a/lldb/scripts/clang.decl-printer-reference-type.diff b/lldb/scripts/clang.decl-printer-reference-type.diff deleted file mode 100644 index b0150fe..0000000 --- a/lldb/scripts/clang.decl-printer-reference-type.diff +++ /dev/null @@ -1,13 +0,0 @@ -Index: lib/AST/DeclPrinter.cpp -=================================================================== ---- lib/AST/DeclPrinter.cpp (revision 152772) -+++ 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!"); - } diff --git a/lldb/scripts/clang.tail-padded-arrays.diff b/lldb/scripts/clang.tail-padded-arrays.diff deleted file mode 100644 index 504d4f0..0000000 --- a/lldb/scripts/clang.tail-padded-arrays.diff +++ /dev/null @@ -1,26 +0,0 @@ -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; diff --git a/lldb/scripts/clang.template-keyword-fixes.diff b/lldb/scripts/clang.template-keyword-fixes.diff deleted file mode 100644 index dbba709..0000000 --- a/lldb/scripts/clang.template-keyword-fixes.diff +++ /dev/null @@ -1,13 +0,0 @@ -Index: lib/AST/ExprConstant.cpp -=================================================================== ---- lib/AST/ExprConstant.cpp (revision 152265) -+++ lib/AST/ExprConstant.cpp (working copy) -@@ -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(); - } - diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index b536b214..1840a07de 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -350,10 +350,12 @@ AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing() Target &target(m_process->GetTarget()); static ConstString s_method_signature("-[NSDictionary objectForKeyedSubscript:]"); + static ConstString s_arclite_method_signature("__arclite_objectForKeyedSubscript"); SymbolContextList sc_list; - if (target.GetImages().FindSymbolsWithNameAndType(s_method_signature, eSymbolTypeCode, sc_list)) + if (target.GetImages().FindSymbolsWithNameAndType(s_method_signature, eSymbolTypeCode, sc_list) || + target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature, eSymbolTypeCode, sc_list)) return true; else return false; diff --git a/lldb/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py b/lldb/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py index 0ce8481..c8fa09a 100644 --- a/lldb/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py +++ b/lldb/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py @@ -112,11 +112,15 @@ class ObjCNewSyntaxTestCase(TestBase): self.expect("expr -o -- @1ull", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["NSNumber", "1"]) - # - #self.expect("expr -o -- @123.45", VARIABLES_DISPLAYED_CORRECTLY, - # substrs = ["NSNumber", "123.45"]) - #self.expect("expr -o -- @123.45f", VARIABLES_DISPLAYED_CORRECTLY, - # substrs = ["NSNumber", "123.45"]) + self.expect("expr -o -- @123.45", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["NSNumber", "123.45"]) + self.expect("expr -o -- @123.45f", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["NSNumber", "123.45"]) + + self.expect("expr -o -- @( 1 + 3 )", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["NSNumber", "4"]) + self.expect("expr -o -- @(\"Hello world\" + 6)", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["NSString", "@\"world\""]) if __name__ == '__main__': -- 2.7.4