1193326Sed//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements semantic analysis for Objective-C expressions. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14212904Sdim#include "clang/Sema/SemaInternal.h" 15193326Sed#include "clang/AST/ASTContext.h" 16193326Sed#include "clang/AST/DeclObjC.h" 17193326Sed#include "clang/AST/ExprObjC.h" 18224145Sdim#include "clang/AST/StmtVisitor.h" 19207619Srdivacky#include "clang/AST/TypeLoc.h" 20249423Sdim#include "clang/Analysis/DomainSpecific/CocoaConventions.h" 21249423Sdim#include "clang/Edit/Commit.h" 22249423Sdim#include "clang/Edit/Rewriters.h" 23249423Sdim#include "clang/Lex/Preprocessor.h" 24249423Sdim#include "clang/Sema/Initialization.h" 25249423Sdim#include "clang/Sema/Lookup.h" 26249423Sdim#include "clang/Sema/Scope.h" 27249423Sdim#include "clang/Sema/ScopeInfo.h" 28193326Sed#include "llvm/ADT/SmallString.h" 29193326Sed 30193326Sedusing namespace clang; 31218893Sdimusing namespace sema; 32226633Sdimusing llvm::makeArrayRef; 33193326Sed 34212904SdimExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, 35212904Sdim Expr **strings, 36212904Sdim unsigned NumStrings) { 37193326Sed StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings); 38193326Sed 39193326Sed // Most ObjC strings are formed out of a single piece. However, we *can* 40193326Sed // have strings formed out of multiple @ strings with multiple pptokens in 41193326Sed // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one 42193326Sed // StringLiteral for ObjCStringLiteral to hold onto. 43193326Sed StringLiteral *S = Strings[0]; 44198092Srdivacky 45193326Sed // If we have a multi-part string, merge it all together. 46193326Sed if (NumStrings != 1) { 47193326Sed // Concatenate objc strings. 48234353Sdim SmallString<128> StrBuf; 49226633Sdim SmallVector<SourceLocation, 8> StrLocs; 50198092Srdivacky 51193326Sed for (unsigned i = 0; i != NumStrings; ++i) { 52193326Sed S = Strings[i]; 53198092Srdivacky 54226633Sdim // ObjC strings can't be wide or UTF. 55226633Sdim if (!S->isAscii()) { 56193326Sed Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) 57193326Sed << S->getSourceRange(); 58193326Sed return true; 59193326Sed } 60198092Srdivacky 61212904Sdim // Append the string. 62212904Sdim StrBuf += S->getString(); 63198092Srdivacky 64193326Sed // Get the locations of the string tokens. 65193326Sed StrLocs.append(S->tokloc_begin(), S->tokloc_end()); 66193326Sed } 67198092Srdivacky 68193326Sed // Create the aggregate string with the appropriate content and location 69193326Sed // information. 70224145Sdim S = StringLiteral::Create(Context, StrBuf, 71226633Sdim StringLiteral::Ascii, /*Pascal=*/false, 72193326Sed Context.getPointerType(Context.CharTy), 73193326Sed &StrLocs[0], StrLocs.size()); 74193326Sed } 75234353Sdim 76234353Sdim return BuildObjCStringLiteral(AtLocs[0], S); 77234353Sdim} 78198092Srdivacky 79234353SdimExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ 80193326Sed // Verify that this composite string is acceptable for ObjC strings. 81193326Sed if (CheckObjCString(S)) 82193326Sed return true; 83193326Sed 84193326Sed // Initialize the constant string interface lazily. This assumes 85193326Sed // the NSString interface is seen in this translation unit. Note: We 86193326Sed // don't use NSConstantString, since the runtime team considers this 87193326Sed // interface private (even though it appears in the header files). 88193326Sed QualType Ty = Context.getObjCConstantStringInterface(); 89193326Sed if (!Ty.isNull()) { 90198092Srdivacky Ty = Context.getObjCObjectPointerType(Ty); 91234353Sdim } else if (getLangOpts().NoConstantCFStrings) { 92218893Sdim IdentifierInfo *NSIdent=0; 93234353Sdim std::string StringClass(getLangOpts().ObjCConstantStringClass); 94218893Sdim 95218893Sdim if (StringClass.empty()) 96218893Sdim NSIdent = &Context.Idents.get("NSConstantString"); 97218893Sdim else 98218893Sdim NSIdent = &Context.Idents.get(StringClass); 99218893Sdim 100234353Sdim NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, 101207619Srdivacky LookupOrdinaryName); 102207619Srdivacky if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { 103207619Srdivacky Context.setObjCConstantStringInterface(StrIF); 104207619Srdivacky Ty = Context.getObjCConstantStringInterface(); 105207619Srdivacky Ty = Context.getObjCObjectPointerType(Ty); 106207619Srdivacky } else { 107207619Srdivacky // If there is no NSConstantString interface defined then treat this 108207619Srdivacky // as error and recover from it. 109207619Srdivacky Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent 110207619Srdivacky << S->getSourceRange(); 111207619Srdivacky Ty = Context.getObjCIdType(); 112207619Srdivacky } 113193326Sed } else { 114239462Sdim IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); 115234353Sdim NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, 116207619Srdivacky LookupOrdinaryName); 117193326Sed if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { 118193326Sed Context.setObjCConstantStringInterface(StrIF); 119193326Sed Ty = Context.getObjCConstantStringInterface(); 120198092Srdivacky Ty = Context.getObjCObjectPointerType(Ty); 121193326Sed } else { 122234353Sdim // If there is no NSString interface defined, implicitly declare 123234353Sdim // a @class NSString; and use that instead. This is to make sure 124234353Sdim // type of an NSString literal is represented correctly, instead of 125234353Sdim // being an 'id' type. 126234353Sdim Ty = Context.getObjCNSStringType(); 127234353Sdim if (Ty.isNull()) { 128234353Sdim ObjCInterfaceDecl *NSStringIDecl = 129234353Sdim ObjCInterfaceDecl::Create (Context, 130234353Sdim Context.getTranslationUnitDecl(), 131234353Sdim SourceLocation(), NSIdent, 132234353Sdim 0, SourceLocation()); 133234353Sdim Ty = Context.getObjCInterfaceType(NSStringIDecl); 134234353Sdim Context.setObjCNSStringType(Ty); 135234353Sdim } 136234353Sdim Ty = Context.getObjCObjectPointerType(Ty); 137193326Sed } 138193326Sed } 139198092Srdivacky 140234353Sdim return new (Context) ObjCStringLiteral(S, Ty, AtLoc); 141193326Sed} 142193326Sed 143239462Sdim/// \brief Emits an error if the given method does not exist, or if the return 144239462Sdim/// type is not an Objective-C object. 145239462Sdimstatic bool validateBoxingMethod(Sema &S, SourceLocation Loc, 146239462Sdim const ObjCInterfaceDecl *Class, 147239462Sdim Selector Sel, const ObjCMethodDecl *Method) { 148239462Sdim if (!Method) { 149239462Sdim // FIXME: Is there a better way to avoid quotes than using getName()? 150239462Sdim S.Diag(Loc, diag::err_undeclared_boxing_method) << Sel << Class->getName(); 151239462Sdim return false; 152239462Sdim } 153239462Sdim 154239462Sdim // Make sure the return type is reasonable. 155239462Sdim QualType ReturnType = Method->getResultType(); 156239462Sdim if (!ReturnType->isObjCObjectPointerType()) { 157239462Sdim S.Diag(Loc, diag::err_objc_literal_method_sig) 158239462Sdim << Sel; 159239462Sdim S.Diag(Method->getLocation(), diag::note_objc_literal_method_return) 160239462Sdim << ReturnType; 161239462Sdim return false; 162239462Sdim } 163239462Sdim 164239462Sdim return true; 165239462Sdim} 166239462Sdim 167234353Sdim/// \brief Retrieve the NSNumber factory method that should be used to create 168234353Sdim/// an Objective-C literal for the given type. 169234353Sdimstatic ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, 170239462Sdim QualType NumberType, 171239462Sdim bool isLiteral = false, 172239462Sdim SourceRange R = SourceRange()) { 173249423Sdim Optional<NSAPI::NSNumberLiteralMethodKind> Kind = 174249423Sdim S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType); 175249423Sdim 176234353Sdim if (!Kind) { 177239462Sdim if (isLiteral) { 178239462Sdim S.Diag(Loc, diag::err_invalid_nsnumber_type) 179239462Sdim << NumberType << R; 180239462Sdim } 181234353Sdim return 0; 182234353Sdim } 183239462Sdim 184234353Sdim // If we already looked up this method, we're done. 185234353Sdim if (S.NSNumberLiteralMethods[*Kind]) 186234353Sdim return S.NSNumberLiteralMethods[*Kind]; 187234353Sdim 188234353Sdim Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind, 189234353Sdim /*Instance=*/false); 190234353Sdim 191239462Sdim ASTContext &CX = S.Context; 192239462Sdim 193239462Sdim // Look up the NSNumber class, if we haven't done so already. It's cached 194239462Sdim // in the Sema instance. 195239462Sdim if (!S.NSNumberDecl) { 196239462Sdim IdentifierInfo *NSNumberId = 197239462Sdim S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber); 198239462Sdim NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId, 199239462Sdim Loc, Sema::LookupOrdinaryName); 200239462Sdim S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); 201239462Sdim if (!S.NSNumberDecl) { 202239462Sdim if (S.getLangOpts().DebuggerObjCLiteral) { 203239462Sdim // Create a stub definition of NSNumber. 204239462Sdim S.NSNumberDecl = ObjCInterfaceDecl::Create(CX, 205239462Sdim CX.getTranslationUnitDecl(), 206239462Sdim SourceLocation(), NSNumberId, 207239462Sdim 0, SourceLocation()); 208239462Sdim } else { 209239462Sdim // Otherwise, require a declaration of NSNumber. 210239462Sdim S.Diag(Loc, diag::err_undeclared_nsnumber); 211239462Sdim return 0; 212239462Sdim } 213239462Sdim } else if (!S.NSNumberDecl->hasDefinition()) { 214239462Sdim S.Diag(Loc, diag::err_undeclared_nsnumber); 215239462Sdim return 0; 216239462Sdim } 217239462Sdim 218239462Sdim // generate the pointer to NSNumber type. 219239462Sdim QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl); 220239462Sdim S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject); 221239462Sdim } 222239462Sdim 223234353Sdim // Look for the appropriate method within NSNumber. 224239462Sdim ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel); 225234353Sdim if (!Method && S.getLangOpts().DebuggerObjCLiteral) { 226239462Sdim // create a stub definition this NSNumber factory method. 227234353Sdim TypeSourceInfo *ResultTInfo = 0; 228239462Sdim Method = ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel, 229239462Sdim S.NSNumberPointer, ResultTInfo, 230239462Sdim S.NSNumberDecl, 231239462Sdim /*isInstance=*/false, /*isVariadic=*/false, 232243830Sdim /*isPropertyAccessor=*/false, 233239462Sdim /*isImplicitlyDeclared=*/true, 234239462Sdim /*isDefined=*/false, 235239462Sdim ObjCMethodDecl::Required, 236239462Sdim /*HasRelatedResultType=*/false); 237234353Sdim ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method, 238234353Sdim SourceLocation(), SourceLocation(), 239239462Sdim &CX.Idents.get("value"), 240239462Sdim NumberType, /*TInfo=*/0, SC_None, 241249423Sdim 0); 242251662Sdim Method->setMethodParams(S.Context, value, None); 243234353Sdim } 244234353Sdim 245239462Sdim if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method)) 246234353Sdim return 0; 247234353Sdim 248234353Sdim // Note: if the parameter type is out-of-line, we'll catch it later in the 249234353Sdim // implicit conversion. 250234353Sdim 251234353Sdim S.NSNumberLiteralMethods[*Kind] = Method; 252234353Sdim return Method; 253234353Sdim} 254234353Sdim 255239462Sdim/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the 256239462Sdim/// numeric literal expression. Type of the expression will be "NSNumber *". 257234353SdimExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { 258234353Sdim // Determine the type of the literal. 259234353Sdim QualType NumberType = Number->getType(); 260234353Sdim if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) { 261234353Sdim // In C, character literals have type 'int'. That's not the type we want 262234353Sdim // to use to determine the Objective-c literal kind. 263234353Sdim switch (Char->getKind()) { 264234353Sdim case CharacterLiteral::Ascii: 265234353Sdim NumberType = Context.CharTy; 266234353Sdim break; 267234353Sdim 268234353Sdim case CharacterLiteral::Wide: 269234353Sdim NumberType = Context.getWCharType(); 270234353Sdim break; 271234353Sdim 272234353Sdim case CharacterLiteral::UTF16: 273234353Sdim NumberType = Context.Char16Ty; 274234353Sdim break; 275234353Sdim 276234353Sdim case CharacterLiteral::UTF32: 277234353Sdim NumberType = Context.Char32Ty; 278234353Sdim break; 279234353Sdim } 280234353Sdim } 281234353Sdim 282234353Sdim // Look for the appropriate method within NSNumber. 283234353Sdim // Construct the literal. 284239462Sdim SourceRange NR(Number->getSourceRange()); 285239462Sdim ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType, 286239462Sdim true, NR); 287234353Sdim if (!Method) 288234353Sdim return ExprError(); 289234353Sdim 290234353Sdim // Convert the number to the type that the parameter expects. 291239462Sdim ParmVarDecl *ParamDecl = Method->param_begin()[0]; 292239462Sdim InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, 293239462Sdim ParamDecl); 294239462Sdim ExprResult ConvertedNumber = PerformCopyInitialization(Entity, 295239462Sdim SourceLocation(), 296239462Sdim Owned(Number)); 297234353Sdim if (ConvertedNumber.isInvalid()) 298234353Sdim return ExprError(); 299234353Sdim Number = ConvertedNumber.get(); 300234353Sdim 301239462Sdim // Use the effective source range of the literal, including the leading '@'. 302234353Sdim return MaybeBindToTemporary( 303239462Sdim new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method, 304239462Sdim SourceRange(AtLoc, NR.getEnd()))); 305234353Sdim} 306234353Sdim 307234353SdimExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, 308234353Sdim SourceLocation ValueLoc, 309234353Sdim bool Value) { 310234353Sdim ExprResult Inner; 311234353Sdim if (getLangOpts().CPlusPlus) { 312234353Sdim Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false); 313234353Sdim } else { 314234353Sdim // C doesn't actually have a way to represent literal values of type 315234353Sdim // _Bool. So, we'll use 0/1 and implicit cast to _Bool. 316234353Sdim Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0); 317234353Sdim Inner = ImpCastExprToType(Inner.get(), Context.BoolTy, 318234353Sdim CK_IntegralToBoolean); 319234353Sdim } 320234353Sdim 321234353Sdim return BuildObjCNumericLiteral(AtLoc, Inner.get()); 322234353Sdim} 323234353Sdim 324234353Sdim/// \brief Check that the given expression is a valid element of an Objective-C 325234353Sdim/// collection literal. 326234353Sdimstatic ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, 327234353Sdim QualType T) { 328234353Sdim // If the expression is type-dependent, there's nothing for us to do. 329234353Sdim if (Element->isTypeDependent()) 330234353Sdim return Element; 331234353Sdim 332234353Sdim ExprResult Result = S.CheckPlaceholderExpr(Element); 333234353Sdim if (Result.isInvalid()) 334234353Sdim return ExprError(); 335234353Sdim Element = Result.get(); 336234353Sdim 337234353Sdim // In C++, check for an implicit conversion to an Objective-C object pointer 338234353Sdim // type. 339234353Sdim if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) { 340234353Sdim InitializedEntity Entity 341239462Sdim = InitializedEntity::InitializeParameter(S.Context, T, 342239462Sdim /*Consumed=*/false); 343234353Sdim InitializationKind Kind 344239462Sdim = InitializationKind::CreateCopy(Element->getLocStart(), 345239462Sdim SourceLocation()); 346251662Sdim InitializationSequence Seq(S, Entity, Kind, Element); 347234353Sdim if (!Seq.Failed()) 348243830Sdim return Seq.Perform(S, Entity, Kind, Element); 349234353Sdim } 350234353Sdim 351234353Sdim Expr *OrigElement = Element; 352234353Sdim 353234353Sdim // Perform lvalue-to-rvalue conversion. 354234353Sdim Result = S.DefaultLvalueConversion(Element); 355234353Sdim if (Result.isInvalid()) 356234353Sdim return ExprError(); 357234353Sdim Element = Result.get(); 358234353Sdim 359234353Sdim // Make sure that we have an Objective-C pointer type or block. 360234353Sdim if (!Element->getType()->isObjCObjectPointerType() && 361234353Sdim !Element->getType()->isBlockPointerType()) { 362234353Sdim bool Recovered = false; 363234353Sdim 364234353Sdim // If this is potentially an Objective-C numeric literal, add the '@'. 365234353Sdim if (isa<IntegerLiteral>(OrigElement) || 366234353Sdim isa<CharacterLiteral>(OrigElement) || 367234353Sdim isa<FloatingLiteral>(OrigElement) || 368234353Sdim isa<ObjCBoolLiteralExpr>(OrigElement) || 369234353Sdim isa<CXXBoolLiteralExpr>(OrigElement)) { 370234353Sdim if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) { 371234353Sdim int Which = isa<CharacterLiteral>(OrigElement) ? 1 372234353Sdim : (isa<CXXBoolLiteralExpr>(OrigElement) || 373234353Sdim isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2 374234353Sdim : 3; 375234353Sdim 376234353Sdim S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) 377234353Sdim << Which << OrigElement->getSourceRange() 378234353Sdim << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); 379234353Sdim 380234353Sdim Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(), 381234353Sdim OrigElement); 382234353Sdim if (Result.isInvalid()) 383234353Sdim return ExprError(); 384234353Sdim 385234353Sdim Element = Result.get(); 386234353Sdim Recovered = true; 387234353Sdim } 388234353Sdim } 389234353Sdim // If this is potentially an Objective-C string literal, add the '@'. 390234353Sdim else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) { 391234353Sdim if (String->isAscii()) { 392234353Sdim S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) 393234353Sdim << 0 << OrigElement->getSourceRange() 394234353Sdim << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); 395234353Sdim 396234353Sdim Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String); 397234353Sdim if (Result.isInvalid()) 398234353Sdim return ExprError(); 399234353Sdim 400234353Sdim Element = Result.get(); 401234353Sdim Recovered = true; 402234353Sdim } 403234353Sdim } 404234353Sdim 405234353Sdim if (!Recovered) { 406234353Sdim S.Diag(Element->getLocStart(), diag::err_invalid_collection_element) 407234353Sdim << Element->getType(); 408234353Sdim return ExprError(); 409234353Sdim } 410234353Sdim } 411234353Sdim 412234353Sdim // Make sure that the element has the type that the container factory 413234353Sdim // function expects. 414234353Sdim return S.PerformCopyInitialization( 415234353Sdim InitializedEntity::InitializeParameter(S.Context, T, 416234353Sdim /*Consumed=*/false), 417234353Sdim Element->getLocStart(), Element); 418234353Sdim} 419234353Sdim 420239462SdimExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { 421239462Sdim if (ValueExpr->isTypeDependent()) { 422239462Sdim ObjCBoxedExpr *BoxedExpr = 423239462Sdim new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR); 424239462Sdim return Owned(BoxedExpr); 425239462Sdim } 426239462Sdim ObjCMethodDecl *BoxingMethod = NULL; 427239462Sdim QualType BoxedType; 428239462Sdim // Convert the expression to an RValue, so we can check for pointer types... 429239462Sdim ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr); 430239462Sdim if (RValue.isInvalid()) { 431239462Sdim return ExprError(); 432239462Sdim } 433239462Sdim ValueExpr = RValue.get(); 434239462Sdim QualType ValueType(ValueExpr->getType()); 435239462Sdim if (const PointerType *PT = ValueType->getAs<PointerType>()) { 436239462Sdim QualType PointeeType = PT->getPointeeType(); 437239462Sdim if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) { 438239462Sdim 439239462Sdim if (!NSStringDecl) { 440239462Sdim IdentifierInfo *NSStringId = 441239462Sdim NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); 442239462Sdim NamedDecl *Decl = LookupSingleName(TUScope, NSStringId, 443239462Sdim SR.getBegin(), LookupOrdinaryName); 444239462Sdim NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl); 445239462Sdim if (!NSStringDecl) { 446239462Sdim if (getLangOpts().DebuggerObjCLiteral) { 447239462Sdim // Support boxed expressions in the debugger w/o NSString declaration. 448239462Sdim DeclContext *TU = Context.getTranslationUnitDecl(); 449239462Sdim NSStringDecl = ObjCInterfaceDecl::Create(Context, TU, 450239462Sdim SourceLocation(), 451239462Sdim NSStringId, 452239462Sdim 0, SourceLocation()); 453239462Sdim } else { 454239462Sdim Diag(SR.getBegin(), diag::err_undeclared_nsstring); 455239462Sdim return ExprError(); 456239462Sdim } 457239462Sdim } else if (!NSStringDecl->hasDefinition()) { 458239462Sdim Diag(SR.getBegin(), diag::err_undeclared_nsstring); 459239462Sdim return ExprError(); 460239462Sdim } 461239462Sdim assert(NSStringDecl && "NSStringDecl should not be NULL"); 462239462Sdim QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl); 463239462Sdim NSStringPointer = Context.getObjCObjectPointerType(NSStringObject); 464239462Sdim } 465239462Sdim 466239462Sdim if (!StringWithUTF8StringMethod) { 467239462Sdim IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String"); 468239462Sdim Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II); 469239462Sdim 470239462Sdim // Look for the appropriate method within NSString. 471239462Sdim BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String); 472239462Sdim if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) { 473239462Sdim // Debugger needs to work even if NSString hasn't been defined. 474239462Sdim TypeSourceInfo *ResultTInfo = 0; 475239462Sdim ObjCMethodDecl *M = 476239462Sdim ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(), 477239462Sdim stringWithUTF8String, NSStringPointer, 478239462Sdim ResultTInfo, NSStringDecl, 479239462Sdim /*isInstance=*/false, /*isVariadic=*/false, 480243830Sdim /*isPropertyAccessor=*/false, 481239462Sdim /*isImplicitlyDeclared=*/true, 482239462Sdim /*isDefined=*/false, 483239462Sdim ObjCMethodDecl::Required, 484239462Sdim /*HasRelatedResultType=*/false); 485239462Sdim QualType ConstCharType = Context.CharTy.withConst(); 486239462Sdim ParmVarDecl *value = 487239462Sdim ParmVarDecl::Create(Context, M, 488239462Sdim SourceLocation(), SourceLocation(), 489239462Sdim &Context.Idents.get("value"), 490239462Sdim Context.getPointerType(ConstCharType), 491239462Sdim /*TInfo=*/0, 492249423Sdim SC_None, 0); 493251662Sdim M->setMethodParams(Context, value, None); 494239462Sdim BoxingMethod = M; 495239462Sdim } 496239462Sdim 497239462Sdim if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl, 498239462Sdim stringWithUTF8String, BoxingMethod)) 499239462Sdim return ExprError(); 500239462Sdim 501239462Sdim StringWithUTF8StringMethod = BoxingMethod; 502239462Sdim } 503239462Sdim 504239462Sdim BoxingMethod = StringWithUTF8StringMethod; 505239462Sdim BoxedType = NSStringPointer; 506239462Sdim } 507239462Sdim } else if (ValueType->isBuiltinType()) { 508239462Sdim // The other types we support are numeric, char and BOOL/bool. We could also 509239462Sdim // provide limited support for structure types, such as NSRange, NSRect, and 510239462Sdim // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h> 511239462Sdim // for more details. 512239462Sdim 513239462Sdim // Check for a top-level character literal. 514239462Sdim if (const CharacterLiteral *Char = 515239462Sdim dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) { 516239462Sdim // In C, character literals have type 'int'. That's not the type we want 517239462Sdim // to use to determine the Objective-c literal kind. 518239462Sdim switch (Char->getKind()) { 519239462Sdim case CharacterLiteral::Ascii: 520239462Sdim ValueType = Context.CharTy; 521239462Sdim break; 522239462Sdim 523239462Sdim case CharacterLiteral::Wide: 524239462Sdim ValueType = Context.getWCharType(); 525239462Sdim break; 526239462Sdim 527239462Sdim case CharacterLiteral::UTF16: 528239462Sdim ValueType = Context.Char16Ty; 529239462Sdim break; 530239462Sdim 531239462Sdim case CharacterLiteral::UTF32: 532239462Sdim ValueType = Context.Char32Ty; 533239462Sdim break; 534239462Sdim } 535239462Sdim } 536239462Sdim 537239462Sdim // FIXME: Do I need to do anything special with BoolTy expressions? 538239462Sdim 539239462Sdim // Look for the appropriate method within NSNumber. 540239462Sdim BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType); 541239462Sdim BoxedType = NSNumberPointer; 542239462Sdim 543239462Sdim } else if (const EnumType *ET = ValueType->getAs<EnumType>()) { 544239462Sdim if (!ET->getDecl()->isComplete()) { 545239462Sdim Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type) 546239462Sdim << ValueType << ValueExpr->getSourceRange(); 547239462Sdim return ExprError(); 548239462Sdim } 549239462Sdim 550239462Sdim BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), 551239462Sdim ET->getDecl()->getIntegerType()); 552239462Sdim BoxedType = NSNumberPointer; 553239462Sdim } 554239462Sdim 555239462Sdim if (!BoxingMethod) { 556239462Sdim Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type) 557239462Sdim << ValueType << ValueExpr->getSourceRange(); 558239462Sdim return ExprError(); 559239462Sdim } 560239462Sdim 561239462Sdim // Convert the expression to the type that the parameter requires. 562239462Sdim ParmVarDecl *ParamDecl = BoxingMethod->param_begin()[0]; 563239462Sdim InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, 564239462Sdim ParamDecl); 565239462Sdim ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity, 566239462Sdim SourceLocation(), 567239462Sdim Owned(ValueExpr)); 568239462Sdim if (ConvertedValueExpr.isInvalid()) 569239462Sdim return ExprError(); 570239462Sdim ValueExpr = ConvertedValueExpr.get(); 571239462Sdim 572239462Sdim ObjCBoxedExpr *BoxedExpr = 573239462Sdim new (Context) ObjCBoxedExpr(ValueExpr, BoxedType, 574239462Sdim BoxingMethod, SR); 575239462Sdim return MaybeBindToTemporary(BoxedExpr); 576239462Sdim} 577239462Sdim 578239462Sdim/// Build an ObjC subscript pseudo-object expression, given that 579239462Sdim/// that's supported by the runtime. 580234353SdimExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, 581234353Sdim Expr *IndexExpr, 582234353Sdim ObjCMethodDecl *getterMethod, 583234353Sdim ObjCMethodDecl *setterMethod) { 584239462Sdim assert(!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic()); 585239462Sdim 586239462Sdim // We can't get dependent types here; our callers should have 587239462Sdim // filtered them out. 588239462Sdim assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && 589239462Sdim "base or index cannot have dependent type here"); 590239462Sdim 591239462Sdim // Filter out placeholders in the index. In theory, overloads could 592239462Sdim // be preserved here, although that might not actually work correctly. 593234353Sdim ExprResult Result = CheckPlaceholderExpr(IndexExpr); 594234353Sdim if (Result.isInvalid()) 595234353Sdim return ExprError(); 596234353Sdim IndexExpr = Result.get(); 597234353Sdim 598239462Sdim // Perform lvalue-to-rvalue conversion on the base. 599234353Sdim Result = DefaultLvalueConversion(BaseExpr); 600234353Sdim if (Result.isInvalid()) 601234353Sdim return ExprError(); 602234353Sdim BaseExpr = Result.get(); 603239462Sdim 604239462Sdim // Build the pseudo-object expression. 605234353Sdim return Owned(ObjCSubscriptRefExpr::Create(Context, 606234353Sdim BaseExpr, 607234353Sdim IndexExpr, 608234353Sdim Context.PseudoObjectTy, 609234353Sdim getterMethod, 610234353Sdim setterMethod, RB)); 611234353Sdim 612234353Sdim} 613234353Sdim 614234353SdimExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { 615234353Sdim // Look up the NSArray class, if we haven't done so already. 616234353Sdim if (!NSArrayDecl) { 617234353Sdim NamedDecl *IF = LookupSingleName(TUScope, 618234353Sdim NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), 619234353Sdim SR.getBegin(), 620234353Sdim LookupOrdinaryName); 621234353Sdim NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); 622234353Sdim if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral) 623234353Sdim NSArrayDecl = ObjCInterfaceDecl::Create (Context, 624234353Sdim Context.getTranslationUnitDecl(), 625234353Sdim SourceLocation(), 626234353Sdim NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), 627234353Sdim 0, SourceLocation()); 628234353Sdim 629234353Sdim if (!NSArrayDecl) { 630234353Sdim Diag(SR.getBegin(), diag::err_undeclared_nsarray); 631234353Sdim return ExprError(); 632234353Sdim } 633234353Sdim } 634234353Sdim 635234353Sdim // Find the arrayWithObjects:count: method, if we haven't done so already. 636234353Sdim QualType IdT = Context.getObjCIdType(); 637234353Sdim if (!ArrayWithObjectsMethod) { 638234353Sdim Selector 639234353Sdim Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount); 640239462Sdim ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel); 641239462Sdim if (!Method && getLangOpts().DebuggerObjCLiteral) { 642234353Sdim TypeSourceInfo *ResultTInfo = 0; 643239462Sdim Method = ObjCMethodDecl::Create(Context, 644234353Sdim SourceLocation(), SourceLocation(), Sel, 645234353Sdim IdT, 646234353Sdim ResultTInfo, 647234353Sdim Context.getTranslationUnitDecl(), 648234353Sdim false /*Instance*/, false/*isVariadic*/, 649243830Sdim /*isPropertyAccessor=*/false, 650234353Sdim /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 651234353Sdim ObjCMethodDecl::Required, 652234353Sdim false); 653234353Sdim SmallVector<ParmVarDecl *, 2> Params; 654239462Sdim ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, 655239462Sdim SourceLocation(), 656239462Sdim SourceLocation(), 657239462Sdim &Context.Idents.get("objects"), 658239462Sdim Context.getPointerType(IdT), 659249423Sdim /*TInfo=*/0, SC_None, 0); 660234353Sdim Params.push_back(objects); 661239462Sdim ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, 662239462Sdim SourceLocation(), 663239462Sdim SourceLocation(), 664239462Sdim &Context.Idents.get("cnt"), 665239462Sdim Context.UnsignedLongTy, 666249423Sdim /*TInfo=*/0, SC_None, 0); 667234353Sdim Params.push_back(cnt); 668251662Sdim Method->setMethodParams(Context, Params, None); 669239462Sdim } 670234353Sdim 671239462Sdim if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method)) 672239462Sdim return ExprError(); 673234353Sdim 674239462Sdim // Dig out the type that all elements should be converted to. 675239462Sdim QualType T = Method->param_begin()[0]->getType(); 676239462Sdim const PointerType *PtrT = T->getAs<PointerType>(); 677239462Sdim if (!PtrT || 678239462Sdim !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) { 679239462Sdim Diag(SR.getBegin(), diag::err_objc_literal_method_sig) 680239462Sdim << Sel; 681239462Sdim Diag(Method->param_begin()[0]->getLocation(), 682239462Sdim diag::note_objc_literal_method_param) 683239462Sdim << 0 << T 684239462Sdim << Context.getPointerType(IdT.withConst()); 685239462Sdim return ExprError(); 686234353Sdim } 687239462Sdim 688239462Sdim // Check that the 'count' parameter is integral. 689239462Sdim if (!Method->param_begin()[1]->getType()->isIntegerType()) { 690239462Sdim Diag(SR.getBegin(), diag::err_objc_literal_method_sig) 691239462Sdim << Sel; 692239462Sdim Diag(Method->param_begin()[1]->getLocation(), 693239462Sdim diag::note_objc_literal_method_param) 694239462Sdim << 1 695239462Sdim << Method->param_begin()[1]->getType() 696239462Sdim << "integral"; 697234353Sdim return ExprError(); 698234353Sdim } 699234353Sdim 700239462Sdim // We've found a good +arrayWithObjects:count: method. Save it! 701239462Sdim ArrayWithObjectsMethod = Method; 702234353Sdim } 703234353Sdim 704239462Sdim QualType ObjectsType = ArrayWithObjectsMethod->param_begin()[0]->getType(); 705239462Sdim QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType(); 706239462Sdim 707234353Sdim // Check that each of the elements provided is valid in a collection literal, 708234353Sdim // performing conversions as necessary. 709243830Sdim Expr **ElementsBuffer = Elements.data(); 710234353Sdim for (unsigned I = 0, N = Elements.size(); I != N; ++I) { 711234353Sdim ExprResult Converted = CheckObjCCollectionLiteralElement(*this, 712234353Sdim ElementsBuffer[I], 713239462Sdim RequiredType); 714234353Sdim if (Converted.isInvalid()) 715234353Sdim return ExprError(); 716234353Sdim 717234353Sdim ElementsBuffer[I] = Converted.get(); 718234353Sdim } 719234353Sdim 720234353Sdim QualType Ty 721234353Sdim = Context.getObjCObjectPointerType( 722234353Sdim Context.getObjCInterfaceType(NSArrayDecl)); 723234353Sdim 724234353Sdim return MaybeBindToTemporary( 725243830Sdim ObjCArrayLiteral::Create(Context, Elements, Ty, 726243830Sdim ArrayWithObjectsMethod, SR)); 727234353Sdim} 728234353Sdim 729234353SdimExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, 730234353Sdim ObjCDictionaryElement *Elements, 731234353Sdim unsigned NumElements) { 732234353Sdim // Look up the NSDictionary class, if we haven't done so already. 733234353Sdim if (!NSDictionaryDecl) { 734234353Sdim NamedDecl *IF = LookupSingleName(TUScope, 735234353Sdim NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), 736234353Sdim SR.getBegin(), LookupOrdinaryName); 737234353Sdim NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); 738234353Sdim if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral) 739234353Sdim NSDictionaryDecl = ObjCInterfaceDecl::Create (Context, 740234353Sdim Context.getTranslationUnitDecl(), 741234353Sdim SourceLocation(), 742234353Sdim NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), 743234353Sdim 0, SourceLocation()); 744234353Sdim 745234353Sdim if (!NSDictionaryDecl) { 746234353Sdim Diag(SR.getBegin(), diag::err_undeclared_nsdictionary); 747234353Sdim return ExprError(); 748234353Sdim } 749234353Sdim } 750234353Sdim 751234353Sdim // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done 752234353Sdim // so already. 753234353Sdim QualType IdT = Context.getObjCIdType(); 754234353Sdim if (!DictionaryWithObjectsMethod) { 755234353Sdim Selector Sel = NSAPIObj->getNSDictionarySelector( 756239462Sdim NSAPI::NSDict_dictionaryWithObjectsForKeysCount); 757239462Sdim ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel); 758239462Sdim if (!Method && getLangOpts().DebuggerObjCLiteral) { 759239462Sdim Method = ObjCMethodDecl::Create(Context, 760234353Sdim SourceLocation(), SourceLocation(), Sel, 761234353Sdim IdT, 762234353Sdim 0 /*TypeSourceInfo */, 763234353Sdim Context.getTranslationUnitDecl(), 764234353Sdim false /*Instance*/, false/*isVariadic*/, 765243830Sdim /*isPropertyAccessor=*/false, 766234353Sdim /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 767234353Sdim ObjCMethodDecl::Required, 768234353Sdim false); 769234353Sdim SmallVector<ParmVarDecl *, 3> Params; 770239462Sdim ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, 771239462Sdim SourceLocation(), 772239462Sdim SourceLocation(), 773239462Sdim &Context.Idents.get("objects"), 774239462Sdim Context.getPointerType(IdT), 775249423Sdim /*TInfo=*/0, SC_None, 0); 776234353Sdim Params.push_back(objects); 777239462Sdim ParmVarDecl *keys = ParmVarDecl::Create(Context, Method, 778239462Sdim SourceLocation(), 779239462Sdim SourceLocation(), 780239462Sdim &Context.Idents.get("keys"), 781239462Sdim Context.getPointerType(IdT), 782249423Sdim /*TInfo=*/0, SC_None, 0); 783234353Sdim Params.push_back(keys); 784239462Sdim ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, 785239462Sdim SourceLocation(), 786239462Sdim SourceLocation(), 787239462Sdim &Context.Idents.get("cnt"), 788239462Sdim Context.UnsignedLongTy, 789249423Sdim /*TInfo=*/0, SC_None, 0); 790234353Sdim Params.push_back(cnt); 791251662Sdim Method->setMethodParams(Context, Params, None); 792234353Sdim } 793234353Sdim 794239462Sdim if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel, 795239462Sdim Method)) 796239462Sdim return ExprError(); 797239462Sdim 798239462Sdim // Dig out the type that all values should be converted to. 799239462Sdim QualType ValueT = Method->param_begin()[0]->getType(); 800239462Sdim const PointerType *PtrValue = ValueT->getAs<PointerType>(); 801239462Sdim if (!PtrValue || 802239462Sdim !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) { 803239462Sdim Diag(SR.getBegin(), diag::err_objc_literal_method_sig) 804239462Sdim << Sel; 805239462Sdim Diag(Method->param_begin()[0]->getLocation(), 806239462Sdim diag::note_objc_literal_method_param) 807239462Sdim << 0 << ValueT 808239462Sdim << Context.getPointerType(IdT.withConst()); 809239462Sdim return ExprError(); 810234353Sdim } 811234353Sdim 812239462Sdim // Dig out the type that all keys should be converted to. 813239462Sdim QualType KeyT = Method->param_begin()[1]->getType(); 814239462Sdim const PointerType *PtrKey = KeyT->getAs<PointerType>(); 815239462Sdim if (!PtrKey || 816239462Sdim !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), 817239462Sdim IdT)) { 818239462Sdim bool err = true; 819239462Sdim if (PtrKey) { 820239462Sdim if (QIDNSCopying.isNull()) { 821239462Sdim // key argument of selector is id<NSCopying>? 822239462Sdim if (ObjCProtocolDecl *NSCopyingPDecl = 823239462Sdim LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) { 824239462Sdim ObjCProtocolDecl *PQ[] = {NSCopyingPDecl}; 825239462Sdim QIDNSCopying = 826239462Sdim Context.getObjCObjectType(Context.ObjCBuiltinIdTy, 827239462Sdim (ObjCProtocolDecl**) PQ,1); 828239462Sdim QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying); 829239462Sdim } 830234353Sdim } 831239462Sdim if (!QIDNSCopying.isNull()) 832239462Sdim err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), 833239462Sdim QIDNSCopying); 834234353Sdim } 835239462Sdim 836239462Sdim if (err) { 837239462Sdim Diag(SR.getBegin(), diag::err_objc_literal_method_sig) 838239462Sdim << Sel; 839239462Sdim Diag(Method->param_begin()[1]->getLocation(), 840239462Sdim diag::note_objc_literal_method_param) 841239462Sdim << 1 << KeyT 842239462Sdim << Context.getPointerType(IdT.withConst()); 843239462Sdim return ExprError(); 844239462Sdim } 845234353Sdim } 846239462Sdim 847239462Sdim // Check that the 'count' parameter is integral. 848239462Sdim QualType CountType = Method->param_begin()[2]->getType(); 849239462Sdim if (!CountType->isIntegerType()) { 850234353Sdim Diag(SR.getBegin(), diag::err_objc_literal_method_sig) 851239462Sdim << Sel; 852239462Sdim Diag(Method->param_begin()[2]->getLocation(), 853234353Sdim diag::note_objc_literal_method_param) 854239462Sdim << 2 << CountType 855239462Sdim << "integral"; 856234353Sdim return ExprError(); 857234353Sdim } 858234353Sdim 859239462Sdim // We've found a good +dictionaryWithObjects:keys:count: method; save it! 860239462Sdim DictionaryWithObjectsMethod = Method; 861234353Sdim } 862234353Sdim 863239462Sdim QualType ValuesT = DictionaryWithObjectsMethod->param_begin()[0]->getType(); 864239462Sdim QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType(); 865239462Sdim QualType KeysT = DictionaryWithObjectsMethod->param_begin()[1]->getType(); 866239462Sdim QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType(); 867239462Sdim 868234353Sdim // Check that each of the keys and values provided is valid in a collection 869234353Sdim // literal, performing conversions as necessary. 870234353Sdim bool HasPackExpansions = false; 871234353Sdim for (unsigned I = 0, N = NumElements; I != N; ++I) { 872234353Sdim // Check the key. 873234353Sdim ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key, 874234353Sdim KeyT); 875234353Sdim if (Key.isInvalid()) 876234353Sdim return ExprError(); 877234353Sdim 878234353Sdim // Check the value. 879234353Sdim ExprResult Value 880234353Sdim = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT); 881234353Sdim if (Value.isInvalid()) 882234353Sdim return ExprError(); 883234353Sdim 884234353Sdim Elements[I].Key = Key.get(); 885234353Sdim Elements[I].Value = Value.get(); 886234353Sdim 887234353Sdim if (Elements[I].EllipsisLoc.isInvalid()) 888234353Sdim continue; 889234353Sdim 890234353Sdim if (!Elements[I].Key->containsUnexpandedParameterPack() && 891234353Sdim !Elements[I].Value->containsUnexpandedParameterPack()) { 892234353Sdim Diag(Elements[I].EllipsisLoc, 893234353Sdim diag::err_pack_expansion_without_parameter_packs) 894234353Sdim << SourceRange(Elements[I].Key->getLocStart(), 895234353Sdim Elements[I].Value->getLocEnd()); 896234353Sdim return ExprError(); 897234353Sdim } 898234353Sdim 899234353Sdim HasPackExpansions = true; 900234353Sdim } 901234353Sdim 902234353Sdim 903234353Sdim QualType Ty 904234353Sdim = Context.getObjCObjectPointerType( 905234353Sdim Context.getObjCInterfaceType(NSDictionaryDecl)); 906234353Sdim return MaybeBindToTemporary( 907234353Sdim ObjCDictionaryLiteral::Create(Context, 908234353Sdim llvm::makeArrayRef(Elements, 909234353Sdim NumElements), 910234353Sdim HasPackExpansions, 911234353Sdim Ty, 912234353Sdim DictionaryWithObjectsMethod, SR)); 913234353Sdim} 914234353Sdim 915223017SdimExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, 916207619Srdivacky TypeSourceInfo *EncodedTypeInfo, 917193725Sed SourceLocation RParenLoc) { 918207619Srdivacky QualType EncodedType = EncodedTypeInfo->getType(); 919193725Sed QualType StrTy; 920198092Srdivacky if (EncodedType->isDependentType()) 921193725Sed StrTy = Context.DependentTy; 922193725Sed else { 923224145Sdim if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled. 924224145Sdim !EncodedType->isVoidType()) // void is handled too. 925223017Sdim if (RequireCompleteType(AtLoc, EncodedType, 926239462Sdim diag::err_incomplete_type_objc_at_encode, 927239462Sdim EncodedTypeInfo->getTypeLoc())) 928223017Sdim return ExprError(); 929223017Sdim 930193725Sed std::string Str; 931193725Sed Context.getObjCEncodingForType(EncodedType, Str); 932193725Sed 933193725Sed // The type of @encode is the same as the type of the corresponding string, 934193725Sed // which is an array type. 935193725Sed StrTy = Context.CharTy; 936193725Sed // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). 937234353Sdim if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) 938193725Sed StrTy.addConst(); 939193725Sed StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), 940193725Sed ArrayType::Normal, 0); 941193725Sed } 942198092Srdivacky 943207619Srdivacky return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc); 944193725Sed} 945193725Sed 946212904SdimExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, 947212904Sdim SourceLocation EncodeLoc, 948212904Sdim SourceLocation LParenLoc, 949212904Sdim ParsedType ty, 950212904Sdim SourceLocation RParenLoc) { 951198092Srdivacky // FIXME: Preserve type source info ? 952207619Srdivacky TypeSourceInfo *TInfo; 953207619Srdivacky QualType EncodedType = GetTypeFromParser(ty, &TInfo); 954207619Srdivacky if (!TInfo) 955207619Srdivacky TInfo = Context.getTrivialTypeSourceInfo(EncodedType, 956207619Srdivacky PP.getLocForEndOfToken(LParenLoc)); 957193326Sed 958207619Srdivacky return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); 959193326Sed} 960193326Sed 961212904SdimExprResult Sema::ParseObjCSelectorExpression(Selector Sel, 962212904Sdim SourceLocation AtLoc, 963212904Sdim SourceLocation SelLoc, 964212904Sdim SourceLocation LParenLoc, 965212904Sdim SourceLocation RParenLoc) { 966198092Srdivacky ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, 967212904Sdim SourceRange(LParenLoc, RParenLoc), false, false); 968194613Sed if (!Method) 969194613Sed Method = LookupFactoryMethodInGlobalPool(Sel, 970194613Sed SourceRange(LParenLoc, RParenLoc)); 971194613Sed if (!Method) 972194613Sed Diag(SelLoc, diag::warn_undeclared_selector) << Sel; 973224145Sdim 974224145Sdim if (!Method || 975224145Sdim Method->getImplementationControl() != ObjCMethodDecl::Optional) { 976224145Sdim llvm::DenseMap<Selector, SourceLocation>::iterator Pos 977224145Sdim = ReferencedSelectors.find(Sel); 978224145Sdim if (Pos == ReferencedSelectors.end()) 979249423Sdim ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); 980224145Sdim } 981194613Sed 982224145Sdim // In ARC, forbid the user from using @selector for 983224145Sdim // retain/release/autorelease/dealloc/retainCount. 984234353Sdim if (getLangOpts().ObjCAutoRefCount) { 985224145Sdim switch (Sel.getMethodFamily()) { 986224145Sdim case OMF_retain: 987224145Sdim case OMF_release: 988224145Sdim case OMF_autorelease: 989224145Sdim case OMF_retainCount: 990224145Sdim case OMF_dealloc: 991224145Sdim Diag(AtLoc, diag::err_arc_illegal_selector) << 992224145Sdim Sel << SourceRange(LParenLoc, RParenLoc); 993224145Sdim break; 994212904Sdim 995224145Sdim case OMF_None: 996224145Sdim case OMF_alloc: 997224145Sdim case OMF_copy: 998226633Sdim case OMF_finalize: 999224145Sdim case OMF_init: 1000224145Sdim case OMF_mutableCopy: 1001224145Sdim case OMF_new: 1002224145Sdim case OMF_self: 1003224145Sdim case OMF_performSelector: 1004224145Sdim break; 1005224145Sdim } 1006224145Sdim } 1007193326Sed QualType Ty = Context.getObjCSelType(); 1008193326Sed return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); 1009193326Sed} 1010193326Sed 1011212904SdimExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, 1012212904Sdim SourceLocation AtLoc, 1013212904Sdim SourceLocation ProtoLoc, 1014212904Sdim SourceLocation LParenLoc, 1015239462Sdim SourceLocation ProtoIdLoc, 1016212904Sdim SourceLocation RParenLoc) { 1017239462Sdim ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc); 1018193326Sed if (!PDecl) { 1019193326Sed Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; 1020193326Sed return true; 1021193326Sed } 1022198092Srdivacky 1023193326Sed QualType Ty = Context.getObjCProtoType(); 1024193326Sed if (Ty.isNull()) 1025193326Sed return true; 1026198092Srdivacky Ty = Context.getObjCObjectPointerType(Ty); 1027239462Sdim return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc); 1028193326Sed} 1029193326Sed 1030218893Sdim/// Try to capture an implicit reference to 'self'. 1031234353SdimObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { 1032234353Sdim DeclContext *DC = getFunctionLevelDeclContext(); 1033218893Sdim 1034218893Sdim // If we're not in an ObjC method, error out. Note that, unlike the 1035218893Sdim // C++ case, we don't require an instance method --- class methods 1036218893Sdim // still have a 'self', and we really do still need to capture it! 1037218893Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC); 1038218893Sdim if (!method) 1039218893Sdim return 0; 1040218893Sdim 1041234353Sdim tryCaptureVariable(method->getSelfDecl(), Loc); 1042218893Sdim 1043218893Sdim return method; 1044218893Sdim} 1045218893Sdim 1046226633Sdimstatic QualType stripObjCInstanceType(ASTContext &Context, QualType T) { 1047226633Sdim if (T == Context.getObjCInstanceType()) 1048226633Sdim return Context.getObjCIdType(); 1049226633Sdim 1050226633Sdim return T; 1051226633Sdim} 1052226633Sdim 1053223017SdimQualType Sema::getMessageSendResultType(QualType ReceiverType, 1054223017Sdim ObjCMethodDecl *Method, 1055223017Sdim bool isClassMessage, bool isSuperMessage) { 1056223017Sdim assert(Method && "Must have a method"); 1057223017Sdim if (!Method->hasRelatedResultType()) 1058223017Sdim return Method->getSendResultType(); 1059223017Sdim 1060223017Sdim // If a method has a related return type: 1061223017Sdim // - if the method found is an instance method, but the message send 1062223017Sdim // was a class message send, T is the declared return type of the method 1063223017Sdim // found 1064223017Sdim if (Method->isInstanceMethod() && isClassMessage) 1065226633Sdim return stripObjCInstanceType(Context, Method->getSendResultType()); 1066223017Sdim 1067223017Sdim // - if the receiver is super, T is a pointer to the class of the 1068223017Sdim // enclosing method definition 1069223017Sdim if (isSuperMessage) { 1070223017Sdim if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) 1071223017Sdim if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) 1072223017Sdim return Context.getObjCObjectPointerType( 1073223017Sdim Context.getObjCInterfaceType(Class)); 1074223017Sdim } 1075223017Sdim 1076223017Sdim // - if the receiver is the name of a class U, T is a pointer to U 1077223017Sdim if (ReceiverType->getAs<ObjCInterfaceType>() || 1078223017Sdim ReceiverType->isObjCQualifiedInterfaceType()) 1079223017Sdim return Context.getObjCObjectPointerType(ReceiverType); 1080223017Sdim // - if the receiver is of type Class or qualified Class type, 1081223017Sdim // T is the declared return type of the method. 1082223017Sdim if (ReceiverType->isObjCClassType() || 1083223017Sdim ReceiverType->isObjCQualifiedClassType()) 1084226633Sdim return stripObjCInstanceType(Context, Method->getSendResultType()); 1085223017Sdim 1086223017Sdim // - if the receiver is id, qualified id, Class, or qualified Class, T 1087223017Sdim // is the receiver type, otherwise 1088223017Sdim // - T is the type of the receiver expression. 1089223017Sdim return ReceiverType; 1090223017Sdim} 1091218893Sdim 1092249423Sdim/// Look for an ObjC method whose result type exactly matches the given type. 1093249423Sdimstatic const ObjCMethodDecl * 1094249423SdimfindExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD, 1095249423Sdim QualType instancetype) { 1096249423Sdim if (MD->getResultType() == instancetype) return MD; 1097249423Sdim 1098249423Sdim // For these purposes, a method in an @implementation overrides a 1099249423Sdim // declaration in the @interface. 1100249423Sdim if (const ObjCImplDecl *impl = 1101249423Sdim dyn_cast<ObjCImplDecl>(MD->getDeclContext())) { 1102249423Sdim const ObjCContainerDecl *iface; 1103249423Sdim if (const ObjCCategoryImplDecl *catImpl = 1104249423Sdim dyn_cast<ObjCCategoryImplDecl>(impl)) { 1105249423Sdim iface = catImpl->getCategoryDecl(); 1106249423Sdim } else { 1107249423Sdim iface = impl->getClassInterface(); 1108249423Sdim } 1109249423Sdim 1110249423Sdim const ObjCMethodDecl *ifaceMD = 1111249423Sdim iface->getMethod(MD->getSelector(), MD->isInstanceMethod()); 1112249423Sdim if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype); 1113249423Sdim } 1114249423Sdim 1115249423Sdim SmallVector<const ObjCMethodDecl *, 4> overrides; 1116249423Sdim MD->getOverriddenMethods(overrides); 1117249423Sdim for (unsigned i = 0, e = overrides.size(); i != e; ++i) { 1118249423Sdim if (const ObjCMethodDecl *result = 1119249423Sdim findExplicitInstancetypeDeclarer(overrides[i], instancetype)) 1120249423Sdim return result; 1121249423Sdim } 1122249423Sdim 1123249423Sdim return 0; 1124249423Sdim} 1125249423Sdim 1126249423Sdimvoid Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { 1127249423Sdim // Only complain if we're in an ObjC method and the required return 1128249423Sdim // type doesn't match the method's declared return type. 1129249423Sdim ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext); 1130249423Sdim if (!MD || !MD->hasRelatedResultType() || 1131249423Sdim Context.hasSameUnqualifiedType(destType, MD->getResultType())) 1132249423Sdim return; 1133249423Sdim 1134249423Sdim // Look for a method overridden by this method which explicitly uses 1135249423Sdim // 'instancetype'. 1136249423Sdim if (const ObjCMethodDecl *overridden = 1137249423Sdim findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) { 1138249423Sdim SourceLocation loc; 1139249423Sdim SourceRange range; 1140249423Sdim if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) { 1141249423Sdim range = TSI->getTypeLoc().getSourceRange(); 1142249423Sdim loc = range.getBegin(); 1143249423Sdim } 1144249423Sdim if (loc.isInvalid()) 1145249423Sdim loc = overridden->getLocation(); 1146249423Sdim Diag(loc, diag::note_related_result_type_explicit) 1147249423Sdim << /*current method*/ 1 << range; 1148249423Sdim return; 1149249423Sdim } 1150249423Sdim 1151249423Sdim // Otherwise, if we have an interesting method family, note that. 1152249423Sdim // This should always trigger if the above didn't. 1153249423Sdim if (ObjCMethodFamily family = MD->getMethodFamily()) 1154249423Sdim Diag(MD->getLocation(), diag::note_related_result_type_family) 1155249423Sdim << /*current method*/ 1 1156249423Sdim << family; 1157249423Sdim} 1158249423Sdim 1159223017Sdimvoid Sema::EmitRelatedResultTypeNote(const Expr *E) { 1160223017Sdim E = E->IgnoreParenImpCasts(); 1161223017Sdim const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E); 1162223017Sdim if (!MsgSend) 1163223017Sdim return; 1164223017Sdim 1165223017Sdim const ObjCMethodDecl *Method = MsgSend->getMethodDecl(); 1166223017Sdim if (!Method) 1167223017Sdim return; 1168223017Sdim 1169223017Sdim if (!Method->hasRelatedResultType()) 1170223017Sdim return; 1171223017Sdim 1172223017Sdim if (Context.hasSameUnqualifiedType(Method->getResultType() 1173223017Sdim .getNonReferenceType(), 1174223017Sdim MsgSend->getType())) 1175223017Sdim return; 1176223017Sdim 1177226633Sdim if (!Context.hasSameUnqualifiedType(Method->getResultType(), 1178226633Sdim Context.getObjCInstanceType())) 1179226633Sdim return; 1180226633Sdim 1181223017Sdim Diag(Method->getLocation(), diag::note_related_result_type_inferred) 1182223017Sdim << Method->isInstanceMethod() << Method->getSelector() 1183223017Sdim << MsgSend->getType(); 1184223017Sdim} 1185223017Sdim 1186223017Sdimbool Sema::CheckMessageArgumentTypes(QualType ReceiverType, 1187223017Sdim Expr **Args, unsigned NumArgs, 1188243830Sdim Selector Sel, 1189243830Sdim ArrayRef<SourceLocation> SelectorLocs, 1190243830Sdim ObjCMethodDecl *Method, 1191223017Sdim bool isClassMessage, bool isSuperMessage, 1192193326Sed SourceLocation lbrac, SourceLocation rbrac, 1193218893Sdim QualType &ReturnType, ExprValueKind &VK) { 1194251662Sdim SourceLocation SelLoc; 1195251662Sdim if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) 1196251662Sdim SelLoc = SelectorLocs.front(); 1197251662Sdim else 1198251662Sdim SelLoc = lbrac; 1199251662Sdim 1200193326Sed if (!Method) { 1201193326Sed // Apply default argument promotion as for (C99 6.5.2.2p6). 1202207619Srdivacky for (unsigned i = 0; i != NumArgs; i++) { 1203207619Srdivacky if (Args[i]->isTypeDependent()) 1204207619Srdivacky continue; 1205207619Srdivacky 1206249423Sdim ExprResult result; 1207249423Sdim if (getLangOpts().DebuggerSupport) { 1208249423Sdim QualType paramTy; // ignored 1209251662Sdim result = checkUnknownAnyArg(SelLoc, Args[i], paramTy); 1210249423Sdim } else { 1211249423Sdim result = DefaultArgumentPromotion(Args[i]); 1212249423Sdim } 1213249423Sdim if (result.isInvalid()) 1214221345Sdim return true; 1215249423Sdim Args[i] = result.take(); 1216207619Srdivacky } 1217193326Sed 1218224145Sdim unsigned DiagID; 1219234353Sdim if (getLangOpts().ObjCAutoRefCount) 1220224145Sdim DiagID = diag::err_arc_method_not_found; 1221224145Sdim else 1222224145Sdim DiagID = isClassMessage ? diag::warn_class_method_not_found 1223224145Sdim : diag::warn_inst_method_not_found; 1224234353Sdim if (!getLangOpts().DebuggerSupport) 1225251662Sdim Diag(SelLoc, DiagID) 1226243830Sdim << Sel << isClassMessage << SourceRange(SelectorLocs.front(), 1227243830Sdim SelectorLocs.back()); 1228224145Sdim 1229224145Sdim // In debuggers, we want to use __unknown_anytype for these 1230224145Sdim // results so that clients can cast them. 1231234353Sdim if (getLangOpts().DebuggerSupport) { 1232224145Sdim ReturnType = Context.UnknownAnyTy; 1233224145Sdim } else { 1234224145Sdim ReturnType = Context.getObjCIdType(); 1235224145Sdim } 1236218893Sdim VK = VK_RValue; 1237193326Sed return false; 1238193326Sed } 1239198092Srdivacky 1240223017Sdim ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, 1241223017Sdim isSuperMessage); 1242218893Sdim VK = Expr::getValueKindForType(Method->getResultType()); 1243198092Srdivacky 1244193326Sed unsigned NumNamedArgs = Sel.getNumArgs(); 1245207619Srdivacky // Method might have more arguments than selector indicates. This is due 1246207619Srdivacky // to addition of c-style arguments in method. 1247207619Srdivacky if (Method->param_size() > Sel.getNumArgs()) 1248207619Srdivacky NumNamedArgs = Method->param_size(); 1249207619Srdivacky // FIXME. This need be cleaned up. 1250207619Srdivacky if (NumArgs < NumNamedArgs) { 1251251662Sdim Diag(SelLoc, diag::err_typecheck_call_too_few_args) 1252218893Sdim << 2 << NumNamedArgs << NumArgs; 1253207619Srdivacky return false; 1254207619Srdivacky } 1255193326Sed 1256193326Sed bool IsError = false; 1257193326Sed for (unsigned i = 0; i < NumNamedArgs; i++) { 1258207619Srdivacky // We can't do any type-checking on a type-dependent argument. 1259207619Srdivacky if (Args[i]->isTypeDependent()) 1260207619Srdivacky continue; 1261207619Srdivacky 1262193326Sed Expr *argExpr = Args[i]; 1263207619Srdivacky 1264234353Sdim ParmVarDecl *param = Method->param_begin()[i]; 1265193326Sed assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 1266198092Srdivacky 1267234353Sdim // Strip the unbridged-cast placeholder expression off unless it's 1268234353Sdim // a consumed argument. 1269234353Sdim if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) && 1270234353Sdim !param->hasAttr<CFConsumedAttr>()) 1271234353Sdim argExpr = stripARCUnbridgedCast(argExpr); 1272234353Sdim 1273249423Sdim // If the parameter is __unknown_anytype, infer its type 1274249423Sdim // from the argument. 1275249423Sdim if (param->getType() == Context.UnknownAnyTy) { 1276249423Sdim QualType paramType; 1277251662Sdim ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType); 1278249423Sdim if (argE.isInvalid()) { 1279249423Sdim IsError = true; 1280249423Sdim } else { 1281249423Sdim Args[i] = argE.take(); 1282249423Sdim 1283249423Sdim // Update the parameter type in-place. 1284249423Sdim param->setType(paramType); 1285249423Sdim } 1286249423Sdim continue; 1287249423Sdim } 1288249423Sdim 1289207619Srdivacky if (RequireCompleteType(argExpr->getSourceRange().getBegin(), 1290234353Sdim param->getType(), 1291239462Sdim diag::err_call_incomplete_argument, argExpr)) 1292207619Srdivacky return true; 1293193326Sed 1294218893Sdim InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, 1295234353Sdim param); 1296251662Sdim ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, Owned(argExpr)); 1297207619Srdivacky if (ArgE.isInvalid()) 1298207619Srdivacky IsError = true; 1299207619Srdivacky else 1300207619Srdivacky Args[i] = ArgE.takeAs<Expr>(); 1301193326Sed } 1302193326Sed 1303193326Sed // Promote additional arguments to variadic methods. 1304193326Sed if (Method->isVariadic()) { 1305207619Srdivacky for (unsigned i = NumNamedArgs; i < NumArgs; ++i) { 1306207619Srdivacky if (Args[i]->isTypeDependent()) 1307207619Srdivacky continue; 1308207619Srdivacky 1309239462Sdim ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 1310239462Sdim 0); 1311221345Sdim IsError |= Arg.isInvalid(); 1312221345Sdim Args[i] = Arg.take(); 1313207619Srdivacky } 1314193326Sed } else { 1315193326Sed // Check for extra arguments to non-variadic methods. 1316193326Sed if (NumArgs != NumNamedArgs) { 1317198092Srdivacky Diag(Args[NumNamedArgs]->getLocStart(), 1318193326Sed diag::err_typecheck_call_too_many_args) 1319207619Srdivacky << 2 /*method*/ << NumNamedArgs << NumArgs 1320207619Srdivacky << Method->getSourceRange() 1321193326Sed << SourceRange(Args[NumNamedArgs]->getLocStart(), 1322193326Sed Args[NumArgs-1]->getLocEnd()); 1323193326Sed } 1324193326Sed } 1325193326Sed 1326251662Sdim DiagnoseSentinelCalls(Method, SelLoc, Args, NumArgs); 1327234353Sdim 1328234353Sdim // Do additional checkings on method. 1329251662Sdim IsError |= CheckObjCMethodCall(Method, SelLoc, 1330251662Sdim llvm::makeArrayRef<const Expr *>(Args, NumArgs)); 1331234353Sdim 1332193326Sed return IsError; 1333193326Sed} 1334193326Sed 1335224145Sdimbool Sema::isSelfExpr(Expr *receiver) { 1336221345Sdim // 'self' is objc 'self' in an objc method only. 1337234353Sdim ObjCMethodDecl *method = 1338251662Sdim dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); 1339234353Sdim if (!method) return false; 1340234353Sdim 1341224145Sdim receiver = receiver->IgnoreParenLValueCasts(); 1342224145Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver)) 1343234353Sdim if (DRE->getDecl() == method->getSelfDecl()) 1344193326Sed return true; 1345193326Sed return false; 1346193326Sed} 1347193326Sed 1348234353Sdim/// LookupMethodInType - Look up a method in an ObjCObjectType. 1349234353SdimObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, 1350234353Sdim bool isInstance) { 1351234353Sdim const ObjCObjectType *objType = type->castAs<ObjCObjectType>(); 1352234353Sdim if (ObjCInterfaceDecl *iface = objType->getInterface()) { 1353234353Sdim // Look it up in the main interface (and categories, etc.) 1354234353Sdim if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance)) 1355234353Sdim return method; 1356234353Sdim 1357234353Sdim // Okay, look for "private" methods declared in any 1358234353Sdim // @implementations we've seen. 1359239462Sdim if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance)) 1360239462Sdim return method; 1361234353Sdim } 1362234353Sdim 1363234353Sdim // Check qualifiers. 1364234353Sdim for (ObjCObjectType::qual_iterator 1365234353Sdim i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i) 1366234353Sdim if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance)) 1367234353Sdim return method; 1368234353Sdim 1369234353Sdim return 0; 1370234353Sdim} 1371234353Sdim 1372221345Sdim/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier 1373221345Sdim/// list of a qualified objective pointer type. 1374221345SdimObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, 1375221345Sdim const ObjCObjectPointerType *OPT, 1376221345Sdim bool Instance) 1377221345Sdim{ 1378221345Sdim ObjCMethodDecl *MD = 0; 1379221345Sdim for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), 1380221345Sdim E = OPT->qual_end(); I != E; ++I) { 1381221345Sdim ObjCProtocolDecl *PROTO = (*I); 1382221345Sdim if ((MD = PROTO->lookupMethod(Sel, Instance))) { 1383221345Sdim return MD; 1384221345Sdim } 1385221345Sdim } 1386221345Sdim return 0; 1387221345Sdim} 1388221345Sdim 1389239462Sdimstatic void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { 1390239462Sdim if (!Receiver) 1391239462Sdim return; 1392239462Sdim 1393239462Sdim if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Receiver)) 1394239462Sdim Receiver = OVE->getSourceExpr(); 1395239462Sdim 1396239462Sdim Expr *RExpr = Receiver->IgnoreParenImpCasts(); 1397239462Sdim SourceLocation Loc = RExpr->getLocStart(); 1398239462Sdim QualType T = RExpr->getType(); 1399243830Sdim const ObjCPropertyDecl *PDecl = 0; 1400243830Sdim const ObjCMethodDecl *GDecl = 0; 1401239462Sdim if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) { 1402239462Sdim RExpr = POE->getSyntacticForm(); 1403239462Sdim if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) { 1404239462Sdim if (PRE->isImplicitProperty()) { 1405239462Sdim GDecl = PRE->getImplicitPropertyGetter(); 1406239462Sdim if (GDecl) { 1407239462Sdim T = GDecl->getResultType(); 1408239462Sdim } 1409239462Sdim } 1410239462Sdim else { 1411239462Sdim PDecl = PRE->getExplicitProperty(); 1412239462Sdim if (PDecl) { 1413239462Sdim T = PDecl->getType(); 1414239462Sdim } 1415239462Sdim } 1416239462Sdim } 1417239462Sdim } 1418239462Sdim else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RExpr)) { 1419239462Sdim // See if receiver is a method which envokes a synthesized getter 1420239462Sdim // backing a 'weak' property. 1421239462Sdim ObjCMethodDecl *Method = ME->getMethodDecl(); 1422243830Sdim if (Method && Method->getSelector().getNumArgs() == 0) { 1423243830Sdim PDecl = Method->findPropertyDecl(); 1424239462Sdim if (PDecl) 1425239462Sdim T = PDecl->getType(); 1426239462Sdim } 1427239462Sdim } 1428239462Sdim 1429243830Sdim if (T.getObjCLifetime() != Qualifiers::OCL_Weak) { 1430243830Sdim if (!PDecl) 1431243830Sdim return; 1432243830Sdim if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)) 1433243830Sdim return; 1434239462Sdim } 1435243830Sdim 1436243830Sdim S.Diag(Loc, diag::warn_receiver_is_weak) 1437243830Sdim << ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2)); 1438243830Sdim 1439243830Sdim if (PDecl) 1440239462Sdim S.Diag(PDecl->getLocation(), diag::note_property_declare); 1441243830Sdim else if (GDecl) 1442243830Sdim S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl; 1443243830Sdim 1444243830Sdim S.Diag(Loc, diag::note_arc_assign_to_strong); 1445239462Sdim} 1446239462Sdim 1447207619Srdivacky/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an 1448207619Srdivacky/// objective C interface. This is a property reference expression. 1449212904SdimExprResult Sema:: 1450207619SrdivackyHandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, 1451224145Sdim Expr *BaseExpr, SourceLocation OpLoc, 1452224145Sdim DeclarationName MemberName, 1453218893Sdim SourceLocation MemberLoc, 1454218893Sdim SourceLocation SuperLoc, QualType SuperType, 1455218893Sdim bool Super) { 1456207619Srdivacky const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); 1457207619Srdivacky ObjCInterfaceDecl *IFace = IFaceT->getDecl(); 1458239462Sdim 1459239462Sdim if (!MemberName.isIdentifier()) { 1460221345Sdim Diag(MemberLoc, diag::err_invalid_property_name) 1461221345Sdim << MemberName << QualType(OPT, 0); 1462221345Sdim return ExprError(); 1463221345Sdim } 1464239462Sdim 1465239462Sdim IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); 1466221345Sdim 1467234353Sdim SourceRange BaseRange = Super? SourceRange(SuperLoc) 1468234353Sdim : BaseExpr->getSourceRange(); 1469234353Sdim if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), 1470239462Sdim diag::err_property_not_found_forward_class, 1471239462Sdim MemberName, BaseRange)) 1472218893Sdim return ExprError(); 1473234353Sdim 1474207619Srdivacky // Search for a declared property first. 1475207619Srdivacky if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { 1476207619Srdivacky // Check whether we can reference this property. 1477207619Srdivacky if (DiagnoseUseOfDecl(PD, MemberLoc)) 1478207619Srdivacky return ExprError(); 1479218893Sdim if (Super) 1480234353Sdim return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, 1481218893Sdim VK_LValue, OK_ObjCProperty, 1482218893Sdim MemberLoc, 1483218893Sdim SuperLoc, SuperType)); 1484218893Sdim else 1485234353Sdim return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, 1486218893Sdim VK_LValue, OK_ObjCProperty, 1487218893Sdim MemberLoc, BaseExpr)); 1488207619Srdivacky } 1489207619Srdivacky // Check protocols on qualified interfaces. 1490207619Srdivacky for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), 1491207619Srdivacky E = OPT->qual_end(); I != E; ++I) 1492207619Srdivacky if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { 1493207619Srdivacky // Check whether we can reference this property. 1494207619Srdivacky if (DiagnoseUseOfDecl(PD, MemberLoc)) 1495207619Srdivacky return ExprError(); 1496239462Sdim 1497218893Sdim if (Super) 1498234353Sdim return Owned(new (Context) ObjCPropertyRefExpr(PD, 1499234353Sdim Context.PseudoObjectTy, 1500218893Sdim VK_LValue, 1501218893Sdim OK_ObjCProperty, 1502218893Sdim MemberLoc, 1503218893Sdim SuperLoc, SuperType)); 1504218893Sdim else 1505234353Sdim return Owned(new (Context) ObjCPropertyRefExpr(PD, 1506234353Sdim Context.PseudoObjectTy, 1507218893Sdim VK_LValue, 1508218893Sdim OK_ObjCProperty, 1509218893Sdim MemberLoc, 1510218893Sdim BaseExpr)); 1511207619Srdivacky } 1512207619Srdivacky // If that failed, look for an "implicit" property by seeing if the nullary 1513207619Srdivacky // selector is implemented. 1514207619Srdivacky 1515207619Srdivacky // FIXME: The logic for looking up nullary and unary selectors should be 1516207619Srdivacky // shared with the code in ActOnInstanceMessage. 1517207619Srdivacky 1518207619Srdivacky Selector Sel = PP.getSelectorTable().getNullarySelector(Member); 1519207619Srdivacky ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); 1520221345Sdim 1521221345Sdim // May be founf in property's qualified list. 1522221345Sdim if (!Getter) 1523221345Sdim Getter = LookupMethodInQualifiedType(Sel, OPT, true); 1524207619Srdivacky 1525207619Srdivacky // If this reference is in an @implementation, check for 'private' methods. 1526207619Srdivacky if (!Getter) 1527218893Sdim Getter = IFace->lookupPrivateMethod(Sel); 1528207619Srdivacky 1529207619Srdivacky if (Getter) { 1530207619Srdivacky // Check if we can reference this property. 1531207619Srdivacky if (DiagnoseUseOfDecl(Getter, MemberLoc)) 1532207619Srdivacky return ExprError(); 1533207619Srdivacky } 1534207619Srdivacky // If we found a getter then this may be a valid dot-reference, we 1535207619Srdivacky // will look for the matching setter, in case it is needed. 1536207619Srdivacky Selector SetterSel = 1537207619Srdivacky SelectorTable::constructSetterName(PP.getIdentifierTable(), 1538207619Srdivacky PP.getSelectorTable(), Member); 1539207619Srdivacky ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); 1540239462Sdim 1541221345Sdim // May be founf in property's qualified list. 1542221345Sdim if (!Setter) 1543221345Sdim Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); 1544221345Sdim 1545207619Srdivacky if (!Setter) { 1546207619Srdivacky // If this reference is in an @implementation, also check for 'private' 1547207619Srdivacky // methods. 1548218893Sdim Setter = IFace->lookupPrivateMethod(SetterSel); 1549207619Srdivacky } 1550221345Sdim 1551207619Srdivacky if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) 1552206084Srdivacky return ExprError(); 1553207619Srdivacky 1554218893Sdim if (Getter || Setter) { 1555218893Sdim if (Super) 1556218893Sdim return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, 1557234353Sdim Context.PseudoObjectTy, 1558234353Sdim VK_LValue, OK_ObjCProperty, 1559218893Sdim MemberLoc, 1560218893Sdim SuperLoc, SuperType)); 1561218893Sdim else 1562218893Sdim return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, 1563234353Sdim Context.PseudoObjectTy, 1564234353Sdim VK_LValue, OK_ObjCProperty, 1565218893Sdim MemberLoc, BaseExpr)); 1566218893Sdim 1567206084Srdivacky } 1568207619Srdivacky 1569207619Srdivacky // Attempt to correct for typos in property names. 1570234353Sdim DeclFilterCCC<ObjCPropertyDecl> Validator; 1571234353Sdim if (TypoCorrection Corrected = CorrectTypo( 1572224145Sdim DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, 1573234353Sdim NULL, Validator, IFace, false, OPT)) { 1574234353Sdim ObjCPropertyDecl *Property = 1575234353Sdim Corrected.getCorrectionDeclAs<ObjCPropertyDecl>(); 1576224145Sdim DeclarationName TypoResult = Corrected.getCorrection(); 1577207619Srdivacky Diag(MemberLoc, diag::err_property_not_found_suggest) 1578207619Srdivacky << MemberName << QualType(OPT, 0) << TypoResult 1579207619Srdivacky << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); 1580207619Srdivacky Diag(Property->getLocation(), diag::note_previous_decl) 1581207619Srdivacky << Property->getDeclName(); 1582224145Sdim return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, 1583224145Sdim TypoResult, MemberLoc, 1584218893Sdim SuperLoc, SuperType, Super); 1585207619Srdivacky } 1586218893Sdim ObjCInterfaceDecl *ClassDeclared; 1587218893Sdim if (ObjCIvarDecl *Ivar = 1588218893Sdim IFace->lookupInstanceVariable(Member, ClassDeclared)) { 1589218893Sdim QualType T = Ivar->getType(); 1590218893Sdim if (const ObjCObjectPointerType * OBJPT = 1591218893Sdim T->getAsObjCInterfacePointerType()) { 1592234353Sdim if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), 1593239462Sdim diag::err_property_not_as_forward_class, 1594239462Sdim MemberName, BaseExpr)) 1595234353Sdim return ExprError(); 1596218893Sdim } 1597224145Sdim Diag(MemberLoc, 1598224145Sdim diag::err_ivar_access_using_property_syntax_suggest) 1599224145Sdim << MemberName << QualType(OPT, 0) << Ivar->getDeclName() 1600224145Sdim << FixItHint::CreateReplacement(OpLoc, "->"); 1601224145Sdim return ExprError(); 1602218893Sdim } 1603207619Srdivacky 1604207619Srdivacky Diag(MemberLoc, diag::err_property_not_found) 1605207619Srdivacky << MemberName << QualType(OPT, 0); 1606218893Sdim if (Setter) 1607207619Srdivacky Diag(Setter->getLocation(), diag::note_getter_unavailable) 1608218893Sdim << MemberName << BaseExpr->getSourceRange(); 1609207619Srdivacky return ExprError(); 1610207619Srdivacky} 1611207619Srdivacky 1612207619Srdivacky 1613207619Srdivacky 1614212904SdimExprResult Sema:: 1615207619SrdivackyActOnClassPropertyRefExpr(IdentifierInfo &receiverName, 1616207619Srdivacky IdentifierInfo &propertyName, 1617207619Srdivacky SourceLocation receiverNameLoc, 1618207619Srdivacky SourceLocation propertyNameLoc) { 1619207619Srdivacky 1620207619Srdivacky IdentifierInfo *receiverNamePtr = &receiverName; 1621207619Srdivacky ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr, 1622207619Srdivacky receiverNameLoc); 1623223017Sdim 1624223017Sdim bool IsSuper = false; 1625207619Srdivacky if (IFace == 0) { 1626207619Srdivacky // If the "receiver" is 'super' in a method, handle it as an expression-like 1627207619Srdivacky // property reference. 1628218893Sdim if (receiverNamePtr->isStr("super")) { 1629223017Sdim IsSuper = true; 1630223017Sdim 1631234353Sdim if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { 1632207619Srdivacky if (CurMethod->isInstanceMethod()) { 1633249423Sdim ObjCInterfaceDecl *Super = 1634249423Sdim CurMethod->getClassInterface()->getSuperClass(); 1635249423Sdim if (!Super) { 1636249423Sdim // The current class does not have a superclass. 1637249423Sdim Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) 1638249423Sdim << CurMethod->getClassInterface()->getIdentifier(); 1639249423Sdim return ExprError(); 1640249423Sdim } 1641249423Sdim QualType T = Context.getObjCInterfaceType(Super); 1642207619Srdivacky T = Context.getObjCObjectPointerType(T); 1643207619Srdivacky 1644207619Srdivacky return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), 1645224145Sdim /*BaseExpr*/0, 1646224145Sdim SourceLocation()/*OpLoc*/, 1647224145Sdim &propertyName, 1648218893Sdim propertyNameLoc, 1649218893Sdim receiverNameLoc, T, true); 1650207619Srdivacky } 1651207619Srdivacky 1652207619Srdivacky // Otherwise, if this is a class method, try dispatching to our 1653207619Srdivacky // superclass. 1654207619Srdivacky IFace = CurMethod->getClassInterface()->getSuperClass(); 1655207619Srdivacky } 1656218893Sdim } 1657207619Srdivacky 1658207619Srdivacky if (IFace == 0) { 1659207619Srdivacky Diag(receiverNameLoc, diag::err_expected_ident_or_lparen); 1660207619Srdivacky return ExprError(); 1661207619Srdivacky } 1662207619Srdivacky } 1663207619Srdivacky 1664193326Sed // Search for a declared property first. 1665193326Sed Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName); 1666195341Sed ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel); 1667193326Sed 1668193326Sed // If this reference is in an @implementation, check for 'private' methods. 1669193326Sed if (!Getter) 1670193326Sed if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) 1671193326Sed if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) 1672198092Srdivacky if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) 1673195341Sed Getter = ImpDecl->getClassMethod(Sel); 1674193326Sed 1675193326Sed if (Getter) { 1676193326Sed // FIXME: refactor/share with ActOnMemberReference(). 1677193326Sed // Check if we can reference this property. 1678193326Sed if (DiagnoseUseOfDecl(Getter, propertyNameLoc)) 1679193326Sed return ExprError(); 1680193326Sed } 1681198092Srdivacky 1682193326Sed // Look for the matching setter, in case it is needed. 1683198092Srdivacky Selector SetterSel = 1684198092Srdivacky SelectorTable::constructSetterName(PP.getIdentifierTable(), 1685193326Sed PP.getSelectorTable(), &propertyName); 1686198092Srdivacky 1687195341Sed ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); 1688193326Sed if (!Setter) { 1689193326Sed // If this reference is in an @implementation, also check for 'private' 1690193326Sed // methods. 1691193326Sed if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) 1692193326Sed if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) 1693198092Srdivacky if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) 1694195341Sed Setter = ImpDecl->getClassMethod(SetterSel); 1695193326Sed } 1696193326Sed // Look through local category implementations associated with the class. 1697198092Srdivacky if (!Setter) 1698198092Srdivacky Setter = IFace->getCategoryClassMethod(SetterSel); 1699193326Sed 1700193326Sed if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc)) 1701193326Sed return ExprError(); 1702193326Sed 1703193326Sed if (Getter || Setter) { 1704223017Sdim if (IsSuper) 1705218893Sdim return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, 1706234353Sdim Context.PseudoObjectTy, 1707234353Sdim VK_LValue, OK_ObjCProperty, 1708218893Sdim propertyNameLoc, 1709223017Sdim receiverNameLoc, 1710223017Sdim Context.getObjCInterfaceType(IFace))); 1711223017Sdim 1712223017Sdim return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, 1713234353Sdim Context.PseudoObjectTy, 1714234353Sdim VK_LValue, OK_ObjCProperty, 1715223017Sdim propertyNameLoc, 1716218893Sdim receiverNameLoc, IFace)); 1717193326Sed } 1718193326Sed return ExprError(Diag(propertyNameLoc, diag::err_property_not_found) 1719193326Sed << &propertyName << Context.getObjCInterfaceType(IFace)); 1720193326Sed} 1721193326Sed 1722234353Sdimnamespace { 1723234353Sdim 1724234353Sdimclass ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { 1725234353Sdim public: 1726234353Sdim ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { 1727234353Sdim // Determine whether "super" is acceptable in the current context. 1728234353Sdim if (Method && Method->getClassInterface()) 1729234353Sdim WantObjCSuper = Method->getClassInterface()->getSuperClass(); 1730234353Sdim } 1731234353Sdim 1732234353Sdim virtual bool ValidateCandidate(const TypoCorrection &candidate) { 1733234353Sdim return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() || 1734234353Sdim candidate.isKeyword("super"); 1735234353Sdim } 1736234353Sdim}; 1737234353Sdim 1738234353Sdim} 1739234353Sdim 1740207619SrdivackySema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, 1741207619Srdivacky IdentifierInfo *Name, 1742207619Srdivacky SourceLocation NameLoc, 1743207619Srdivacky bool IsSuper, 1744207619Srdivacky bool HasTrailingDot, 1745212904Sdim ParsedType &ReceiverType) { 1746212904Sdim ReceiverType = ParsedType(); 1747193326Sed 1748207619Srdivacky // If the identifier is "super" and there is no trailing dot, we're 1749218893Sdim // messaging super. If the identifier is "super" and there is a 1750218893Sdim // trailing dot, it's an instance message. 1751218893Sdim if (IsSuper && S->isInObjcMethodScope()) 1752218893Sdim return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage; 1753207619Srdivacky 1754207619Srdivacky LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); 1755207619Srdivacky LookupName(Result, S); 1756207619Srdivacky 1757207619Srdivacky switch (Result.getResultKind()) { 1758207619Srdivacky case LookupResult::NotFound: 1759207619Srdivacky // Normal name lookup didn't find anything. If we're in an 1760207619Srdivacky // Objective-C method, look for ivars. If we find one, we're done! 1761218893Sdim // FIXME: This is a hack. Ivar lookup should be part of normal 1762218893Sdim // lookup. 1763207619Srdivacky if (ObjCMethodDecl *Method = getCurMethodDecl()) { 1764234353Sdim if (!Method->getClassInterface()) { 1765234353Sdim // Fall back: let the parser try to parse it as an instance message. 1766234353Sdim return ObjCInstanceMessage; 1767234353Sdim } 1768234353Sdim 1769207619Srdivacky ObjCInterfaceDecl *ClassDeclared; 1770207619Srdivacky if (Method->getClassInterface()->lookupInstanceVariable(Name, 1771207619Srdivacky ClassDeclared)) 1772207619Srdivacky return ObjCInstanceMessage; 1773207619Srdivacky } 1774218893Sdim 1775207619Srdivacky // Break out; we'll perform typo correction below. 1776207619Srdivacky break; 1777193326Sed 1778207619Srdivacky case LookupResult::NotFoundInCurrentInstantiation: 1779207619Srdivacky case LookupResult::FoundOverloaded: 1780207619Srdivacky case LookupResult::FoundUnresolvedValue: 1781207619Srdivacky case LookupResult::Ambiguous: 1782207619Srdivacky Result.suppressDiagnostics(); 1783207619Srdivacky return ObjCInstanceMessage; 1784198092Srdivacky 1785207619Srdivacky case LookupResult::Found: { 1786218893Sdim // If the identifier is a class or not, and there is a trailing dot, 1787218893Sdim // it's an instance message. 1788218893Sdim if (HasTrailingDot) 1789218893Sdim return ObjCInstanceMessage; 1790207619Srdivacky // We found something. If it's a type, then we have a class 1791207619Srdivacky // message. Otherwise, it's an instance message. 1792207619Srdivacky NamedDecl *ND = Result.getFoundDecl(); 1793207619Srdivacky QualType T; 1794207619Srdivacky if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) 1795207619Srdivacky T = Context.getObjCInterfaceType(Class); 1796249423Sdim else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) { 1797207619Srdivacky T = Context.getTypeDeclType(Type); 1798249423Sdim DiagnoseUseOfDecl(Type, NameLoc); 1799249423Sdim } 1800249423Sdim else 1801207619Srdivacky return ObjCInstanceMessage; 1802207619Srdivacky 1803207619Srdivacky // We have a class message, and T is the type we're 1804207619Srdivacky // messaging. Build source-location information for it. 1805207619Srdivacky TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); 1806212904Sdim ReceiverType = CreateParsedType(T, TSInfo); 1807207619Srdivacky return ObjCClassMessage; 1808207619Srdivacky } 1809207619Srdivacky } 1810207619Srdivacky 1811234353Sdim ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl()); 1812224145Sdim if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), 1813224145Sdim Result.getLookupKind(), S, NULL, 1814234353Sdim Validator)) { 1815234353Sdim if (Corrected.isKeyword()) { 1816234353Sdim // If we've found the keyword "super" (the only keyword that would be 1817234353Sdim // returned by CorrectTypo), this is a send to super. 1818234353Sdim Diag(NameLoc, diag::err_unknown_receiver_suggest) 1819234353Sdim << Name << Corrected.getCorrection() 1820234353Sdim << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); 1821234353Sdim return ObjCSuperMessage; 1822234353Sdim } else if (ObjCInterfaceDecl *Class = 1823234353Sdim Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { 1824207619Srdivacky // If we found a declaration, correct when it refers to an Objective-C 1825207619Srdivacky // class. 1826207619Srdivacky Diag(NameLoc, diag::err_unknown_receiver_suggest) 1827224145Sdim << Name << Corrected.getCorrection() 1828234353Sdim << FixItHint::CreateReplacement(SourceRange(NameLoc), 1829234353Sdim Class->getNameAsString()); 1830234353Sdim Diag(Class->getLocation(), diag::note_previous_decl) 1831234353Sdim << Corrected.getCorrection(); 1832234353Sdim 1833234353Sdim QualType T = Context.getObjCInterfaceType(Class); 1834234353Sdim TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); 1835234353Sdim ReceiverType = CreateParsedType(T, TSInfo); 1836234353Sdim return ObjCClassMessage; 1837198092Srdivacky } 1838207619Srdivacky } 1839207619Srdivacky 1840207619Srdivacky // Fall back: let the parser try to parse it as an instance message. 1841207619Srdivacky return ObjCInstanceMessage; 1842207619Srdivacky} 1843198092Srdivacky 1844212904SdimExprResult Sema::ActOnSuperMessage(Scope *S, 1845218893Sdim SourceLocation SuperLoc, 1846218893Sdim Selector Sel, 1847218893Sdim SourceLocation LBracLoc, 1848226633Sdim ArrayRef<SourceLocation> SelectorLocs, 1849218893Sdim SourceLocation RBracLoc, 1850218893Sdim MultiExprArg Args) { 1851207619Srdivacky // Determine whether we are inside a method or not. 1852234353Sdim ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc); 1853207619Srdivacky if (!Method) { 1854207619Srdivacky Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); 1855207619Srdivacky return ExprError(); 1856207619Srdivacky } 1857204643Srdivacky 1858207619Srdivacky ObjCInterfaceDecl *Class = Method->getClassInterface(); 1859207619Srdivacky if (!Class) { 1860207619Srdivacky Diag(SuperLoc, diag::error_no_super_class_message) 1861207619Srdivacky << Method->getDeclName(); 1862207619Srdivacky return ExprError(); 1863193326Sed } 1864207619Srdivacky 1865207619Srdivacky ObjCInterfaceDecl *Super = Class->getSuperClass(); 1866207619Srdivacky if (!Super) { 1867207619Srdivacky // The current class does not have a superclass. 1868218893Sdim Diag(SuperLoc, diag::error_root_class_cannot_use_super) 1869218893Sdim << Class->getIdentifier(); 1870207619Srdivacky return ExprError(); 1871193326Sed } 1872198092Srdivacky 1873207619Srdivacky // We are in a method whose class has a superclass, so 'super' 1874207619Srdivacky // is acting as a keyword. 1875243830Sdim if (Method->getSelector() == Sel) 1876243830Sdim getCurFunction()->ObjCShouldCallSuper = false; 1877243830Sdim 1878207619Srdivacky if (Method->isInstanceMethod()) { 1879207619Srdivacky // Since we are in an instance method, this is an instance 1880207619Srdivacky // message to the superclass instance. 1881207619Srdivacky QualType SuperTy = Context.getObjCInterfaceType(Super); 1882207619Srdivacky SuperTy = Context.getObjCObjectPointerType(SuperTy); 1883212904Sdim return BuildInstanceMessage(0, SuperTy, SuperLoc, 1884218893Sdim Sel, /*Method=*/0, 1885243830Sdim LBracLoc, SelectorLocs, RBracLoc, Args); 1886207619Srdivacky } 1887207619Srdivacky 1888207619Srdivacky // Since we are in a class method, this is a class message to 1889207619Srdivacky // the superclass. 1890207619Srdivacky return BuildClassMessage(/*ReceiverTypeInfo=*/0, 1891207619Srdivacky Context.getObjCInterfaceType(Super), 1892218893Sdim SuperLoc, Sel, /*Method=*/0, 1893243830Sdim LBracLoc, SelectorLocs, RBracLoc, Args); 1894207619Srdivacky} 1895193326Sed 1896234353Sdim 1897234353SdimExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType, 1898234353Sdim bool isSuperReceiver, 1899234353Sdim SourceLocation Loc, 1900234353Sdim Selector Sel, 1901234353Sdim ObjCMethodDecl *Method, 1902234353Sdim MultiExprArg Args) { 1903234353Sdim TypeSourceInfo *receiverTypeInfo = 0; 1904234353Sdim if (!ReceiverType.isNull()) 1905234353Sdim receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType); 1906234353Sdim 1907234353Sdim return BuildClassMessage(receiverTypeInfo, ReceiverType, 1908234353Sdim /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(), 1909234353Sdim Sel, Method, Loc, Loc, Loc, Args, 1910234353Sdim /*isImplicit=*/true); 1911234353Sdim 1912234353Sdim} 1913234353Sdim 1914234353Sdimstatic void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, 1915234353Sdim unsigned DiagID, 1916234353Sdim bool (*refactor)(const ObjCMessageExpr *, 1917234353Sdim const NSAPI &, edit::Commit &)) { 1918234353Sdim SourceLocation MsgLoc = Msg->getExprLoc(); 1919234353Sdim if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored) 1920234353Sdim return; 1921234353Sdim 1922234353Sdim SourceManager &SM = S.SourceMgr; 1923234353Sdim edit::Commit ECommit(SM, S.LangOpts); 1924234353Sdim if (refactor(Msg,*S.NSAPIObj, ECommit)) { 1925234353Sdim DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID) 1926234353Sdim << Msg->getSelector() << Msg->getSourceRange(); 1927234353Sdim // FIXME: Don't emit diagnostic at all if fixits are non-commitable. 1928234353Sdim if (!ECommit.isCommitable()) 1929234353Sdim return; 1930234353Sdim for (edit::Commit::edit_iterator 1931234353Sdim I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) { 1932234353Sdim const edit::Commit::Edit &Edit = *I; 1933234353Sdim switch (Edit.Kind) { 1934234353Sdim case edit::Commit::Act_Insert: 1935234353Sdim Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc, 1936234353Sdim Edit.Text, 1937234353Sdim Edit.BeforePrev)); 1938234353Sdim break; 1939234353Sdim case edit::Commit::Act_InsertFromRange: 1940234353Sdim Builder.AddFixItHint( 1941234353Sdim FixItHint::CreateInsertionFromRange(Edit.OrigLoc, 1942234353Sdim Edit.getInsertFromRange(SM), 1943234353Sdim Edit.BeforePrev)); 1944234353Sdim break; 1945234353Sdim case edit::Commit::Act_Remove: 1946234353Sdim Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM))); 1947234353Sdim break; 1948234353Sdim } 1949234353Sdim } 1950234353Sdim } 1951234353Sdim} 1952234353Sdim 1953234353Sdimstatic void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) { 1954234353Sdim applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use, 1955234353Sdim edit::rewriteObjCRedundantCallWithLiteral); 1956234353Sdim} 1957234353Sdim 1958207619Srdivacky/// \brief Build an Objective-C class message expression. 1959207619Srdivacky/// 1960207619Srdivacky/// This routine takes care of both normal class messages and 1961207619Srdivacky/// class messages to the superclass. 1962207619Srdivacky/// 1963207619Srdivacky/// \param ReceiverTypeInfo Type source information that describes the 1964207619Srdivacky/// receiver of this message. This may be NULL, in which case we are 1965207619Srdivacky/// sending to the superclass and \p SuperLoc must be a valid source 1966207619Srdivacky/// location. 1967198092Srdivacky 1968207619Srdivacky/// \param ReceiverType The type of the object receiving the 1969207619Srdivacky/// message. When \p ReceiverTypeInfo is non-NULL, this is the same 1970207619Srdivacky/// type as that refers to. For a superclass send, this is the type of 1971207619Srdivacky/// the superclass. 1972207619Srdivacky/// 1973207619Srdivacky/// \param SuperLoc The location of the "super" keyword in a 1974207619Srdivacky/// superclass message. 1975207619Srdivacky/// 1976207619Srdivacky/// \param Sel The selector to which the message is being sent. 1977207619Srdivacky/// 1978207619Srdivacky/// \param Method The method that this class message is invoking, if 1979207619Srdivacky/// already known. 1980207619Srdivacky/// 1981207619Srdivacky/// \param LBracLoc The location of the opening square bracket ']'. 1982207619Srdivacky/// 1983239462Sdim/// \param RBracLoc The location of the closing square bracket ']'. 1984207619Srdivacky/// 1985239462Sdim/// \param ArgsIn The message arguments. 1986212904SdimExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, 1987218893Sdim QualType ReceiverType, 1988218893Sdim SourceLocation SuperLoc, 1989218893Sdim Selector Sel, 1990218893Sdim ObjCMethodDecl *Method, 1991218893Sdim SourceLocation LBracLoc, 1992226633Sdim ArrayRef<SourceLocation> SelectorLocs, 1993218893Sdim SourceLocation RBracLoc, 1994234353Sdim MultiExprArg ArgsIn, 1995234353Sdim bool isImplicit) { 1996218893Sdim SourceLocation Loc = SuperLoc.isValid()? SuperLoc 1997218893Sdim : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); 1998218893Sdim if (LBracLoc.isInvalid()) { 1999218893Sdim Diag(Loc, diag::err_missing_open_square_message_send) 2000218893Sdim << FixItHint::CreateInsertion(Loc, "["); 2001218893Sdim LBracLoc = Loc; 2002218893Sdim } 2003251662Sdim SourceLocation SelLoc; 2004251662Sdim if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) 2005251662Sdim SelLoc = SelectorLocs.front(); 2006251662Sdim else 2007251662Sdim SelLoc = Loc; 2008251662Sdim 2009207619Srdivacky if (ReceiverType->isDependentType()) { 2010207619Srdivacky // If the receiver type is dependent, we can't type-check anything 2011207619Srdivacky // at this point. Build a dependent expression. 2012207619Srdivacky unsigned NumArgs = ArgsIn.size(); 2013243830Sdim Expr **Args = ArgsIn.data(); 2014207619Srdivacky assert(SuperLoc.isInvalid() && "Message to super with dependent type"); 2015218893Sdim return Owned(ObjCMessageExpr::Create(Context, ReceiverType, 2016218893Sdim VK_RValue, LBracLoc, ReceiverTypeInfo, 2017226633Sdim Sel, SelectorLocs, /*Method=*/0, 2018234353Sdim makeArrayRef(Args, NumArgs),RBracLoc, 2019234353Sdim isImplicit)); 2020207619Srdivacky } 2021207619Srdivacky 2022207619Srdivacky // Find the class to which we are sending this message. 2023207619Srdivacky ObjCInterfaceDecl *Class = 0; 2024208600Srdivacky const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>(); 2025208600Srdivacky if (!ClassType || !(Class = ClassType->getInterface())) { 2026207619Srdivacky Diag(Loc, diag::err_invalid_receiver_class_message) 2027207619Srdivacky << ReceiverType; 2028207619Srdivacky return ExprError(); 2029207619Srdivacky } 2030207619Srdivacky assert(Class && "We don't know which class we're messaging?"); 2031234353Sdim // objc++ diagnoses during typename annotation. 2032234353Sdim if (!getLangOpts().CPlusPlus) 2033251662Sdim (void)DiagnoseUseOfDecl(Class, SelLoc); 2034207619Srdivacky // Find the method we are messaging. 2035207619Srdivacky if (!Method) { 2036234353Sdim SourceRange TypeRange 2037234353Sdim = SuperLoc.isValid()? SourceRange(SuperLoc) 2038234353Sdim : ReceiverTypeInfo->getTypeLoc().getSourceRange(); 2039239462Sdim if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), 2040234353Sdim (getLangOpts().ObjCAutoRefCount 2041239462Sdim ? diag::err_arc_receiver_forward_class 2042239462Sdim : diag::warn_receiver_forward_class), 2043239462Sdim TypeRange)) { 2044207619Srdivacky // A forward class used in messaging is treated as a 'Class' 2045207619Srdivacky Method = LookupFactoryMethodInGlobalPool(Sel, 2046207619Srdivacky SourceRange(LBracLoc, RBracLoc)); 2047234353Sdim if (Method && !getLangOpts().ObjCAutoRefCount) 2048207619Srdivacky Diag(Method->getLocation(), diag::note_method_sent_forward_class) 2049207619Srdivacky << Method->getDeclName(); 2050207619Srdivacky } 2051207619Srdivacky if (!Method) 2052207619Srdivacky Method = Class->lookupClassMethod(Sel); 2053207619Srdivacky 2054207619Srdivacky // If we have an implementation in scope, check "private" methods. 2055207619Srdivacky if (!Method) 2056239462Sdim Method = Class->lookupPrivateClassMethod(Sel); 2057207619Srdivacky 2058251662Sdim if (Method && DiagnoseUseOfDecl(Method, SelLoc)) 2059207619Srdivacky return ExprError(); 2060207619Srdivacky } 2061207619Srdivacky 2062207619Srdivacky // Check the argument types and determine the result type. 2063207619Srdivacky QualType ReturnType; 2064218893Sdim ExprValueKind VK = VK_RValue; 2065218893Sdim 2066207619Srdivacky unsigned NumArgs = ArgsIn.size(); 2067243830Sdim Expr **Args = ArgsIn.data(); 2068243830Sdim if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, SelectorLocs, 2069243830Sdim Method, true, 2070223017Sdim SuperLoc.isValid(), LBracLoc, RBracLoc, 2071223017Sdim ReturnType, VK)) 2072207619Srdivacky return ExprError(); 2073207619Srdivacky 2074218893Sdim if (Method && !Method->getResultType()->isVoidType() && 2075218893Sdim RequireCompleteType(LBracLoc, Method->getResultType(), 2076218893Sdim diag::err_illegal_message_expr_incomplete_type)) 2077218893Sdim return ExprError(); 2078218893Sdim 2079207619Srdivacky // Construct the appropriate ObjCMessageExpr. 2080234353Sdim ObjCMessageExpr *Result; 2081207619Srdivacky if (SuperLoc.isValid()) 2082218893Sdim Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 2083208600Srdivacky SuperLoc, /*IsInstanceSuper=*/false, 2084226633Sdim ReceiverType, Sel, SelectorLocs, 2085226633Sdim Method, makeArrayRef(Args, NumArgs), 2086234353Sdim RBracLoc, isImplicit); 2087234353Sdim else { 2088218893Sdim Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 2089226633Sdim ReceiverTypeInfo, Sel, SelectorLocs, 2090226633Sdim Method, makeArrayRef(Args, NumArgs), 2091234353Sdim RBracLoc, isImplicit); 2092234353Sdim if (!isImplicit) 2093234353Sdim checkCocoaAPI(*this, Result); 2094234353Sdim } 2095208600Srdivacky return MaybeBindToTemporary(Result); 2096193326Sed} 2097193326Sed 2098207619Srdivacky// ActOnClassMessage - used for both unary and keyword messages. 2099193326Sed// ArgExprs is optional - if it is present, the number of expressions 2100193326Sed// is obtained from Sel.getNumArgs(). 2101212904SdimExprResult Sema::ActOnClassMessage(Scope *S, 2102218893Sdim ParsedType Receiver, 2103218893Sdim Selector Sel, 2104218893Sdim SourceLocation LBracLoc, 2105226633Sdim ArrayRef<SourceLocation> SelectorLocs, 2106218893Sdim SourceLocation RBracLoc, 2107218893Sdim MultiExprArg Args) { 2108207619Srdivacky TypeSourceInfo *ReceiverTypeInfo; 2109207619Srdivacky QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo); 2110207619Srdivacky if (ReceiverType.isNull()) 2111207619Srdivacky return ExprError(); 2112198092Srdivacky 2113198092Srdivacky 2114207619Srdivacky if (!ReceiverTypeInfo) 2115207619Srdivacky ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc); 2116198092Srdivacky 2117207619Srdivacky return BuildClassMessage(ReceiverTypeInfo, ReceiverType, 2118207619Srdivacky /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, 2119243830Sdim LBracLoc, SelectorLocs, RBracLoc, Args); 2120207619Srdivacky} 2121193326Sed 2122234353SdimExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, 2123234353Sdim QualType ReceiverType, 2124234353Sdim SourceLocation Loc, 2125234353Sdim Selector Sel, 2126234353Sdim ObjCMethodDecl *Method, 2127234353Sdim MultiExprArg Args) { 2128234353Sdim return BuildInstanceMessage(Receiver, ReceiverType, 2129234353Sdim /*SuperLoc=*/!Receiver ? Loc : SourceLocation(), 2130234353Sdim Sel, Method, Loc, Loc, Loc, Args, 2131234353Sdim /*isImplicit=*/true); 2132234353Sdim} 2133234353Sdim 2134207619Srdivacky/// \brief Build an Objective-C instance message expression. 2135207619Srdivacky/// 2136207619Srdivacky/// This routine takes care of both normal instance messages and 2137207619Srdivacky/// instance messages to the superclass instance. 2138207619Srdivacky/// 2139207619Srdivacky/// \param Receiver The expression that computes the object that will 2140207619Srdivacky/// receive this message. This may be empty, in which case we are 2141207619Srdivacky/// sending to the superclass instance and \p SuperLoc must be a valid 2142207619Srdivacky/// source location. 2143207619Srdivacky/// 2144207619Srdivacky/// \param ReceiverType The (static) type of the object receiving the 2145207619Srdivacky/// message. When a \p Receiver expression is provided, this is the 2146207619Srdivacky/// same type as that expression. For a superclass instance send, this 2147207619Srdivacky/// is a pointer to the type of the superclass. 2148207619Srdivacky/// 2149207619Srdivacky/// \param SuperLoc The location of the "super" keyword in a 2150207619Srdivacky/// superclass instance message. 2151207619Srdivacky/// 2152207619Srdivacky/// \param Sel The selector to which the message is being sent. 2153207619Srdivacky/// 2154207619Srdivacky/// \param Method The method that this instance message is invoking, if 2155207619Srdivacky/// already known. 2156207619Srdivacky/// 2157207619Srdivacky/// \param LBracLoc The location of the opening square bracket ']'. 2158207619Srdivacky/// 2159239462Sdim/// \param RBracLoc The location of the closing square bracket ']'. 2160207619Srdivacky/// 2161239462Sdim/// \param ArgsIn The message arguments. 2162212904SdimExprResult Sema::BuildInstanceMessage(Expr *Receiver, 2163218893Sdim QualType ReceiverType, 2164218893Sdim SourceLocation SuperLoc, 2165218893Sdim Selector Sel, 2166218893Sdim ObjCMethodDecl *Method, 2167218893Sdim SourceLocation LBracLoc, 2168226633Sdim ArrayRef<SourceLocation> SelectorLocs, 2169218893Sdim SourceLocation RBracLoc, 2170234353Sdim MultiExprArg ArgsIn, 2171234353Sdim bool isImplicit) { 2172218893Sdim // The location of the receiver. 2173218893Sdim SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); 2174251662Sdim SourceRange RecRange = 2175251662Sdim SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange(); 2176251662Sdim SourceLocation SelLoc; 2177251662Sdim if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) 2178251662Sdim SelLoc = SelectorLocs.front(); 2179251662Sdim else 2180251662Sdim SelLoc = Loc; 2181251662Sdim 2182218893Sdim if (LBracLoc.isInvalid()) { 2183218893Sdim Diag(Loc, diag::err_missing_open_square_message_send) 2184218893Sdim << FixItHint::CreateInsertion(Loc, "["); 2185218893Sdim LBracLoc = Loc; 2186218893Sdim } 2187218893Sdim 2188207619Srdivacky // If we have a receiver expression, perform appropriate promotions 2189207619Srdivacky // and determine receiver type. 2190207619Srdivacky if (Receiver) { 2191234353Sdim if (Receiver->hasPlaceholderType()) { 2192234353Sdim ExprResult Result; 2193234353Sdim if (Receiver->getType() == Context.UnknownAnyTy) 2194234353Sdim Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType()); 2195234353Sdim else 2196234353Sdim Result = CheckPlaceholderExpr(Receiver); 2197234353Sdim if (Result.isInvalid()) return ExprError(); 2198234353Sdim Receiver = Result.take(); 2199234353Sdim } 2200234353Sdim 2201207619Srdivacky if (Receiver->isTypeDependent()) { 2202207619Srdivacky // If the receiver is type-dependent, we can't type-check anything 2203207619Srdivacky // at this point. Build a dependent expression. 2204207619Srdivacky unsigned NumArgs = ArgsIn.size(); 2205243830Sdim Expr **Args = ArgsIn.data(); 2206207619Srdivacky assert(SuperLoc.isInvalid() && "Message to super with dependent type"); 2207207619Srdivacky return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, 2208218893Sdim VK_RValue, LBracLoc, Receiver, Sel, 2209226633Sdim SelectorLocs, /*Method=*/0, 2210226633Sdim makeArrayRef(Args, NumArgs), 2211234353Sdim RBracLoc, isImplicit)); 2212193326Sed } 2213193326Sed 2214207619Srdivacky // If necessary, apply function/array conversion to the receiver. 2215207619Srdivacky // C99 6.7.5.3p[7,8]. 2216221345Sdim ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); 2217221345Sdim if (Result.isInvalid()) 2218221345Sdim return ExprError(); 2219221345Sdim Receiver = Result.take(); 2220207619Srdivacky ReceiverType = Receiver->getType(); 2221249423Sdim 2222249423Sdim // If the receiver is an ObjC pointer, a block pointer, or an 2223249423Sdim // __attribute__((NSObject)) pointer, we don't need to do any 2224249423Sdim // special conversion in order to look up a receiver. 2225249423Sdim if (ReceiverType->isObjCRetainableType()) { 2226249423Sdim // do nothing 2227249423Sdim } else if (!getLangOpts().ObjCAutoRefCount && 2228249423Sdim !Context.getObjCIdType().isNull() && 2229249423Sdim (ReceiverType->isPointerType() || 2230249423Sdim ReceiverType->isIntegerType())) { 2231249423Sdim // Implicitly convert integers and pointers to 'id' but emit a warning. 2232249423Sdim // But not in ARC. 2233249423Sdim Diag(Loc, diag::warn_bad_receiver_type) 2234249423Sdim << ReceiverType 2235249423Sdim << Receiver->getSourceRange(); 2236249423Sdim if (ReceiverType->isPointerType()) { 2237249423Sdim Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), 2238249423Sdim CK_CPointerToObjCPointerCast).take(); 2239249423Sdim } else { 2240249423Sdim // TODO: specialized warning on null receivers? 2241249423Sdim bool IsNull = Receiver->isNullPointerConstant(Context, 2242249423Sdim Expr::NPC_ValueDependentIsNull); 2243249423Sdim CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer; 2244249423Sdim Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), 2245249423Sdim Kind).take(); 2246249423Sdim } 2247249423Sdim ReceiverType = Receiver->getType(); 2248249423Sdim } else if (getLangOpts().CPlusPlus) { 2249249423Sdim ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver); 2250249423Sdim if (result.isUsable()) { 2251249423Sdim Receiver = result.take(); 2252249423Sdim ReceiverType = Receiver->getType(); 2253249423Sdim } 2254249423Sdim } 2255207619Srdivacky } 2256193326Sed 2257249423Sdim // There's a somewhat weird interaction here where we assume that we 2258249423Sdim // won't actually have a method unless we also don't need to do some 2259249423Sdim // of the more detailed type-checking on the receiver. 2260249423Sdim 2261207619Srdivacky if (!Method) { 2262207619Srdivacky // Handle messages to id. 2263212904Sdim bool receiverIsId = ReceiverType->isObjCIdType(); 2264212904Sdim if (receiverIsId || ReceiverType->isBlockPointerType() || 2265207619Srdivacky (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) { 2266207619Srdivacky Method = LookupInstanceMethodInGlobalPool(Sel, 2267212904Sdim SourceRange(LBracLoc, RBracLoc), 2268212904Sdim receiverIsId); 2269207619Srdivacky if (!Method) 2270207619Srdivacky Method = LookupFactoryMethodInGlobalPool(Sel, 2271239462Sdim SourceRange(LBracLoc,RBracLoc), 2272212904Sdim receiverIsId); 2273207619Srdivacky } else if (ReceiverType->isObjCClassType() || 2274207619Srdivacky ReceiverType->isObjCQualifiedClassType()) { 2275207619Srdivacky // Handle messages to Class. 2276221345Sdim // We allow sending a message to a qualified Class ("Class<foo>"), which 2277221345Sdim // is ok as long as one of the protocols implements the selector (if not, warn). 2278221345Sdim if (const ObjCObjectPointerType *QClassTy 2279221345Sdim = ReceiverType->getAsObjCQualifiedClassType()) { 2280221345Sdim // Search protocols for class methods. 2281221345Sdim Method = LookupMethodInQualifiedType(Sel, QClassTy, false); 2282221345Sdim if (!Method) { 2283221345Sdim Method = LookupMethodInQualifiedType(Sel, QClassTy, true); 2284221345Sdim // warn if instance method found for a Class message. 2285221345Sdim if (Method) { 2286251662Sdim Diag(SelLoc, diag::warn_instance_method_on_class_found) 2287221345Sdim << Method->getSelector() << Sel; 2288234353Sdim Diag(Method->getLocation(), diag::note_method_declared_at) 2289234353Sdim << Method->getDeclName(); 2290221345Sdim } 2291221345Sdim } 2292221345Sdim } else { 2293221345Sdim if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 2294221345Sdim if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { 2295221345Sdim // First check the public methods in the class interface. 2296221345Sdim Method = ClassDecl->lookupClassMethod(Sel); 2297193326Sed 2298221345Sdim if (!Method) 2299239462Sdim Method = ClassDecl->lookupPrivateClassMethod(Sel); 2300221345Sdim } 2301251662Sdim if (Method && DiagnoseUseOfDecl(Method, SelLoc)) 2302221345Sdim return ExprError(); 2303207619Srdivacky } 2304221345Sdim if (!Method) { 2305221345Sdim // If not messaging 'self', look for any factory method named 'Sel'. 2306221345Sdim if (!Receiver || !isSelfExpr(Receiver)) { 2307221345Sdim Method = LookupFactoryMethodInGlobalPool(Sel, 2308221345Sdim SourceRange(LBracLoc, RBracLoc), 2309221345Sdim true); 2310221345Sdim if (!Method) { 2311221345Sdim // If no class (factory) method was found, check if an _instance_ 2312221345Sdim // method of the same name exists in the root class only. 2313221345Sdim Method = LookupInstanceMethodInGlobalPool(Sel, 2314212904Sdim SourceRange(LBracLoc, RBracLoc), 2315221345Sdim true); 2316221345Sdim if (Method) 2317221345Sdim if (const ObjCInterfaceDecl *ID = 2318221345Sdim dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { 2319221345Sdim if (ID->getSuperClass()) 2320251662Sdim Diag(SelLoc, diag::warn_root_inst_method_not_found) 2321221345Sdim << Sel << SourceRange(LBracLoc, RBracLoc); 2322221345Sdim } 2323221345Sdim } 2324207619Srdivacky } 2325207619Srdivacky } 2326207619Srdivacky } 2327207619Srdivacky } else { 2328207619Srdivacky ObjCInterfaceDecl* ClassDecl = 0; 2329198092Srdivacky 2330207619Srdivacky // We allow sending a message to a qualified ID ("id<foo>"), which is ok as 2331207619Srdivacky // long as one of the protocols implements the selector (if not, warn). 2332239462Sdim // And as long as message is not deprecated/unavailable (warn if it is). 2333207619Srdivacky if (const ObjCObjectPointerType *QIdTy 2334207619Srdivacky = ReceiverType->getAsObjCQualifiedIdType()) { 2335207619Srdivacky // Search protocols for instance methods. 2336221345Sdim Method = LookupMethodInQualifiedType(Sel, QIdTy, true); 2337221345Sdim if (!Method) 2338221345Sdim Method = LookupMethodInQualifiedType(Sel, QIdTy, false); 2339251662Sdim if (Method && DiagnoseUseOfDecl(Method, SelLoc)) 2340239462Sdim return ExprError(); 2341207619Srdivacky } else if (const ObjCObjectPointerType *OCIType 2342207619Srdivacky = ReceiverType->getAsObjCInterfacePointerType()) { 2343207619Srdivacky // We allow sending a message to a pointer to an interface (an object). 2344207619Srdivacky ClassDecl = OCIType->getInterfaceDecl(); 2345224145Sdim 2346234353Sdim // Try to complete the type. Under ARC, this is a hard error from which 2347234353Sdim // we don't try to recover. 2348234353Sdim const ObjCInterfaceDecl *forwardClass = 0; 2349234353Sdim if (RequireCompleteType(Loc, OCIType->getPointeeType(), 2350234353Sdim getLangOpts().ObjCAutoRefCount 2351239462Sdim ? diag::err_arc_receiver_forward_instance 2352239462Sdim : diag::warn_receiver_forward_instance, 2353239462Sdim Receiver? Receiver->getSourceRange() 2354239462Sdim : SourceRange(SuperLoc))) { 2355234353Sdim if (getLangOpts().ObjCAutoRefCount) 2356234353Sdim return ExprError(); 2357234353Sdim 2358234353Sdim forwardClass = OCIType->getInterfaceDecl(); 2359234353Sdim Diag(Receiver ? Receiver->getLocStart() 2360234353Sdim : SuperLoc, diag::note_receiver_is_id); 2361234353Sdim Method = 0; 2362234353Sdim } else { 2363234353Sdim Method = ClassDecl->lookupInstanceMethod(Sel); 2364224145Sdim } 2365224145Sdim 2366221345Sdim if (!Method) 2367207619Srdivacky // Search protocol qualifiers. 2368221345Sdim Method = LookupMethodInQualifiedType(Sel, OCIType, true); 2369221345Sdim 2370207619Srdivacky if (!Method) { 2371207619Srdivacky // If we have implementations in scope, check "private" methods. 2372239462Sdim Method = ClassDecl->lookupPrivateMethod(Sel); 2373198092Srdivacky 2374234353Sdim if (!Method && getLangOpts().ObjCAutoRefCount) { 2375251662Sdim Diag(SelLoc, diag::err_arc_may_not_respond) 2376251662Sdim << OCIType->getPointeeType() << Sel << RecRange 2377249423Sdim << SourceRange(SelectorLocs.front(), SelectorLocs.back()); 2378224145Sdim return ExprError(); 2379224145Sdim } 2380224145Sdim 2381207619Srdivacky if (!Method && (!Receiver || !isSelfExpr(Receiver))) { 2382207619Srdivacky // If we still haven't found a method, look in the global pool. This 2383207619Srdivacky // behavior isn't very desirable, however we need it for GCC 2384207619Srdivacky // compatibility. FIXME: should we deviate?? 2385207619Srdivacky if (OCIType->qual_empty()) { 2386207619Srdivacky Method = LookupInstanceMethodInGlobalPool(Sel, 2387239462Sdim SourceRange(LBracLoc, RBracLoc)); 2388218893Sdim if (Method && !forwardClass) 2389251662Sdim Diag(SelLoc, diag::warn_maynot_respond) 2390251662Sdim << OCIType->getInterfaceDecl()->getIdentifier() 2391251662Sdim << Sel << RecRange; 2392193326Sed } 2393207619Srdivacky } 2394193326Sed } 2395251662Sdim if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass)) 2396207619Srdivacky return ExprError(); 2397226633Sdim } else { 2398249423Sdim // Reject other random receiver types (e.g. structs). 2399249423Sdim Diag(Loc, diag::err_bad_receiver_type) 2400249423Sdim << ReceiverType << Receiver->getSourceRange(); 2401249423Sdim return ExprError(); 2402193326Sed } 2403193326Sed } 2404193326Sed } 2405198092Srdivacky 2406207619Srdivacky // Check the message arguments. 2407207619Srdivacky unsigned NumArgs = ArgsIn.size(); 2408243830Sdim Expr **Args = ArgsIn.data(); 2409207619Srdivacky QualType ReturnType; 2410218893Sdim ExprValueKind VK = VK_RValue; 2411218893Sdim bool ClassMessage = (ReceiverType->isObjCClassType() || 2412218893Sdim ReceiverType->isObjCQualifiedClassType()); 2413243830Sdim if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, 2414243830Sdim SelectorLocs, Method, 2415223017Sdim ClassMessage, SuperLoc.isValid(), 2416218893Sdim LBracLoc, RBracLoc, ReturnType, VK)) 2417207619Srdivacky return ExprError(); 2418210299Sed 2419218893Sdim if (Method && !Method->getResultType()->isVoidType() && 2420218893Sdim RequireCompleteType(LBracLoc, Method->getResultType(), 2421218893Sdim diag::err_illegal_message_expr_incomplete_type)) 2422218893Sdim return ExprError(); 2423198092Srdivacky 2424224145Sdim // In ARC, forbid the user from sending messages to 2425224145Sdim // retain/release/autorelease/dealloc/retainCount explicitly. 2426234353Sdim if (getLangOpts().ObjCAutoRefCount) { 2427224145Sdim ObjCMethodFamily family = 2428224145Sdim (Method ? Method->getMethodFamily() : Sel.getMethodFamily()); 2429224145Sdim switch (family) { 2430224145Sdim case OMF_init: 2431224145Sdim if (Method) 2432224145Sdim checkInitMethod(Method, ReceiverType); 2433224145Sdim 2434224145Sdim case OMF_None: 2435224145Sdim case OMF_alloc: 2436224145Sdim case OMF_copy: 2437226633Sdim case OMF_finalize: 2438224145Sdim case OMF_mutableCopy: 2439224145Sdim case OMF_new: 2440224145Sdim case OMF_self: 2441224145Sdim break; 2442224145Sdim 2443224145Sdim case OMF_dealloc: 2444224145Sdim case OMF_retain: 2445224145Sdim case OMF_release: 2446224145Sdim case OMF_autorelease: 2447224145Sdim case OMF_retainCount: 2448251662Sdim Diag(SelLoc, diag::err_arc_illegal_explicit_message) 2449251662Sdim << Sel << RecRange; 2450224145Sdim break; 2451224145Sdim 2452224145Sdim case OMF_performSelector: 2453224145Sdim if (Method && NumArgs >= 1) { 2454224145Sdim if (ObjCSelectorExpr *SelExp = dyn_cast<ObjCSelectorExpr>(Args[0])) { 2455224145Sdim Selector ArgSel = SelExp->getSelector(); 2456224145Sdim ObjCMethodDecl *SelMethod = 2457224145Sdim LookupInstanceMethodInGlobalPool(ArgSel, 2458224145Sdim SelExp->getSourceRange()); 2459224145Sdim if (!SelMethod) 2460224145Sdim SelMethod = 2461224145Sdim LookupFactoryMethodInGlobalPool(ArgSel, 2462224145Sdim SelExp->getSourceRange()); 2463224145Sdim if (SelMethod) { 2464224145Sdim ObjCMethodFamily SelFamily = SelMethod->getMethodFamily(); 2465224145Sdim switch (SelFamily) { 2466224145Sdim case OMF_alloc: 2467224145Sdim case OMF_copy: 2468224145Sdim case OMF_mutableCopy: 2469224145Sdim case OMF_new: 2470224145Sdim case OMF_self: 2471224145Sdim case OMF_init: 2472224145Sdim // Issue error, unless ns_returns_not_retained. 2473224145Sdim if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) { 2474224145Sdim // selector names a +1 method 2475226633Sdim Diag(SelLoc, 2476224145Sdim diag::err_arc_perform_selector_retains); 2477234353Sdim Diag(SelMethod->getLocation(), diag::note_method_declared_at) 2478234353Sdim << SelMethod->getDeclName(); 2479224145Sdim } 2480224145Sdim break; 2481224145Sdim default: 2482224145Sdim // +0 call. OK. unless ns_returns_retained. 2483224145Sdim if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) { 2484224145Sdim // selector names a +1 method 2485226633Sdim Diag(SelLoc, 2486224145Sdim diag::err_arc_perform_selector_retains); 2487234353Sdim Diag(SelMethod->getLocation(), diag::note_method_declared_at) 2488234353Sdim << SelMethod->getDeclName(); 2489224145Sdim } 2490224145Sdim break; 2491224145Sdim } 2492224145Sdim } 2493224145Sdim } else { 2494224145Sdim // error (may leak). 2495226633Sdim Diag(SelLoc, diag::warn_arc_perform_selector_leaks); 2496224145Sdim Diag(Args[0]->getExprLoc(), diag::note_used_here); 2497224145Sdim } 2498224145Sdim } 2499224145Sdim break; 2500224145Sdim } 2501224145Sdim } 2502224145Sdim 2503207619Srdivacky // Construct the appropriate ObjCMessageExpr instance. 2504224145Sdim ObjCMessageExpr *Result; 2505207619Srdivacky if (SuperLoc.isValid()) 2506218893Sdim Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 2507208600Srdivacky SuperLoc, /*IsInstanceSuper=*/true, 2508226633Sdim ReceiverType, Sel, SelectorLocs, Method, 2509234353Sdim makeArrayRef(Args, NumArgs), RBracLoc, 2510234353Sdim isImplicit); 2511234353Sdim else { 2512218893Sdim Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 2513226633Sdim Receiver, Sel, SelectorLocs, Method, 2514234353Sdim makeArrayRef(Args, NumArgs), RBracLoc, 2515234353Sdim isImplicit); 2516234353Sdim if (!isImplicit) 2517234353Sdim checkCocoaAPI(*this, Result); 2518234353Sdim } 2519224145Sdim 2520234353Sdim if (getLangOpts().ObjCAutoRefCount) { 2521239462Sdim DiagnoseARCUseOfWeakReceiver(*this, Receiver); 2522234353Sdim 2523224145Sdim // In ARC, annotate delegate init calls. 2524224145Sdim if (Result->getMethodFamily() == OMF_init && 2525224145Sdim (SuperLoc.isValid() || isSelfExpr(Receiver))) { 2526224145Sdim // Only consider init calls *directly* in init implementations, 2527224145Sdim // not within blocks. 2528224145Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CurContext); 2529224145Sdim if (method && method->getMethodFamily() == OMF_init) { 2530224145Sdim // The implicit assignment to self means we also don't want to 2531224145Sdim // consume the result. 2532224145Sdim Result->setDelegateInitCall(true); 2533224145Sdim return Owned(Result); 2534224145Sdim } 2535224145Sdim } 2536224145Sdim 2537224145Sdim // In ARC, check for message sends which are likely to introduce 2538224145Sdim // retain cycles. 2539224145Sdim checkRetainCycles(Result); 2540243830Sdim 2541243830Sdim if (!isImplicit && Method) { 2542243830Sdim if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { 2543243830Sdim bool IsWeak = 2544243830Sdim Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak; 2545243830Sdim if (!IsWeak && Sel.isUnarySelector()) 2546243830Sdim IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; 2547243830Sdim 2548243830Sdim if (IsWeak) { 2549243830Sdim DiagnosticsEngine::Level Level = 2550243830Sdim Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, 2551243830Sdim LBracLoc); 2552243830Sdim if (Level != DiagnosticsEngine::Ignored) 2553243830Sdim getCurFunction()->recordUseOfWeak(Result, Prop); 2554243830Sdim 2555243830Sdim } 2556243830Sdim } 2557243830Sdim } 2558224145Sdim } 2559224145Sdim 2560208600Srdivacky return MaybeBindToTemporary(Result); 2561207619Srdivacky} 2562198092Srdivacky 2563249423Sdimstatic void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) { 2564249423Sdim if (ObjCSelectorExpr *OSE = 2565249423Sdim dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) { 2566249423Sdim Selector Sel = OSE->getSelector(); 2567249423Sdim SourceLocation Loc = OSE->getAtLoc(); 2568249423Sdim llvm::DenseMap<Selector, SourceLocation>::iterator Pos 2569249423Sdim = S.ReferencedSelectors.find(Sel); 2570249423Sdim if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc) 2571249423Sdim S.ReferencedSelectors.erase(Pos); 2572249423Sdim } 2573249423Sdim} 2574249423Sdim 2575207619Srdivacky// ActOnInstanceMessage - used for both unary and keyword messages. 2576207619Srdivacky// ArgExprs is optional - if it is present, the number of expressions 2577207619Srdivacky// is obtained from Sel.getNumArgs(). 2578212904SdimExprResult Sema::ActOnInstanceMessage(Scope *S, 2579212904Sdim Expr *Receiver, 2580212904Sdim Selector Sel, 2581212904Sdim SourceLocation LBracLoc, 2582226633Sdim ArrayRef<SourceLocation> SelectorLocs, 2583212904Sdim SourceLocation RBracLoc, 2584212904Sdim MultiExprArg Args) { 2585207619Srdivacky if (!Receiver) 2586207619Srdivacky return ExprError(); 2587198092Srdivacky 2588249423Sdim // A ParenListExpr can show up while doing error recovery with invalid code. 2589249423Sdim if (isa<ParenListExpr>(Receiver)) { 2590249423Sdim ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver); 2591249423Sdim if (Result.isInvalid()) return ExprError(); 2592249423Sdim Receiver = Result.take(); 2593249423Sdim } 2594249423Sdim 2595249423Sdim if (RespondsToSelectorSel.isNull()) { 2596249423Sdim IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector"); 2597249423Sdim RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId); 2598249423Sdim } 2599249423Sdim if (Sel == RespondsToSelectorSel) 2600249423Sdim RemoveSelectorFromWarningCache(*this, Args[0]); 2601249423Sdim 2602212904Sdim return BuildInstanceMessage(Receiver, Receiver->getType(), 2603207619Srdivacky /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, 2604243830Sdim LBracLoc, SelectorLocs, RBracLoc, Args); 2605193326Sed} 2606193326Sed 2607224145Sdimenum ARCConversionTypeClass { 2608226633Sdim /// int, void, struct A 2609224145Sdim ACTC_none, 2610226633Sdim 2611226633Sdim /// id, void (^)() 2612224145Sdim ACTC_retainable, 2613226633Sdim 2614226633Sdim /// id*, id***, void (^*)(), 2615226633Sdim ACTC_indirectRetainable, 2616226633Sdim 2617226633Sdim /// void* might be a normal C type, or it might a CF type. 2618226633Sdim ACTC_voidPtr, 2619226633Sdim 2620226633Sdim /// struct A* 2621226633Sdim ACTC_coreFoundation 2622224145Sdim}; 2623226633Sdimstatic bool isAnyRetainable(ARCConversionTypeClass ACTC) { 2624226633Sdim return (ACTC == ACTC_retainable || 2625226633Sdim ACTC == ACTC_coreFoundation || 2626226633Sdim ACTC == ACTC_voidPtr); 2627226633Sdim} 2628226633Sdimstatic bool isAnyCLike(ARCConversionTypeClass ACTC) { 2629226633Sdim return ACTC == ACTC_none || 2630226633Sdim ACTC == ACTC_voidPtr || 2631226633Sdim ACTC == ACTC_coreFoundation; 2632226633Sdim} 2633226633Sdim 2634224145Sdimstatic ARCConversionTypeClass classifyTypeForARCConversion(QualType type) { 2635226633Sdim bool isIndirect = false; 2636224145Sdim 2637224145Sdim // Ignore an outermost reference type. 2638226633Sdim if (const ReferenceType *ref = type->getAs<ReferenceType>()) { 2639224145Sdim type = ref->getPointeeType(); 2640226633Sdim isIndirect = true; 2641226633Sdim } 2642224145Sdim 2643224145Sdim // Drill through pointers and arrays recursively. 2644224145Sdim while (true) { 2645224145Sdim if (const PointerType *ptr = type->getAs<PointerType>()) { 2646224145Sdim type = ptr->getPointeeType(); 2647226633Sdim 2648226633Sdim // The first level of pointer may be the innermost pointer on a CF type. 2649226633Sdim if (!isIndirect) { 2650226633Sdim if (type->isVoidType()) return ACTC_voidPtr; 2651226633Sdim if (type->isRecordType()) return ACTC_coreFoundation; 2652226633Sdim } 2653224145Sdim } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) { 2654224145Sdim type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0); 2655224145Sdim } else { 2656224145Sdim break; 2657224145Sdim } 2658226633Sdim isIndirect = true; 2659224145Sdim } 2660224145Sdim 2661226633Sdim if (isIndirect) { 2662226633Sdim if (type->isObjCARCBridgableType()) 2663226633Sdim return ACTC_indirectRetainable; 2664226633Sdim return ACTC_none; 2665226633Sdim } 2666226633Sdim 2667226633Sdim if (type->isObjCARCBridgableType()) 2668226633Sdim return ACTC_retainable; 2669226633Sdim 2670226633Sdim return ACTC_none; 2671224145Sdim} 2672224145Sdim 2673224145Sdimnamespace { 2674226633Sdim /// A result from the cast checker. 2675226633Sdim enum ACCResult { 2676226633Sdim /// Cannot be casted. 2677226633Sdim ACC_invalid, 2678226633Sdim 2679226633Sdim /// Can be safely retained or not retained. 2680226633Sdim ACC_bottom, 2681226633Sdim 2682226633Sdim /// Can be casted at +0. 2683226633Sdim ACC_plusZero, 2684226633Sdim 2685226633Sdim /// Can be casted at +1. 2686226633Sdim ACC_plusOne 2687226633Sdim }; 2688226633Sdim ACCResult merge(ACCResult left, ACCResult right) { 2689226633Sdim if (left == right) return left; 2690226633Sdim if (left == ACC_bottom) return right; 2691226633Sdim if (right == ACC_bottom) return left; 2692226633Sdim return ACC_invalid; 2693226633Sdim } 2694226633Sdim 2695226633Sdim /// A checker which white-lists certain expressions whose conversion 2696226633Sdim /// to or from retainable type would otherwise be forbidden in ARC. 2697226633Sdim class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> { 2698226633Sdim typedef StmtVisitor<ARCCastChecker, ACCResult> super; 2699226633Sdim 2700224145Sdim ASTContext &Context; 2701226633Sdim ARCConversionTypeClass SourceClass; 2702226633Sdim ARCConversionTypeClass TargetClass; 2703239462Sdim bool Diagnose; 2704226633Sdim 2705226633Sdim static bool isCFType(QualType type) { 2706226633Sdim // Someday this can use ns_bridged. For now, it has to do this. 2707226633Sdim return type->isCARCBridgableType(); 2708224145Sdim } 2709226633Sdim 2710226633Sdim public: 2711226633Sdim ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source, 2712239462Sdim ARCConversionTypeClass target, bool diagnose) 2713239462Sdim : Context(Context), SourceClass(source), TargetClass(target), 2714239462Sdim Diagnose(diagnose) {} 2715226633Sdim 2716226633Sdim using super::Visit; 2717226633Sdim ACCResult Visit(Expr *e) { 2718226633Sdim return super::Visit(e->IgnoreParens()); 2719224145Sdim } 2720226633Sdim 2721226633Sdim ACCResult VisitStmt(Stmt *s) { 2722226633Sdim return ACC_invalid; 2723226633Sdim } 2724226633Sdim 2725226633Sdim /// Null pointer constants can be casted however you please. 2726226633Sdim ACCResult VisitExpr(Expr *e) { 2727226633Sdim if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) 2728226633Sdim return ACC_bottom; 2729226633Sdim return ACC_invalid; 2730226633Sdim } 2731226633Sdim 2732226633Sdim /// Objective-C string literals can be safely casted. 2733226633Sdim ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) { 2734226633Sdim // If we're casting to any retainable type, go ahead. Global 2735226633Sdim // strings are immune to retains, so this is bottom. 2736226633Sdim if (isAnyRetainable(TargetClass)) return ACC_bottom; 2737226633Sdim 2738226633Sdim return ACC_invalid; 2739226633Sdim } 2740224145Sdim 2741226633Sdim /// Look through certain implicit and explicit casts. 2742226633Sdim ACCResult VisitCastExpr(CastExpr *e) { 2743224145Sdim switch (e->getCastKind()) { 2744224145Sdim case CK_NullToPointer: 2745226633Sdim return ACC_bottom; 2746226633Sdim 2747224145Sdim case CK_NoOp: 2748224145Sdim case CK_LValueToRValue: 2749224145Sdim case CK_BitCast: 2750226633Sdim case CK_CPointerToObjCPointerCast: 2751226633Sdim case CK_BlockPointerToObjCPointerCast: 2752224145Sdim case CK_AnyPointerToBlockPointerCast: 2753224145Sdim return Visit(e->getSubExpr()); 2754226633Sdim 2755224145Sdim default: 2756226633Sdim return ACC_invalid; 2757224145Sdim } 2758224145Sdim } 2759226633Sdim 2760226633Sdim /// Look through unary extension. 2761226633Sdim ACCResult VisitUnaryExtension(UnaryOperator *e) { 2762224145Sdim return Visit(e->getSubExpr()); 2763224145Sdim } 2764226633Sdim 2765226633Sdim /// Ignore the LHS of a comma operator. 2766226633Sdim ACCResult VisitBinComma(BinaryOperator *e) { 2767224145Sdim return Visit(e->getRHS()); 2768224145Sdim } 2769226633Sdim 2770226633Sdim /// Conditional operators are okay if both sides are okay. 2771226633Sdim ACCResult VisitConditionalOperator(ConditionalOperator *e) { 2772226633Sdim ACCResult left = Visit(e->getTrueExpr()); 2773226633Sdim if (left == ACC_invalid) return ACC_invalid; 2774226633Sdim return merge(left, Visit(e->getFalseExpr())); 2775224145Sdim } 2776226633Sdim 2777234353Sdim /// Look through pseudo-objects. 2778234353Sdim ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) { 2779234353Sdim // If we're getting here, we should always have a result. 2780234353Sdim return Visit(e->getResultExpr()); 2781234353Sdim } 2782234353Sdim 2783226633Sdim /// Statement expressions are okay if their result expression is okay. 2784226633Sdim ACCResult VisitStmtExpr(StmtExpr *e) { 2785224145Sdim return Visit(e->getSubStmt()->body_back()); 2786224145Sdim } 2787226633Sdim 2788226633Sdim /// Some declaration references are okay. 2789226633Sdim ACCResult VisitDeclRefExpr(DeclRefExpr *e) { 2790226633Sdim // References to global constants from system headers are okay. 2791226633Sdim // These are things like 'kCFStringTransformToLatin'. They are 2792226633Sdim // can also be assumed to be immune to retains. 2793226633Sdim VarDecl *var = dyn_cast<VarDecl>(e->getDecl()); 2794226633Sdim if (isAnyRetainable(TargetClass) && 2795226633Sdim isAnyRetainable(SourceClass) && 2796226633Sdim var && 2797226633Sdim var->getStorageClass() == SC_Extern && 2798226633Sdim var->getType().isConstQualified() && 2799226633Sdim Context.getSourceManager().isInSystemHeader(var->getLocation())) { 2800226633Sdim return ACC_bottom; 2801226633Sdim } 2802226633Sdim 2803226633Sdim // Nothing else. 2804226633Sdim return ACC_invalid; 2805224145Sdim } 2806224145Sdim 2807226633Sdim /// Some calls are okay. 2808226633Sdim ACCResult VisitCallExpr(CallExpr *e) { 2809226633Sdim if (FunctionDecl *fn = e->getDirectCallee()) 2810226633Sdim if (ACCResult result = checkCallToFunction(fn)) 2811226633Sdim return result; 2812226633Sdim 2813226633Sdim return super::VisitCallExpr(e); 2814224145Sdim } 2815226633Sdim 2816226633Sdim ACCResult checkCallToFunction(FunctionDecl *fn) { 2817226633Sdim // Require a CF*Ref return type. 2818226633Sdim if (!isCFType(fn->getResultType())) 2819226633Sdim return ACC_invalid; 2820226633Sdim 2821226633Sdim if (!isAnyRetainable(TargetClass)) 2822226633Sdim return ACC_invalid; 2823226633Sdim 2824226633Sdim // Honor an explicit 'not retained' attribute. 2825226633Sdim if (fn->hasAttr<CFReturnsNotRetainedAttr>()) 2826226633Sdim return ACC_plusZero; 2827226633Sdim 2828226633Sdim // Honor an explicit 'retained' attribute, except that for 2829226633Sdim // now we're not going to permit implicit handling of +1 results, 2830226633Sdim // because it's a bit frightening. 2831226633Sdim if (fn->hasAttr<CFReturnsRetainedAttr>()) 2832239462Sdim return Diagnose ? ACC_plusOne 2833239462Sdim : ACC_invalid; // ACC_plusOne if we start accepting this 2834226633Sdim 2835226633Sdim // Recognize this specific builtin function, which is used by CFSTR. 2836226633Sdim unsigned builtinID = fn->getBuiltinID(); 2837226633Sdim if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString) 2838226633Sdim return ACC_bottom; 2839226633Sdim 2840226633Sdim // Otherwise, don't do anything implicit with an unaudited function. 2841226633Sdim if (!fn->hasAttr<CFAuditedTransferAttr>()) 2842226633Sdim return ACC_invalid; 2843239462Sdim 2844226633Sdim // Otherwise, it's +0 unless it follows the create convention. 2845226633Sdim if (ento::coreFoundation::followsCreateRule(fn)) 2846239462Sdim return Diagnose ? ACC_plusOne 2847239462Sdim : ACC_invalid; // ACC_plusOne if we start accepting this 2848226633Sdim 2849226633Sdim return ACC_plusZero; 2850226633Sdim } 2851226633Sdim 2852226633Sdim ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) { 2853226633Sdim return checkCallToMethod(e->getMethodDecl()); 2854226633Sdim } 2855226633Sdim 2856226633Sdim ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) { 2857226633Sdim ObjCMethodDecl *method; 2858226633Sdim if (e->isExplicitProperty()) 2859226633Sdim method = e->getExplicitProperty()->getGetterMethodDecl(); 2860226633Sdim else 2861226633Sdim method = e->getImplicitPropertyGetter(); 2862226633Sdim return checkCallToMethod(method); 2863226633Sdim } 2864226633Sdim 2865226633Sdim ACCResult checkCallToMethod(ObjCMethodDecl *method) { 2866226633Sdim if (!method) return ACC_invalid; 2867226633Sdim 2868226633Sdim // Check for message sends to functions returning CF types. We 2869226633Sdim // just obey the Cocoa conventions with these, even though the 2870226633Sdim // return type is CF. 2871226633Sdim if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType())) 2872226633Sdim return ACC_invalid; 2873226633Sdim 2874226633Sdim // If the method is explicitly marked not-retained, it's +0. 2875226633Sdim if (method->hasAttr<CFReturnsNotRetainedAttr>()) 2876226633Sdim return ACC_plusZero; 2877226633Sdim 2878226633Sdim // If the method is explicitly marked as returning retained, or its 2879226633Sdim // selector follows a +1 Cocoa convention, treat it as +1. 2880226633Sdim if (method->hasAttr<CFReturnsRetainedAttr>()) 2881226633Sdim return ACC_plusOne; 2882226633Sdim 2883226633Sdim switch (method->getSelector().getMethodFamily()) { 2884226633Sdim case OMF_alloc: 2885226633Sdim case OMF_copy: 2886226633Sdim case OMF_mutableCopy: 2887226633Sdim case OMF_new: 2888226633Sdim return ACC_plusOne; 2889226633Sdim 2890226633Sdim default: 2891226633Sdim // Otherwise, treat it as +0. 2892226633Sdim return ACC_plusZero; 2893224145Sdim } 2894224145Sdim } 2895226633Sdim }; 2896224145Sdim} 2897224145Sdim 2898239462Sdimbool Sema::isKnownName(StringRef name) { 2899239462Sdim if (name.empty()) 2900239462Sdim return false; 2901239462Sdim LookupResult R(*this, &Context.Idents.get(name), SourceLocation(), 2902234353Sdim Sema::LookupOrdinaryName); 2903239462Sdim return LookupName(R, TUScope, false); 2904234353Sdim} 2905234353Sdim 2906234353Sdimstatic void addFixitForObjCARCConversion(Sema &S, 2907234353Sdim DiagnosticBuilder &DiagB, 2908234353Sdim Sema::CheckedConversionKind CCK, 2909234353Sdim SourceLocation afterLParen, 2910234353Sdim QualType castType, 2911234353Sdim Expr *castExpr, 2912249423Sdim Expr *realCast, 2913234353Sdim const char *bridgeKeyword, 2914234353Sdim const char *CFBridgeName) { 2915234353Sdim // We handle C-style and implicit casts here. 2916234353Sdim switch (CCK) { 2917234353Sdim case Sema::CCK_ImplicitConversion: 2918234353Sdim case Sema::CCK_CStyleCast: 2919249423Sdim case Sema::CCK_OtherCast: 2920234353Sdim break; 2921234353Sdim case Sema::CCK_FunctionalCast: 2922234353Sdim return; 2923234353Sdim } 2924234353Sdim 2925234353Sdim if (CFBridgeName) { 2926249423Sdim if (CCK == Sema::CCK_OtherCast) { 2927249423Sdim if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) { 2928249423Sdim SourceRange range(NCE->getOperatorLoc(), 2929249423Sdim NCE->getAngleBrackets().getEnd()); 2930249423Sdim SmallString<32> BridgeCall; 2931249423Sdim 2932249423Sdim SourceManager &SM = S.getSourceManager(); 2933249423Sdim char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1)); 2934249423Sdim if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts())) 2935249423Sdim BridgeCall += ' '; 2936249423Sdim 2937249423Sdim BridgeCall += CFBridgeName; 2938249423Sdim DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall)); 2939249423Sdim } 2940249423Sdim return; 2941249423Sdim } 2942234353Sdim Expr *castedE = castExpr; 2943234353Sdim if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE)) 2944234353Sdim castedE = CCE->getSubExpr(); 2945234353Sdim castedE = castedE->IgnoreImpCasts(); 2946234353Sdim SourceRange range = castedE->getSourceRange(); 2947239462Sdim 2948239462Sdim SmallString<32> BridgeCall; 2949239462Sdim 2950239462Sdim SourceManager &SM = S.getSourceManager(); 2951239462Sdim char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1)); 2952239462Sdim if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts())) 2953239462Sdim BridgeCall += ' '; 2954239462Sdim 2955239462Sdim BridgeCall += CFBridgeName; 2956239462Sdim 2957234353Sdim if (isa<ParenExpr>(castedE)) { 2958234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), 2959239462Sdim BridgeCall)); 2960234353Sdim } else { 2961239462Sdim BridgeCall += '('; 2962234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), 2963239462Sdim BridgeCall)); 2964234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion( 2965234353Sdim S.PP.getLocForEndOfToken(range.getEnd()), 2966234353Sdim ")")); 2967234353Sdim } 2968234353Sdim return; 2969234353Sdim } 2970234353Sdim 2971234353Sdim if (CCK == Sema::CCK_CStyleCast) { 2972234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword)); 2973249423Sdim } else if (CCK == Sema::CCK_OtherCast) { 2974249423Sdim if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) { 2975249423Sdim std::string castCode = "("; 2976249423Sdim castCode += bridgeKeyword; 2977249423Sdim castCode += castType.getAsString(); 2978249423Sdim castCode += ")"; 2979249423Sdim SourceRange Range(NCE->getOperatorLoc(), 2980249423Sdim NCE->getAngleBrackets().getEnd()); 2981249423Sdim DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode)); 2982249423Sdim } 2983234353Sdim } else { 2984234353Sdim std::string castCode = "("; 2985234353Sdim castCode += bridgeKeyword; 2986234353Sdim castCode += castType.getAsString(); 2987234353Sdim castCode += ")"; 2988234353Sdim Expr *castedE = castExpr->IgnoreImpCasts(); 2989234353Sdim SourceRange range = castedE->getSourceRange(); 2990234353Sdim if (isa<ParenExpr>(castedE)) { 2991234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), 2992234353Sdim castCode)); 2993234353Sdim } else { 2994234353Sdim castCode += "("; 2995234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), 2996234353Sdim castCode)); 2997234353Sdim DiagB.AddFixItHint(FixItHint::CreateInsertion( 2998234353Sdim S.PP.getLocForEndOfToken(range.getEnd()), 2999234353Sdim ")")); 3000234353Sdim } 3001234353Sdim } 3002234353Sdim} 3003234353Sdim 3004234353Sdimstatic void 3005234353SdimdiagnoseObjCARCConversion(Sema &S, SourceRange castRange, 3006234353Sdim QualType castType, ARCConversionTypeClass castACTC, 3007249423Sdim Expr *castExpr, Expr *realCast, 3008249423Sdim ARCConversionTypeClass exprACTC, 3009234353Sdim Sema::CheckedConversionKind CCK) { 3010234353Sdim SourceLocation loc = 3011234353Sdim (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); 3012234353Sdim 3013234353Sdim if (S.makeUnavailableInSystemHeader(loc, 3014234353Sdim "converts between Objective-C and C pointers in -fobjc-arc")) 3015234353Sdim return; 3016234353Sdim 3017234353Sdim QualType castExprType = castExpr->getType(); 3018234353Sdim 3019234353Sdim unsigned srcKind = 0; 3020234353Sdim switch (exprACTC) { 3021234353Sdim case ACTC_none: 3022234353Sdim case ACTC_coreFoundation: 3023234353Sdim case ACTC_voidPtr: 3024234353Sdim srcKind = (castExprType->isPointerType() ? 1 : 0); 3025234353Sdim break; 3026234353Sdim case ACTC_retainable: 3027234353Sdim srcKind = (castExprType->isBlockPointerType() ? 2 : 3); 3028234353Sdim break; 3029234353Sdim case ACTC_indirectRetainable: 3030234353Sdim srcKind = 4; 3031234353Sdim break; 3032234353Sdim } 3033234353Sdim 3034234353Sdim // Check whether this could be fixed with a bridge cast. 3035234353Sdim SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin()); 3036234353Sdim SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc; 3037234353Sdim 3038234353Sdim // Bridge from an ARC type to a CF type. 3039234353Sdim if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) { 3040234353Sdim 3041234353Sdim S.Diag(loc, diag::err_arc_cast_requires_bridge) 3042234353Sdim << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit 3043234353Sdim << 2 // of C pointer type 3044234353Sdim << castExprType 3045234353Sdim << unsigned(castType->isBlockPointerType()) // to ObjC|block type 3046234353Sdim << castType 3047234353Sdim << castRange 3048234353Sdim << castExpr->getSourceRange(); 3049239462Sdim bool br = S.isKnownName("CFBridgingRelease"); 3050239462Sdim ACCResult CreateRule = 3051239462Sdim ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr); 3052239462Sdim assert(CreateRule != ACC_bottom && "This cast should already be accepted."); 3053239462Sdim if (CreateRule != ACC_plusOne) 3054234353Sdim { 3055249423Sdim DiagnosticBuilder DiagB = 3056249423Sdim (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) 3057249423Sdim : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); 3058249423Sdim 3059234353Sdim addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, 3060249423Sdim castType, castExpr, realCast, "__bridge ", 0); 3061234353Sdim } 3062239462Sdim if (CreateRule != ACC_plusZero) 3063234353Sdim { 3064249423Sdim DiagnosticBuilder DiagB = 3065249423Sdim (CCK == Sema::CCK_OtherCast && !br) ? 3066249423Sdim S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType : 3067249423Sdim S.Diag(br ? castExpr->getExprLoc() : noteLoc, 3068249423Sdim diag::note_arc_bridge_transfer) 3069249423Sdim << castExprType << br; 3070249423Sdim 3071234353Sdim addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, 3072249423Sdim castType, castExpr, realCast, "__bridge_transfer ", 3073234353Sdim br ? "CFBridgingRelease" : 0); 3074234353Sdim } 3075234353Sdim 3076234353Sdim return; 3077234353Sdim } 3078234353Sdim 3079234353Sdim // Bridge from a CF type to an ARC type. 3080234353Sdim if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { 3081239462Sdim bool br = S.isKnownName("CFBridgingRetain"); 3082234353Sdim S.Diag(loc, diag::err_arc_cast_requires_bridge) 3083234353Sdim << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit 3084234353Sdim << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type 3085234353Sdim << castExprType 3086234353Sdim << 2 // to C pointer type 3087234353Sdim << castType 3088234353Sdim << castRange 3089234353Sdim << castExpr->getSourceRange(); 3090239462Sdim ACCResult CreateRule = 3091239462Sdim ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr); 3092239462Sdim assert(CreateRule != ACC_bottom && "This cast should already be accepted."); 3093239462Sdim if (CreateRule != ACC_plusOne) 3094234353Sdim { 3095249423Sdim DiagnosticBuilder DiagB = 3096249423Sdim (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) 3097249423Sdim : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); 3098234353Sdim addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, 3099249423Sdim castType, castExpr, realCast, "__bridge ", 0); 3100234353Sdim } 3101239462Sdim if (CreateRule != ACC_plusZero) 3102234353Sdim { 3103249423Sdim DiagnosticBuilder DiagB = 3104249423Sdim (CCK == Sema::CCK_OtherCast && !br) ? 3105249423Sdim S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType : 3106249423Sdim S.Diag(br ? castExpr->getExprLoc() : noteLoc, 3107249423Sdim diag::note_arc_bridge_retained) 3108249423Sdim << castType << br; 3109249423Sdim 3110234353Sdim addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, 3111249423Sdim castType, castExpr, realCast, "__bridge_retained ", 3112234353Sdim br ? "CFBridgingRetain" : 0); 3113234353Sdim } 3114234353Sdim 3115234353Sdim return; 3116234353Sdim } 3117234353Sdim 3118234353Sdim S.Diag(loc, diag::err_arc_mismatched_cast) 3119234353Sdim << (CCK != Sema::CCK_ImplicitConversion) 3120234353Sdim << srcKind << castExprType << castType 3121234353Sdim << castRange << castExpr->getSourceRange(); 3122234353Sdim} 3123234353Sdim 3124234353SdimSema::ARCConversionResult 3125224145SdimSema::CheckObjCARCConversion(SourceRange castRange, QualType castType, 3126224145Sdim Expr *&castExpr, CheckedConversionKind CCK) { 3127224145Sdim QualType castExprType = castExpr->getType(); 3128226633Sdim 3129226633Sdim // For the purposes of the classification, we assume reference types 3130226633Sdim // will bind to temporaries. 3131226633Sdim QualType effCastType = castType; 3132226633Sdim if (const ReferenceType *ref = castType->getAs<ReferenceType>()) 3133226633Sdim effCastType = ref->getPointeeType(); 3134224145Sdim 3135224145Sdim ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType); 3136226633Sdim ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType); 3137234353Sdim if (exprACTC == castACTC) { 3138234353Sdim // check for viablity and report error if casting an rvalue to a 3139234353Sdim // life-time qualifier. 3140234353Sdim if ((castACTC == ACTC_retainable) && 3141234353Sdim (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) && 3142234353Sdim (castType != castExprType)) { 3143234353Sdim const Type *DT = castType.getTypePtr(); 3144234353Sdim QualType QDT = castType; 3145234353Sdim // We desugar some types but not others. We ignore those 3146234353Sdim // that cannot happen in a cast; i.e. auto, and those which 3147234353Sdim // should not be de-sugared; i.e typedef. 3148234353Sdim if (const ParenType *PT = dyn_cast<ParenType>(DT)) 3149234353Sdim QDT = PT->desugar(); 3150234353Sdim else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT)) 3151234353Sdim QDT = TP->desugar(); 3152234353Sdim else if (const AttributedType *AT = dyn_cast<AttributedType>(DT)) 3153234353Sdim QDT = AT->desugar(); 3154234353Sdim if (QDT != castType && 3155234353Sdim QDT.getObjCLifetime() != Qualifiers::OCL_None) { 3156234353Sdim SourceLocation loc = 3157234353Sdim (castRange.isValid() ? castRange.getBegin() 3158234353Sdim : castExpr->getExprLoc()); 3159234353Sdim Diag(loc, diag::err_arc_nolifetime_behavior); 3160234353Sdim } 3161234353Sdim } 3162234353Sdim return ACR_okay; 3163234353Sdim } 3164234353Sdim 3165234353Sdim if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; 3166226633Sdim 3167226633Sdim // Allow all of these types to be cast to integer types (but not 3168226633Sdim // vice-versa). 3169226633Sdim if (castACTC == ACTC_none && castType->isIntegralType(Context)) 3170234353Sdim return ACR_okay; 3171224145Sdim 3172224145Sdim // Allow casts between pointers to lifetime types (e.g., __strong id*) 3173224145Sdim // and pointers to void (e.g., cv void *). Casting from void* to lifetime* 3174224145Sdim // must be explicit. 3175226633Sdim if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr) 3176234353Sdim return ACR_okay; 3177226633Sdim if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && 3178226633Sdim CCK != CCK_ImplicitConversion) 3179234353Sdim return ACR_okay; 3180226633Sdim 3181239462Sdim switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { 3182226633Sdim // For invalid casts, fall through. 3183226633Sdim case ACC_invalid: 3184226633Sdim break; 3185226633Sdim 3186226633Sdim // Do nothing for both bottom and +0. 3187226633Sdim case ACC_bottom: 3188226633Sdim case ACC_plusZero: 3189234353Sdim return ACR_okay; 3190226633Sdim 3191226633Sdim // If the result is +1, consume it here. 3192226633Sdim case ACC_plusOne: 3193226633Sdim castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), 3194226633Sdim CK_ARCConsumeObject, castExpr, 3195226633Sdim 0, VK_RValue); 3196226633Sdim ExprNeedsCleanups = true; 3197234353Sdim return ACR_okay; 3198224145Sdim } 3199234353Sdim 3200234353Sdim // If this is a non-implicit cast from id or block type to a 3201234353Sdim // CoreFoundation type, delay complaining in case the cast is used 3202234353Sdim // in an acceptable context. 3203234353Sdim if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && 3204234353Sdim CCK != CCK_ImplicitConversion) 3205234353Sdim return ACR_unbridged; 3206234353Sdim 3207234353Sdim diagnoseObjCARCConversion(*this, castRange, castType, castACTC, 3208249423Sdim castExpr, castExpr, exprACTC, CCK); 3209234353Sdim return ACR_okay; 3210234353Sdim} 3211234353Sdim 3212234353Sdim/// Given that we saw an expression with the ARCUnbridgedCastTy 3213234353Sdim/// placeholder type, complain bitterly. 3214234353Sdimvoid Sema::diagnoseARCUnbridgedCast(Expr *e) { 3215234353Sdim // We expect the spurious ImplicitCastExpr to already have been stripped. 3216234353Sdim assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); 3217234353Sdim CastExpr *realCast = cast<CastExpr>(e->IgnoreParens()); 3218234353Sdim 3219234353Sdim SourceRange castRange; 3220234353Sdim QualType castType; 3221234353Sdim CheckedConversionKind CCK; 3222234353Sdim 3223234353Sdim if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) { 3224234353Sdim castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc()); 3225234353Sdim castType = cast->getTypeAsWritten(); 3226234353Sdim CCK = CCK_CStyleCast; 3227234353Sdim } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) { 3228234353Sdim castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(); 3229234353Sdim castType = cast->getTypeAsWritten(); 3230234353Sdim CCK = CCK_OtherCast; 3231234353Sdim } else { 3232234353Sdim castType = cast->getType(); 3233234353Sdim CCK = CCK_ImplicitConversion; 3234224145Sdim } 3235234353Sdim 3236234353Sdim ARCConversionTypeClass castACTC = 3237234353Sdim classifyTypeForARCConversion(castType.getNonReferenceType()); 3238234353Sdim 3239234353Sdim Expr *castExpr = realCast->getSubExpr(); 3240234353Sdim assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable); 3241234353Sdim 3242234353Sdim diagnoseObjCARCConversion(*this, castRange, castType, castACTC, 3243249423Sdim castExpr, realCast, ACTC_retainable, CCK); 3244234353Sdim} 3245234353Sdim 3246234353Sdim/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast 3247234353Sdim/// type, remove the placeholder cast. 3248234353SdimExpr *Sema::stripARCUnbridgedCast(Expr *e) { 3249234353Sdim assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); 3250234353Sdim 3251234353Sdim if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) { 3252234353Sdim Expr *sub = stripARCUnbridgedCast(pe->getSubExpr()); 3253234353Sdim return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub); 3254234353Sdim } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) { 3255234353Sdim assert(uo->getOpcode() == UO_Extension); 3256234353Sdim Expr *sub = stripARCUnbridgedCast(uo->getSubExpr()); 3257234353Sdim return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(), 3258234353Sdim sub->getValueKind(), sub->getObjectKind(), 3259234353Sdim uo->getOperatorLoc()); 3260234353Sdim } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 3261234353Sdim assert(!gse->isResultDependent()); 3262234353Sdim 3263234353Sdim unsigned n = gse->getNumAssocs(); 3264234353Sdim SmallVector<Expr*, 4> subExprs(n); 3265234353Sdim SmallVector<TypeSourceInfo*, 4> subTypes(n); 3266234353Sdim for (unsigned i = 0; i != n; ++i) { 3267234353Sdim subTypes[i] = gse->getAssocTypeSourceInfo(i); 3268234353Sdim Expr *sub = gse->getAssocExpr(i); 3269234353Sdim if (i == gse->getResultIndex()) 3270234353Sdim sub = stripARCUnbridgedCast(sub); 3271234353Sdim subExprs[i] = sub; 3272224145Sdim } 3273224145Sdim 3274234353Sdim return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), 3275234353Sdim gse->getControllingExpr(), 3276243830Sdim subTypes, subExprs, 3277243830Sdim gse->getDefaultLoc(), 3278234353Sdim gse->getRParenLoc(), 3279234353Sdim gse->containsUnexpandedParameterPack(), 3280234353Sdim gse->getResultIndex()); 3281234353Sdim } else { 3282234353Sdim assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!"); 3283234353Sdim return cast<ImplicitCastExpr>(e)->getSubExpr(); 3284224145Sdim } 3285224145Sdim} 3286224145Sdim 3287224145Sdimbool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, 3288224145Sdim QualType exprType) { 3289224145Sdim QualType canCastType = 3290224145Sdim Context.getCanonicalType(castType).getUnqualifiedType(); 3291224145Sdim QualType canExprType = 3292224145Sdim Context.getCanonicalType(exprType).getUnqualifiedType(); 3293224145Sdim if (isa<ObjCObjectPointerType>(canCastType) && 3294224145Sdim castType.getObjCLifetime() == Qualifiers::OCL_Weak && 3295224145Sdim canExprType->isObjCObjectPointerType()) { 3296224145Sdim if (const ObjCObjectPointerType *ObjT = 3297224145Sdim canExprType->getAs<ObjCObjectPointerType>()) 3298243830Sdim if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl()) 3299243830Sdim return !ObjI->isArcWeakrefUnavailable(); 3300224145Sdim } 3301224145Sdim return true; 3302224145Sdim} 3303224145Sdim 3304224145Sdim/// Look for an ObjCReclaimReturnedObject cast and destroy it. 3305224145Sdimstatic Expr *maybeUndoReclaimObject(Expr *e) { 3306224145Sdim // For now, we just undo operands that are *immediately* reclaim 3307224145Sdim // expressions, which prevents the vast majority of potential 3308224145Sdim // problems here. To catch them all, we'd need to rebuild arbitrary 3309224145Sdim // value-propagating subexpressions --- we can't reliably rebuild 3310224145Sdim // in-place because of expression sharing. 3311224145Sdim if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) 3312226633Sdim if (ice->getCastKind() == CK_ARCReclaimReturnedObject) 3313224145Sdim return ice->getSubExpr(); 3314224145Sdim 3315224145Sdim return e; 3316224145Sdim} 3317224145Sdim 3318224145SdimExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, 3319224145Sdim ObjCBridgeCastKind Kind, 3320224145Sdim SourceLocation BridgeKeywordLoc, 3321224145Sdim TypeSourceInfo *TSInfo, 3322224145Sdim Expr *SubExpr) { 3323226633Sdim ExprResult SubResult = UsualUnaryConversions(SubExpr); 3324226633Sdim if (SubResult.isInvalid()) return ExprError(); 3325226633Sdim SubExpr = SubResult.take(); 3326226633Sdim 3327224145Sdim QualType T = TSInfo->getType(); 3328224145Sdim QualType FromType = SubExpr->getType(); 3329224145Sdim 3330226633Sdim CastKind CK; 3331226633Sdim 3332224145Sdim bool MustConsume = false; 3333224145Sdim if (T->isDependentType() || SubExpr->isTypeDependent()) { 3334224145Sdim // Okay: we'll build a dependent expression type. 3335226633Sdim CK = CK_Dependent; 3336224145Sdim } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) { 3337224145Sdim // Casting CF -> id 3338226633Sdim CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast 3339226633Sdim : CK_CPointerToObjCPointerCast); 3340224145Sdim switch (Kind) { 3341224145Sdim case OBC_Bridge: 3342224145Sdim break; 3343224145Sdim 3344234353Sdim case OBC_BridgeRetained: { 3345239462Sdim bool br = isKnownName("CFBridgingRelease"); 3346224145Sdim Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) 3347224145Sdim << 2 3348224145Sdim << FromType 3349224145Sdim << (T->isBlockPointerType()? 1 : 0) 3350224145Sdim << T 3351224145Sdim << SubExpr->getSourceRange() 3352224145Sdim << Kind; 3353224145Sdim Diag(BridgeKeywordLoc, diag::note_arc_bridge) 3354224145Sdim << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge"); 3355224145Sdim Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer) 3356234353Sdim << FromType << br 3357224145Sdim << FixItHint::CreateReplacement(BridgeKeywordLoc, 3358234353Sdim br ? "CFBridgingRelease " 3359234353Sdim : "__bridge_transfer "); 3360224145Sdim 3361224145Sdim Kind = OBC_Bridge; 3362224145Sdim break; 3363234353Sdim } 3364224145Sdim 3365224145Sdim case OBC_BridgeTransfer: 3366224145Sdim // We must consume the Objective-C object produced by the cast. 3367224145Sdim MustConsume = true; 3368224145Sdim break; 3369224145Sdim } 3370224145Sdim } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) { 3371224145Sdim // Okay: id -> CF 3372226633Sdim CK = CK_BitCast; 3373224145Sdim switch (Kind) { 3374224145Sdim case OBC_Bridge: 3375224145Sdim // Reclaiming a value that's going to be __bridge-casted to CF 3376224145Sdim // is very dangerous, so we don't do it. 3377224145Sdim SubExpr = maybeUndoReclaimObject(SubExpr); 3378224145Sdim break; 3379224145Sdim 3380224145Sdim case OBC_BridgeRetained: 3381224145Sdim // Produce the object before casting it. 3382224145Sdim SubExpr = ImplicitCastExpr::Create(Context, FromType, 3383226633Sdim CK_ARCProduceObject, 3384224145Sdim SubExpr, 0, VK_RValue); 3385224145Sdim break; 3386224145Sdim 3387234353Sdim case OBC_BridgeTransfer: { 3388239462Sdim bool br = isKnownName("CFBridgingRetain"); 3389224145Sdim Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) 3390224145Sdim << (FromType->isBlockPointerType()? 1 : 0) 3391224145Sdim << FromType 3392224145Sdim << 2 3393224145Sdim << T 3394224145Sdim << SubExpr->getSourceRange() 3395224145Sdim << Kind; 3396224145Sdim 3397224145Sdim Diag(BridgeKeywordLoc, diag::note_arc_bridge) 3398224145Sdim << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge "); 3399224145Sdim Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained) 3400234353Sdim << T << br 3401234353Sdim << FixItHint::CreateReplacement(BridgeKeywordLoc, 3402234353Sdim br ? "CFBridgingRetain " : "__bridge_retained"); 3403224145Sdim 3404224145Sdim Kind = OBC_Bridge; 3405224145Sdim break; 3406224145Sdim } 3407234353Sdim } 3408224145Sdim } else { 3409224145Sdim Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible) 3410224145Sdim << FromType << T << Kind 3411224145Sdim << SubExpr->getSourceRange() 3412224145Sdim << TSInfo->getTypeLoc().getSourceRange(); 3413224145Sdim return ExprError(); 3414224145Sdim } 3415224145Sdim 3416226633Sdim Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK, 3417224145Sdim BridgeKeywordLoc, 3418224145Sdim TSInfo, SubExpr); 3419224145Sdim 3420224145Sdim if (MustConsume) { 3421224145Sdim ExprNeedsCleanups = true; 3422226633Sdim Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, 3423224145Sdim 0, VK_RValue); 3424224145Sdim } 3425224145Sdim 3426224145Sdim return Result; 3427224145Sdim} 3428224145Sdim 3429224145SdimExprResult Sema::ActOnObjCBridgedCast(Scope *S, 3430224145Sdim SourceLocation LParenLoc, 3431224145Sdim ObjCBridgeCastKind Kind, 3432224145Sdim SourceLocation BridgeKeywordLoc, 3433224145Sdim ParsedType Type, 3434224145Sdim SourceLocation RParenLoc, 3435224145Sdim Expr *SubExpr) { 3436224145Sdim TypeSourceInfo *TSInfo = 0; 3437224145Sdim QualType T = GetTypeFromParser(Type, &TSInfo); 3438224145Sdim if (!TSInfo) 3439224145Sdim TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc); 3440224145Sdim return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo, 3441224145Sdim SubExpr); 3442224145Sdim} 3443