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