1 //===----- SemaObjC.cpp ---- Semantic Analysis for Objective-C ------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file implements semantic analysis for Objective-C. 10 /// 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Sema/SemaObjC.h" 14 #include "clang/AST/ASTMutationListener.h" 15 #include "clang/AST/EvaluatedExprVisitor.h" 16 #include "clang/AST/StmtObjC.h" 17 #include "clang/Basic/DiagnosticSema.h" 18 #include "clang/Lex/Preprocessor.h" 19 #include "clang/Sema/Attr.h" 20 #include "clang/Sema/Lookup.h" 21 #include "clang/Sema/ParsedAttr.h" 22 #include "clang/Sema/ScopeInfo.h" 23 #include "clang/Sema/Sema.h" 24 #include "clang/Sema/TemplateDeduction.h" 25 #include "llvm/Support/ConvertUTF.h" 26 27 namespace clang { 28 29 SemaObjC::SemaObjC(Sema &S) 30 : SemaBase(S), NSNumberDecl(nullptr), NSValueDecl(nullptr), 31 NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), 32 ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), 33 ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), 34 DictionaryWithObjectsMethod(nullptr) {} 35 36 StmtResult SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc, 37 Stmt *First, Expr *collection, 38 SourceLocation RParenLoc) { 39 ASTContext &Context = getASTContext(); 40 SemaRef.setFunctionHasBranchProtectedScope(); 41 42 ExprResult CollectionExprResult = 43 CheckObjCForCollectionOperand(ForLoc, collection); 44 45 if (First) { 46 QualType FirstType; 47 if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) { 48 if (!DS->isSingleDecl()) 49 return StmtError(Diag((*DS->decl_begin())->getLocation(), 50 diag::err_toomany_element_decls)); 51 52 VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl()); 53 if (!D || D->isInvalidDecl()) 54 return StmtError(); 55 56 FirstType = D->getType(); 57 // C99 6.8.5p3: The declaration part of a 'for' statement shall only 58 // declare identifiers for objects having storage class 'auto' or 59 // 'register'. 60 if (!D->hasLocalStorage()) 61 return StmtError( 62 Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for)); 63 64 // If the type contained 'auto', deduce the 'auto' to 'id'. 65 if (FirstType->getContainedAutoType()) { 66 SourceLocation Loc = D->getLocation(); 67 OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue); 68 Expr *DeducedInit = &OpaqueId; 69 sema::TemplateDeductionInfo Info(Loc); 70 FirstType = QualType(); 71 TemplateDeductionResult Result = SemaRef.DeduceAutoType( 72 D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); 73 if (Result != TemplateDeductionResult::Success && 74 Result != TemplateDeductionResult::AlreadyDiagnosed) 75 SemaRef.DiagnoseAutoDeductionFailure(D, DeducedInit); 76 if (FirstType.isNull()) { 77 D->setInvalidDecl(); 78 return StmtError(); 79 } 80 81 D->setType(FirstType); 82 83 if (!SemaRef.inTemplateInstantiation()) { 84 SourceLocation Loc = 85 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); 86 Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName(); 87 } 88 } 89 90 } else { 91 Expr *FirstE = cast<Expr>(First); 92 if (!FirstE->isTypeDependent() && !FirstE->isLValue()) 93 return StmtError( 94 Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue) 95 << First->getSourceRange()); 96 97 FirstType = static_cast<Expr *>(First)->getType(); 98 if (FirstType.isConstQualified()) 99 Diag(ForLoc, diag::err_selector_element_const_type) 100 << FirstType << First->getSourceRange(); 101 } 102 if (!FirstType->isDependentType() && 103 !FirstType->isObjCObjectPointerType() && 104 !FirstType->isBlockPointerType()) 105 return StmtError(Diag(ForLoc, diag::err_selector_element_type) 106 << FirstType << First->getSourceRange()); 107 } 108 109 if (CollectionExprResult.isInvalid()) 110 return StmtError(); 111 112 CollectionExprResult = SemaRef.ActOnFinishFullExpr(CollectionExprResult.get(), 113 /*DiscardedValue*/ false); 114 if (CollectionExprResult.isInvalid()) 115 return StmtError(); 116 117 return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(), 118 nullptr, ForLoc, RParenLoc); 119 } 120 121 ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc, 122 Expr *collection) { 123 ASTContext &Context = getASTContext(); 124 if (!collection) 125 return ExprError(); 126 127 ExprResult result = SemaRef.CorrectDelayedTyposInExpr(collection); 128 if (!result.isUsable()) 129 return ExprError(); 130 collection = result.get(); 131 132 // Bail out early if we've got a type-dependent expression. 133 if (collection->isTypeDependent()) 134 return collection; 135 136 // Perform normal l-value conversion. 137 result = SemaRef.DefaultFunctionArrayLvalueConversion(collection); 138 if (result.isInvalid()) 139 return ExprError(); 140 collection = result.get(); 141 142 // The operand needs to have object-pointer type. 143 // TODO: should we do a contextual conversion? 144 const ObjCObjectPointerType *pointerType = 145 collection->getType()->getAs<ObjCObjectPointerType>(); 146 if (!pointerType) 147 return Diag(forLoc, diag::err_collection_expr_type) 148 << collection->getType() << collection->getSourceRange(); 149 150 // Check that the operand provides 151 // - countByEnumeratingWithState:objects:count: 152 const ObjCObjectType *objectType = pointerType->getObjectType(); 153 ObjCInterfaceDecl *iface = objectType->getInterface(); 154 155 // If we have a forward-declared type, we can't do this check. 156 // Under ARC, it is an error not to have a forward-declared class. 157 if (iface && 158 (getLangOpts().ObjCAutoRefCount 159 ? SemaRef.RequireCompleteType(forLoc, QualType(objectType, 0), 160 diag::err_arc_collection_forward, 161 collection) 162 : !SemaRef.isCompleteType(forLoc, QualType(objectType, 0)))) { 163 // Otherwise, if we have any useful type information, check that 164 // the type declares the appropriate method. 165 } else if (iface || !objectType->qual_empty()) { 166 const IdentifierInfo *selectorIdents[] = { 167 &Context.Idents.get("countByEnumeratingWithState"), 168 &Context.Idents.get("objects"), &Context.Idents.get("count")}; 169 Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); 170 171 ObjCMethodDecl *method = nullptr; 172 173 // If there's an interface, look in both the public and private APIs. 174 if (iface) { 175 method = iface->lookupInstanceMethod(selector); 176 if (!method) 177 method = iface->lookupPrivateMethod(selector); 178 } 179 180 // Also check protocol qualifiers. 181 if (!method) 182 method = LookupMethodInQualifiedType(selector, pointerType, 183 /*instance*/ true); 184 185 // If we didn't find it anywhere, give up. 186 if (!method) { 187 Diag(forLoc, diag::warn_collection_expr_type) 188 << collection->getType() << selector << collection->getSourceRange(); 189 } 190 191 // TODO: check for an incompatible signature? 192 } 193 194 // Wrap up any cleanups in the expression. 195 return collection; 196 } 197 198 StmtResult SemaObjC::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { 199 if (!S || !B) 200 return StmtError(); 201 ObjCForCollectionStmt *ForStmt = cast<ObjCForCollectionStmt>(S); 202 203 ForStmt->setBody(B); 204 return S; 205 } 206 207 StmtResult SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc, 208 SourceLocation RParen, Decl *Parm, 209 Stmt *Body) { 210 ASTContext &Context = getASTContext(); 211 VarDecl *Var = cast_or_null<VarDecl>(Parm); 212 if (Var && Var->isInvalidDecl()) 213 return StmtError(); 214 215 return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body); 216 } 217 218 StmtResult SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { 219 ASTContext &Context = getASTContext(); 220 return new (Context) ObjCAtFinallyStmt(AtLoc, Body); 221 } 222 223 StmtResult SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, 224 MultiStmtArg CatchStmts, 225 Stmt *Finally) { 226 ASTContext &Context = getASTContext(); 227 if (!getLangOpts().ObjCExceptions) 228 Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; 229 230 // Objective-C try is incompatible with SEH __try. 231 sema::FunctionScopeInfo *FSI = SemaRef.getCurFunction(); 232 if (FSI->FirstSEHTryLoc.isValid()) { 233 Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1; 234 Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; 235 } 236 237 FSI->setHasObjCTry(AtLoc); 238 unsigned NumCatchStmts = CatchStmts.size(); 239 return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), 240 NumCatchStmts, Finally); 241 } 242 243 StmtResult SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { 244 ASTContext &Context = getASTContext(); 245 if (Throw) { 246 ExprResult Result = SemaRef.DefaultLvalueConversion(Throw); 247 if (Result.isInvalid()) 248 return StmtError(); 249 250 Result = 251 SemaRef.ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); 252 if (Result.isInvalid()) 253 return StmtError(); 254 Throw = Result.get(); 255 256 QualType ThrowType = Throw->getType(); 257 // Make sure the expression type is an ObjC pointer or "void *". 258 if (!ThrowType->isDependentType() && 259 !ThrowType->isObjCObjectPointerType()) { 260 const PointerType *PT = ThrowType->getAs<PointerType>(); 261 if (!PT || !PT->getPointeeType()->isVoidType()) 262 return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object) 263 << Throw->getType() << Throw->getSourceRange()); 264 } 265 } 266 267 return new (Context) ObjCAtThrowStmt(AtLoc, Throw); 268 } 269 270 StmtResult SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, 271 Scope *CurScope) { 272 if (!getLangOpts().ObjCExceptions) 273 Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; 274 275 if (!Throw) { 276 // @throw without an expression designates a rethrow (which must occur 277 // in the context of an @catch clause). 278 Scope *AtCatchParent = CurScope; 279 while (AtCatchParent && !AtCatchParent->isAtCatchScope()) 280 AtCatchParent = AtCatchParent->getParent(); 281 if (!AtCatchParent) 282 return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch)); 283 } 284 return BuildObjCAtThrowStmt(AtLoc, Throw); 285 } 286 287 ExprResult SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, 288 Expr *operand) { 289 ExprResult result = SemaRef.DefaultLvalueConversion(operand); 290 if (result.isInvalid()) 291 return ExprError(); 292 operand = result.get(); 293 294 // Make sure the expression type is an ObjC pointer or "void *". 295 QualType type = operand->getType(); 296 if (!type->isDependentType() && !type->isObjCObjectPointerType()) { 297 const PointerType *pointerType = type->getAs<PointerType>(); 298 if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { 299 if (getLangOpts().CPlusPlus) { 300 if (SemaRef.RequireCompleteType(atLoc, type, 301 diag::err_incomplete_receiver_type)) 302 return Diag(atLoc, diag::err_objc_synchronized_expects_object) 303 << type << operand->getSourceRange(); 304 305 ExprResult result = 306 SemaRef.PerformContextuallyConvertToObjCPointer(operand); 307 if (result.isInvalid()) 308 return ExprError(); 309 if (!result.isUsable()) 310 return Diag(atLoc, diag::err_objc_synchronized_expects_object) 311 << type << operand->getSourceRange(); 312 313 operand = result.get(); 314 } else { 315 return Diag(atLoc, diag::err_objc_synchronized_expects_object) 316 << type << operand->getSourceRange(); 317 } 318 } 319 } 320 321 // The operand to @synchronized is a full-expression. 322 return SemaRef.ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); 323 } 324 325 StmtResult SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, 326 Expr *SyncExpr, 327 Stmt *SyncBody) { 328 ASTContext &Context = getASTContext(); 329 // We can't jump into or indirect-jump out of a @synchronized block. 330 SemaRef.setFunctionHasBranchProtectedScope(); 331 return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody); 332 } 333 334 StmtResult SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, 335 Stmt *Body) { 336 ASTContext &Context = getASTContext(); 337 SemaRef.setFunctionHasBranchProtectedScope(); 338 return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body); 339 } 340 341 TypeResult SemaObjC::actOnObjCProtocolQualifierType( 342 SourceLocation lAngleLoc, ArrayRef<Decl *> protocols, 343 ArrayRef<SourceLocation> protocolLocs, SourceLocation rAngleLoc) { 344 ASTContext &Context = getASTContext(); 345 // Form id<protocol-list>. 346 QualType Result = Context.getObjCObjectType( 347 Context.ObjCBuiltinIdTy, {}, 348 llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(), 349 protocols.size()), 350 false); 351 Result = Context.getObjCObjectPointerType(Result); 352 353 TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); 354 TypeLoc ResultTL = ResultTInfo->getTypeLoc(); 355 356 auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>(); 357 ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit 358 359 auto ObjCObjectTL = 360 ObjCObjectPointerTL.getPointeeLoc().castAs<ObjCObjectTypeLoc>(); 361 ObjCObjectTL.setHasBaseTypeAsWritten(false); 362 ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation()); 363 364 // No type arguments. 365 ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); 366 ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); 367 368 // Fill in protocol qualifiers. 369 ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc); 370 ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc); 371 for (unsigned i = 0, n = protocols.size(); i != n; ++i) 372 ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]); 373 374 // We're done. Return the completed type to the parser. 375 return SemaRef.CreateParsedType(Result, ResultTInfo); 376 } 377 378 TypeResult SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers( 379 Scope *S, SourceLocation Loc, ParsedType BaseType, 380 SourceLocation TypeArgsLAngleLoc, ArrayRef<ParsedType> TypeArgs, 381 SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc, 382 ArrayRef<Decl *> Protocols, ArrayRef<SourceLocation> ProtocolLocs, 383 SourceLocation ProtocolRAngleLoc) { 384 ASTContext &Context = getASTContext(); 385 TypeSourceInfo *BaseTypeInfo = nullptr; 386 QualType T = SemaRef.GetTypeFromParser(BaseType, &BaseTypeInfo); 387 if (T.isNull()) 388 return true; 389 390 // Handle missing type-source info. 391 if (!BaseTypeInfo) 392 BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc); 393 394 // Extract type arguments. 395 SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos; 396 for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) { 397 TypeSourceInfo *TypeArgInfo = nullptr; 398 QualType TypeArg = SemaRef.GetTypeFromParser(TypeArgs[i], &TypeArgInfo); 399 if (TypeArg.isNull()) { 400 ActualTypeArgInfos.clear(); 401 break; 402 } 403 404 assert(TypeArgInfo && "No type source info?"); 405 ActualTypeArgInfos.push_back(TypeArgInfo); 406 } 407 408 // Build the object type. 409 QualType Result = BuildObjCObjectType( 410 T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(), 411 TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc, 412 ProtocolLAngleLoc, 413 llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(), 414 Protocols.size()), 415 ProtocolLocs, ProtocolRAngleLoc, 416 /*FailOnError=*/false, 417 /*Rebuilding=*/false); 418 419 if (Result == T) 420 return BaseType; 421 422 // Create source information for this type. 423 TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); 424 TypeLoc ResultTL = ResultTInfo->getTypeLoc(); 425 426 // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an 427 // object pointer type. Fill in source information for it. 428 if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) { 429 // The '*' is implicit. 430 ObjCObjectPointerTL.setStarLoc(SourceLocation()); 431 ResultTL = ObjCObjectPointerTL.getPointeeLoc(); 432 } 433 434 if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) { 435 // Protocol qualifier information. 436 if (OTPTL.getNumProtocols() > 0) { 437 assert(OTPTL.getNumProtocols() == Protocols.size()); 438 OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc); 439 OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc); 440 for (unsigned i = 0, n = Protocols.size(); i != n; ++i) 441 OTPTL.setProtocolLoc(i, ProtocolLocs[i]); 442 } 443 444 // We're done. Return the completed type to the parser. 445 return SemaRef.CreateParsedType(Result, ResultTInfo); 446 } 447 448 auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>(); 449 450 // Type argument information. 451 if (ObjCObjectTL.getNumTypeArgs() > 0) { 452 assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size()); 453 ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc); 454 ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc); 455 for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i) 456 ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]); 457 } else { 458 ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); 459 ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); 460 } 461 462 // Protocol qualifier information. 463 if (ObjCObjectTL.getNumProtocols() > 0) { 464 assert(ObjCObjectTL.getNumProtocols() == Protocols.size()); 465 ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc); 466 ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc); 467 for (unsigned i = 0, n = Protocols.size(); i != n; ++i) 468 ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]); 469 } else { 470 ObjCObjectTL.setProtocolLAngleLoc(SourceLocation()); 471 ObjCObjectTL.setProtocolRAngleLoc(SourceLocation()); 472 } 473 474 // Base type. 475 ObjCObjectTL.setHasBaseTypeAsWritten(true); 476 if (ObjCObjectTL.getType() == T) 477 ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc()); 478 else 479 ObjCObjectTL.getBaseLoc().initialize(Context, Loc); 480 481 // We're done. Return the completed type to the parser. 482 return SemaRef.CreateParsedType(Result, ResultTInfo); 483 } 484 485 QualType SemaObjC::BuildObjCTypeParamType( 486 const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc, 487 ArrayRef<ObjCProtocolDecl *> Protocols, 488 ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc, 489 bool FailOnError) { 490 ASTContext &Context = getASTContext(); 491 QualType Result = QualType(Decl->getTypeForDecl(), 0); 492 if (!Protocols.empty()) { 493 bool HasError; 494 Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError); 495 if (HasError) { 496 Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers) 497 << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); 498 if (FailOnError) 499 Result = QualType(); 500 } 501 if (FailOnError && Result.isNull()) 502 return QualType(); 503 } 504 505 return Result; 506 } 507 508 /// Apply Objective-C type arguments to the given type. 509 static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, 510 ArrayRef<TypeSourceInfo *> typeArgs, 511 SourceRange typeArgsRange, bool failOnError, 512 bool rebuilding) { 513 // We can only apply type arguments to an Objective-C class type. 514 const auto *objcObjectType = type->getAs<ObjCObjectType>(); 515 if (!objcObjectType || !objcObjectType->getInterface()) { 516 S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange; 517 518 if (failOnError) 519 return QualType(); 520 return type; 521 } 522 523 // The class type must be parameterized. 524 ObjCInterfaceDecl *objcClass = objcObjectType->getInterface(); 525 ObjCTypeParamList *typeParams = objcClass->getTypeParamList(); 526 if (!typeParams) { 527 S.Diag(loc, diag::err_objc_type_args_non_parameterized_class) 528 << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange); 529 530 if (failOnError) 531 return QualType(); 532 533 return type; 534 } 535 536 // The type must not already be specialized. 537 if (objcObjectType->isSpecialized()) { 538 S.Diag(loc, diag::err_objc_type_args_specialized_class) 539 << type << FixItHint::CreateRemoval(typeArgsRange); 540 541 if (failOnError) 542 return QualType(); 543 544 return type; 545 } 546 547 // Check the type arguments. 548 SmallVector<QualType, 4> finalTypeArgs; 549 unsigned numTypeParams = typeParams->size(); 550 bool anyPackExpansions = false; 551 for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) { 552 TypeSourceInfo *typeArgInfo = typeArgs[i]; 553 QualType typeArg = typeArgInfo->getType(); 554 555 // Type arguments cannot have explicit qualifiers or nullability. 556 // We ignore indirect sources of these, e.g. behind typedefs or 557 // template arguments. 558 if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) { 559 bool diagnosed = false; 560 SourceRange rangeToRemove; 561 if (auto attr = qual.getAs<AttributedTypeLoc>()) { 562 rangeToRemove = attr.getLocalSourceRange(); 563 if (attr.getTypePtr()->getImmediateNullability()) { 564 typeArg = attr.getTypePtr()->getModifiedType(); 565 S.Diag(attr.getBeginLoc(), 566 diag::err_objc_type_arg_explicit_nullability) 567 << typeArg << FixItHint::CreateRemoval(rangeToRemove); 568 diagnosed = true; 569 } 570 } 571 572 // When rebuilding, qualifiers might have gotten here through a 573 // final substitution. 574 if (!rebuilding && !diagnosed) { 575 S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified) 576 << typeArg << typeArg.getQualifiers().getAsString() 577 << FixItHint::CreateRemoval(rangeToRemove); 578 } 579 } 580 581 // Remove qualifiers even if they're non-local. 582 typeArg = typeArg.getUnqualifiedType(); 583 584 finalTypeArgs.push_back(typeArg); 585 586 if (typeArg->getAs<PackExpansionType>()) 587 anyPackExpansions = true; 588 589 // Find the corresponding type parameter, if there is one. 590 ObjCTypeParamDecl *typeParam = nullptr; 591 if (!anyPackExpansions) { 592 if (i < numTypeParams) { 593 typeParam = typeParams->begin()[i]; 594 } else { 595 // Too many arguments. 596 S.Diag(loc, diag::err_objc_type_args_wrong_arity) 597 << false << objcClass->getDeclName() << (unsigned)typeArgs.size() 598 << numTypeParams; 599 S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; 600 601 if (failOnError) 602 return QualType(); 603 604 return type; 605 } 606 } 607 608 // Objective-C object pointer types must be substitutable for the bounds. 609 if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) { 610 // If we don't have a type parameter to match against, assume 611 // everything is fine. There was a prior pack expansion that 612 // means we won't be able to match anything. 613 if (!typeParam) { 614 assert(anyPackExpansions && "Too many arguments?"); 615 continue; 616 } 617 618 // Retrieve the bound. 619 QualType bound = typeParam->getUnderlyingType(); 620 const auto *boundObjC = bound->castAs<ObjCObjectPointerType>(); 621 622 // Determine whether the type argument is substitutable for the bound. 623 if (typeArgObjC->isObjCIdType()) { 624 // When the type argument is 'id', the only acceptable type 625 // parameter bound is 'id'. 626 if (boundObjC->isObjCIdType()) 627 continue; 628 } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) { 629 // Otherwise, we follow the assignability rules. 630 continue; 631 } 632 633 // Diagnose the mismatch. 634 S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), 635 diag::err_objc_type_arg_does_not_match_bound) 636 << typeArg << bound << typeParam->getDeclName(); 637 S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) 638 << typeParam->getDeclName(); 639 640 if (failOnError) 641 return QualType(); 642 643 return type; 644 } 645 646 // Block pointer types are permitted for unqualified 'id' bounds. 647 if (typeArg->isBlockPointerType()) { 648 // If we don't have a type parameter to match against, assume 649 // everything is fine. There was a prior pack expansion that 650 // means we won't be able to match anything. 651 if (!typeParam) { 652 assert(anyPackExpansions && "Too many arguments?"); 653 continue; 654 } 655 656 // Retrieve the bound. 657 QualType bound = typeParam->getUnderlyingType(); 658 if (bound->isBlockCompatibleObjCPointerType(S.Context)) 659 continue; 660 661 // Diagnose the mismatch. 662 S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), 663 diag::err_objc_type_arg_does_not_match_bound) 664 << typeArg << bound << typeParam->getDeclName(); 665 S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) 666 << typeParam->getDeclName(); 667 668 if (failOnError) 669 return QualType(); 670 671 return type; 672 } 673 674 // Types that have __attribute__((NSObject)) are permitted. 675 if (typeArg->isObjCNSObjectType()) { 676 continue; 677 } 678 679 // Dependent types will be checked at instantiation time. 680 if (typeArg->isDependentType()) { 681 continue; 682 } 683 684 // Diagnose non-id-compatible type arguments. 685 S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), 686 diag::err_objc_type_arg_not_id_compatible) 687 << typeArg << typeArgInfo->getTypeLoc().getSourceRange(); 688 689 if (failOnError) 690 return QualType(); 691 692 return type; 693 } 694 695 // Make sure we didn't have the wrong number of arguments. 696 if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) { 697 S.Diag(loc, diag::err_objc_type_args_wrong_arity) 698 << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName() 699 << (unsigned)finalTypeArgs.size() << (unsigned)numTypeParams; 700 S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; 701 702 if (failOnError) 703 return QualType(); 704 705 return type; 706 } 707 708 // Success. Form the specialized type. 709 return S.Context.getObjCObjectType(type, finalTypeArgs, {}, false); 710 } 711 712 QualType SemaObjC::BuildObjCObjectType( 713 QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, 714 ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc, 715 SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols, 716 ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc, 717 bool FailOnError, bool Rebuilding) { 718 ASTContext &Context = getASTContext(); 719 QualType Result = BaseType; 720 if (!TypeArgs.empty()) { 721 Result = 722 applyObjCTypeArgs(SemaRef, Loc, Result, TypeArgs, 723 SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc), 724 FailOnError, Rebuilding); 725 if (FailOnError && Result.isNull()) 726 return QualType(); 727 } 728 729 if (!Protocols.empty()) { 730 bool HasError; 731 Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError); 732 if (HasError) { 733 Diag(Loc, diag::err_invalid_protocol_qualifiers) 734 << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); 735 if (FailOnError) 736 Result = QualType(); 737 } 738 if (FailOnError && Result.isNull()) 739 return QualType(); 740 } 741 742 return Result; 743 } 744 745 ParsedType SemaObjC::ActOnObjCInstanceType(SourceLocation Loc) { 746 ASTContext &Context = getASTContext(); 747 QualType T = Context.getObjCInstanceType(); 748 TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc); 749 return SemaRef.CreateParsedType(T, TInfo); 750 } 751 752 //===--- CHECK: Objective-C retain cycles ----------------------------------// 753 754 namespace { 755 756 struct RetainCycleOwner { 757 VarDecl *Variable = nullptr; 758 SourceRange Range; 759 SourceLocation Loc; 760 bool Indirect = false; 761 762 RetainCycleOwner() = default; 763 764 void setLocsFrom(Expr *e) { 765 Loc = e->getExprLoc(); 766 Range = e->getSourceRange(); 767 } 768 }; 769 770 } // namespace 771 772 /// Consider whether capturing the given variable can possibly lead to 773 /// a retain cycle. 774 static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { 775 // In ARC, it's captured strongly iff the variable has __strong 776 // lifetime. In MRR, it's captured strongly if the variable is 777 // __block and has an appropriate type. 778 if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong) 779 return false; 780 781 owner.Variable = var; 782 if (ref) 783 owner.setLocsFrom(ref); 784 return true; 785 } 786 787 static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { 788 while (true) { 789 e = e->IgnoreParens(); 790 if (CastExpr *cast = dyn_cast<CastExpr>(e)) { 791 switch (cast->getCastKind()) { 792 case CK_BitCast: 793 case CK_LValueBitCast: 794 case CK_LValueToRValue: 795 case CK_ARCReclaimReturnedObject: 796 e = cast->getSubExpr(); 797 continue; 798 799 default: 800 return false; 801 } 802 } 803 804 if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) { 805 ObjCIvarDecl *ivar = ref->getDecl(); 806 if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong) 807 return false; 808 809 // Try to find a retain cycle in the base. 810 if (!findRetainCycleOwner(S, ref->getBase(), owner)) 811 return false; 812 813 if (ref->isFreeIvar()) 814 owner.setLocsFrom(ref); 815 owner.Indirect = true; 816 return true; 817 } 818 819 if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) { 820 VarDecl *var = dyn_cast<VarDecl>(ref->getDecl()); 821 if (!var) 822 return false; 823 return considerVariable(var, ref, owner); 824 } 825 826 if (MemberExpr *member = dyn_cast<MemberExpr>(e)) { 827 if (member->isArrow()) 828 return false; 829 830 // Don't count this as an indirect ownership. 831 e = member->getBase(); 832 continue; 833 } 834 835 if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { 836 // Only pay attention to pseudo-objects on property references. 837 ObjCPropertyRefExpr *pre = dyn_cast<ObjCPropertyRefExpr>( 838 pseudo->getSyntacticForm()->IgnoreParens()); 839 if (!pre) 840 return false; 841 if (pre->isImplicitProperty()) 842 return false; 843 ObjCPropertyDecl *property = pre->getExplicitProperty(); 844 if (!property->isRetaining() && 845 !(property->getPropertyIvarDecl() && 846 property->getPropertyIvarDecl()->getType().getObjCLifetime() == 847 Qualifiers::OCL_Strong)) 848 return false; 849 850 owner.Indirect = true; 851 if (pre->isSuperReceiver()) { 852 owner.Variable = S.getCurMethodDecl()->getSelfDecl(); 853 if (!owner.Variable) 854 return false; 855 owner.Loc = pre->getLocation(); 856 owner.Range = pre->getSourceRange(); 857 return true; 858 } 859 e = const_cast<Expr *>( 860 cast<OpaqueValueExpr>(pre->getBase())->getSourceExpr()); 861 continue; 862 } 863 864 // Array ivars? 865 866 return false; 867 } 868 } 869 870 namespace { 871 872 struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> { 873 VarDecl *Variable; 874 Expr *Capturer = nullptr; 875 bool VarWillBeReased = false; 876 877 FindCaptureVisitor(ASTContext &Context, VarDecl *variable) 878 : EvaluatedExprVisitor<FindCaptureVisitor>(Context), Variable(variable) {} 879 880 void VisitDeclRefExpr(DeclRefExpr *ref) { 881 if (ref->getDecl() == Variable && !Capturer) 882 Capturer = ref; 883 } 884 885 void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { 886 if (Capturer) 887 return; 888 Visit(ref->getBase()); 889 if (Capturer && ref->isFreeIvar()) 890 Capturer = ref; 891 } 892 893 void VisitBlockExpr(BlockExpr *block) { 894 // Look inside nested blocks 895 if (block->getBlockDecl()->capturesVariable(Variable)) 896 Visit(block->getBlockDecl()->getBody()); 897 } 898 899 void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) { 900 if (Capturer) 901 return; 902 if (OVE->getSourceExpr()) 903 Visit(OVE->getSourceExpr()); 904 } 905 906 void VisitBinaryOperator(BinaryOperator *BinOp) { 907 if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign) 908 return; 909 Expr *LHS = BinOp->getLHS(); 910 if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) { 911 if (DRE->getDecl() != Variable) 912 return; 913 if (Expr *RHS = BinOp->getRHS()) { 914 RHS = RHS->IgnoreParenCasts(); 915 std::optional<llvm::APSInt> Value; 916 VarWillBeReased = 917 (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && 918 *Value == 0); 919 } 920 } 921 } 922 }; 923 924 } // namespace 925 926 /// Check whether the given argument is a block which captures a 927 /// variable. 928 static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { 929 assert(owner.Variable && owner.Loc.isValid()); 930 931 e = e->IgnoreParenCasts(); 932 933 // Look through [^{...} copy] and Block_copy(^{...}). 934 if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) { 935 Selector Cmd = ME->getSelector(); 936 if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { 937 e = ME->getInstanceReceiver(); 938 if (!e) 939 return nullptr; 940 e = e->IgnoreParenCasts(); 941 } 942 } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) { 943 if (CE->getNumArgs() == 1) { 944 FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl()); 945 if (Fn) { 946 const IdentifierInfo *FnI = Fn->getIdentifier(); 947 if (FnI && FnI->isStr("_Block_copy")) { 948 e = CE->getArg(0)->IgnoreParenCasts(); 949 } 950 } 951 } 952 } 953 954 BlockExpr *block = dyn_cast<BlockExpr>(e); 955 if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) 956 return nullptr; 957 958 FindCaptureVisitor visitor(S.Context, owner.Variable); 959 visitor.Visit(block->getBlockDecl()->getBody()); 960 return visitor.VarWillBeReased ? nullptr : visitor.Capturer; 961 } 962 963 static void diagnoseRetainCycle(Sema &S, Expr *capturer, 964 RetainCycleOwner &owner) { 965 assert(capturer); 966 assert(owner.Variable && owner.Loc.isValid()); 967 968 S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle) 969 << owner.Variable << capturer->getSourceRange(); 970 S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner) 971 << owner.Indirect << owner.Range; 972 } 973 974 /// Check for a keyword selector that starts with the word 'add' or 975 /// 'set'. 976 static bool isSetterLikeSelector(Selector sel) { 977 if (sel.isUnarySelector()) 978 return false; 979 980 StringRef str = sel.getNameForSlot(0); 981 str = str.ltrim('_'); 982 if (str.starts_with("set")) 983 str = str.substr(3); 984 else if (str.starts_with("add")) { 985 // Specially allow 'addOperationWithBlock:'. 986 if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock")) 987 return false; 988 str = str.substr(3); 989 } else 990 return false; 991 992 if (str.empty()) 993 return true; 994 return !isLowercase(str.front()); 995 } 996 997 static std::optional<int> 998 GetNSMutableArrayArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) { 999 bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass( 1000 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableArray); 1001 if (!IsMutableArray) { 1002 return std::nullopt; 1003 } 1004 1005 Selector Sel = Message->getSelector(); 1006 1007 std::optional<NSAPI::NSArrayMethodKind> MKOpt = 1008 S.NSAPIObj->getNSArrayMethodKind(Sel); 1009 if (!MKOpt) { 1010 return std::nullopt; 1011 } 1012 1013 NSAPI::NSArrayMethodKind MK = *MKOpt; 1014 1015 switch (MK) { 1016 case NSAPI::NSMutableArr_addObject: 1017 case NSAPI::NSMutableArr_insertObjectAtIndex: 1018 case NSAPI::NSMutableArr_setObjectAtIndexedSubscript: 1019 return 0; 1020 case NSAPI::NSMutableArr_replaceObjectAtIndex: 1021 return 1; 1022 1023 default: 1024 return std::nullopt; 1025 } 1026 1027 return std::nullopt; 1028 } 1029 1030 static std::optional<int> 1031 GetNSMutableDictionaryArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) { 1032 bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass( 1033 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary); 1034 if (!IsMutableDictionary) { 1035 return std::nullopt; 1036 } 1037 1038 Selector Sel = Message->getSelector(); 1039 1040 std::optional<NSAPI::NSDictionaryMethodKind> MKOpt = 1041 S.NSAPIObj->getNSDictionaryMethodKind(Sel); 1042 if (!MKOpt) { 1043 return std::nullopt; 1044 } 1045 1046 NSAPI::NSDictionaryMethodKind MK = *MKOpt; 1047 1048 switch (MK) { 1049 case NSAPI::NSMutableDict_setObjectForKey: 1050 case NSAPI::NSMutableDict_setValueForKey: 1051 case NSAPI::NSMutableDict_setObjectForKeyedSubscript: 1052 return 0; 1053 1054 default: 1055 return std::nullopt; 1056 } 1057 1058 return std::nullopt; 1059 } 1060 1061 static std::optional<int> GetNSSetArgumentIndex(SemaObjC &S, 1062 ObjCMessageExpr *Message) { 1063 bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass( 1064 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableSet); 1065 1066 bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass( 1067 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet); 1068 if (!IsMutableSet && !IsMutableOrderedSet) { 1069 return std::nullopt; 1070 } 1071 1072 Selector Sel = Message->getSelector(); 1073 1074 std::optional<NSAPI::NSSetMethodKind> MKOpt = 1075 S.NSAPIObj->getNSSetMethodKind(Sel); 1076 if (!MKOpt) { 1077 return std::nullopt; 1078 } 1079 1080 NSAPI::NSSetMethodKind MK = *MKOpt; 1081 1082 switch (MK) { 1083 case NSAPI::NSMutableSet_addObject: 1084 case NSAPI::NSOrderedSet_setObjectAtIndex: 1085 case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript: 1086 case NSAPI::NSOrderedSet_insertObjectAtIndex: 1087 return 0; 1088 case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject: 1089 return 1; 1090 } 1091 1092 return std::nullopt; 1093 } 1094 1095 void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr *Message) { 1096 if (!Message->isInstanceMessage()) { 1097 return; 1098 } 1099 1100 std::optional<int> ArgOpt; 1101 1102 if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) && 1103 !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) && 1104 !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) { 1105 return; 1106 } 1107 1108 int ArgIndex = *ArgOpt; 1109 1110 Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts(); 1111 if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) { 1112 Arg = OE->getSourceExpr()->IgnoreImpCasts(); 1113 } 1114 1115 if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) { 1116 if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) { 1117 if (ArgRE->isObjCSelfExpr()) { 1118 Diag(Message->getSourceRange().getBegin(), 1119 diag::warn_objc_circular_container) 1120 << ArgRE->getDecl() << StringRef("'super'"); 1121 } 1122 } 1123 } else { 1124 Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts(); 1125 1126 if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) { 1127 Receiver = OE->getSourceExpr()->IgnoreImpCasts(); 1128 } 1129 1130 if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) { 1131 if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) { 1132 if (ReceiverRE->getDecl() == ArgRE->getDecl()) { 1133 ValueDecl *Decl = ReceiverRE->getDecl(); 1134 Diag(Message->getSourceRange().getBegin(), 1135 diag::warn_objc_circular_container) 1136 << Decl << Decl; 1137 if (!ArgRE->isObjCSelfExpr()) { 1138 Diag(Decl->getLocation(), 1139 diag::note_objc_circular_container_declared_here) 1140 << Decl; 1141 } 1142 } 1143 } 1144 } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) { 1145 if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) { 1146 if (IvarRE->getDecl() == IvarArgRE->getDecl()) { 1147 ObjCIvarDecl *Decl = IvarRE->getDecl(); 1148 Diag(Message->getSourceRange().getBegin(), 1149 diag::warn_objc_circular_container) 1150 << Decl << Decl; 1151 Diag(Decl->getLocation(), 1152 diag::note_objc_circular_container_declared_here) 1153 << Decl; 1154 } 1155 } 1156 } 1157 } 1158 } 1159 1160 /// Check a message send to see if it's likely to cause a retain cycle. 1161 void SemaObjC::checkRetainCycles(ObjCMessageExpr *msg) { 1162 // Only check instance methods whose selector looks like a setter. 1163 if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) 1164 return; 1165 1166 // Try to find a variable that the receiver is strongly owned by. 1167 RetainCycleOwner owner; 1168 if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { 1169 if (!findRetainCycleOwner(SemaRef, msg->getInstanceReceiver(), owner)) 1170 return; 1171 } else { 1172 assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); 1173 owner.Variable = SemaRef.getCurMethodDecl()->getSelfDecl(); 1174 owner.Loc = msg->getSuperLoc(); 1175 owner.Range = msg->getSuperLoc(); 1176 } 1177 1178 // Check whether the receiver is captured by any of the arguments. 1179 const ObjCMethodDecl *MD = msg->getMethodDecl(); 1180 for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) { 1181 if (Expr *capturer = findCapturingExpr(SemaRef, msg->getArg(i), owner)) { 1182 // noescape blocks should not be retained by the method. 1183 if (MD && MD->parameters()[i]->hasAttr<NoEscapeAttr>()) 1184 continue; 1185 return diagnoseRetainCycle(SemaRef, capturer, owner); 1186 } 1187 } 1188 } 1189 1190 /// Check a property assign to see if it's likely to cause a retain cycle. 1191 void SemaObjC::checkRetainCycles(Expr *receiver, Expr *argument) { 1192 RetainCycleOwner owner; 1193 if (!findRetainCycleOwner(SemaRef, receiver, owner)) 1194 return; 1195 1196 if (Expr *capturer = findCapturingExpr(SemaRef, argument, owner)) 1197 diagnoseRetainCycle(SemaRef, capturer, owner); 1198 } 1199 1200 void SemaObjC::checkRetainCycles(VarDecl *Var, Expr *Init) { 1201 RetainCycleOwner Owner; 1202 if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner)) 1203 return; 1204 1205 // Because we don't have an expression for the variable, we have to set the 1206 // location explicitly here. 1207 Owner.Loc = Var->getLocation(); 1208 Owner.Range = Var->getSourceRange(); 1209 1210 if (Expr *Capturer = findCapturingExpr(SemaRef, Init, Owner)) 1211 diagnoseRetainCycle(SemaRef, Capturer, Owner); 1212 } 1213 1214 /// CheckObjCString - Checks that the argument to the builtin 1215 /// CFString constructor is correct 1216 /// Note: It might also make sense to do the UTF-16 conversion here (would 1217 /// simplify the backend). 1218 bool SemaObjC::CheckObjCString(Expr *Arg) { 1219 Arg = Arg->IgnoreParenCasts(); 1220 StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); 1221 1222 if (!Literal || !Literal->isOrdinary()) { 1223 Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant) 1224 << Arg->getSourceRange(); 1225 return true; 1226 } 1227 1228 if (Literal->containsNonAsciiOrNull()) { 1229 StringRef String = Literal->getString(); 1230 unsigned NumBytes = String.size(); 1231 SmallVector<llvm::UTF16, 128> ToBuf(NumBytes); 1232 const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); 1233 llvm::UTF16 *ToPtr = &ToBuf[0]; 1234 1235 llvm::ConversionResult Result = 1236 llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, 1237 ToPtr + NumBytes, llvm::strictConversion); 1238 // Check for conversion failure. 1239 if (Result != llvm::conversionOK) 1240 Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated) 1241 << Arg->getSourceRange(); 1242 } 1243 return false; 1244 } 1245 1246 bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, 1247 ArrayRef<const Expr *> Args) { 1248 Sema::VariadicCallType CallType = 1249 Method->isVariadic() ? Sema::VariadicMethod : Sema::VariadicDoesNotApply; 1250 1251 SemaRef.checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args, 1252 /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), 1253 CallType); 1254 1255 SemaRef.CheckTCBEnforcement(lbrac, Method); 1256 1257 return false; 1258 } 1259 1260 const DeclContext *SemaObjC::getCurObjCLexicalContext() const { 1261 const DeclContext *DC = SemaRef.getCurLexicalContext(); 1262 // A category implicitly has the attribute of the interface. 1263 if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC)) 1264 DC = CatD->getClassInterface(); 1265 return DC; 1266 } 1267 1268 /// Retrieve the identifier "NSError". 1269 IdentifierInfo *SemaObjC::getNSErrorIdent() { 1270 if (!Ident_NSError) 1271 Ident_NSError = SemaRef.PP.getIdentifierInfo("NSError"); 1272 1273 return Ident_NSError; 1274 } 1275 1276 void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) { 1277 assert( 1278 IDecl->getLexicalParent() == SemaRef.CurContext && 1279 "The next DeclContext should be lexically contained in the current one."); 1280 SemaRef.CurContext = IDecl; 1281 } 1282 1283 void SemaObjC::ActOnObjCContainerFinishDefinition() { 1284 // Exit this scope of this interface definition. 1285 SemaRef.PopDeclContext(); 1286 } 1287 1288 void SemaObjC::ActOnObjCTemporaryExitContainerContext( 1289 ObjCContainerDecl *ObjCCtx) { 1290 assert(ObjCCtx == SemaRef.CurContext && "Mismatch of container contexts"); 1291 SemaRef.OriginalLexicalContext = ObjCCtx; 1292 ActOnObjCContainerFinishDefinition(); 1293 } 1294 1295 void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) { 1296 ActOnObjCContainerStartDefinition(ObjCCtx); 1297 SemaRef.OriginalLexicalContext = nullptr; 1298 } 1299 1300 /// Find the protocol with the given name, if any. 1301 ObjCProtocolDecl *SemaObjC::LookupProtocol(IdentifierInfo *II, 1302 SourceLocation IdLoc, 1303 RedeclarationKind Redecl) { 1304 Decl *D = SemaRef.LookupSingleName(SemaRef.TUScope, II, IdLoc, 1305 Sema::LookupObjCProtocolName, Redecl); 1306 return cast_or_null<ObjCProtocolDecl>(D); 1307 } 1308 1309 /// Determine whether this is an Objective-C writeback conversion, 1310 /// used for parameter passing when performing automatic reference counting. 1311 /// 1312 /// \param FromType The type we're converting form. 1313 /// 1314 /// \param ToType The type we're converting to. 1315 /// 1316 /// \param ConvertedType The type that will be produced after applying 1317 /// this conversion. 1318 bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType, 1319 QualType &ConvertedType) { 1320 ASTContext &Context = getASTContext(); 1321 if (!getLangOpts().ObjCAutoRefCount || 1322 Context.hasSameUnqualifiedType(FromType, ToType)) 1323 return false; 1324 1325 // Parameter must be a pointer to __autoreleasing (with no other qualifiers). 1326 QualType ToPointee; 1327 if (const PointerType *ToPointer = ToType->getAs<PointerType>()) 1328 ToPointee = ToPointer->getPointeeType(); 1329 else 1330 return false; 1331 1332 Qualifiers ToQuals = ToPointee.getQualifiers(); 1333 if (!ToPointee->isObjCLifetimeType() || 1334 ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || 1335 !ToQuals.withoutObjCLifetime().empty()) 1336 return false; 1337 1338 // Argument must be a pointer to __strong to __weak. 1339 QualType FromPointee; 1340 if (const PointerType *FromPointer = FromType->getAs<PointerType>()) 1341 FromPointee = FromPointer->getPointeeType(); 1342 else 1343 return false; 1344 1345 Qualifiers FromQuals = FromPointee.getQualifiers(); 1346 if (!FromPointee->isObjCLifetimeType() || 1347 (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && 1348 FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) 1349 return false; 1350 1351 // Make sure that we have compatible qualifiers. 1352 FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); 1353 if (!ToQuals.compatiblyIncludes(FromQuals, getASTContext())) 1354 return false; 1355 1356 // Remove qualifiers from the pointee type we're converting from; they 1357 // aren't used in the compatibility check belong, and we'll be adding back 1358 // qualifiers (with __autoreleasing) if the compatibility check succeeds. 1359 FromPointee = FromPointee.getUnqualifiedType(); 1360 1361 // The unqualified form of the pointee types must be compatible. 1362 ToPointee = ToPointee.getUnqualifiedType(); 1363 bool IncompatibleObjC; 1364 if (Context.typesAreCompatible(FromPointee, ToPointee)) 1365 FromPointee = ToPointee; 1366 else if (!SemaRef.isObjCPointerConversion(FromPointee, ToPointee, FromPointee, 1367 IncompatibleObjC)) 1368 return false; 1369 1370 /// Construct the type we're converting to, which is a pointer to 1371 /// __autoreleasing pointee. 1372 FromPointee = Context.getQualifiedType(FromPointee, FromQuals); 1373 ConvertedType = Context.getPointerType(FromPointee); 1374 return true; 1375 } 1376 1377 /// CheckSubscriptingKind - This routine decide what type 1378 /// of indexing represented by "FromE" is being done. 1379 SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) { 1380 // If the expression already has integral or enumeration type, we're golden. 1381 QualType T = FromE->getType(); 1382 if (T->isIntegralOrEnumerationType()) 1383 return SemaObjC::OS_Array; 1384 1385 // If we don't have a class type in C++, there's no way we can get an 1386 // expression of integral or enumeration type. 1387 const RecordType *RecordTy = T->getAs<RecordType>(); 1388 if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType())) 1389 // All other scalar cases are assumed to be dictionary indexing which 1390 // caller handles, with diagnostics if needed. 1391 return SemaObjC::OS_Dictionary; 1392 if (!getLangOpts().CPlusPlus || !RecordTy || RecordTy->isIncompleteType()) { 1393 // No indexing can be done. Issue diagnostics and quit. 1394 const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); 1395 if (isa<StringLiteral>(IndexExpr)) 1396 Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) 1397 << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); 1398 else 1399 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) << T; 1400 return SemaObjC::OS_Error; 1401 } 1402 1403 // We must have a complete class type. 1404 if (SemaRef.RequireCompleteType(FromE->getExprLoc(), T, 1405 diag::err_objc_index_incomplete_class_type, 1406 FromE)) 1407 return SemaObjC::OS_Error; 1408 1409 // Look for a conversion to an integral, enumeration type, or 1410 // objective-C pointer type. 1411 int NoIntegrals = 0, NoObjCIdPointers = 0; 1412 SmallVector<CXXConversionDecl *, 4> ConversionDecls; 1413 1414 for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl()) 1415 ->getVisibleConversionFunctions()) { 1416 if (CXXConversionDecl *Conversion = 1417 dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) { 1418 QualType CT = Conversion->getConversionType().getNonReferenceType(); 1419 if (CT->isIntegralOrEnumerationType()) { 1420 ++NoIntegrals; 1421 ConversionDecls.push_back(Conversion); 1422 } else if (CT->isObjCIdType() || CT->isBlockPointerType()) { 1423 ++NoObjCIdPointers; 1424 ConversionDecls.push_back(Conversion); 1425 } 1426 } 1427 } 1428 if (NoIntegrals == 1 && NoObjCIdPointers == 0) 1429 return SemaObjC::OS_Array; 1430 if (NoIntegrals == 0 && NoObjCIdPointers == 1) 1431 return SemaObjC::OS_Dictionary; 1432 if (NoIntegrals == 0 && NoObjCIdPointers == 0) { 1433 // No conversion function was found. Issue diagnostic and return. 1434 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 1435 << FromE->getType(); 1436 return SemaObjC::OS_Error; 1437 } 1438 Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) 1439 << FromE->getType(); 1440 for (unsigned int i = 0; i < ConversionDecls.size(); i++) 1441 Diag(ConversionDecls[i]->getLocation(), 1442 diag::note_conv_function_declared_at); 1443 1444 return SemaObjC::OS_Error; 1445 } 1446 1447 void SemaObjC::AddCFAuditedAttribute(Decl *D) { 1448 ASTContext &Context = getASTContext(); 1449 IdentifierInfo *Ident; 1450 SourceLocation Loc; 1451 std::tie(Ident, Loc) = SemaRef.PP.getPragmaARCCFCodeAuditedInfo(); 1452 if (!Loc.isValid()) 1453 return; 1454 1455 // Don't add a redundant or conflicting attribute. 1456 if (D->hasAttr<CFAuditedTransferAttr>() || 1457 D->hasAttr<CFUnknownTransferAttr>()) 1458 return; 1459 1460 AttributeCommonInfo Info(Ident, SourceRange(Loc), 1461 AttributeCommonInfo::Form::Pragma()); 1462 D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info)); 1463 } 1464 1465 bool SemaObjC::isCFError(RecordDecl *RD) { 1466 // If we already know about CFError, test it directly. 1467 if (CFError) 1468 return CFError == RD; 1469 1470 // Check whether this is CFError, which we identify based on its bridge to 1471 // NSError. CFErrorRef used to be declared with "objc_bridge" but is now 1472 // declared with "objc_bridge_mutable", so look for either one of the two 1473 // attributes. 1474 if (RD->getTagKind() == TagTypeKind::Struct) { 1475 IdentifierInfo *bridgedType = nullptr; 1476 if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>()) 1477 bridgedType = bridgeAttr->getBridgedType(); 1478 else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>()) 1479 bridgedType = bridgeAttr->getBridgedType(); 1480 1481 if (bridgedType == getNSErrorIdent()) { 1482 CFError = RD; 1483 return true; 1484 } 1485 } 1486 1487 return false; 1488 } 1489 1490 bool SemaObjC::isNSStringType(QualType T, bool AllowNSAttributedString) { 1491 const auto *PT = T->getAs<ObjCObjectPointerType>(); 1492 if (!PT) 1493 return false; 1494 1495 ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); 1496 if (!Cls) 1497 return false; 1498 1499 IdentifierInfo *ClsName = Cls->getIdentifier(); 1500 1501 if (AllowNSAttributedString && 1502 ClsName == &getASTContext().Idents.get("NSAttributedString")) 1503 return true; 1504 // FIXME: Should we walk the chain of classes? 1505 return ClsName == &getASTContext().Idents.get("NSString") || 1506 ClsName == &getASTContext().Idents.get("NSMutableString"); 1507 } 1508 1509 bool SemaObjC::isCFStringType(QualType T) { 1510 const auto *PT = T->getAs<PointerType>(); 1511 if (!PT) 1512 return false; 1513 1514 const auto *RT = PT->getPointeeType()->getAs<RecordType>(); 1515 if (!RT) 1516 return false; 1517 1518 const RecordDecl *RD = RT->getDecl(); 1519 if (RD->getTagKind() != TagTypeKind::Struct) 1520 return false; 1521 1522 return RD->getIdentifier() == &getASTContext().Idents.get("__CFString"); 1523 } 1524 1525 static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { 1526 // The IBOutlet/IBOutletCollection attributes only apply to instance 1527 // variables or properties of Objective-C classes. The outlet must also 1528 // have an object reference type. 1529 if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) { 1530 if (!VD->getType()->getAs<ObjCObjectPointerType>()) { 1531 S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) 1532 << AL << VD->getType() << 0; 1533 return false; 1534 } 1535 } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { 1536 if (!PD->getType()->getAs<ObjCObjectPointerType>()) { 1537 S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) 1538 << AL << PD->getType() << 1; 1539 return false; 1540 } 1541 } else { 1542 S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL; 1543 return false; 1544 } 1545 1546 return true; 1547 } 1548 1549 void SemaObjC::handleIBOutlet(Decl *D, const ParsedAttr &AL) { 1550 if (!checkIBOutletCommon(SemaRef, D, AL)) 1551 return; 1552 1553 D->addAttr(::new (getASTContext()) IBOutletAttr(getASTContext(), AL)); 1554 } 1555 1556 void SemaObjC::handleIBOutletCollection(Decl *D, const ParsedAttr &AL) { 1557 1558 ASTContext &Context = getASTContext(); 1559 // The iboutletcollection attribute can have zero or one arguments. 1560 if (AL.getNumArgs() > 1) { 1561 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; 1562 return; 1563 } 1564 1565 if (!checkIBOutletCommon(SemaRef, D, AL)) 1566 return; 1567 1568 ParsedType PT; 1569 1570 if (AL.hasParsedType()) 1571 PT = AL.getTypeArg(); 1572 else { 1573 PT = SemaRef.getTypeName( 1574 Context.Idents.get("NSObject"), AL.getLoc(), 1575 SemaRef.getScopeForContext(D->getDeclContext()->getParent())); 1576 if (!PT) { 1577 Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; 1578 return; 1579 } 1580 } 1581 1582 TypeSourceInfo *QTLoc = nullptr; 1583 QualType QT = SemaRef.GetTypeFromParser(PT, &QTLoc); 1584 if (!QTLoc) 1585 QTLoc = Context.getTrivialTypeSourceInfo(QT, AL.getLoc()); 1586 1587 // Diagnose use of non-object type in iboutletcollection attribute. 1588 // FIXME. Gnu attribute extension ignores use of builtin types in 1589 // attributes. So, __attribute__((iboutletcollection(char))) will be 1590 // treated as __attribute__((iboutletcollection())). 1591 if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { 1592 Diag(AL.getLoc(), QT->isBuiltinType() 1593 ? diag::err_iboutletcollection_builtintype 1594 : diag::err_iboutletcollection_type) 1595 << QT; 1596 return; 1597 } 1598 1599 D->addAttr(::new (Context) IBOutletCollectionAttr(Context, AL, QTLoc)); 1600 } 1601 1602 void SemaObjC::handleSuppresProtocolAttr(Decl *D, const ParsedAttr &AL) { 1603 if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) { 1604 Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition) 1605 << AL << AL.getRange(); 1606 return; 1607 } 1608 1609 D->addAttr(::new (getASTContext()) 1610 ObjCExplicitProtocolImplAttr(getASTContext(), AL)); 1611 } 1612 1613 void SemaObjC::handleDirectAttr(Decl *D, const ParsedAttr &AL) { 1614 // objc_direct cannot be set on methods declared in the context of a protocol 1615 if (isa<ObjCProtocolDecl>(D->getDeclContext())) { 1616 Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false; 1617 return; 1618 } 1619 1620 if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) { 1621 handleSimpleAttribute<ObjCDirectAttr>(*this, D, AL); 1622 } else { 1623 Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; 1624 } 1625 } 1626 1627 void SemaObjC::handleDirectMembersAttr(Decl *D, const ParsedAttr &AL) { 1628 if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) { 1629 handleSimpleAttribute<ObjCDirectMembersAttr>(*this, D, AL); 1630 } else { 1631 Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; 1632 } 1633 } 1634 1635 void SemaObjC::handleMethodFamilyAttr(Decl *D, const ParsedAttr &AL) { 1636 const auto *M = cast<ObjCMethodDecl>(D); 1637 if (!AL.isArgIdent(0)) { 1638 Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 1639 << AL << 1 << AANT_ArgumentIdentifier; 1640 return; 1641 } 1642 1643 IdentifierLoc *IL = AL.getArgAsIdent(0); 1644 ObjCMethodFamilyAttr::FamilyKind F; 1645 if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { 1646 Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident; 1647 return; 1648 } 1649 1650 if (F == ObjCMethodFamilyAttr::OMF_init && 1651 !M->getReturnType()->isObjCObjectPointerType()) { 1652 Diag(M->getLocation(), diag::err_init_method_bad_return_type) 1653 << M->getReturnType(); 1654 // Ignore the attribute. 1655 return; 1656 } 1657 1658 D->addAttr(new (getASTContext()) 1659 ObjCMethodFamilyAttr(getASTContext(), AL, F)); 1660 } 1661 1662 void SemaObjC::handleNSObject(Decl *D, const ParsedAttr &AL) { 1663 if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { 1664 QualType T = TD->getUnderlyingType(); 1665 if (!T->isCARCBridgableType()) { 1666 Diag(TD->getLocation(), diag::err_nsobject_attribute); 1667 return; 1668 } 1669 } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { 1670 QualType T = PD->getType(); 1671 if (!T->isCARCBridgableType()) { 1672 Diag(PD->getLocation(), diag::err_nsobject_attribute); 1673 return; 1674 } 1675 } else { 1676 // It is okay to include this attribute on properties, e.g.: 1677 // 1678 // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); 1679 // 1680 // In this case it follows tradition and suppresses an error in the above 1681 // case. 1682 Diag(D->getLocation(), diag::warn_nsobject_attribute); 1683 } 1684 D->addAttr(::new (getASTContext()) ObjCNSObjectAttr(getASTContext(), AL)); 1685 } 1686 1687 void SemaObjC::handleIndependentClass(Decl *D, const ParsedAttr &AL) { 1688 if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { 1689 QualType T = TD->getUnderlyingType(); 1690 if (!T->isObjCObjectPointerType()) { 1691 Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute); 1692 return; 1693 } 1694 } else { 1695 Diag(D->getLocation(), diag::warn_independentclass_attribute); 1696 return; 1697 } 1698 D->addAttr(::new (getASTContext()) 1699 ObjCIndependentClassAttr(getASTContext(), AL)); 1700 } 1701 1702 void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) { 1703 if (!AL.isArgIdent(0)) { 1704 Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 1705 << AL << 1 << AANT_ArgumentIdentifier; 1706 return; 1707 } 1708 1709 IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 1710 BlocksAttr::BlockType type; 1711 if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { 1712 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; 1713 return; 1714 } 1715 1716 D->addAttr(::new (getASTContext()) BlocksAttr(getASTContext(), AL, type)); 1717 } 1718 1719 static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) { 1720 return QT->isDependentType() || QT->isObjCRetainableType(); 1721 } 1722 1723 static bool isValidSubjectOfNSAttribute(QualType QT) { 1724 return QT->isDependentType() || QT->isObjCObjectPointerType() || 1725 QT->isObjCNSObjectType(); 1726 } 1727 1728 static bool isValidSubjectOfCFAttribute(QualType QT) { 1729 return QT->isDependentType() || QT->isPointerType() || 1730 isValidSubjectOfNSAttribute(QT); 1731 } 1732 1733 static bool isValidSubjectOfOSAttribute(QualType QT) { 1734 if (QT->isDependentType()) 1735 return true; 1736 QualType PT = QT->getPointeeType(); 1737 return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr; 1738 } 1739 1740 void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI, 1741 Sema::RetainOwnershipKind K, 1742 bool IsTemplateInstantiation) { 1743 ValueDecl *VD = cast<ValueDecl>(D); 1744 switch (K) { 1745 case Sema::RetainOwnershipKind::OS: 1746 handleSimpleAttributeOrDiagnose<OSConsumedAttr>( 1747 *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()), 1748 diag::warn_ns_attribute_wrong_parameter_type, 1749 /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1); 1750 return; 1751 case Sema::RetainOwnershipKind::NS: 1752 handleSimpleAttributeOrDiagnose<NSConsumedAttr>( 1753 *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()), 1754 1755 // These attributes are normally just advisory, but in ARC, ns_consumed 1756 // is significant. Allow non-dependent code to contain inappropriate 1757 // attributes even in ARC, but require template instantiations to be 1758 // set up correctly. 1759 ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount) 1760 ? diag::err_ns_attribute_wrong_parameter_type 1761 : diag::warn_ns_attribute_wrong_parameter_type), 1762 /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0); 1763 return; 1764 case Sema::RetainOwnershipKind::CF: 1765 handleSimpleAttributeOrDiagnose<CFConsumedAttr>( 1766 *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()), 1767 diag::warn_ns_attribute_wrong_parameter_type, 1768 /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1); 1769 return; 1770 } 1771 } 1772 1773 Sema::RetainOwnershipKind 1774 SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) { 1775 switch (AL.getKind()) { 1776 case ParsedAttr::AT_CFConsumed: 1777 case ParsedAttr::AT_CFReturnsRetained: 1778 case ParsedAttr::AT_CFReturnsNotRetained: 1779 return Sema::RetainOwnershipKind::CF; 1780 case ParsedAttr::AT_OSConsumesThis: 1781 case ParsedAttr::AT_OSConsumed: 1782 case ParsedAttr::AT_OSReturnsRetained: 1783 case ParsedAttr::AT_OSReturnsNotRetained: 1784 case ParsedAttr::AT_OSReturnsRetainedOnZero: 1785 case ParsedAttr::AT_OSReturnsRetainedOnNonZero: 1786 return Sema::RetainOwnershipKind::OS; 1787 case ParsedAttr::AT_NSConsumesSelf: 1788 case ParsedAttr::AT_NSConsumed: 1789 case ParsedAttr::AT_NSReturnsRetained: 1790 case ParsedAttr::AT_NSReturnsNotRetained: 1791 case ParsedAttr::AT_NSReturnsAutoreleased: 1792 return Sema::RetainOwnershipKind::NS; 1793 default: 1794 llvm_unreachable("Wrong argument supplied"); 1795 } 1796 } 1797 1798 bool SemaObjC::checkNSReturnsRetainedReturnType(SourceLocation Loc, 1799 QualType QT) { 1800 if (isValidSubjectOfNSReturnsRetainedAttribute(QT)) 1801 return false; 1802 1803 Diag(Loc, diag::warn_ns_attribute_wrong_return_type) 1804 << "'ns_returns_retained'" << 0 << 0; 1805 return true; 1806 } 1807 1808 /// \return whether the parameter is a pointer to OSObject pointer. 1809 bool SemaObjC::isValidOSObjectOutParameter(const Decl *D) { 1810 const auto *PVD = dyn_cast<ParmVarDecl>(D); 1811 if (!PVD) 1812 return false; 1813 QualType QT = PVD->getType(); 1814 QualType PT = QT->getPointeeType(); 1815 return !PT.isNull() && isValidSubjectOfOSAttribute(PT); 1816 } 1817 1818 void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) { 1819 QualType ReturnType; 1820 Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL); 1821 1822 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 1823 ReturnType = MD->getReturnType(); 1824 } else if (getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && 1825 (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) { 1826 return; // ignore: was handled as a type attribute 1827 } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { 1828 ReturnType = PD->getType(); 1829 } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 1830 ReturnType = FD->getReturnType(); 1831 } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) { 1832 // Attributes on parameters are used for out-parameters, 1833 // passed as pointers-to-pointers. 1834 unsigned DiagID = K == Sema::RetainOwnershipKind::CF 1835 ? /*pointer-to-CF-pointer*/ 2 1836 : /*pointer-to-OSObject-pointer*/ 3; 1837 ReturnType = Param->getType()->getPointeeType(); 1838 if (ReturnType.isNull()) { 1839 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) 1840 << AL << DiagID << AL.getRange(); 1841 return; 1842 } 1843 } else if (AL.isUsedAsTypeAttr()) { 1844 return; 1845 } else { 1846 AttributeDeclKind ExpectedDeclKind; 1847 switch (AL.getKind()) { 1848 default: 1849 llvm_unreachable("invalid ownership attribute"); 1850 case ParsedAttr::AT_NSReturnsRetained: 1851 case ParsedAttr::AT_NSReturnsAutoreleased: 1852 case ParsedAttr::AT_NSReturnsNotRetained: 1853 ExpectedDeclKind = ExpectedFunctionOrMethod; 1854 break; 1855 1856 case ParsedAttr::AT_OSReturnsRetained: 1857 case ParsedAttr::AT_OSReturnsNotRetained: 1858 case ParsedAttr::AT_CFReturnsRetained: 1859 case ParsedAttr::AT_CFReturnsNotRetained: 1860 ExpectedDeclKind = ExpectedFunctionMethodOrParameter; 1861 break; 1862 } 1863 Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type) 1864 << AL.getRange() << AL << AL.isRegularKeywordAttribute() 1865 << ExpectedDeclKind; 1866 return; 1867 } 1868 1869 bool TypeOK; 1870 bool Cf; 1871 unsigned ParmDiagID = 2; // Pointer-to-CF-pointer 1872 switch (AL.getKind()) { 1873 default: 1874 llvm_unreachable("invalid ownership attribute"); 1875 case ParsedAttr::AT_NSReturnsRetained: 1876 TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType); 1877 Cf = false; 1878 break; 1879 1880 case ParsedAttr::AT_NSReturnsAutoreleased: 1881 case ParsedAttr::AT_NSReturnsNotRetained: 1882 TypeOK = isValidSubjectOfNSAttribute(ReturnType); 1883 Cf = false; 1884 break; 1885 1886 case ParsedAttr::AT_CFReturnsRetained: 1887 case ParsedAttr::AT_CFReturnsNotRetained: 1888 TypeOK = isValidSubjectOfCFAttribute(ReturnType); 1889 Cf = true; 1890 break; 1891 1892 case ParsedAttr::AT_OSReturnsRetained: 1893 case ParsedAttr::AT_OSReturnsNotRetained: 1894 TypeOK = isValidSubjectOfOSAttribute(ReturnType); 1895 Cf = true; 1896 ParmDiagID = 3; // Pointer-to-OSObject-pointer 1897 break; 1898 } 1899 1900 if (!TypeOK) { 1901 if (AL.isUsedAsTypeAttr()) 1902 return; 1903 1904 if (isa<ParmVarDecl>(D)) { 1905 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) 1906 << AL << ParmDiagID << AL.getRange(); 1907 } else { 1908 // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. 1909 enum : unsigned { Function, Method, Property } SubjectKind = Function; 1910 if (isa<ObjCMethodDecl>(D)) 1911 SubjectKind = Method; 1912 else if (isa<ObjCPropertyDecl>(D)) 1913 SubjectKind = Property; 1914 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) 1915 << AL << SubjectKind << Cf << AL.getRange(); 1916 } 1917 return; 1918 } 1919 1920 switch (AL.getKind()) { 1921 default: 1922 llvm_unreachable("invalid ownership attribute"); 1923 case ParsedAttr::AT_NSReturnsAutoreleased: 1924 handleSimpleAttribute<NSReturnsAutoreleasedAttr>(*this, D, AL); 1925 return; 1926 case ParsedAttr::AT_CFReturnsNotRetained: 1927 handleSimpleAttribute<CFReturnsNotRetainedAttr>(*this, D, AL); 1928 return; 1929 case ParsedAttr::AT_NSReturnsNotRetained: 1930 handleSimpleAttribute<NSReturnsNotRetainedAttr>(*this, D, AL); 1931 return; 1932 case ParsedAttr::AT_CFReturnsRetained: 1933 handleSimpleAttribute<CFReturnsRetainedAttr>(*this, D, AL); 1934 return; 1935 case ParsedAttr::AT_NSReturnsRetained: 1936 handleSimpleAttribute<NSReturnsRetainedAttr>(*this, D, AL); 1937 return; 1938 case ParsedAttr::AT_OSReturnsRetained: 1939 handleSimpleAttribute<OSReturnsRetainedAttr>(*this, D, AL); 1940 return; 1941 case ParsedAttr::AT_OSReturnsNotRetained: 1942 handleSimpleAttribute<OSReturnsNotRetainedAttr>(*this, D, AL); 1943 return; 1944 }; 1945 } 1946 1947 void SemaObjC::handleReturnsInnerPointerAttr(Decl *D, const ParsedAttr &Attrs) { 1948 const int EP_ObjCMethod = 1; 1949 const int EP_ObjCProperty = 2; 1950 1951 SourceLocation loc = Attrs.getLoc(); 1952 QualType resultType; 1953 if (isa<ObjCMethodDecl>(D)) 1954 resultType = cast<ObjCMethodDecl>(D)->getReturnType(); 1955 else 1956 resultType = cast<ObjCPropertyDecl>(D)->getType(); 1957 1958 if (!resultType->isReferenceType() && 1959 (!resultType->isPointerType() || resultType->isObjCRetainableType())) { 1960 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) 1961 << SourceRange(loc) << Attrs 1962 << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty) 1963 << /*non-retainable pointer*/ 2; 1964 1965 // Drop the attribute. 1966 return; 1967 } 1968 1969 D->addAttr(::new (getASTContext()) 1970 ObjCReturnsInnerPointerAttr(getASTContext(), Attrs)); 1971 } 1972 1973 void SemaObjC::handleRequiresSuperAttr(Decl *D, const ParsedAttr &Attrs) { 1974 const auto *Method = cast<ObjCMethodDecl>(D); 1975 1976 const DeclContext *DC = Method->getDeclContext(); 1977 if (const auto *PDecl = dyn_cast_if_present<ObjCProtocolDecl>(DC)) { 1978 Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) 1979 << Attrs << 0; 1980 Diag(PDecl->getLocation(), diag::note_protocol_decl); 1981 return; 1982 } 1983 if (Method->getMethodFamily() == OMF_dealloc) { 1984 Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) 1985 << Attrs << 1; 1986 return; 1987 } 1988 1989 D->addAttr(::new (getASTContext()) 1990 ObjCRequiresSuperAttr(getASTContext(), Attrs)); 1991 } 1992 1993 void SemaObjC::handleNSErrorDomain(Decl *D, const ParsedAttr &Attr) { 1994 if (!isa<TagDecl>(D)) { 1995 Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0; 1996 return; 1997 } 1998 1999 IdentifierLoc *IdentLoc = 2000 Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr; 2001 if (!IdentLoc || !IdentLoc->Ident) { 2002 // Try to locate the argument directly. 2003 SourceLocation Loc = Attr.getLoc(); 2004 if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0)) 2005 Loc = Attr.getArgAsExpr(0)->getBeginLoc(); 2006 2007 Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0; 2008 return; 2009 } 2010 2011 // Verify that the identifier is a valid decl in the C decl namespace. 2012 LookupResult Result(SemaRef, DeclarationName(IdentLoc->Ident), 2013 SourceLocation(), 2014 Sema::LookupNameKind::LookupOrdinaryName); 2015 if (!SemaRef.LookupName(Result, SemaRef.TUScope) || 2016 !Result.getAsSingle<VarDecl>()) { 2017 Diag(IdentLoc->Loc, diag::err_nserrordomain_invalid_decl) 2018 << 1 << IdentLoc->Ident; 2019 return; 2020 } 2021 2022 D->addAttr(::new (getASTContext()) 2023 NSErrorDomainAttr(getASTContext(), Attr, IdentLoc->Ident)); 2024 } 2025 2026 void SemaObjC::handleBridgeAttr(Decl *D, const ParsedAttr &AL) { 2027 IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; 2028 2029 if (!Parm) { 2030 Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; 2031 return; 2032 } 2033 2034 // Typedefs only allow objc_bridge(id) and have some additional checking. 2035 if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { 2036 if (!Parm->Ident->isStr("id")) { 2037 Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL; 2038 return; 2039 } 2040 2041 // Only allow 'cv void *'. 2042 QualType T = TD->getUnderlyingType(); 2043 if (!T->isVoidPointerType()) { 2044 Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer); 2045 return; 2046 } 2047 } 2048 2049 D->addAttr(::new (getASTContext()) 2050 ObjCBridgeAttr(getASTContext(), AL, Parm->Ident)); 2051 } 2052 2053 void SemaObjC::handleBridgeMutableAttr(Decl *D, const ParsedAttr &AL) { 2054 IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; 2055 2056 if (!Parm) { 2057 Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; 2058 return; 2059 } 2060 2061 D->addAttr(::new (getASTContext()) 2062 ObjCBridgeMutableAttr(getASTContext(), AL, Parm->Ident)); 2063 } 2064 2065 void SemaObjC::handleBridgeRelatedAttr(Decl *D, const ParsedAttr &AL) { 2066 IdentifierInfo *RelatedClass = 2067 AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr; 2068 if (!RelatedClass) { 2069 Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; 2070 return; 2071 } 2072 IdentifierInfo *ClassMethod = 2073 AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr; 2074 IdentifierInfo *InstanceMethod = 2075 AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr; 2076 D->addAttr(::new (getASTContext()) ObjCBridgeRelatedAttr( 2077 getASTContext(), AL, RelatedClass, ClassMethod, InstanceMethod)); 2078 } 2079 2080 void SemaObjC::handleDesignatedInitializer(Decl *D, const ParsedAttr &AL) { 2081 DeclContext *Ctx = D->getDeclContext(); 2082 2083 // This attribute can only be applied to methods in interfaces or class 2084 // extensions. 2085 if (!isa<ObjCInterfaceDecl>(Ctx) && 2086 !(isa<ObjCCategoryDecl>(Ctx) && 2087 cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) { 2088 Diag(D->getLocation(), diag::err_designated_init_attr_non_init); 2089 return; 2090 } 2091 2092 ObjCInterfaceDecl *IFace; 2093 if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx)) 2094 IFace = CatDecl->getClassInterface(); 2095 else 2096 IFace = cast<ObjCInterfaceDecl>(Ctx); 2097 2098 if (!IFace) 2099 return; 2100 2101 IFace->setHasDesignatedInitializers(); 2102 D->addAttr(::new (getASTContext()) 2103 ObjCDesignatedInitializerAttr(getASTContext(), AL)); 2104 } 2105 2106 void SemaObjC::handleRuntimeName(Decl *D, const ParsedAttr &AL) { 2107 StringRef MetaDataName; 2108 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, MetaDataName)) 2109 return; 2110 D->addAttr(::new (getASTContext()) 2111 ObjCRuntimeNameAttr(getASTContext(), AL, MetaDataName)); 2112 } 2113 2114 // When a user wants to use objc_boxable with a union or struct 2115 // but they don't have access to the declaration (legacy/third-party code) 2116 // then they can 'enable' this feature with a typedef: 2117 // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct; 2118 void SemaObjC::handleBoxable(Decl *D, const ParsedAttr &AL) { 2119 bool notify = false; 2120 2121 auto *RD = dyn_cast<RecordDecl>(D); 2122 if (RD && RD->getDefinition()) { 2123 RD = RD->getDefinition(); 2124 notify = true; 2125 } 2126 2127 if (RD) { 2128 ObjCBoxableAttr *BoxableAttr = 2129 ::new (getASTContext()) ObjCBoxableAttr(getASTContext(), AL); 2130 RD->addAttr(BoxableAttr); 2131 if (notify) { 2132 // we need to notify ASTReader/ASTWriter about 2133 // modification of existing declaration 2134 if (ASTMutationListener *L = SemaRef.getASTMutationListener()) 2135 L->AddedAttributeToRecord(BoxableAttr, RD); 2136 } 2137 } 2138 } 2139 2140 void SemaObjC::handleOwnershipAttr(Decl *D, const ParsedAttr &AL) { 2141 if (hasDeclarator(D)) 2142 return; 2143 2144 Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type) 2145 << AL.getRange() << AL << AL.isRegularKeywordAttribute() 2146 << ExpectedVariable; 2147 } 2148 2149 void SemaObjC::handlePreciseLifetimeAttr(Decl *D, const ParsedAttr &AL) { 2150 const auto *VD = cast<ValueDecl>(D); 2151 QualType QT = VD->getType(); 2152 2153 if (!QT->isDependentType() && !QT->isObjCLifetimeType()) { 2154 Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) << QT; 2155 return; 2156 } 2157 2158 Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime(); 2159 2160 // If we have no lifetime yet, check the lifetime we're presumably 2161 // going to infer. 2162 if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType()) 2163 Lifetime = QT->getObjCARCImplicitLifetime(); 2164 2165 switch (Lifetime) { 2166 case Qualifiers::OCL_None: 2167 assert(QT->isDependentType() && 2168 "didn't infer lifetime for non-dependent type?"); 2169 break; 2170 2171 case Qualifiers::OCL_Weak: // meaningful 2172 case Qualifiers::OCL_Strong: // meaningful 2173 break; 2174 2175 case Qualifiers::OCL_ExplicitNone: 2176 case Qualifiers::OCL_Autoreleasing: 2177 Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless) 2178 << (Lifetime == Qualifiers::OCL_Autoreleasing); 2179 break; 2180 } 2181 2182 D->addAttr(::new (getASTContext()) 2183 ObjCPreciseLifetimeAttr(getASTContext(), AL)); 2184 } 2185 2186 static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD, 2187 bool DiagnoseFailure) { 2188 QualType Ty = VD->getType(); 2189 if (!Ty->isObjCRetainableType()) { 2190 if (DiagnoseFailure) { 2191 S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) 2192 << 0; 2193 } 2194 return false; 2195 } 2196 2197 Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime(); 2198 2199 // SemaObjC::inferObjCARCLifetime must run after processing decl attributes 2200 // (because __block lowers to an attribute), so if the lifetime hasn't been 2201 // explicitly specified, infer it locally now. 2202 if (LifetimeQual == Qualifiers::OCL_None) 2203 LifetimeQual = Ty->getObjCARCImplicitLifetime(); 2204 2205 // The attributes only really makes sense for __strong variables; ignore any 2206 // attempts to annotate a parameter with any other lifetime qualifier. 2207 if (LifetimeQual != Qualifiers::OCL_Strong) { 2208 if (DiagnoseFailure) { 2209 S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) 2210 << 1; 2211 } 2212 return false; 2213 } 2214 2215 // Tampering with the type of a VarDecl here is a bit of a hack, but we need 2216 // to ensure that the variable is 'const' so that we can error on 2217 // modification, which can otherwise over-release. 2218 VD->setType(Ty.withConst()); 2219 VD->setARCPseudoStrong(true); 2220 return true; 2221 } 2222 2223 void SemaObjC::handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL) { 2224 if (auto *VD = dyn_cast<VarDecl>(D)) { 2225 assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically"); 2226 if (!VD->hasLocalStorage()) { 2227 Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) << 0; 2228 return; 2229 } 2230 2231 if (!tryMakeVariablePseudoStrong(SemaRef, VD, /*DiagnoseFailure=*/true)) 2232 return; 2233 2234 handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL); 2235 return; 2236 } 2237 2238 // If D is a function-like declaration (method, block, or function), then we 2239 // make every parameter psuedo-strong. 2240 unsigned NumParams = 2241 hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0; 2242 for (unsigned I = 0; I != NumParams; ++I) { 2243 auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I)); 2244 QualType Ty = PVD->getType(); 2245 2246 // If a user wrote a parameter with __strong explicitly, then assume they 2247 // want "real" strong semantics for that parameter. This works because if 2248 // the parameter was written with __strong, then the strong qualifier will 2249 // be non-local. 2250 if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() == 2251 Qualifiers::OCL_Strong) 2252 continue; 2253 2254 tryMakeVariablePseudoStrong(SemaRef, PVD, /*DiagnoseFailure=*/false); 2255 } 2256 handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL); 2257 } 2258 2259 bool SemaObjC::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { 2260 Sema::FormatStringInfo FSI; 2261 if ((SemaRef.GetFormatStringType(Format) == Sema::FST_NSString) && 2262 SemaRef.getFormatStringInfo(Format, false, true, &FSI)) { 2263 Idx = FSI.FormatIdx; 2264 return true; 2265 } 2266 return false; 2267 } 2268 2269 /// Diagnose use of %s directive in an NSString which is being passed 2270 /// as formatting string to formatting method. 2271 void SemaObjC::DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl, 2272 Expr **Args, 2273 unsigned NumArgs) { 2274 unsigned Idx = 0; 2275 bool Format = false; 2276 ObjCStringFormatFamily SFFamily = FDecl->getObjCFStringFormattingFamily(); 2277 if (SFFamily == ObjCStringFormatFamily::SFF_CFString) { 2278 Idx = 2; 2279 Format = true; 2280 } else 2281 for (const auto *I : FDecl->specific_attrs<FormatAttr>()) { 2282 if (GetFormatNSStringIdx(I, Idx)) { 2283 Format = true; 2284 break; 2285 } 2286 } 2287 if (!Format || NumArgs <= Idx) 2288 return; 2289 const Expr *FormatExpr = Args[Idx]; 2290 if (const CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(FormatExpr)) 2291 FormatExpr = CSCE->getSubExpr(); 2292 const StringLiteral *FormatString; 2293 if (const ObjCStringLiteral *OSL = 2294 dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) 2295 FormatString = OSL->getString(); 2296 else 2297 FormatString = dyn_cast<StringLiteral>(FormatExpr->IgnoreParenImpCasts()); 2298 if (!FormatString) 2299 return; 2300 if (SemaRef.FormatStringHasSArg(FormatString)) { 2301 Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string) 2302 << "%s" << 1 << 1; 2303 Diag(FDecl->getLocation(), diag::note_entity_declared_at) 2304 << FDecl->getDeclName(); 2305 } 2306 } 2307 2308 bool SemaObjC::isSignedCharBool(QualType Ty) { 2309 return Ty->isSpecificBuiltinType(BuiltinType::SChar) && getLangOpts().ObjC && 2310 NSAPIObj->isObjCBOOLType(Ty); 2311 } 2312 2313 void SemaObjC::adornBoolConversionDiagWithTernaryFixit( 2314 Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder) { 2315 Expr *Ignored = SourceExpr->IgnoreImplicit(); 2316 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ignored)) 2317 Ignored = OVE->getSourceExpr(); 2318 bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) || 2319 isa<BinaryOperator>(Ignored) || 2320 isa<CXXOperatorCallExpr>(Ignored); 2321 SourceLocation EndLoc = SemaRef.getLocForEndOfToken(SourceExpr->getEndLoc()); 2322 if (NeedsParens) 2323 Builder << FixItHint::CreateInsertion(SourceExpr->getBeginLoc(), "(") 2324 << FixItHint::CreateInsertion(EndLoc, ")"); 2325 Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO"); 2326 } 2327 2328 /// Check a single element within a collection literal against the 2329 /// target element type. 2330 static void checkCollectionLiteralElement(Sema &S, QualType TargetElementType, 2331 Expr *Element, unsigned ElementKind) { 2332 // Skip a bitcast to 'id' or qualified 'id'. 2333 if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) { 2334 if (ICE->getCastKind() == CK_BitCast && 2335 ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>()) 2336 Element = ICE->getSubExpr(); 2337 } 2338 2339 QualType ElementType = Element->getType(); 2340 ExprResult ElementResult(Element); 2341 if (ElementType->getAs<ObjCObjectPointerType>() && 2342 S.CheckSingleAssignmentConstraints(TargetElementType, ElementResult, 2343 false, false) != Sema::Compatible) { 2344 S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element) 2345 << ElementType << ElementKind << TargetElementType 2346 << Element->getSourceRange(); 2347 } 2348 2349 if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element)) 2350 S.ObjC().checkArrayLiteral(TargetElementType, ArrayLiteral); 2351 else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element)) 2352 S.ObjC().checkDictionaryLiteral(TargetElementType, DictionaryLiteral); 2353 } 2354 2355 /// Check an Objective-C array literal being converted to the given 2356 /// target type. 2357 void SemaObjC::checkArrayLiteral(QualType TargetType, 2358 ObjCArrayLiteral *ArrayLiteral) { 2359 if (!NSArrayDecl) 2360 return; 2361 2362 const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>(); 2363 if (!TargetObjCPtr) 2364 return; 2365 2366 if (TargetObjCPtr->isUnspecialized() || 2367 TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() != 2368 NSArrayDecl->getCanonicalDecl()) 2369 return; 2370 2371 auto TypeArgs = TargetObjCPtr->getTypeArgs(); 2372 if (TypeArgs.size() != 1) 2373 return; 2374 2375 QualType TargetElementType = TypeArgs[0]; 2376 for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) { 2377 checkCollectionLiteralElement(SemaRef, TargetElementType, 2378 ArrayLiteral->getElement(I), 0); 2379 } 2380 } 2381 2382 void SemaObjC::checkDictionaryLiteral( 2383 QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral) { 2384 if (!NSDictionaryDecl) 2385 return; 2386 2387 const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>(); 2388 if (!TargetObjCPtr) 2389 return; 2390 2391 if (TargetObjCPtr->isUnspecialized() || 2392 TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() != 2393 NSDictionaryDecl->getCanonicalDecl()) 2394 return; 2395 2396 auto TypeArgs = TargetObjCPtr->getTypeArgs(); 2397 if (TypeArgs.size() != 2) 2398 return; 2399 2400 QualType TargetKeyType = TypeArgs[0]; 2401 QualType TargetObjectType = TypeArgs[1]; 2402 for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) { 2403 auto Element = DictionaryLiteral->getKeyValueElement(I); 2404 checkCollectionLiteralElement(SemaRef, TargetKeyType, Element.Key, 1); 2405 checkCollectionLiteralElement(SemaRef, TargetObjectType, Element.Value, 2); 2406 } 2407 } 2408 2409 } // namespace clang 2410