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