| 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<Expr>; |
| -def ObjCNumericLiteral : DStmt<Expr>; |
| +def ObjCBoxedExpr : DStmt<Expr>; |
| def ObjCArrayLiteral : DStmt<Expr>; |
| def ObjCDictionaryLiteral : DStmt<Expr>; |
| def ObjCEncodeExpr : DStmt<Expr>; |
| 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<TypedefType>(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<Expr>(Number); } |
| - const Expr *getNumber() const { return cast<Expr>(Number); } |
| + Expr *getSubExpr() { return cast<Expr>(SubExpr); } |
| + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } |
| |
| - ObjCMethodDecl *getObjCNumericLiteralMethod() const { |
| - return ObjCNumericLiteralMethod; |
| + ObjCMethodDecl *getBoxingMethod() const { |
| + return BoxingMethod; |
| } |
| - |
| - SourceLocation getAtLoc() const { return AtLoc; } |
| |
| + SourceLocation getAtLoc() const { return Range.getBegin(); } |
| + |
| SourceRange getSourceRange() const { |
| - 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<NSNumberLiteralMethodKind> |
| - getNSNumberFactoryMethodKind(QualType T); |
| + llvm::Optional<NSNumberLiteralMethodKind> |
| + 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 @@ |
| <li><a href="#objc_instancetype">Related result types</a></li> |
| <li><a href="#objc_arc">Automatic reference counting</a></li> |
| <li><a href="#objc_fixed_enum">Enumerations with a fixed underlying type</a></li> |
| - </ul> |
| + </ul> |
| </li> |
| <li><a href="#overloading-in-c">Function Overloading in C</a></li> |
| <li><a href="#complex-list-init">Initializer lists for complex numbers in C</a></li> |
| 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<unsigned>(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<Expr*, 4> MsgExprs; |
| + SmallVector<Expr*, 4> ClsExprs; |
| + QualType argType = Context->getPointerType(Context->CharTy); |
| + |
| + // Create a call to objc_getClass("<BoxingClass>"). 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("<BoxingMethod>:"), etc. |
| + // it will be the 2nd argument. |
| + SmallVector<Expr*, 4> 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<ImplicitCastExpr>(subExpr)) { |
| + QualType type = ICE->getType(); |
| + const Expr *SubExpr = ICE->IgnoreParenImpCasts(); |
| + CastKind CK = CK_BitCast; |
| + if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType()) |
| + CK = CK_IntegralToBoolean; |
| + subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr); |
| + } |
| + MsgExprs.push_back(subExpr); |
| + |
| + SmallVector<QualType, 4> 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<FunctionType>(); |
| + 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<Expr*, 16> InitExprs; |
| + unsigned NumElements = Exp->getNumElements(); |
| + unsigned UnsignedIntSize = |
| + static_cast<unsigned>(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<Expr*, 32> MsgExprs; |
| + SmallVector<Expr*, 4> 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<ObjCObjectType>()->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<Expr*, 4> 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<QualType, 4> 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<FunctionType>(); |
| + 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<Expr*, 16> KeyExprs; |
| + SmallVector<Expr*, 16> ValueExprs; |
| + |
| + unsigned NumElements = Exp->getNumElements(); |
| + unsigned UnsignedIntSize = |
| + static_cast<unsigned>(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 <NSCopying> [])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<Expr*, 32> MsgExprs; |
| + SmallVector<Expr*, 4> 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<ObjCObjectType>()->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<Expr*, 4> 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 <NSCopying> [])keys |
| + MsgExprs.push_back(DictKeyObjects); |
| + |
| + // (NSUInteger)cnt |
| + Expr *cnt = IntegerLiteral::Create(*Context, |
| + llvm::APInt(UnsignedIntSize, NumElements), |
| + Context->UnsignedIntTy, SourceLocation()); |
| + MsgExprs.push_back(cnt); |
| + |
| + |
| + SmallVector<QualType, 8> 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<PointerType>()) { |
| + 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<FunctionType>(); |
| + 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<ObjCStringLiteral>(S)) |
| return RewriteObjCStringLiteral(AtString); |
| + |
| + if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S)) |
| + return RewriteObjCBoolLiteralExpr(BoolLitExpr); |
| + |
| + if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S)) |
| + return RewriteObjCBoxedExpr(BoxedExpr); |
| + |
| + if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S)) |
| + return RewriteObjCArrayLiteralExpr(ArrayLitExpr); |
| + |
| + if (ObjCDictionaryLiteral *DictionaryLitExpr = |
| + dyn_cast<ObjCDictionaryLiteral>(S)) |
| + return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr); |
| |
| if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(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<typename Derived> |
| ExprResult |
| -TreeTransform<Derived>::TransformObjCNumericLiteral(ObjCNumericLiteral *E) { |
| - return SemaRef.MaybeBindToTemporary(E); |
| +TreeTransform<Derived>::TransformObjCBoxedExpr(ObjCBoxedExpr *E) { |
| + ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); |
| + if (SubExpr.isInvalid()) |
| + return ExprError(); |
| + |
| + if (!getDerived().AlwaysRebuild() && |
| + SubExpr.get() == E->getSubExpr()) |
| + return SemaRef.Owned(E); |
| + |
| + return getDerived().RebuildObjCBoxedExpr(E->getSourceRange(), SubExpr.get()); |
| } |
| |
| template<typename Derived> |
| 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<ObjCMessageExpr>(E)) { |
| D = Send->getMethodDecl(); |
| - } else if (ObjCNumericLiteral *NumLit = dyn_cast<ObjCNumericLiteral>(E)) { |
| - D = NumLit->getObjCNumericLiteralMethod(); |
| + } else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) { |
| + D = BoxedExpr->getBoxingMethod(); |
| } else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) { |
| D = ArrayLit->getArrayWithObjectsMethod(); |
| } else if (ObjCDictionaryLiteral *DictLit |
| @@ -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<ConstantArrayTypeLoc>(FD->getTypeSourceInfo()->getTypeLoc()); |
| - const Expr *SizeExpr = dyn_cast<IntegerLiteral>(TL.getSizeExpr()); |
| - if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) |
| - return false; |
| |
| + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); |
| + if (TInfo) { |
| + ConstantArrayTypeLoc TL = |
| + cast<ConstantArrayTypeLoc>(TInfo->getTypeLoc()); |
| + const Expr *SizeExpr = dyn_cast<IntegerLiteral>(TL.getSizeExpr()); |
| + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) |
| + return false; |
| + } |
| + |
| const RecordDecl *RD = dyn_cast<RecordDecl>(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<ObjCInterfaceDecl>(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<NSAPI::NSNumberLiteralMethodKind> Kind |
| - = S.NSAPIObj->getNSNumberFactoryMethodKind(T); |
| + = S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType); |
| |
| if (!Kind) { |
| - S.Diag(Loc, diag::err_invalid_nsnumber_type) |
| - << T << Range; |
| + if (isLiteral) { |
| + S.Diag(Loc, diag::err_invalid_nsnumber_type) |
| + << NumberType << R; |
| + } |
| return 0; |
| } |
| - |
| + |
| // If we already looked up this method, we're done. |
| if (S.NSNumberLiteralMethods[*Kind]) |
| return S.NSNumberLiteralMethods[*Kind]; |
| |
| 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<ObjCInterfaceDecl>(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<SourceLocation>()); |
| } |
| |
| @@ -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<ObjCInterfaceDecl>(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<CharacterLiteral>(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<PointerType>()) { |
| + 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<ObjCInterfaceDecl>(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<SourceLocation>()); |
| + 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 <Foundation/NSGeometry.h> |
| + // for more details. |
| + |
| + // Check for a top-level character literal. |
| + if (const CharacterLiteral *Char = |
| + dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) { |
| + // In C, character literals have type 'int'. That's not the type we want |
| + // to use to determine the Objective-c literal kind. |
| + switch (Char->getKind()) { |
| + case CharacterLiteral::Ascii: |
| + ValueType = Context.CharTy; |
| + break; |
| + |
| + case CharacterLiteral::Wide: |
| + ValueType = Context.getWCharType(); |
| + break; |
| + |
| + case CharacterLiteral::UTF16: |
| + ValueType = Context.Char16Ty; |
| + break; |
| + |
| + case CharacterLiteral::UTF32: |
| + ValueType = Context.Char32Ty; |
| + break; |
| + } |
| + } |
| + |
| + // FIXME: Do I need to do anything special with BoolTy expressions? |
| + |
| + // Look for the appropriate method within NSNumber. |
| + BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType); |
| + BoxedType = NSNumberPointer; |
| + |
| + } else if (const EnumType *ET = ValueType->getAs<EnumType>()) { |
| + 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<ObjCInterfaceDecl>(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<ObjCInterfaceDecl>(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<TemplateArgument> &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<std::pair<Decl *, Decl *> > &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<NamedDecl *, 4> ConflictingDecls; |
| llvm::SmallVector<NamedDecl *, 2> FoundDecls; |
| DC->localUncachedLookup(SearchName, FoundDecls); |
| @@ -2349,26 +2362,32 @@ |
| |
| if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(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<FieldDecl>(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<const Type *, const Type *>::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::NSNumberLiteralMethodKind> |
| -NSAPI::getNSNumberFactoryMethodKind(QualType T) { |
| +NSAPI::getNSNumberFactoryMethodKind(QualType T) const { |
| const BuiltinType *BT = T->getAs<BuiltinType>(); |
| if (!BT) |
| return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); |
| - |
| + |
| + const TypedefType *TDT = T->getAs<TypedefType>(); |
| + 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<NSAPI::NSNumberLiteralMethodKind>(); |
| } |
| + |
| +/// \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<TypedefType>()) { |
| + 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<VectorType>()) |
| BaseType = VTy->getElementType(); |
| + else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) |
| + 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<TypedefType>(Cur)) |
| + return TDT; |
| + switch (Cur->getTypeClass()) { |
| +#define ABSTRACT_TYPE(Class, Parent) |
| +#define TYPE(Class, Parent) \ |
| + case Class: { \ |
| + const Class##Type *Ty = cast<Class##Type>(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<ObjCInterfaceDecl*>(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<typename LValue> |
| static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) { |
| - const Expr *E = LV.getLValueBase().dyn_cast<const Expr*>(); |
| + const Expr *E = LV.getLValueBase().template dyn_cast<const Expr*>(); |
| return E && isa<StringLiteral>(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<Type>:] method. |
| +/// EmitObjCBoxedExpr - This routine generates code to call |
| +/// the appropriate expression boxing method. This will either be |
| +/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:]. |
| /// |
| -llvm::Value *CodeGenFunction::EmitObjCNumericLiteral(const ObjCNumericLiteral *E) { |
| +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<CXXRecordDecl>(RD)) { |
| + if (!CRD->hasDefinition() && CRD->hasExternalLexicalStorage()) { |
| + ExternalASTSource *EAS = CRD->getASTContext().getExternalSource(); |
| + if (!EAS) |
| + return false; |
| + EAS->CompleteType(const_cast<CXXRecordDecl*>(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<RecordType>()->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<ObjCMethodDecl>(Record, Idx); |
| - E->AtLoc = ReadSourceLocation(Record, Idx); |
| + E->SubExpr = Reader.ReadSubStmt(); |
| + E->BoxingMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx); |
| + E->Range = ReadSourceRange(Record, Idx); |
| } |
| |
| void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { |
| @@ -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) { |