diff options
Diffstat (limited to 'clang/lib/Sema/SemaExprObjC.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 197 |
1 files changed, 98 insertions, 99 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 6cd06262195..904a7d5d447 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -168,6 +168,76 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc, return true; } +/// \brief Maps ObjCLiteralKind to NSClassIdKindKind +static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind( + Sema::ObjCLiteralKind LiteralKind) { + switch (LiteralKind) { + case Sema::LK_Array: + return NSAPI::ClassId_NSArray; + case Sema::LK_Dictionary: + return NSAPI::ClassId_NSDictionary; + case Sema::LK_Numeric: + return NSAPI::ClassId_NSNumber; + case Sema::LK_String: + return NSAPI::ClassId_NSString; + case Sema::LK_Boxed: + return NSAPI::ClassId_NSValue; + + // there is no corresponding matching + // between LK_None/LK_Block and NSClassIdKindKind + case Sema::LK_Block: + case Sema::LK_None: + llvm_unreachable("LiteralKind can't be converted into a ClassKind"); + } +} + +/// \brief Validates ObjCInterfaceDecl availability. +/// ObjCInterfaceDecl, used to create ObjC literals, should be defined +/// if clang not in a debugger mode. +static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl, + SourceLocation Loc, + Sema::ObjCLiteralKind LiteralKind) { + if (!Decl) { + NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind); + IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind); + S.Diag(Loc, diag::err_undeclared_objc_literal_class) + << II->getName() << LiteralKind; + return false; + } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) { + S.Diag(Loc, diag::err_undeclared_objc_literal_class) + << Decl->getName() << LiteralKind; + S.Diag(Decl->getLocation(), diag::note_forward_class); + return false; + } + + return true; +} + +/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind. +/// Used to create ObjC literals, such as NSDictionary (@{}), +/// NSArray (@[]) and Boxed Expressions (@()) +static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S, + SourceLocation Loc, + Sema::ObjCLiteralKind LiteralKind) { + NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind); + IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind); + NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc, + Sema::LookupOrdinaryName); + ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!ID && S.getLangOpts().DebuggerObjCLiteral) { + ASTContext &Context = S.Context; + TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II, + nullptr, nullptr, SourceLocation()); + } + + if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) { + ID = nullptr; + } + + return ID; +} + /// \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, @@ -197,26 +267,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, // Look up the NSNumber class, if we haven't done so already. It's cached // in the Sema instance. if (!S.NSNumberDecl) { - IdentifierInfo *NSNumberId = - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber); - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId, - Loc, Sema::LookupOrdinaryName); - S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc, + Sema::LK_Numeric); if (!S.NSNumberDecl) { - if (S.getLangOpts().DebuggerObjCLiteral) { - // Create a stub definition of NSNumber. - S.NSNumberDecl = ObjCInterfaceDecl::Create(CX, - CX.getTranslationUnitDecl(), - SourceLocation(), NSNumberId, - nullptr, nullptr, - SourceLocation()); - } else { - // Otherwise, require a declaration of NSNumber. - S.Diag(Loc, diag::err_undeclared_nsnumber); - return nullptr; - } - } else if (!S.NSNumberDecl->hasDefinition()) { - S.Diag(Loc, diag::err_undeclared_nsnumber); return nullptr; } } @@ -457,6 +510,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { if (RValue.isInvalid()) { return ExprError(); } + SourceLocation Loc = SR.getBegin(); ValueExpr = RValue.get(); QualType ValueType(ValueExpr->getType()); if (const PointerType *PT = ValueType->getAs<PointerType>()) { @@ -464,29 +518,11 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) { if (!NSStringDecl) { - IdentifierInfo *NSStringId = - NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); - NamedDecl *Decl = LookupSingleName(TUScope, NSStringId, - SR.getBegin(), LookupOrdinaryName); - NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl); + NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_String); if (!NSStringDecl) { - if (getLangOpts().DebuggerObjCLiteral) { - // Support boxed expressions in the debugger w/o NSString declaration. - DeclContext *TU = Context.getTranslationUnitDecl(); - NSStringDecl = ObjCInterfaceDecl::Create(Context, TU, - SourceLocation(), - NSStringId, - nullptr, nullptr, - SourceLocation()); - } else { - Diag(SR.getBegin(), diag::err_undeclared_nsstring); - return ExprError(); - } - } else if (!NSStringDecl->hasDefinition()) { - Diag(SR.getBegin(), diag::err_undeclared_nsstring); return ExprError(); } - assert(NSStringDecl && "NSStringDecl should not be NULL"); QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl); NSStringPointer = Context.getObjCObjectPointerType(NSStringObject); } @@ -520,7 +556,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = M; } - if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl, + if (!validateBoxingMethod(*this, Loc, NSStringDecl, stringWithUTF8String, BoxingMethod)) return ExprError(); @@ -563,16 +599,16 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // FIXME: Do I need to do anything special with BoolTy expressions? // Look for the appropriate method within NSNumber. - BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType); + BoxingMethod = getNSNumberFactoryMethod(*this, Loc, 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) + Diag(Loc, diag::err_objc_incomplete_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } - BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), + BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ET->getDecl()->getIntegerType()); BoxedType = NSNumberPointer; } else if (ValueType->isObjCBoxableRecordType()) { @@ -582,29 +618,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // Look up the NSValue class, if we haven't done so already. It's cached // in the Sema instance. if (!NSValueDecl) { - IdentifierInfo *NSValueId = - NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue); - NamedDecl *IF = LookupSingleName(TUScope, NSValueId, - SR.getBegin(), Sema::LookupOrdinaryName); - NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_Boxed); if (!NSValueDecl) { - if (getLangOpts().DebuggerObjCLiteral) { - // Create a stub definition of NSValue. - DeclContext *TU = Context.getTranslationUnitDecl(); - NSValueDecl = ObjCInterfaceDecl::Create(Context, TU, - SourceLocation(), NSValueId, - nullptr, nullptr, - SourceLocation()); - } else { - // Otherwise, require a declaration of NSValue. - Diag(SR.getBegin(), diag::err_undeclared_nsvalue); - return ExprError(); - } - } else if (!NSValueDecl->hasDefinition()) { - Diag(SR.getBegin(), diag::err_undeclared_nsvalue); return ExprError(); } - + // generate the pointer to NSValue type. QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl); NSValuePointer = Context.getObjCObjectPointerType(NSValueObject); @@ -663,7 +682,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = M; } - if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl, + if (!validateBoxingMethod(*this, Loc, NSValueDecl, ValueWithBytesObjCType, BoxingMethod)) return ExprError(); @@ -671,8 +690,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { } if (!ValueType.isTriviallyCopyableType(Context)) { - Diag(SR.getBegin(), - diag::err_objc_non_trivially_copyable_boxed_expression_type) + Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } @@ -682,12 +700,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { } if (!BoxingMethod) { - Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type) + Diag(Loc, diag::err_objc_illegal_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } - DiagnoseUseOfDecl(BoxingMethod, SR.getBegin()); + DiagnoseUseOfDecl(BoxingMethod, Loc); ExprResult ConvertedValueExpr; if (ValueType->isObjCBoxableRecordType()) { @@ -746,26 +764,16 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, } 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 && getLangOpts().DebuggerObjCLiteral) - NSArrayDecl = ObjCInterfaceDecl::Create (Context, - Context.getTranslationUnitDecl(), - SourceLocation(), - NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), - nullptr, nullptr, SourceLocation()); + SourceLocation Loc = SR.getBegin(); + if (!NSArrayDecl) { + NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_Array); if (!NSArrayDecl) { - Diag(SR.getBegin(), diag::err_undeclared_nsarray); return ExprError(); } } - + // Find the arrayWithObjects:count: method, if we haven't done so already. QualType IdT = Context.getObjCIdType(); if (!ArrayWithObjectsMethod) { @@ -801,7 +809,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Method->setMethodParams(Context, Params, None); } - if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method)) + if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method)) return ExprError(); // Dig out the type that all elements should be converted to. @@ -862,25 +870,16 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, ObjCDictionaryElement *Elements, unsigned NumElements) { - // Look up the NSDictionary class, if we haven't done so already. - if (!NSDictionaryDecl) { - NamedDecl *IF = LookupSingleName(TUScope, - NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), - SR.getBegin(), LookupOrdinaryName); - NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); - if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral) - NSDictionaryDecl = ObjCInterfaceDecl::Create (Context, - Context.getTranslationUnitDecl(), - SourceLocation(), - NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), - nullptr, nullptr, SourceLocation()); + SourceLocation Loc = SR.getBegin(); + if (!NSDictionaryDecl) { + NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_Dictionary); if (!NSDictionaryDecl) { - Diag(SR.getBegin(), diag::err_undeclared_nsdictionary); - return ExprError(); + return ExprError(); } } - + // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done // so already. QualType IdT = Context.getObjCIdType(); |

