131a203faSVlad Serebrennikov //===----- SemaObjC.cpp ---- Semantic Analysis for Objective-C ------------===// 231a203faSVlad Serebrennikov // 331a203faSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 431a203faSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information. 531a203faSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 631a203faSVlad Serebrennikov // 731a203faSVlad Serebrennikov //===----------------------------------------------------------------------===// 831a203faSVlad Serebrennikov /// \file 931a203faSVlad Serebrennikov /// This file implements semantic analysis for Objective-C. 1031a203faSVlad Serebrennikov /// 1131a203faSVlad Serebrennikov //===----------------------------------------------------------------------===// 1231a203faSVlad Serebrennikov 1331a203faSVlad Serebrennikov #include "clang/Sema/SemaObjC.h" 146b755b0cSVlad Serebrennikov #include "clang/AST/ASTMutationListener.h" 1531a203faSVlad Serebrennikov #include "clang/AST/EvaluatedExprVisitor.h" 1631a203faSVlad Serebrennikov #include "clang/AST/StmtObjC.h" 1731a203faSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h" 1831a203faSVlad Serebrennikov #include "clang/Lex/Preprocessor.h" 196b755b0cSVlad Serebrennikov #include "clang/Sema/Attr.h" 2027d37ee4SVlad Serebrennikov #include "clang/Sema/Lookup.h" 216b755b0cSVlad Serebrennikov #include "clang/Sema/ParsedAttr.h" 2231a203faSVlad Serebrennikov #include "clang/Sema/ScopeInfo.h" 2331a203faSVlad Serebrennikov #include "clang/Sema/Sema.h" 2431a203faSVlad Serebrennikov #include "clang/Sema/TemplateDeduction.h" 2531a203faSVlad Serebrennikov #include "llvm/Support/ConvertUTF.h" 2631a203faSVlad Serebrennikov 2731a203faSVlad Serebrennikov namespace clang { 2831a203faSVlad Serebrennikov 2931a203faSVlad Serebrennikov SemaObjC::SemaObjC(Sema &S) 3031a203faSVlad Serebrennikov : SemaBase(S), NSNumberDecl(nullptr), NSValueDecl(nullptr), 3131a203faSVlad Serebrennikov NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), 3231a203faSVlad Serebrennikov ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), 3331a203faSVlad Serebrennikov ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), 3431a203faSVlad Serebrennikov DictionaryWithObjectsMethod(nullptr) {} 3531a203faSVlad Serebrennikov 3631a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc, 3731a203faSVlad Serebrennikov Stmt *First, Expr *collection, 3831a203faSVlad Serebrennikov SourceLocation RParenLoc) { 3931a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 4031a203faSVlad Serebrennikov SemaRef.setFunctionHasBranchProtectedScope(); 4131a203faSVlad Serebrennikov 4231a203faSVlad Serebrennikov ExprResult CollectionExprResult = 4331a203faSVlad Serebrennikov CheckObjCForCollectionOperand(ForLoc, collection); 4431a203faSVlad Serebrennikov 4531a203faSVlad Serebrennikov if (First) { 4631a203faSVlad Serebrennikov QualType FirstType; 4731a203faSVlad Serebrennikov if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) { 4831a203faSVlad Serebrennikov if (!DS->isSingleDecl()) 4931a203faSVlad Serebrennikov return StmtError(Diag((*DS->decl_begin())->getLocation(), 5031a203faSVlad Serebrennikov diag::err_toomany_element_decls)); 5131a203faSVlad Serebrennikov 5231a203faSVlad Serebrennikov VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl()); 5331a203faSVlad Serebrennikov if (!D || D->isInvalidDecl()) 5431a203faSVlad Serebrennikov return StmtError(); 5531a203faSVlad Serebrennikov 5631a203faSVlad Serebrennikov FirstType = D->getType(); 5731a203faSVlad Serebrennikov // C99 6.8.5p3: The declaration part of a 'for' statement shall only 5831a203faSVlad Serebrennikov // declare identifiers for objects having storage class 'auto' or 5931a203faSVlad Serebrennikov // 'register'. 6031a203faSVlad Serebrennikov if (!D->hasLocalStorage()) 6131a203faSVlad Serebrennikov return StmtError( 6231a203faSVlad Serebrennikov Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for)); 6331a203faSVlad Serebrennikov 6431a203faSVlad Serebrennikov // If the type contained 'auto', deduce the 'auto' to 'id'. 6531a203faSVlad Serebrennikov if (FirstType->getContainedAutoType()) { 6631a203faSVlad Serebrennikov SourceLocation Loc = D->getLocation(); 6731a203faSVlad Serebrennikov OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue); 6831a203faSVlad Serebrennikov Expr *DeducedInit = &OpaqueId; 6931a203faSVlad Serebrennikov sema::TemplateDeductionInfo Info(Loc); 7031a203faSVlad Serebrennikov FirstType = QualType(); 7131a203faSVlad Serebrennikov TemplateDeductionResult Result = SemaRef.DeduceAutoType( 7231a203faSVlad Serebrennikov D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); 7331a203faSVlad Serebrennikov if (Result != TemplateDeductionResult::Success && 7431a203faSVlad Serebrennikov Result != TemplateDeductionResult::AlreadyDiagnosed) 7531a203faSVlad Serebrennikov SemaRef.DiagnoseAutoDeductionFailure(D, DeducedInit); 7631a203faSVlad Serebrennikov if (FirstType.isNull()) { 7731a203faSVlad Serebrennikov D->setInvalidDecl(); 7831a203faSVlad Serebrennikov return StmtError(); 7931a203faSVlad Serebrennikov } 8031a203faSVlad Serebrennikov 8131a203faSVlad Serebrennikov D->setType(FirstType); 8231a203faSVlad Serebrennikov 8331a203faSVlad Serebrennikov if (!SemaRef.inTemplateInstantiation()) { 8431a203faSVlad Serebrennikov SourceLocation Loc = 8531a203faSVlad Serebrennikov D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); 8631a203faSVlad Serebrennikov Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName(); 8731a203faSVlad Serebrennikov } 8831a203faSVlad Serebrennikov } 8931a203faSVlad Serebrennikov 9031a203faSVlad Serebrennikov } else { 9131a203faSVlad Serebrennikov Expr *FirstE = cast<Expr>(First); 9231a203faSVlad Serebrennikov if (!FirstE->isTypeDependent() && !FirstE->isLValue()) 9331a203faSVlad Serebrennikov return StmtError( 9431a203faSVlad Serebrennikov Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue) 9531a203faSVlad Serebrennikov << First->getSourceRange()); 9631a203faSVlad Serebrennikov 9731a203faSVlad Serebrennikov FirstType = static_cast<Expr *>(First)->getType(); 9831a203faSVlad Serebrennikov if (FirstType.isConstQualified()) 9931a203faSVlad Serebrennikov Diag(ForLoc, diag::err_selector_element_const_type) 10031a203faSVlad Serebrennikov << FirstType << First->getSourceRange(); 10131a203faSVlad Serebrennikov } 10231a203faSVlad Serebrennikov if (!FirstType->isDependentType() && 10331a203faSVlad Serebrennikov !FirstType->isObjCObjectPointerType() && 10431a203faSVlad Serebrennikov !FirstType->isBlockPointerType()) 10531a203faSVlad Serebrennikov return StmtError(Diag(ForLoc, diag::err_selector_element_type) 10631a203faSVlad Serebrennikov << FirstType << First->getSourceRange()); 10731a203faSVlad Serebrennikov } 10831a203faSVlad Serebrennikov 10931a203faSVlad Serebrennikov if (CollectionExprResult.isInvalid()) 11031a203faSVlad Serebrennikov return StmtError(); 11131a203faSVlad Serebrennikov 11231a203faSVlad Serebrennikov CollectionExprResult = SemaRef.ActOnFinishFullExpr(CollectionExprResult.get(), 11331a203faSVlad Serebrennikov /*DiscardedValue*/ false); 11431a203faSVlad Serebrennikov if (CollectionExprResult.isInvalid()) 11531a203faSVlad Serebrennikov return StmtError(); 11631a203faSVlad Serebrennikov 11731a203faSVlad Serebrennikov return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(), 11831a203faSVlad Serebrennikov nullptr, ForLoc, RParenLoc); 11931a203faSVlad Serebrennikov } 12031a203faSVlad Serebrennikov 12131a203faSVlad Serebrennikov ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc, 12231a203faSVlad Serebrennikov Expr *collection) { 12331a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 12431a203faSVlad Serebrennikov if (!collection) 12531a203faSVlad Serebrennikov return ExprError(); 12631a203faSVlad Serebrennikov 12731a203faSVlad Serebrennikov ExprResult result = SemaRef.CorrectDelayedTyposInExpr(collection); 12831a203faSVlad Serebrennikov if (!result.isUsable()) 12931a203faSVlad Serebrennikov return ExprError(); 13031a203faSVlad Serebrennikov collection = result.get(); 13131a203faSVlad Serebrennikov 13231a203faSVlad Serebrennikov // Bail out early if we've got a type-dependent expression. 13331a203faSVlad Serebrennikov if (collection->isTypeDependent()) 13431a203faSVlad Serebrennikov return collection; 13531a203faSVlad Serebrennikov 13631a203faSVlad Serebrennikov // Perform normal l-value conversion. 13731a203faSVlad Serebrennikov result = SemaRef.DefaultFunctionArrayLvalueConversion(collection); 13831a203faSVlad Serebrennikov if (result.isInvalid()) 13931a203faSVlad Serebrennikov return ExprError(); 14031a203faSVlad Serebrennikov collection = result.get(); 14131a203faSVlad Serebrennikov 14231a203faSVlad Serebrennikov // The operand needs to have object-pointer type. 14331a203faSVlad Serebrennikov // TODO: should we do a contextual conversion? 14431a203faSVlad Serebrennikov const ObjCObjectPointerType *pointerType = 14531a203faSVlad Serebrennikov collection->getType()->getAs<ObjCObjectPointerType>(); 14631a203faSVlad Serebrennikov if (!pointerType) 14731a203faSVlad Serebrennikov return Diag(forLoc, diag::err_collection_expr_type) 14831a203faSVlad Serebrennikov << collection->getType() << collection->getSourceRange(); 14931a203faSVlad Serebrennikov 15031a203faSVlad Serebrennikov // Check that the operand provides 15131a203faSVlad Serebrennikov // - countByEnumeratingWithState:objects:count: 15231a203faSVlad Serebrennikov const ObjCObjectType *objectType = pointerType->getObjectType(); 15331a203faSVlad Serebrennikov ObjCInterfaceDecl *iface = objectType->getInterface(); 15431a203faSVlad Serebrennikov 15531a203faSVlad Serebrennikov // If we have a forward-declared type, we can't do this check. 15631a203faSVlad Serebrennikov // Under ARC, it is an error not to have a forward-declared class. 15731a203faSVlad Serebrennikov if (iface && 15831a203faSVlad Serebrennikov (getLangOpts().ObjCAutoRefCount 15931a203faSVlad Serebrennikov ? SemaRef.RequireCompleteType(forLoc, QualType(objectType, 0), 16031a203faSVlad Serebrennikov diag::err_arc_collection_forward, 16131a203faSVlad Serebrennikov collection) 16231a203faSVlad Serebrennikov : !SemaRef.isCompleteType(forLoc, QualType(objectType, 0)))) { 16331a203faSVlad Serebrennikov // Otherwise, if we have any useful type information, check that 16431a203faSVlad Serebrennikov // the type declares the appropriate method. 16531a203faSVlad Serebrennikov } else if (iface || !objectType->qual_empty()) { 16631a203faSVlad Serebrennikov const IdentifierInfo *selectorIdents[] = { 16731a203faSVlad Serebrennikov &Context.Idents.get("countByEnumeratingWithState"), 16831a203faSVlad Serebrennikov &Context.Idents.get("objects"), &Context.Idents.get("count")}; 16931a203faSVlad Serebrennikov Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); 17031a203faSVlad Serebrennikov 17131a203faSVlad Serebrennikov ObjCMethodDecl *method = nullptr; 17231a203faSVlad Serebrennikov 17331a203faSVlad Serebrennikov // If there's an interface, look in both the public and private APIs. 17431a203faSVlad Serebrennikov if (iface) { 17531a203faSVlad Serebrennikov method = iface->lookupInstanceMethod(selector); 17631a203faSVlad Serebrennikov if (!method) 17731a203faSVlad Serebrennikov method = iface->lookupPrivateMethod(selector); 17831a203faSVlad Serebrennikov } 17931a203faSVlad Serebrennikov 18031a203faSVlad Serebrennikov // Also check protocol qualifiers. 18131a203faSVlad Serebrennikov if (!method) 18231a203faSVlad Serebrennikov method = LookupMethodInQualifiedType(selector, pointerType, 18331a203faSVlad Serebrennikov /*instance*/ true); 18431a203faSVlad Serebrennikov 18531a203faSVlad Serebrennikov // If we didn't find it anywhere, give up. 18631a203faSVlad Serebrennikov if (!method) { 18731a203faSVlad Serebrennikov Diag(forLoc, diag::warn_collection_expr_type) 18831a203faSVlad Serebrennikov << collection->getType() << selector << collection->getSourceRange(); 18931a203faSVlad Serebrennikov } 19031a203faSVlad Serebrennikov 19131a203faSVlad Serebrennikov // TODO: check for an incompatible signature? 19231a203faSVlad Serebrennikov } 19331a203faSVlad Serebrennikov 19431a203faSVlad Serebrennikov // Wrap up any cleanups in the expression. 19531a203faSVlad Serebrennikov return collection; 19631a203faSVlad Serebrennikov } 19731a203faSVlad Serebrennikov 19831a203faSVlad Serebrennikov StmtResult SemaObjC::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { 19931a203faSVlad Serebrennikov if (!S || !B) 20031a203faSVlad Serebrennikov return StmtError(); 20131a203faSVlad Serebrennikov ObjCForCollectionStmt *ForStmt = cast<ObjCForCollectionStmt>(S); 20231a203faSVlad Serebrennikov 20331a203faSVlad Serebrennikov ForStmt->setBody(B); 20431a203faSVlad Serebrennikov return S; 20531a203faSVlad Serebrennikov } 20631a203faSVlad Serebrennikov 20731a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc, 20831a203faSVlad Serebrennikov SourceLocation RParen, Decl *Parm, 20931a203faSVlad Serebrennikov Stmt *Body) { 21031a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 21131a203faSVlad Serebrennikov VarDecl *Var = cast_or_null<VarDecl>(Parm); 21231a203faSVlad Serebrennikov if (Var && Var->isInvalidDecl()) 21331a203faSVlad Serebrennikov return StmtError(); 21431a203faSVlad Serebrennikov 21531a203faSVlad Serebrennikov return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body); 21631a203faSVlad Serebrennikov } 21731a203faSVlad Serebrennikov 21831a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { 21931a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 22031a203faSVlad Serebrennikov return new (Context) ObjCAtFinallyStmt(AtLoc, Body); 22131a203faSVlad Serebrennikov } 22231a203faSVlad Serebrennikov 22331a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, 22431a203faSVlad Serebrennikov MultiStmtArg CatchStmts, 22531a203faSVlad Serebrennikov Stmt *Finally) { 22631a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 22731a203faSVlad Serebrennikov if (!getLangOpts().ObjCExceptions) 22831a203faSVlad Serebrennikov Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; 22931a203faSVlad Serebrennikov 23031a203faSVlad Serebrennikov // Objective-C try is incompatible with SEH __try. 23131a203faSVlad Serebrennikov sema::FunctionScopeInfo *FSI = SemaRef.getCurFunction(); 23231a203faSVlad Serebrennikov if (FSI->FirstSEHTryLoc.isValid()) { 23331a203faSVlad Serebrennikov Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1; 23431a203faSVlad Serebrennikov Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; 23531a203faSVlad Serebrennikov } 23631a203faSVlad Serebrennikov 23731a203faSVlad Serebrennikov FSI->setHasObjCTry(AtLoc); 23831a203faSVlad Serebrennikov unsigned NumCatchStmts = CatchStmts.size(); 23931a203faSVlad Serebrennikov return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), 24031a203faSVlad Serebrennikov NumCatchStmts, Finally); 24131a203faSVlad Serebrennikov } 24231a203faSVlad Serebrennikov 24331a203faSVlad Serebrennikov StmtResult SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { 24431a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 24531a203faSVlad Serebrennikov if (Throw) { 24631a203faSVlad Serebrennikov ExprResult Result = SemaRef.DefaultLvalueConversion(Throw); 24731a203faSVlad Serebrennikov if (Result.isInvalid()) 24831a203faSVlad Serebrennikov return StmtError(); 24931a203faSVlad Serebrennikov 25031a203faSVlad Serebrennikov Result = 25131a203faSVlad Serebrennikov SemaRef.ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); 25231a203faSVlad Serebrennikov if (Result.isInvalid()) 25331a203faSVlad Serebrennikov return StmtError(); 25431a203faSVlad Serebrennikov Throw = Result.get(); 25531a203faSVlad Serebrennikov 25631a203faSVlad Serebrennikov QualType ThrowType = Throw->getType(); 25731a203faSVlad Serebrennikov // Make sure the expression type is an ObjC pointer or "void *". 25831a203faSVlad Serebrennikov if (!ThrowType->isDependentType() && 25931a203faSVlad Serebrennikov !ThrowType->isObjCObjectPointerType()) { 26031a203faSVlad Serebrennikov const PointerType *PT = ThrowType->getAs<PointerType>(); 26131a203faSVlad Serebrennikov if (!PT || !PT->getPointeeType()->isVoidType()) 26231a203faSVlad Serebrennikov return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object) 26331a203faSVlad Serebrennikov << Throw->getType() << Throw->getSourceRange()); 26431a203faSVlad Serebrennikov } 26531a203faSVlad Serebrennikov } 26631a203faSVlad Serebrennikov 26731a203faSVlad Serebrennikov return new (Context) ObjCAtThrowStmt(AtLoc, Throw); 26831a203faSVlad Serebrennikov } 26931a203faSVlad Serebrennikov 27031a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, 27131a203faSVlad Serebrennikov Scope *CurScope) { 27231a203faSVlad Serebrennikov if (!getLangOpts().ObjCExceptions) 27331a203faSVlad Serebrennikov Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; 27431a203faSVlad Serebrennikov 27531a203faSVlad Serebrennikov if (!Throw) { 27631a203faSVlad Serebrennikov // @throw without an expression designates a rethrow (which must occur 27731a203faSVlad Serebrennikov // in the context of an @catch clause). 27831a203faSVlad Serebrennikov Scope *AtCatchParent = CurScope; 27931a203faSVlad Serebrennikov while (AtCatchParent && !AtCatchParent->isAtCatchScope()) 28031a203faSVlad Serebrennikov AtCatchParent = AtCatchParent->getParent(); 28131a203faSVlad Serebrennikov if (!AtCatchParent) 28231a203faSVlad Serebrennikov return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch)); 28331a203faSVlad Serebrennikov } 28431a203faSVlad Serebrennikov return BuildObjCAtThrowStmt(AtLoc, Throw); 28531a203faSVlad Serebrennikov } 28631a203faSVlad Serebrennikov 28731a203faSVlad Serebrennikov ExprResult SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, 28831a203faSVlad Serebrennikov Expr *operand) { 28931a203faSVlad Serebrennikov ExprResult result = SemaRef.DefaultLvalueConversion(operand); 29031a203faSVlad Serebrennikov if (result.isInvalid()) 29131a203faSVlad Serebrennikov return ExprError(); 29231a203faSVlad Serebrennikov operand = result.get(); 29331a203faSVlad Serebrennikov 29431a203faSVlad Serebrennikov // Make sure the expression type is an ObjC pointer or "void *". 29531a203faSVlad Serebrennikov QualType type = operand->getType(); 29631a203faSVlad Serebrennikov if (!type->isDependentType() && !type->isObjCObjectPointerType()) { 29731a203faSVlad Serebrennikov const PointerType *pointerType = type->getAs<PointerType>(); 29831a203faSVlad Serebrennikov if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { 29931a203faSVlad Serebrennikov if (getLangOpts().CPlusPlus) { 30031a203faSVlad Serebrennikov if (SemaRef.RequireCompleteType(atLoc, type, 30131a203faSVlad Serebrennikov diag::err_incomplete_receiver_type)) 30231a203faSVlad Serebrennikov return Diag(atLoc, diag::err_objc_synchronized_expects_object) 30331a203faSVlad Serebrennikov << type << operand->getSourceRange(); 30431a203faSVlad Serebrennikov 30531a203faSVlad Serebrennikov ExprResult result = 30631a203faSVlad Serebrennikov SemaRef.PerformContextuallyConvertToObjCPointer(operand); 30731a203faSVlad Serebrennikov if (result.isInvalid()) 30831a203faSVlad Serebrennikov return ExprError(); 30931a203faSVlad Serebrennikov if (!result.isUsable()) 31031a203faSVlad Serebrennikov return Diag(atLoc, diag::err_objc_synchronized_expects_object) 31131a203faSVlad Serebrennikov << type << operand->getSourceRange(); 31231a203faSVlad Serebrennikov 31331a203faSVlad Serebrennikov operand = result.get(); 31431a203faSVlad Serebrennikov } else { 31531a203faSVlad Serebrennikov return Diag(atLoc, diag::err_objc_synchronized_expects_object) 31631a203faSVlad Serebrennikov << type << operand->getSourceRange(); 31731a203faSVlad Serebrennikov } 31831a203faSVlad Serebrennikov } 31931a203faSVlad Serebrennikov } 32031a203faSVlad Serebrennikov 32131a203faSVlad Serebrennikov // The operand to @synchronized is a full-expression. 32231a203faSVlad Serebrennikov return SemaRef.ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); 32331a203faSVlad Serebrennikov } 32431a203faSVlad Serebrennikov 32531a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, 32631a203faSVlad Serebrennikov Expr *SyncExpr, 32731a203faSVlad Serebrennikov Stmt *SyncBody) { 32831a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 32931a203faSVlad Serebrennikov // We can't jump into or indirect-jump out of a @synchronized block. 33031a203faSVlad Serebrennikov SemaRef.setFunctionHasBranchProtectedScope(); 33131a203faSVlad Serebrennikov return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody); 33231a203faSVlad Serebrennikov } 33331a203faSVlad Serebrennikov 33431a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, 33531a203faSVlad Serebrennikov Stmt *Body) { 33631a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 33731a203faSVlad Serebrennikov SemaRef.setFunctionHasBranchProtectedScope(); 33831a203faSVlad Serebrennikov return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body); 33931a203faSVlad Serebrennikov } 34031a203faSVlad Serebrennikov 34131a203faSVlad Serebrennikov TypeResult SemaObjC::actOnObjCProtocolQualifierType( 34231a203faSVlad Serebrennikov SourceLocation lAngleLoc, ArrayRef<Decl *> protocols, 34331a203faSVlad Serebrennikov ArrayRef<SourceLocation> protocolLocs, SourceLocation rAngleLoc) { 34431a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 34531a203faSVlad Serebrennikov // Form id<protocol-list>. 34631a203faSVlad Serebrennikov QualType Result = Context.getObjCObjectType( 34731a203faSVlad Serebrennikov Context.ObjCBuiltinIdTy, {}, 34831a203faSVlad Serebrennikov llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(), 34931a203faSVlad Serebrennikov protocols.size()), 35031a203faSVlad Serebrennikov false); 35131a203faSVlad Serebrennikov Result = Context.getObjCObjectPointerType(Result); 35231a203faSVlad Serebrennikov 35331a203faSVlad Serebrennikov TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); 35431a203faSVlad Serebrennikov TypeLoc ResultTL = ResultTInfo->getTypeLoc(); 35531a203faSVlad Serebrennikov 35631a203faSVlad Serebrennikov auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>(); 35731a203faSVlad Serebrennikov ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit 35831a203faSVlad Serebrennikov 35931a203faSVlad Serebrennikov auto ObjCObjectTL = 36031a203faSVlad Serebrennikov ObjCObjectPointerTL.getPointeeLoc().castAs<ObjCObjectTypeLoc>(); 36131a203faSVlad Serebrennikov ObjCObjectTL.setHasBaseTypeAsWritten(false); 36231a203faSVlad Serebrennikov ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation()); 36331a203faSVlad Serebrennikov 36431a203faSVlad Serebrennikov // No type arguments. 36531a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); 36631a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); 36731a203faSVlad Serebrennikov 36831a203faSVlad Serebrennikov // Fill in protocol qualifiers. 36931a203faSVlad Serebrennikov ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc); 37031a203faSVlad Serebrennikov ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc); 37131a203faSVlad Serebrennikov for (unsigned i = 0, n = protocols.size(); i != n; ++i) 37231a203faSVlad Serebrennikov ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]); 37331a203faSVlad Serebrennikov 37431a203faSVlad Serebrennikov // We're done. Return the completed type to the parser. 37531a203faSVlad Serebrennikov return SemaRef.CreateParsedType(Result, ResultTInfo); 37631a203faSVlad Serebrennikov } 37731a203faSVlad Serebrennikov 37831a203faSVlad Serebrennikov TypeResult SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers( 37931a203faSVlad Serebrennikov Scope *S, SourceLocation Loc, ParsedType BaseType, 38031a203faSVlad Serebrennikov SourceLocation TypeArgsLAngleLoc, ArrayRef<ParsedType> TypeArgs, 38131a203faSVlad Serebrennikov SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc, 38231a203faSVlad Serebrennikov ArrayRef<Decl *> Protocols, ArrayRef<SourceLocation> ProtocolLocs, 38331a203faSVlad Serebrennikov SourceLocation ProtocolRAngleLoc) { 38431a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 38531a203faSVlad Serebrennikov TypeSourceInfo *BaseTypeInfo = nullptr; 38631a203faSVlad Serebrennikov QualType T = SemaRef.GetTypeFromParser(BaseType, &BaseTypeInfo); 38731a203faSVlad Serebrennikov if (T.isNull()) 38831a203faSVlad Serebrennikov return true; 38931a203faSVlad Serebrennikov 39031a203faSVlad Serebrennikov // Handle missing type-source info. 39131a203faSVlad Serebrennikov if (!BaseTypeInfo) 39231a203faSVlad Serebrennikov BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc); 39331a203faSVlad Serebrennikov 39431a203faSVlad Serebrennikov // Extract type arguments. 39531a203faSVlad Serebrennikov SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos; 39631a203faSVlad Serebrennikov for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) { 39731a203faSVlad Serebrennikov TypeSourceInfo *TypeArgInfo = nullptr; 39831a203faSVlad Serebrennikov QualType TypeArg = SemaRef.GetTypeFromParser(TypeArgs[i], &TypeArgInfo); 39931a203faSVlad Serebrennikov if (TypeArg.isNull()) { 40031a203faSVlad Serebrennikov ActualTypeArgInfos.clear(); 40131a203faSVlad Serebrennikov break; 40231a203faSVlad Serebrennikov } 40331a203faSVlad Serebrennikov 40431a203faSVlad Serebrennikov assert(TypeArgInfo && "No type source info?"); 40531a203faSVlad Serebrennikov ActualTypeArgInfos.push_back(TypeArgInfo); 40631a203faSVlad Serebrennikov } 40731a203faSVlad Serebrennikov 40831a203faSVlad Serebrennikov // Build the object type. 40931a203faSVlad Serebrennikov QualType Result = BuildObjCObjectType( 41031a203faSVlad Serebrennikov T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(), 41131a203faSVlad Serebrennikov TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc, 41231a203faSVlad Serebrennikov ProtocolLAngleLoc, 41331a203faSVlad Serebrennikov llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(), 41431a203faSVlad Serebrennikov Protocols.size()), 41531a203faSVlad Serebrennikov ProtocolLocs, ProtocolRAngleLoc, 41631a203faSVlad Serebrennikov /*FailOnError=*/false, 41731a203faSVlad Serebrennikov /*Rebuilding=*/false); 41831a203faSVlad Serebrennikov 41931a203faSVlad Serebrennikov if (Result == T) 42031a203faSVlad Serebrennikov return BaseType; 42131a203faSVlad Serebrennikov 42231a203faSVlad Serebrennikov // Create source information for this type. 42331a203faSVlad Serebrennikov TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result); 42431a203faSVlad Serebrennikov TypeLoc ResultTL = ResultTInfo->getTypeLoc(); 42531a203faSVlad Serebrennikov 42631a203faSVlad Serebrennikov // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an 42731a203faSVlad Serebrennikov // object pointer type. Fill in source information for it. 42831a203faSVlad Serebrennikov if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) { 42931a203faSVlad Serebrennikov // The '*' is implicit. 43031a203faSVlad Serebrennikov ObjCObjectPointerTL.setStarLoc(SourceLocation()); 43131a203faSVlad Serebrennikov ResultTL = ObjCObjectPointerTL.getPointeeLoc(); 43231a203faSVlad Serebrennikov } 43331a203faSVlad Serebrennikov 43431a203faSVlad Serebrennikov if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) { 43531a203faSVlad Serebrennikov // Protocol qualifier information. 43631a203faSVlad Serebrennikov if (OTPTL.getNumProtocols() > 0) { 43731a203faSVlad Serebrennikov assert(OTPTL.getNumProtocols() == Protocols.size()); 43831a203faSVlad Serebrennikov OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc); 43931a203faSVlad Serebrennikov OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc); 44031a203faSVlad Serebrennikov for (unsigned i = 0, n = Protocols.size(); i != n; ++i) 44131a203faSVlad Serebrennikov OTPTL.setProtocolLoc(i, ProtocolLocs[i]); 44231a203faSVlad Serebrennikov } 44331a203faSVlad Serebrennikov 44431a203faSVlad Serebrennikov // We're done. Return the completed type to the parser. 44531a203faSVlad Serebrennikov return SemaRef.CreateParsedType(Result, ResultTInfo); 44631a203faSVlad Serebrennikov } 44731a203faSVlad Serebrennikov 44831a203faSVlad Serebrennikov auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>(); 44931a203faSVlad Serebrennikov 45031a203faSVlad Serebrennikov // Type argument information. 45131a203faSVlad Serebrennikov if (ObjCObjectTL.getNumTypeArgs() > 0) { 45231a203faSVlad Serebrennikov assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size()); 45331a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc); 45431a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc); 45531a203faSVlad Serebrennikov for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i) 45631a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]); 45731a203faSVlad Serebrennikov } else { 45831a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation()); 45931a203faSVlad Serebrennikov ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation()); 46031a203faSVlad Serebrennikov } 46131a203faSVlad Serebrennikov 46231a203faSVlad Serebrennikov // Protocol qualifier information. 46331a203faSVlad Serebrennikov if (ObjCObjectTL.getNumProtocols() > 0) { 46431a203faSVlad Serebrennikov assert(ObjCObjectTL.getNumProtocols() == Protocols.size()); 46531a203faSVlad Serebrennikov ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc); 46631a203faSVlad Serebrennikov ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc); 46731a203faSVlad Serebrennikov for (unsigned i = 0, n = Protocols.size(); i != n; ++i) 46831a203faSVlad Serebrennikov ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]); 46931a203faSVlad Serebrennikov } else { 47031a203faSVlad Serebrennikov ObjCObjectTL.setProtocolLAngleLoc(SourceLocation()); 47131a203faSVlad Serebrennikov ObjCObjectTL.setProtocolRAngleLoc(SourceLocation()); 47231a203faSVlad Serebrennikov } 47331a203faSVlad Serebrennikov 47431a203faSVlad Serebrennikov // Base type. 47531a203faSVlad Serebrennikov ObjCObjectTL.setHasBaseTypeAsWritten(true); 47631a203faSVlad Serebrennikov if (ObjCObjectTL.getType() == T) 47731a203faSVlad Serebrennikov ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc()); 47831a203faSVlad Serebrennikov else 47931a203faSVlad Serebrennikov ObjCObjectTL.getBaseLoc().initialize(Context, Loc); 48031a203faSVlad Serebrennikov 48131a203faSVlad Serebrennikov // We're done. Return the completed type to the parser. 48231a203faSVlad Serebrennikov return SemaRef.CreateParsedType(Result, ResultTInfo); 48331a203faSVlad Serebrennikov } 48431a203faSVlad Serebrennikov 48531a203faSVlad Serebrennikov QualType SemaObjC::BuildObjCTypeParamType( 48631a203faSVlad Serebrennikov const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc, 48731a203faSVlad Serebrennikov ArrayRef<ObjCProtocolDecl *> Protocols, 48831a203faSVlad Serebrennikov ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc, 48931a203faSVlad Serebrennikov bool FailOnError) { 49031a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 49131a203faSVlad Serebrennikov QualType Result = QualType(Decl->getTypeForDecl(), 0); 49231a203faSVlad Serebrennikov if (!Protocols.empty()) { 49331a203faSVlad Serebrennikov bool HasError; 49431a203faSVlad Serebrennikov Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError); 49531a203faSVlad Serebrennikov if (HasError) { 49631a203faSVlad Serebrennikov Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers) 49731a203faSVlad Serebrennikov << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); 49831a203faSVlad Serebrennikov if (FailOnError) 49931a203faSVlad Serebrennikov Result = QualType(); 50031a203faSVlad Serebrennikov } 50131a203faSVlad Serebrennikov if (FailOnError && Result.isNull()) 50231a203faSVlad Serebrennikov return QualType(); 50331a203faSVlad Serebrennikov } 50431a203faSVlad Serebrennikov 50531a203faSVlad Serebrennikov return Result; 50631a203faSVlad Serebrennikov } 50731a203faSVlad Serebrennikov 50831a203faSVlad Serebrennikov /// Apply Objective-C type arguments to the given type. 50931a203faSVlad Serebrennikov static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, 51031a203faSVlad Serebrennikov ArrayRef<TypeSourceInfo *> typeArgs, 51131a203faSVlad Serebrennikov SourceRange typeArgsRange, bool failOnError, 51231a203faSVlad Serebrennikov bool rebuilding) { 51331a203faSVlad Serebrennikov // We can only apply type arguments to an Objective-C class type. 51431a203faSVlad Serebrennikov const auto *objcObjectType = type->getAs<ObjCObjectType>(); 51531a203faSVlad Serebrennikov if (!objcObjectType || !objcObjectType->getInterface()) { 51631a203faSVlad Serebrennikov S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange; 51731a203faSVlad Serebrennikov 51831a203faSVlad Serebrennikov if (failOnError) 51931a203faSVlad Serebrennikov return QualType(); 52031a203faSVlad Serebrennikov return type; 52131a203faSVlad Serebrennikov } 52231a203faSVlad Serebrennikov 52331a203faSVlad Serebrennikov // The class type must be parameterized. 52431a203faSVlad Serebrennikov ObjCInterfaceDecl *objcClass = objcObjectType->getInterface(); 52531a203faSVlad Serebrennikov ObjCTypeParamList *typeParams = objcClass->getTypeParamList(); 52631a203faSVlad Serebrennikov if (!typeParams) { 52731a203faSVlad Serebrennikov S.Diag(loc, diag::err_objc_type_args_non_parameterized_class) 52831a203faSVlad Serebrennikov << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange); 52931a203faSVlad Serebrennikov 53031a203faSVlad Serebrennikov if (failOnError) 53131a203faSVlad Serebrennikov return QualType(); 53231a203faSVlad Serebrennikov 53331a203faSVlad Serebrennikov return type; 53431a203faSVlad Serebrennikov } 53531a203faSVlad Serebrennikov 53631a203faSVlad Serebrennikov // The type must not already be specialized. 53731a203faSVlad Serebrennikov if (objcObjectType->isSpecialized()) { 53831a203faSVlad Serebrennikov S.Diag(loc, diag::err_objc_type_args_specialized_class) 53931a203faSVlad Serebrennikov << type << FixItHint::CreateRemoval(typeArgsRange); 54031a203faSVlad Serebrennikov 54131a203faSVlad Serebrennikov if (failOnError) 54231a203faSVlad Serebrennikov return QualType(); 54331a203faSVlad Serebrennikov 54431a203faSVlad Serebrennikov return type; 54531a203faSVlad Serebrennikov } 54631a203faSVlad Serebrennikov 54731a203faSVlad Serebrennikov // Check the type arguments. 54831a203faSVlad Serebrennikov SmallVector<QualType, 4> finalTypeArgs; 54931a203faSVlad Serebrennikov unsigned numTypeParams = typeParams->size(); 55031a203faSVlad Serebrennikov bool anyPackExpansions = false; 55131a203faSVlad Serebrennikov for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) { 55231a203faSVlad Serebrennikov TypeSourceInfo *typeArgInfo = typeArgs[i]; 55331a203faSVlad Serebrennikov QualType typeArg = typeArgInfo->getType(); 55431a203faSVlad Serebrennikov 55531a203faSVlad Serebrennikov // Type arguments cannot have explicit qualifiers or nullability. 55631a203faSVlad Serebrennikov // We ignore indirect sources of these, e.g. behind typedefs or 55731a203faSVlad Serebrennikov // template arguments. 55831a203faSVlad Serebrennikov if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) { 55931a203faSVlad Serebrennikov bool diagnosed = false; 56031a203faSVlad Serebrennikov SourceRange rangeToRemove; 56131a203faSVlad Serebrennikov if (auto attr = qual.getAs<AttributedTypeLoc>()) { 56231a203faSVlad Serebrennikov rangeToRemove = attr.getLocalSourceRange(); 56331a203faSVlad Serebrennikov if (attr.getTypePtr()->getImmediateNullability()) { 56431a203faSVlad Serebrennikov typeArg = attr.getTypePtr()->getModifiedType(); 56531a203faSVlad Serebrennikov S.Diag(attr.getBeginLoc(), 56631a203faSVlad Serebrennikov diag::err_objc_type_arg_explicit_nullability) 56731a203faSVlad Serebrennikov << typeArg << FixItHint::CreateRemoval(rangeToRemove); 56831a203faSVlad Serebrennikov diagnosed = true; 56931a203faSVlad Serebrennikov } 57031a203faSVlad Serebrennikov } 57131a203faSVlad Serebrennikov 57231a203faSVlad Serebrennikov // When rebuilding, qualifiers might have gotten here through a 57331a203faSVlad Serebrennikov // final substitution. 57431a203faSVlad Serebrennikov if (!rebuilding && !diagnosed) { 57531a203faSVlad Serebrennikov S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified) 57631a203faSVlad Serebrennikov << typeArg << typeArg.getQualifiers().getAsString() 57731a203faSVlad Serebrennikov << FixItHint::CreateRemoval(rangeToRemove); 57831a203faSVlad Serebrennikov } 57931a203faSVlad Serebrennikov } 58031a203faSVlad Serebrennikov 58131a203faSVlad Serebrennikov // Remove qualifiers even if they're non-local. 58231a203faSVlad Serebrennikov typeArg = typeArg.getUnqualifiedType(); 58331a203faSVlad Serebrennikov 58431a203faSVlad Serebrennikov finalTypeArgs.push_back(typeArg); 58531a203faSVlad Serebrennikov 58631a203faSVlad Serebrennikov if (typeArg->getAs<PackExpansionType>()) 58731a203faSVlad Serebrennikov anyPackExpansions = true; 58831a203faSVlad Serebrennikov 58931a203faSVlad Serebrennikov // Find the corresponding type parameter, if there is one. 59031a203faSVlad Serebrennikov ObjCTypeParamDecl *typeParam = nullptr; 59131a203faSVlad Serebrennikov if (!anyPackExpansions) { 59231a203faSVlad Serebrennikov if (i < numTypeParams) { 59331a203faSVlad Serebrennikov typeParam = typeParams->begin()[i]; 59431a203faSVlad Serebrennikov } else { 59531a203faSVlad Serebrennikov // Too many arguments. 59631a203faSVlad Serebrennikov S.Diag(loc, diag::err_objc_type_args_wrong_arity) 59731a203faSVlad Serebrennikov << false << objcClass->getDeclName() << (unsigned)typeArgs.size() 59831a203faSVlad Serebrennikov << numTypeParams; 59931a203faSVlad Serebrennikov S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; 60031a203faSVlad Serebrennikov 60131a203faSVlad Serebrennikov if (failOnError) 60231a203faSVlad Serebrennikov return QualType(); 60331a203faSVlad Serebrennikov 60431a203faSVlad Serebrennikov return type; 60531a203faSVlad Serebrennikov } 60631a203faSVlad Serebrennikov } 60731a203faSVlad Serebrennikov 60831a203faSVlad Serebrennikov // Objective-C object pointer types must be substitutable for the bounds. 60931a203faSVlad Serebrennikov if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) { 61031a203faSVlad Serebrennikov // If we don't have a type parameter to match against, assume 61131a203faSVlad Serebrennikov // everything is fine. There was a prior pack expansion that 61231a203faSVlad Serebrennikov // means we won't be able to match anything. 61331a203faSVlad Serebrennikov if (!typeParam) { 61431a203faSVlad Serebrennikov assert(anyPackExpansions && "Too many arguments?"); 61531a203faSVlad Serebrennikov continue; 61631a203faSVlad Serebrennikov } 61731a203faSVlad Serebrennikov 61831a203faSVlad Serebrennikov // Retrieve the bound. 61931a203faSVlad Serebrennikov QualType bound = typeParam->getUnderlyingType(); 62031a203faSVlad Serebrennikov const auto *boundObjC = bound->castAs<ObjCObjectPointerType>(); 62131a203faSVlad Serebrennikov 62231a203faSVlad Serebrennikov // Determine whether the type argument is substitutable for the bound. 62331a203faSVlad Serebrennikov if (typeArgObjC->isObjCIdType()) { 62431a203faSVlad Serebrennikov // When the type argument is 'id', the only acceptable type 62531a203faSVlad Serebrennikov // parameter bound is 'id'. 62631a203faSVlad Serebrennikov if (boundObjC->isObjCIdType()) 62731a203faSVlad Serebrennikov continue; 62831a203faSVlad Serebrennikov } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) { 62931a203faSVlad Serebrennikov // Otherwise, we follow the assignability rules. 63031a203faSVlad Serebrennikov continue; 63131a203faSVlad Serebrennikov } 63231a203faSVlad Serebrennikov 63331a203faSVlad Serebrennikov // Diagnose the mismatch. 63431a203faSVlad Serebrennikov S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), 63531a203faSVlad Serebrennikov diag::err_objc_type_arg_does_not_match_bound) 63631a203faSVlad Serebrennikov << typeArg << bound << typeParam->getDeclName(); 63731a203faSVlad Serebrennikov S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) 63831a203faSVlad Serebrennikov << typeParam->getDeclName(); 63931a203faSVlad Serebrennikov 64031a203faSVlad Serebrennikov if (failOnError) 64131a203faSVlad Serebrennikov return QualType(); 64231a203faSVlad Serebrennikov 64331a203faSVlad Serebrennikov return type; 64431a203faSVlad Serebrennikov } 64531a203faSVlad Serebrennikov 64631a203faSVlad Serebrennikov // Block pointer types are permitted for unqualified 'id' bounds. 64731a203faSVlad Serebrennikov if (typeArg->isBlockPointerType()) { 64831a203faSVlad Serebrennikov // If we don't have a type parameter to match against, assume 64931a203faSVlad Serebrennikov // everything is fine. There was a prior pack expansion that 65031a203faSVlad Serebrennikov // means we won't be able to match anything. 65131a203faSVlad Serebrennikov if (!typeParam) { 65231a203faSVlad Serebrennikov assert(anyPackExpansions && "Too many arguments?"); 65331a203faSVlad Serebrennikov continue; 65431a203faSVlad Serebrennikov } 65531a203faSVlad Serebrennikov 65631a203faSVlad Serebrennikov // Retrieve the bound. 65731a203faSVlad Serebrennikov QualType bound = typeParam->getUnderlyingType(); 65831a203faSVlad Serebrennikov if (bound->isBlockCompatibleObjCPointerType(S.Context)) 65931a203faSVlad Serebrennikov continue; 66031a203faSVlad Serebrennikov 66131a203faSVlad Serebrennikov // Diagnose the mismatch. 66231a203faSVlad Serebrennikov S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), 66331a203faSVlad Serebrennikov diag::err_objc_type_arg_does_not_match_bound) 66431a203faSVlad Serebrennikov << typeArg << bound << typeParam->getDeclName(); 66531a203faSVlad Serebrennikov S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here) 66631a203faSVlad Serebrennikov << typeParam->getDeclName(); 66731a203faSVlad Serebrennikov 66831a203faSVlad Serebrennikov if (failOnError) 66931a203faSVlad Serebrennikov return QualType(); 67031a203faSVlad Serebrennikov 67131a203faSVlad Serebrennikov return type; 67231a203faSVlad Serebrennikov } 67331a203faSVlad Serebrennikov 67431a203faSVlad Serebrennikov // Types that have __attribute__((NSObject)) are permitted. 67531a203faSVlad Serebrennikov if (typeArg->isObjCNSObjectType()) { 67631a203faSVlad Serebrennikov continue; 67731a203faSVlad Serebrennikov } 67831a203faSVlad Serebrennikov 67931a203faSVlad Serebrennikov // Dependent types will be checked at instantiation time. 68031a203faSVlad Serebrennikov if (typeArg->isDependentType()) { 68131a203faSVlad Serebrennikov continue; 68231a203faSVlad Serebrennikov } 68331a203faSVlad Serebrennikov 68431a203faSVlad Serebrennikov // Diagnose non-id-compatible type arguments. 68531a203faSVlad Serebrennikov S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(), 68631a203faSVlad Serebrennikov diag::err_objc_type_arg_not_id_compatible) 68731a203faSVlad Serebrennikov << typeArg << typeArgInfo->getTypeLoc().getSourceRange(); 68831a203faSVlad Serebrennikov 68931a203faSVlad Serebrennikov if (failOnError) 69031a203faSVlad Serebrennikov return QualType(); 69131a203faSVlad Serebrennikov 69231a203faSVlad Serebrennikov return type; 69331a203faSVlad Serebrennikov } 69431a203faSVlad Serebrennikov 69531a203faSVlad Serebrennikov // Make sure we didn't have the wrong number of arguments. 69631a203faSVlad Serebrennikov if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) { 69731a203faSVlad Serebrennikov S.Diag(loc, diag::err_objc_type_args_wrong_arity) 69831a203faSVlad Serebrennikov << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName() 69931a203faSVlad Serebrennikov << (unsigned)finalTypeArgs.size() << (unsigned)numTypeParams; 70031a203faSVlad Serebrennikov S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; 70131a203faSVlad Serebrennikov 70231a203faSVlad Serebrennikov if (failOnError) 70331a203faSVlad Serebrennikov return QualType(); 70431a203faSVlad Serebrennikov 70531a203faSVlad Serebrennikov return type; 70631a203faSVlad Serebrennikov } 70731a203faSVlad Serebrennikov 70831a203faSVlad Serebrennikov // Success. Form the specialized type. 70931a203faSVlad Serebrennikov return S.Context.getObjCObjectType(type, finalTypeArgs, {}, false); 71031a203faSVlad Serebrennikov } 71131a203faSVlad Serebrennikov 71231a203faSVlad Serebrennikov QualType SemaObjC::BuildObjCObjectType( 71331a203faSVlad Serebrennikov QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, 71431a203faSVlad Serebrennikov ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc, 71531a203faSVlad Serebrennikov SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols, 71631a203faSVlad Serebrennikov ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc, 71731a203faSVlad Serebrennikov bool FailOnError, bool Rebuilding) { 71831a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 71931a203faSVlad Serebrennikov QualType Result = BaseType; 72031a203faSVlad Serebrennikov if (!TypeArgs.empty()) { 72131a203faSVlad Serebrennikov Result = 72231a203faSVlad Serebrennikov applyObjCTypeArgs(SemaRef, Loc, Result, TypeArgs, 72331a203faSVlad Serebrennikov SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc), 72431a203faSVlad Serebrennikov FailOnError, Rebuilding); 72531a203faSVlad Serebrennikov if (FailOnError && Result.isNull()) 72631a203faSVlad Serebrennikov return QualType(); 72731a203faSVlad Serebrennikov } 72831a203faSVlad Serebrennikov 72931a203faSVlad Serebrennikov if (!Protocols.empty()) { 73031a203faSVlad Serebrennikov bool HasError; 73131a203faSVlad Serebrennikov Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError); 73231a203faSVlad Serebrennikov if (HasError) { 73331a203faSVlad Serebrennikov Diag(Loc, diag::err_invalid_protocol_qualifiers) 73431a203faSVlad Serebrennikov << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc); 73531a203faSVlad Serebrennikov if (FailOnError) 73631a203faSVlad Serebrennikov Result = QualType(); 73731a203faSVlad Serebrennikov } 73831a203faSVlad Serebrennikov if (FailOnError && Result.isNull()) 73931a203faSVlad Serebrennikov return QualType(); 74031a203faSVlad Serebrennikov } 74131a203faSVlad Serebrennikov 74231a203faSVlad Serebrennikov return Result; 74331a203faSVlad Serebrennikov } 74431a203faSVlad Serebrennikov 74531a203faSVlad Serebrennikov ParsedType SemaObjC::ActOnObjCInstanceType(SourceLocation Loc) { 74631a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 74731a203faSVlad Serebrennikov QualType T = Context.getObjCInstanceType(); 74831a203faSVlad Serebrennikov TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc); 74931a203faSVlad Serebrennikov return SemaRef.CreateParsedType(T, TInfo); 75031a203faSVlad Serebrennikov } 75131a203faSVlad Serebrennikov 75231a203faSVlad Serebrennikov //===--- CHECK: Objective-C retain cycles ----------------------------------// 75331a203faSVlad Serebrennikov 75431a203faSVlad Serebrennikov namespace { 75531a203faSVlad Serebrennikov 75631a203faSVlad Serebrennikov struct RetainCycleOwner { 75731a203faSVlad Serebrennikov VarDecl *Variable = nullptr; 75831a203faSVlad Serebrennikov SourceRange Range; 75931a203faSVlad Serebrennikov SourceLocation Loc; 76031a203faSVlad Serebrennikov bool Indirect = false; 76131a203faSVlad Serebrennikov 76231a203faSVlad Serebrennikov RetainCycleOwner() = default; 76331a203faSVlad Serebrennikov 76431a203faSVlad Serebrennikov void setLocsFrom(Expr *e) { 76531a203faSVlad Serebrennikov Loc = e->getExprLoc(); 76631a203faSVlad Serebrennikov Range = e->getSourceRange(); 76731a203faSVlad Serebrennikov } 76831a203faSVlad Serebrennikov }; 76931a203faSVlad Serebrennikov 77031a203faSVlad Serebrennikov } // namespace 77131a203faSVlad Serebrennikov 77231a203faSVlad Serebrennikov /// Consider whether capturing the given variable can possibly lead to 77331a203faSVlad Serebrennikov /// a retain cycle. 77431a203faSVlad Serebrennikov static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { 77531a203faSVlad Serebrennikov // In ARC, it's captured strongly iff the variable has __strong 77631a203faSVlad Serebrennikov // lifetime. In MRR, it's captured strongly if the variable is 77731a203faSVlad Serebrennikov // __block and has an appropriate type. 77831a203faSVlad Serebrennikov if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong) 77931a203faSVlad Serebrennikov return false; 78031a203faSVlad Serebrennikov 78131a203faSVlad Serebrennikov owner.Variable = var; 78231a203faSVlad Serebrennikov if (ref) 78331a203faSVlad Serebrennikov owner.setLocsFrom(ref); 78431a203faSVlad Serebrennikov return true; 78531a203faSVlad Serebrennikov } 78631a203faSVlad Serebrennikov 78731a203faSVlad Serebrennikov static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { 78831a203faSVlad Serebrennikov while (true) { 78931a203faSVlad Serebrennikov e = e->IgnoreParens(); 79031a203faSVlad Serebrennikov if (CastExpr *cast = dyn_cast<CastExpr>(e)) { 79131a203faSVlad Serebrennikov switch (cast->getCastKind()) { 79231a203faSVlad Serebrennikov case CK_BitCast: 79331a203faSVlad Serebrennikov case CK_LValueBitCast: 79431a203faSVlad Serebrennikov case CK_LValueToRValue: 79531a203faSVlad Serebrennikov case CK_ARCReclaimReturnedObject: 79631a203faSVlad Serebrennikov e = cast->getSubExpr(); 79731a203faSVlad Serebrennikov continue; 79831a203faSVlad Serebrennikov 79931a203faSVlad Serebrennikov default: 80031a203faSVlad Serebrennikov return false; 80131a203faSVlad Serebrennikov } 80231a203faSVlad Serebrennikov } 80331a203faSVlad Serebrennikov 80431a203faSVlad Serebrennikov if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) { 80531a203faSVlad Serebrennikov ObjCIvarDecl *ivar = ref->getDecl(); 80631a203faSVlad Serebrennikov if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong) 80731a203faSVlad Serebrennikov return false; 80831a203faSVlad Serebrennikov 80931a203faSVlad Serebrennikov // Try to find a retain cycle in the base. 81031a203faSVlad Serebrennikov if (!findRetainCycleOwner(S, ref->getBase(), owner)) 81131a203faSVlad Serebrennikov return false; 81231a203faSVlad Serebrennikov 81331a203faSVlad Serebrennikov if (ref->isFreeIvar()) 81431a203faSVlad Serebrennikov owner.setLocsFrom(ref); 81531a203faSVlad Serebrennikov owner.Indirect = true; 81631a203faSVlad Serebrennikov return true; 81731a203faSVlad Serebrennikov } 81831a203faSVlad Serebrennikov 81931a203faSVlad Serebrennikov if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) { 82031a203faSVlad Serebrennikov VarDecl *var = dyn_cast<VarDecl>(ref->getDecl()); 82131a203faSVlad Serebrennikov if (!var) 82231a203faSVlad Serebrennikov return false; 82331a203faSVlad Serebrennikov return considerVariable(var, ref, owner); 82431a203faSVlad Serebrennikov } 82531a203faSVlad Serebrennikov 82631a203faSVlad Serebrennikov if (MemberExpr *member = dyn_cast<MemberExpr>(e)) { 82731a203faSVlad Serebrennikov if (member->isArrow()) 82831a203faSVlad Serebrennikov return false; 82931a203faSVlad Serebrennikov 83031a203faSVlad Serebrennikov // Don't count this as an indirect ownership. 83131a203faSVlad Serebrennikov e = member->getBase(); 83231a203faSVlad Serebrennikov continue; 83331a203faSVlad Serebrennikov } 83431a203faSVlad Serebrennikov 83531a203faSVlad Serebrennikov if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { 83631a203faSVlad Serebrennikov // Only pay attention to pseudo-objects on property references. 83731a203faSVlad Serebrennikov ObjCPropertyRefExpr *pre = dyn_cast<ObjCPropertyRefExpr>( 83831a203faSVlad Serebrennikov pseudo->getSyntacticForm()->IgnoreParens()); 83931a203faSVlad Serebrennikov if (!pre) 84031a203faSVlad Serebrennikov return false; 84131a203faSVlad Serebrennikov if (pre->isImplicitProperty()) 84231a203faSVlad Serebrennikov return false; 84331a203faSVlad Serebrennikov ObjCPropertyDecl *property = pre->getExplicitProperty(); 84431a203faSVlad Serebrennikov if (!property->isRetaining() && 84531a203faSVlad Serebrennikov !(property->getPropertyIvarDecl() && 84631a203faSVlad Serebrennikov property->getPropertyIvarDecl()->getType().getObjCLifetime() == 84731a203faSVlad Serebrennikov Qualifiers::OCL_Strong)) 84831a203faSVlad Serebrennikov return false; 84931a203faSVlad Serebrennikov 85031a203faSVlad Serebrennikov owner.Indirect = true; 85131a203faSVlad Serebrennikov if (pre->isSuperReceiver()) { 85231a203faSVlad Serebrennikov owner.Variable = S.getCurMethodDecl()->getSelfDecl(); 85331a203faSVlad Serebrennikov if (!owner.Variable) 85431a203faSVlad Serebrennikov return false; 85531a203faSVlad Serebrennikov owner.Loc = pre->getLocation(); 85631a203faSVlad Serebrennikov owner.Range = pre->getSourceRange(); 85731a203faSVlad Serebrennikov return true; 85831a203faSVlad Serebrennikov } 85931a203faSVlad Serebrennikov e = const_cast<Expr *>( 86031a203faSVlad Serebrennikov cast<OpaqueValueExpr>(pre->getBase())->getSourceExpr()); 86131a203faSVlad Serebrennikov continue; 86231a203faSVlad Serebrennikov } 86331a203faSVlad Serebrennikov 86431a203faSVlad Serebrennikov // Array ivars? 86531a203faSVlad Serebrennikov 86631a203faSVlad Serebrennikov return false; 86731a203faSVlad Serebrennikov } 86831a203faSVlad Serebrennikov } 86931a203faSVlad Serebrennikov 87031a203faSVlad Serebrennikov namespace { 87131a203faSVlad Serebrennikov 87231a203faSVlad Serebrennikov struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> { 87331a203faSVlad Serebrennikov VarDecl *Variable; 87431a203faSVlad Serebrennikov Expr *Capturer = nullptr; 87531a203faSVlad Serebrennikov bool VarWillBeReased = false; 87631a203faSVlad Serebrennikov 87731a203faSVlad Serebrennikov FindCaptureVisitor(ASTContext &Context, VarDecl *variable) 87831a203faSVlad Serebrennikov : EvaluatedExprVisitor<FindCaptureVisitor>(Context), Variable(variable) {} 87931a203faSVlad Serebrennikov 88031a203faSVlad Serebrennikov void VisitDeclRefExpr(DeclRefExpr *ref) { 88131a203faSVlad Serebrennikov if (ref->getDecl() == Variable && !Capturer) 88231a203faSVlad Serebrennikov Capturer = ref; 88331a203faSVlad Serebrennikov } 88431a203faSVlad Serebrennikov 88531a203faSVlad Serebrennikov void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { 88631a203faSVlad Serebrennikov if (Capturer) 88731a203faSVlad Serebrennikov return; 88831a203faSVlad Serebrennikov Visit(ref->getBase()); 88931a203faSVlad Serebrennikov if (Capturer && ref->isFreeIvar()) 89031a203faSVlad Serebrennikov Capturer = ref; 89131a203faSVlad Serebrennikov } 89231a203faSVlad Serebrennikov 89331a203faSVlad Serebrennikov void VisitBlockExpr(BlockExpr *block) { 89431a203faSVlad Serebrennikov // Look inside nested blocks 89531a203faSVlad Serebrennikov if (block->getBlockDecl()->capturesVariable(Variable)) 89631a203faSVlad Serebrennikov Visit(block->getBlockDecl()->getBody()); 89731a203faSVlad Serebrennikov } 89831a203faSVlad Serebrennikov 89931a203faSVlad Serebrennikov void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) { 90031a203faSVlad Serebrennikov if (Capturer) 90131a203faSVlad Serebrennikov return; 90231a203faSVlad Serebrennikov if (OVE->getSourceExpr()) 90331a203faSVlad Serebrennikov Visit(OVE->getSourceExpr()); 90431a203faSVlad Serebrennikov } 90531a203faSVlad Serebrennikov 90631a203faSVlad Serebrennikov void VisitBinaryOperator(BinaryOperator *BinOp) { 90731a203faSVlad Serebrennikov if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign) 90831a203faSVlad Serebrennikov return; 90931a203faSVlad Serebrennikov Expr *LHS = BinOp->getLHS(); 91031a203faSVlad Serebrennikov if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) { 91131a203faSVlad Serebrennikov if (DRE->getDecl() != Variable) 91231a203faSVlad Serebrennikov return; 91331a203faSVlad Serebrennikov if (Expr *RHS = BinOp->getRHS()) { 91431a203faSVlad Serebrennikov RHS = RHS->IgnoreParenCasts(); 91531a203faSVlad Serebrennikov std::optional<llvm::APSInt> Value; 91631a203faSVlad Serebrennikov VarWillBeReased = 91731a203faSVlad Serebrennikov (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && 91831a203faSVlad Serebrennikov *Value == 0); 91931a203faSVlad Serebrennikov } 92031a203faSVlad Serebrennikov } 92131a203faSVlad Serebrennikov } 92231a203faSVlad Serebrennikov }; 92331a203faSVlad Serebrennikov 92431a203faSVlad Serebrennikov } // namespace 92531a203faSVlad Serebrennikov 92631a203faSVlad Serebrennikov /// Check whether the given argument is a block which captures a 92731a203faSVlad Serebrennikov /// variable. 92831a203faSVlad Serebrennikov static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { 92931a203faSVlad Serebrennikov assert(owner.Variable && owner.Loc.isValid()); 93031a203faSVlad Serebrennikov 93131a203faSVlad Serebrennikov e = e->IgnoreParenCasts(); 93231a203faSVlad Serebrennikov 93331a203faSVlad Serebrennikov // Look through [^{...} copy] and Block_copy(^{...}). 93431a203faSVlad Serebrennikov if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) { 93531a203faSVlad Serebrennikov Selector Cmd = ME->getSelector(); 93631a203faSVlad Serebrennikov if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { 93731a203faSVlad Serebrennikov e = ME->getInstanceReceiver(); 93831a203faSVlad Serebrennikov if (!e) 93931a203faSVlad Serebrennikov return nullptr; 94031a203faSVlad Serebrennikov e = e->IgnoreParenCasts(); 94131a203faSVlad Serebrennikov } 94231a203faSVlad Serebrennikov } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) { 94331a203faSVlad Serebrennikov if (CE->getNumArgs() == 1) { 94431a203faSVlad Serebrennikov FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl()); 94531a203faSVlad Serebrennikov if (Fn) { 94631a203faSVlad Serebrennikov const IdentifierInfo *FnI = Fn->getIdentifier(); 94731a203faSVlad Serebrennikov if (FnI && FnI->isStr("_Block_copy")) { 94831a203faSVlad Serebrennikov e = CE->getArg(0)->IgnoreParenCasts(); 94931a203faSVlad Serebrennikov } 95031a203faSVlad Serebrennikov } 95131a203faSVlad Serebrennikov } 95231a203faSVlad Serebrennikov } 95331a203faSVlad Serebrennikov 95431a203faSVlad Serebrennikov BlockExpr *block = dyn_cast<BlockExpr>(e); 95531a203faSVlad Serebrennikov if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) 95631a203faSVlad Serebrennikov return nullptr; 95731a203faSVlad Serebrennikov 95831a203faSVlad Serebrennikov FindCaptureVisitor visitor(S.Context, owner.Variable); 95931a203faSVlad Serebrennikov visitor.Visit(block->getBlockDecl()->getBody()); 96031a203faSVlad Serebrennikov return visitor.VarWillBeReased ? nullptr : visitor.Capturer; 96131a203faSVlad Serebrennikov } 96231a203faSVlad Serebrennikov 96331a203faSVlad Serebrennikov static void diagnoseRetainCycle(Sema &S, Expr *capturer, 96431a203faSVlad Serebrennikov RetainCycleOwner &owner) { 96531a203faSVlad Serebrennikov assert(capturer); 96631a203faSVlad Serebrennikov assert(owner.Variable && owner.Loc.isValid()); 96731a203faSVlad Serebrennikov 96831a203faSVlad Serebrennikov S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle) 96931a203faSVlad Serebrennikov << owner.Variable << capturer->getSourceRange(); 97031a203faSVlad Serebrennikov S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner) 97131a203faSVlad Serebrennikov << owner.Indirect << owner.Range; 97231a203faSVlad Serebrennikov } 97331a203faSVlad Serebrennikov 97431a203faSVlad Serebrennikov /// Check for a keyword selector that starts with the word 'add' or 97531a203faSVlad Serebrennikov /// 'set'. 97631a203faSVlad Serebrennikov static bool isSetterLikeSelector(Selector sel) { 97731a203faSVlad Serebrennikov if (sel.isUnarySelector()) 97831a203faSVlad Serebrennikov return false; 97931a203faSVlad Serebrennikov 98031a203faSVlad Serebrennikov StringRef str = sel.getNameForSlot(0); 98131a203faSVlad Serebrennikov str = str.ltrim('_'); 98231a203faSVlad Serebrennikov if (str.starts_with("set")) 98331a203faSVlad Serebrennikov str = str.substr(3); 98431a203faSVlad Serebrennikov else if (str.starts_with("add")) { 98531a203faSVlad Serebrennikov // Specially allow 'addOperationWithBlock:'. 98631a203faSVlad Serebrennikov if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock")) 98731a203faSVlad Serebrennikov return false; 98831a203faSVlad Serebrennikov str = str.substr(3); 98931a203faSVlad Serebrennikov } else 99031a203faSVlad Serebrennikov return false; 99131a203faSVlad Serebrennikov 99231a203faSVlad Serebrennikov if (str.empty()) 99331a203faSVlad Serebrennikov return true; 99431a203faSVlad Serebrennikov return !isLowercase(str.front()); 99531a203faSVlad Serebrennikov } 99631a203faSVlad Serebrennikov 99731a203faSVlad Serebrennikov static std::optional<int> 99831a203faSVlad Serebrennikov GetNSMutableArrayArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) { 99931a203faSVlad Serebrennikov bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass( 100031a203faSVlad Serebrennikov Message->getReceiverInterface(), NSAPI::ClassId_NSMutableArray); 100131a203faSVlad Serebrennikov if (!IsMutableArray) { 100231a203faSVlad Serebrennikov return std::nullopt; 100331a203faSVlad Serebrennikov } 100431a203faSVlad Serebrennikov 100531a203faSVlad Serebrennikov Selector Sel = Message->getSelector(); 100631a203faSVlad Serebrennikov 100731a203faSVlad Serebrennikov std::optional<NSAPI::NSArrayMethodKind> MKOpt = 100831a203faSVlad Serebrennikov S.NSAPIObj->getNSArrayMethodKind(Sel); 100931a203faSVlad Serebrennikov if (!MKOpt) { 101031a203faSVlad Serebrennikov return std::nullopt; 101131a203faSVlad Serebrennikov } 101231a203faSVlad Serebrennikov 101331a203faSVlad Serebrennikov NSAPI::NSArrayMethodKind MK = *MKOpt; 101431a203faSVlad Serebrennikov 101531a203faSVlad Serebrennikov switch (MK) { 101631a203faSVlad Serebrennikov case NSAPI::NSMutableArr_addObject: 101731a203faSVlad Serebrennikov case NSAPI::NSMutableArr_insertObjectAtIndex: 101831a203faSVlad Serebrennikov case NSAPI::NSMutableArr_setObjectAtIndexedSubscript: 101931a203faSVlad Serebrennikov return 0; 102031a203faSVlad Serebrennikov case NSAPI::NSMutableArr_replaceObjectAtIndex: 102131a203faSVlad Serebrennikov return 1; 102231a203faSVlad Serebrennikov 102331a203faSVlad Serebrennikov default: 102431a203faSVlad Serebrennikov return std::nullopt; 102531a203faSVlad Serebrennikov } 102631a203faSVlad Serebrennikov 102731a203faSVlad Serebrennikov return std::nullopt; 102831a203faSVlad Serebrennikov } 102931a203faSVlad Serebrennikov 103031a203faSVlad Serebrennikov static std::optional<int> 103131a203faSVlad Serebrennikov GetNSMutableDictionaryArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) { 103231a203faSVlad Serebrennikov bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass( 103331a203faSVlad Serebrennikov Message->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary); 103431a203faSVlad Serebrennikov if (!IsMutableDictionary) { 103531a203faSVlad Serebrennikov return std::nullopt; 103631a203faSVlad Serebrennikov } 103731a203faSVlad Serebrennikov 103831a203faSVlad Serebrennikov Selector Sel = Message->getSelector(); 103931a203faSVlad Serebrennikov 104031a203faSVlad Serebrennikov std::optional<NSAPI::NSDictionaryMethodKind> MKOpt = 104131a203faSVlad Serebrennikov S.NSAPIObj->getNSDictionaryMethodKind(Sel); 104231a203faSVlad Serebrennikov if (!MKOpt) { 104331a203faSVlad Serebrennikov return std::nullopt; 104431a203faSVlad Serebrennikov } 104531a203faSVlad Serebrennikov 104631a203faSVlad Serebrennikov NSAPI::NSDictionaryMethodKind MK = *MKOpt; 104731a203faSVlad Serebrennikov 104831a203faSVlad Serebrennikov switch (MK) { 104931a203faSVlad Serebrennikov case NSAPI::NSMutableDict_setObjectForKey: 105031a203faSVlad Serebrennikov case NSAPI::NSMutableDict_setValueForKey: 105131a203faSVlad Serebrennikov case NSAPI::NSMutableDict_setObjectForKeyedSubscript: 105231a203faSVlad Serebrennikov return 0; 105331a203faSVlad Serebrennikov 105431a203faSVlad Serebrennikov default: 105531a203faSVlad Serebrennikov return std::nullopt; 105631a203faSVlad Serebrennikov } 105731a203faSVlad Serebrennikov 105831a203faSVlad Serebrennikov return std::nullopt; 105931a203faSVlad Serebrennikov } 106031a203faSVlad Serebrennikov 106131a203faSVlad Serebrennikov static std::optional<int> GetNSSetArgumentIndex(SemaObjC &S, 106231a203faSVlad Serebrennikov ObjCMessageExpr *Message) { 106331a203faSVlad Serebrennikov bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass( 106431a203faSVlad Serebrennikov Message->getReceiverInterface(), NSAPI::ClassId_NSMutableSet); 106531a203faSVlad Serebrennikov 106631a203faSVlad Serebrennikov bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass( 106731a203faSVlad Serebrennikov Message->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet); 106831a203faSVlad Serebrennikov if (!IsMutableSet && !IsMutableOrderedSet) { 106931a203faSVlad Serebrennikov return std::nullopt; 107031a203faSVlad Serebrennikov } 107131a203faSVlad Serebrennikov 107231a203faSVlad Serebrennikov Selector Sel = Message->getSelector(); 107331a203faSVlad Serebrennikov 107431a203faSVlad Serebrennikov std::optional<NSAPI::NSSetMethodKind> MKOpt = 107531a203faSVlad Serebrennikov S.NSAPIObj->getNSSetMethodKind(Sel); 107631a203faSVlad Serebrennikov if (!MKOpt) { 107731a203faSVlad Serebrennikov return std::nullopt; 107831a203faSVlad Serebrennikov } 107931a203faSVlad Serebrennikov 108031a203faSVlad Serebrennikov NSAPI::NSSetMethodKind MK = *MKOpt; 108131a203faSVlad Serebrennikov 108231a203faSVlad Serebrennikov switch (MK) { 108331a203faSVlad Serebrennikov case NSAPI::NSMutableSet_addObject: 108431a203faSVlad Serebrennikov case NSAPI::NSOrderedSet_setObjectAtIndex: 108531a203faSVlad Serebrennikov case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript: 108631a203faSVlad Serebrennikov case NSAPI::NSOrderedSet_insertObjectAtIndex: 108731a203faSVlad Serebrennikov return 0; 108831a203faSVlad Serebrennikov case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject: 108931a203faSVlad Serebrennikov return 1; 109031a203faSVlad Serebrennikov } 109131a203faSVlad Serebrennikov 109231a203faSVlad Serebrennikov return std::nullopt; 109331a203faSVlad Serebrennikov } 109431a203faSVlad Serebrennikov 109531a203faSVlad Serebrennikov void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr *Message) { 109631a203faSVlad Serebrennikov if (!Message->isInstanceMessage()) { 109731a203faSVlad Serebrennikov return; 109831a203faSVlad Serebrennikov } 109931a203faSVlad Serebrennikov 110031a203faSVlad Serebrennikov std::optional<int> ArgOpt; 110131a203faSVlad Serebrennikov 110231a203faSVlad Serebrennikov if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) && 110331a203faSVlad Serebrennikov !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) && 110431a203faSVlad Serebrennikov !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) { 110531a203faSVlad Serebrennikov return; 110631a203faSVlad Serebrennikov } 110731a203faSVlad Serebrennikov 110831a203faSVlad Serebrennikov int ArgIndex = *ArgOpt; 110931a203faSVlad Serebrennikov 111031a203faSVlad Serebrennikov Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts(); 111131a203faSVlad Serebrennikov if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) { 111231a203faSVlad Serebrennikov Arg = OE->getSourceExpr()->IgnoreImpCasts(); 111331a203faSVlad Serebrennikov } 111431a203faSVlad Serebrennikov 111531a203faSVlad Serebrennikov if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) { 111631a203faSVlad Serebrennikov if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) { 111731a203faSVlad Serebrennikov if (ArgRE->isObjCSelfExpr()) { 111831a203faSVlad Serebrennikov Diag(Message->getSourceRange().getBegin(), 111931a203faSVlad Serebrennikov diag::warn_objc_circular_container) 112031a203faSVlad Serebrennikov << ArgRE->getDecl() << StringRef("'super'"); 112131a203faSVlad Serebrennikov } 112231a203faSVlad Serebrennikov } 112331a203faSVlad Serebrennikov } else { 112431a203faSVlad Serebrennikov Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts(); 112531a203faSVlad Serebrennikov 112631a203faSVlad Serebrennikov if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) { 112731a203faSVlad Serebrennikov Receiver = OE->getSourceExpr()->IgnoreImpCasts(); 112831a203faSVlad Serebrennikov } 112931a203faSVlad Serebrennikov 113031a203faSVlad Serebrennikov if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) { 113131a203faSVlad Serebrennikov if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) { 113231a203faSVlad Serebrennikov if (ReceiverRE->getDecl() == ArgRE->getDecl()) { 113331a203faSVlad Serebrennikov ValueDecl *Decl = ReceiverRE->getDecl(); 113431a203faSVlad Serebrennikov Diag(Message->getSourceRange().getBegin(), 113531a203faSVlad Serebrennikov diag::warn_objc_circular_container) 113631a203faSVlad Serebrennikov << Decl << Decl; 113731a203faSVlad Serebrennikov if (!ArgRE->isObjCSelfExpr()) { 113831a203faSVlad Serebrennikov Diag(Decl->getLocation(), 113931a203faSVlad Serebrennikov diag::note_objc_circular_container_declared_here) 114031a203faSVlad Serebrennikov << Decl; 114131a203faSVlad Serebrennikov } 114231a203faSVlad Serebrennikov } 114331a203faSVlad Serebrennikov } 114431a203faSVlad Serebrennikov } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) { 114531a203faSVlad Serebrennikov if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) { 114631a203faSVlad Serebrennikov if (IvarRE->getDecl() == IvarArgRE->getDecl()) { 114731a203faSVlad Serebrennikov ObjCIvarDecl *Decl = IvarRE->getDecl(); 114831a203faSVlad Serebrennikov Diag(Message->getSourceRange().getBegin(), 114931a203faSVlad Serebrennikov diag::warn_objc_circular_container) 115031a203faSVlad Serebrennikov << Decl << Decl; 115131a203faSVlad Serebrennikov Diag(Decl->getLocation(), 115231a203faSVlad Serebrennikov diag::note_objc_circular_container_declared_here) 115331a203faSVlad Serebrennikov << Decl; 115431a203faSVlad Serebrennikov } 115531a203faSVlad Serebrennikov } 115631a203faSVlad Serebrennikov } 115731a203faSVlad Serebrennikov } 115831a203faSVlad Serebrennikov } 115931a203faSVlad Serebrennikov 116031a203faSVlad Serebrennikov /// Check a message send to see if it's likely to cause a retain cycle. 116131a203faSVlad Serebrennikov void SemaObjC::checkRetainCycles(ObjCMessageExpr *msg) { 116231a203faSVlad Serebrennikov // Only check instance methods whose selector looks like a setter. 116331a203faSVlad Serebrennikov if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) 116431a203faSVlad Serebrennikov return; 116531a203faSVlad Serebrennikov 116631a203faSVlad Serebrennikov // Try to find a variable that the receiver is strongly owned by. 116731a203faSVlad Serebrennikov RetainCycleOwner owner; 116831a203faSVlad Serebrennikov if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { 116931a203faSVlad Serebrennikov if (!findRetainCycleOwner(SemaRef, msg->getInstanceReceiver(), owner)) 117031a203faSVlad Serebrennikov return; 117131a203faSVlad Serebrennikov } else { 117231a203faSVlad Serebrennikov assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); 117331a203faSVlad Serebrennikov owner.Variable = SemaRef.getCurMethodDecl()->getSelfDecl(); 117431a203faSVlad Serebrennikov owner.Loc = msg->getSuperLoc(); 117531a203faSVlad Serebrennikov owner.Range = msg->getSuperLoc(); 117631a203faSVlad Serebrennikov } 117731a203faSVlad Serebrennikov 117831a203faSVlad Serebrennikov // Check whether the receiver is captured by any of the arguments. 117931a203faSVlad Serebrennikov const ObjCMethodDecl *MD = msg->getMethodDecl(); 118031a203faSVlad Serebrennikov for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) { 118131a203faSVlad Serebrennikov if (Expr *capturer = findCapturingExpr(SemaRef, msg->getArg(i), owner)) { 118231a203faSVlad Serebrennikov // noescape blocks should not be retained by the method. 118331a203faSVlad Serebrennikov if (MD && MD->parameters()[i]->hasAttr<NoEscapeAttr>()) 118431a203faSVlad Serebrennikov continue; 118531a203faSVlad Serebrennikov return diagnoseRetainCycle(SemaRef, capturer, owner); 118631a203faSVlad Serebrennikov } 118731a203faSVlad Serebrennikov } 118831a203faSVlad Serebrennikov } 118931a203faSVlad Serebrennikov 119031a203faSVlad Serebrennikov /// Check a property assign to see if it's likely to cause a retain cycle. 119131a203faSVlad Serebrennikov void SemaObjC::checkRetainCycles(Expr *receiver, Expr *argument) { 119231a203faSVlad Serebrennikov RetainCycleOwner owner; 119331a203faSVlad Serebrennikov if (!findRetainCycleOwner(SemaRef, receiver, owner)) 119431a203faSVlad Serebrennikov return; 119531a203faSVlad Serebrennikov 119631a203faSVlad Serebrennikov if (Expr *capturer = findCapturingExpr(SemaRef, argument, owner)) 119731a203faSVlad Serebrennikov diagnoseRetainCycle(SemaRef, capturer, owner); 119831a203faSVlad Serebrennikov } 119931a203faSVlad Serebrennikov 120031a203faSVlad Serebrennikov void SemaObjC::checkRetainCycles(VarDecl *Var, Expr *Init) { 120131a203faSVlad Serebrennikov RetainCycleOwner Owner; 120231a203faSVlad Serebrennikov if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner)) 120331a203faSVlad Serebrennikov return; 120431a203faSVlad Serebrennikov 120531a203faSVlad Serebrennikov // Because we don't have an expression for the variable, we have to set the 120631a203faSVlad Serebrennikov // location explicitly here. 120731a203faSVlad Serebrennikov Owner.Loc = Var->getLocation(); 120831a203faSVlad Serebrennikov Owner.Range = Var->getSourceRange(); 120931a203faSVlad Serebrennikov 121031a203faSVlad Serebrennikov if (Expr *Capturer = findCapturingExpr(SemaRef, Init, Owner)) 121131a203faSVlad Serebrennikov diagnoseRetainCycle(SemaRef, Capturer, Owner); 121231a203faSVlad Serebrennikov } 121331a203faSVlad Serebrennikov 121431a203faSVlad Serebrennikov /// CheckObjCString - Checks that the argument to the builtin 121531a203faSVlad Serebrennikov /// CFString constructor is correct 121631a203faSVlad Serebrennikov /// Note: It might also make sense to do the UTF-16 conversion here (would 121731a203faSVlad Serebrennikov /// simplify the backend). 121831a203faSVlad Serebrennikov bool SemaObjC::CheckObjCString(Expr *Arg) { 121931a203faSVlad Serebrennikov Arg = Arg->IgnoreParenCasts(); 122031a203faSVlad Serebrennikov StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); 122131a203faSVlad Serebrennikov 122231a203faSVlad Serebrennikov if (!Literal || !Literal->isOrdinary()) { 122331a203faSVlad Serebrennikov Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant) 122431a203faSVlad Serebrennikov << Arg->getSourceRange(); 122531a203faSVlad Serebrennikov return true; 122631a203faSVlad Serebrennikov } 122731a203faSVlad Serebrennikov 122831a203faSVlad Serebrennikov if (Literal->containsNonAsciiOrNull()) { 122931a203faSVlad Serebrennikov StringRef String = Literal->getString(); 123031a203faSVlad Serebrennikov unsigned NumBytes = String.size(); 123131a203faSVlad Serebrennikov SmallVector<llvm::UTF16, 128> ToBuf(NumBytes); 123231a203faSVlad Serebrennikov const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); 123331a203faSVlad Serebrennikov llvm::UTF16 *ToPtr = &ToBuf[0]; 123431a203faSVlad Serebrennikov 123531a203faSVlad Serebrennikov llvm::ConversionResult Result = 123631a203faSVlad Serebrennikov llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, 123731a203faSVlad Serebrennikov ToPtr + NumBytes, llvm::strictConversion); 123831a203faSVlad Serebrennikov // Check for conversion failure. 123931a203faSVlad Serebrennikov if (Result != llvm::conversionOK) 124031a203faSVlad Serebrennikov Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated) 124131a203faSVlad Serebrennikov << Arg->getSourceRange(); 124231a203faSVlad Serebrennikov } 124331a203faSVlad Serebrennikov return false; 124431a203faSVlad Serebrennikov } 124531a203faSVlad Serebrennikov 124631a203faSVlad Serebrennikov bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, 124731a203faSVlad Serebrennikov ArrayRef<const Expr *> Args) { 124831a203faSVlad Serebrennikov Sema::VariadicCallType CallType = 124931a203faSVlad Serebrennikov Method->isVariadic() ? Sema::VariadicMethod : Sema::VariadicDoesNotApply; 125031a203faSVlad Serebrennikov 125131a203faSVlad Serebrennikov SemaRef.checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args, 125231a203faSVlad Serebrennikov /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), 125331a203faSVlad Serebrennikov CallType); 125431a203faSVlad Serebrennikov 125531a203faSVlad Serebrennikov SemaRef.CheckTCBEnforcement(lbrac, Method); 125631a203faSVlad Serebrennikov 125731a203faSVlad Serebrennikov return false; 125831a203faSVlad Serebrennikov } 125931a203faSVlad Serebrennikov 126031a203faSVlad Serebrennikov const DeclContext *SemaObjC::getCurObjCLexicalContext() const { 126131a203faSVlad Serebrennikov const DeclContext *DC = SemaRef.getCurLexicalContext(); 126231a203faSVlad Serebrennikov // A category implicitly has the attribute of the interface. 126331a203faSVlad Serebrennikov if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC)) 126431a203faSVlad Serebrennikov DC = CatD->getClassInterface(); 126531a203faSVlad Serebrennikov return DC; 126631a203faSVlad Serebrennikov } 126731a203faSVlad Serebrennikov 126831a203faSVlad Serebrennikov /// Retrieve the identifier "NSError". 126931a203faSVlad Serebrennikov IdentifierInfo *SemaObjC::getNSErrorIdent() { 127031a203faSVlad Serebrennikov if (!Ident_NSError) 127131a203faSVlad Serebrennikov Ident_NSError = SemaRef.PP.getIdentifierInfo("NSError"); 127231a203faSVlad Serebrennikov 127331a203faSVlad Serebrennikov return Ident_NSError; 127431a203faSVlad Serebrennikov } 127531a203faSVlad Serebrennikov 127631a203faSVlad Serebrennikov void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) { 127731a203faSVlad Serebrennikov assert( 127831a203faSVlad Serebrennikov IDecl->getLexicalParent() == SemaRef.CurContext && 127931a203faSVlad Serebrennikov "The next DeclContext should be lexically contained in the current one."); 128031a203faSVlad Serebrennikov SemaRef.CurContext = IDecl; 128131a203faSVlad Serebrennikov } 128231a203faSVlad Serebrennikov 128331a203faSVlad Serebrennikov void SemaObjC::ActOnObjCContainerFinishDefinition() { 128431a203faSVlad Serebrennikov // Exit this scope of this interface definition. 128531a203faSVlad Serebrennikov SemaRef.PopDeclContext(); 128631a203faSVlad Serebrennikov } 128731a203faSVlad Serebrennikov 128831a203faSVlad Serebrennikov void SemaObjC::ActOnObjCTemporaryExitContainerContext( 128931a203faSVlad Serebrennikov ObjCContainerDecl *ObjCCtx) { 129031a203faSVlad Serebrennikov assert(ObjCCtx == SemaRef.CurContext && "Mismatch of container contexts"); 129131a203faSVlad Serebrennikov SemaRef.OriginalLexicalContext = ObjCCtx; 129231a203faSVlad Serebrennikov ActOnObjCContainerFinishDefinition(); 129331a203faSVlad Serebrennikov } 129431a203faSVlad Serebrennikov 129531a203faSVlad Serebrennikov void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) { 129631a203faSVlad Serebrennikov ActOnObjCContainerStartDefinition(ObjCCtx); 129731a203faSVlad Serebrennikov SemaRef.OriginalLexicalContext = nullptr; 129831a203faSVlad Serebrennikov } 129931a203faSVlad Serebrennikov 130031a203faSVlad Serebrennikov /// Find the protocol with the given name, if any. 130131a203faSVlad Serebrennikov ObjCProtocolDecl *SemaObjC::LookupProtocol(IdentifierInfo *II, 130231a203faSVlad Serebrennikov SourceLocation IdLoc, 130331a203faSVlad Serebrennikov RedeclarationKind Redecl) { 130431a203faSVlad Serebrennikov Decl *D = SemaRef.LookupSingleName(SemaRef.TUScope, II, IdLoc, 130531a203faSVlad Serebrennikov Sema::LookupObjCProtocolName, Redecl); 130631a203faSVlad Serebrennikov return cast_or_null<ObjCProtocolDecl>(D); 130731a203faSVlad Serebrennikov } 130831a203faSVlad Serebrennikov 130931a203faSVlad Serebrennikov /// Determine whether this is an Objective-C writeback conversion, 131031a203faSVlad Serebrennikov /// used for parameter passing when performing automatic reference counting. 131131a203faSVlad Serebrennikov /// 131231a203faSVlad Serebrennikov /// \param FromType The type we're converting form. 131331a203faSVlad Serebrennikov /// 131431a203faSVlad Serebrennikov /// \param ToType The type we're converting to. 131531a203faSVlad Serebrennikov /// 131631a203faSVlad Serebrennikov /// \param ConvertedType The type that will be produced after applying 131731a203faSVlad Serebrennikov /// this conversion. 131831a203faSVlad Serebrennikov bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType, 131931a203faSVlad Serebrennikov QualType &ConvertedType) { 132031a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 132131a203faSVlad Serebrennikov if (!getLangOpts().ObjCAutoRefCount || 132231a203faSVlad Serebrennikov Context.hasSameUnqualifiedType(FromType, ToType)) 132331a203faSVlad Serebrennikov return false; 132431a203faSVlad Serebrennikov 132531a203faSVlad Serebrennikov // Parameter must be a pointer to __autoreleasing (with no other qualifiers). 132631a203faSVlad Serebrennikov QualType ToPointee; 132731a203faSVlad Serebrennikov if (const PointerType *ToPointer = ToType->getAs<PointerType>()) 132831a203faSVlad Serebrennikov ToPointee = ToPointer->getPointeeType(); 132931a203faSVlad Serebrennikov else 133031a203faSVlad Serebrennikov return false; 133131a203faSVlad Serebrennikov 133231a203faSVlad Serebrennikov Qualifiers ToQuals = ToPointee.getQualifiers(); 133331a203faSVlad Serebrennikov if (!ToPointee->isObjCLifetimeType() || 133431a203faSVlad Serebrennikov ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || 133531a203faSVlad Serebrennikov !ToQuals.withoutObjCLifetime().empty()) 133631a203faSVlad Serebrennikov return false; 133731a203faSVlad Serebrennikov 133831a203faSVlad Serebrennikov // Argument must be a pointer to __strong to __weak. 133931a203faSVlad Serebrennikov QualType FromPointee; 134031a203faSVlad Serebrennikov if (const PointerType *FromPointer = FromType->getAs<PointerType>()) 134131a203faSVlad Serebrennikov FromPointee = FromPointer->getPointeeType(); 134231a203faSVlad Serebrennikov else 134331a203faSVlad Serebrennikov return false; 134431a203faSVlad Serebrennikov 134531a203faSVlad Serebrennikov Qualifiers FromQuals = FromPointee.getQualifiers(); 134631a203faSVlad Serebrennikov if (!FromPointee->isObjCLifetimeType() || 134731a203faSVlad Serebrennikov (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && 134831a203faSVlad Serebrennikov FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) 134931a203faSVlad Serebrennikov return false; 135031a203faSVlad Serebrennikov 135131a203faSVlad Serebrennikov // Make sure that we have compatible qualifiers. 135231a203faSVlad Serebrennikov FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); 1353*b9d678d2SJoseph Huber if (!ToQuals.compatiblyIncludes(FromQuals, getASTContext())) 135431a203faSVlad Serebrennikov return false; 135531a203faSVlad Serebrennikov 135631a203faSVlad Serebrennikov // Remove qualifiers from the pointee type we're converting from; they 135731a203faSVlad Serebrennikov // aren't used in the compatibility check belong, and we'll be adding back 135831a203faSVlad Serebrennikov // qualifiers (with __autoreleasing) if the compatibility check succeeds. 135931a203faSVlad Serebrennikov FromPointee = FromPointee.getUnqualifiedType(); 136031a203faSVlad Serebrennikov 136131a203faSVlad Serebrennikov // The unqualified form of the pointee types must be compatible. 136231a203faSVlad Serebrennikov ToPointee = ToPointee.getUnqualifiedType(); 136331a203faSVlad Serebrennikov bool IncompatibleObjC; 136431a203faSVlad Serebrennikov if (Context.typesAreCompatible(FromPointee, ToPointee)) 136531a203faSVlad Serebrennikov FromPointee = ToPointee; 136631a203faSVlad Serebrennikov else if (!SemaRef.isObjCPointerConversion(FromPointee, ToPointee, FromPointee, 136731a203faSVlad Serebrennikov IncompatibleObjC)) 136831a203faSVlad Serebrennikov return false; 136931a203faSVlad Serebrennikov 137031a203faSVlad Serebrennikov /// Construct the type we're converting to, which is a pointer to 137131a203faSVlad Serebrennikov /// __autoreleasing pointee. 137231a203faSVlad Serebrennikov FromPointee = Context.getQualifiedType(FromPointee, FromQuals); 137331a203faSVlad Serebrennikov ConvertedType = Context.getPointerType(FromPointee); 137431a203faSVlad Serebrennikov return true; 137531a203faSVlad Serebrennikov } 137631a203faSVlad Serebrennikov 137731a203faSVlad Serebrennikov /// CheckSubscriptingKind - This routine decide what type 137831a203faSVlad Serebrennikov /// of indexing represented by "FromE" is being done. 137931a203faSVlad Serebrennikov SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) { 138031a203faSVlad Serebrennikov // If the expression already has integral or enumeration type, we're golden. 138131a203faSVlad Serebrennikov QualType T = FromE->getType(); 138231a203faSVlad Serebrennikov if (T->isIntegralOrEnumerationType()) 138331a203faSVlad Serebrennikov return SemaObjC::OS_Array; 138431a203faSVlad Serebrennikov 138531a203faSVlad Serebrennikov // If we don't have a class type in C++, there's no way we can get an 138631a203faSVlad Serebrennikov // expression of integral or enumeration type. 138731a203faSVlad Serebrennikov const RecordType *RecordTy = T->getAs<RecordType>(); 138831a203faSVlad Serebrennikov if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType())) 138931a203faSVlad Serebrennikov // All other scalar cases are assumed to be dictionary indexing which 139031a203faSVlad Serebrennikov // caller handles, with diagnostics if needed. 139131a203faSVlad Serebrennikov return SemaObjC::OS_Dictionary; 139231a203faSVlad Serebrennikov if (!getLangOpts().CPlusPlus || !RecordTy || RecordTy->isIncompleteType()) { 139331a203faSVlad Serebrennikov // No indexing can be done. Issue diagnostics and quit. 139431a203faSVlad Serebrennikov const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); 139531a203faSVlad Serebrennikov if (isa<StringLiteral>(IndexExpr)) 139631a203faSVlad Serebrennikov Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) 139731a203faSVlad Serebrennikov << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); 139831a203faSVlad Serebrennikov else 139931a203faSVlad Serebrennikov Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) << T; 140031a203faSVlad Serebrennikov return SemaObjC::OS_Error; 140131a203faSVlad Serebrennikov } 140231a203faSVlad Serebrennikov 140331a203faSVlad Serebrennikov // We must have a complete class type. 140431a203faSVlad Serebrennikov if (SemaRef.RequireCompleteType(FromE->getExprLoc(), T, 140531a203faSVlad Serebrennikov diag::err_objc_index_incomplete_class_type, 140631a203faSVlad Serebrennikov FromE)) 140731a203faSVlad Serebrennikov return SemaObjC::OS_Error; 140831a203faSVlad Serebrennikov 140931a203faSVlad Serebrennikov // Look for a conversion to an integral, enumeration type, or 141031a203faSVlad Serebrennikov // objective-C pointer type. 141131a203faSVlad Serebrennikov int NoIntegrals = 0, NoObjCIdPointers = 0; 141231a203faSVlad Serebrennikov SmallVector<CXXConversionDecl *, 4> ConversionDecls; 141331a203faSVlad Serebrennikov 141431a203faSVlad Serebrennikov for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl()) 141531a203faSVlad Serebrennikov ->getVisibleConversionFunctions()) { 141631a203faSVlad Serebrennikov if (CXXConversionDecl *Conversion = 141731a203faSVlad Serebrennikov dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) { 141831a203faSVlad Serebrennikov QualType CT = Conversion->getConversionType().getNonReferenceType(); 141931a203faSVlad Serebrennikov if (CT->isIntegralOrEnumerationType()) { 142031a203faSVlad Serebrennikov ++NoIntegrals; 142131a203faSVlad Serebrennikov ConversionDecls.push_back(Conversion); 142231a203faSVlad Serebrennikov } else if (CT->isObjCIdType() || CT->isBlockPointerType()) { 142331a203faSVlad Serebrennikov ++NoObjCIdPointers; 142431a203faSVlad Serebrennikov ConversionDecls.push_back(Conversion); 142531a203faSVlad Serebrennikov } 142631a203faSVlad Serebrennikov } 142731a203faSVlad Serebrennikov } 142831a203faSVlad Serebrennikov if (NoIntegrals == 1 && NoObjCIdPointers == 0) 142931a203faSVlad Serebrennikov return SemaObjC::OS_Array; 143031a203faSVlad Serebrennikov if (NoIntegrals == 0 && NoObjCIdPointers == 1) 143131a203faSVlad Serebrennikov return SemaObjC::OS_Dictionary; 143231a203faSVlad Serebrennikov if (NoIntegrals == 0 && NoObjCIdPointers == 0) { 143331a203faSVlad Serebrennikov // No conversion function was found. Issue diagnostic and return. 143431a203faSVlad Serebrennikov Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 143531a203faSVlad Serebrennikov << FromE->getType(); 143631a203faSVlad Serebrennikov return SemaObjC::OS_Error; 143731a203faSVlad Serebrennikov } 143831a203faSVlad Serebrennikov Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) 143931a203faSVlad Serebrennikov << FromE->getType(); 144031a203faSVlad Serebrennikov for (unsigned int i = 0; i < ConversionDecls.size(); i++) 144131a203faSVlad Serebrennikov Diag(ConversionDecls[i]->getLocation(), 144231a203faSVlad Serebrennikov diag::note_conv_function_declared_at); 144331a203faSVlad Serebrennikov 144431a203faSVlad Serebrennikov return SemaObjC::OS_Error; 144531a203faSVlad Serebrennikov } 144631a203faSVlad Serebrennikov 144731a203faSVlad Serebrennikov void SemaObjC::AddCFAuditedAttribute(Decl *D) { 144831a203faSVlad Serebrennikov ASTContext &Context = getASTContext(); 144931a203faSVlad Serebrennikov IdentifierInfo *Ident; 145031a203faSVlad Serebrennikov SourceLocation Loc; 145131a203faSVlad Serebrennikov std::tie(Ident, Loc) = SemaRef.PP.getPragmaARCCFCodeAuditedInfo(); 145231a203faSVlad Serebrennikov if (!Loc.isValid()) 145331a203faSVlad Serebrennikov return; 145431a203faSVlad Serebrennikov 145531a203faSVlad Serebrennikov // Don't add a redundant or conflicting attribute. 145631a203faSVlad Serebrennikov if (D->hasAttr<CFAuditedTransferAttr>() || 145731a203faSVlad Serebrennikov D->hasAttr<CFUnknownTransferAttr>()) 145831a203faSVlad Serebrennikov return; 145931a203faSVlad Serebrennikov 146031a203faSVlad Serebrennikov AttributeCommonInfo Info(Ident, SourceRange(Loc), 146131a203faSVlad Serebrennikov AttributeCommonInfo::Form::Pragma()); 146231a203faSVlad Serebrennikov D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info)); 146331a203faSVlad Serebrennikov } 146431a203faSVlad Serebrennikov 146531a203faSVlad Serebrennikov bool SemaObjC::isCFError(RecordDecl *RD) { 146631a203faSVlad Serebrennikov // If we already know about CFError, test it directly. 146731a203faSVlad Serebrennikov if (CFError) 146831a203faSVlad Serebrennikov return CFError == RD; 146931a203faSVlad Serebrennikov 147031a203faSVlad Serebrennikov // Check whether this is CFError, which we identify based on its bridge to 147131a203faSVlad Serebrennikov // NSError. CFErrorRef used to be declared with "objc_bridge" but is now 147231a203faSVlad Serebrennikov // declared with "objc_bridge_mutable", so look for either one of the two 147331a203faSVlad Serebrennikov // attributes. 147431a203faSVlad Serebrennikov if (RD->getTagKind() == TagTypeKind::Struct) { 147531a203faSVlad Serebrennikov IdentifierInfo *bridgedType = nullptr; 147631a203faSVlad Serebrennikov if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>()) 147731a203faSVlad Serebrennikov bridgedType = bridgeAttr->getBridgedType(); 147831a203faSVlad Serebrennikov else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>()) 147931a203faSVlad Serebrennikov bridgedType = bridgeAttr->getBridgedType(); 148031a203faSVlad Serebrennikov 148131a203faSVlad Serebrennikov if (bridgedType == getNSErrorIdent()) { 148231a203faSVlad Serebrennikov CFError = RD; 148331a203faSVlad Serebrennikov return true; 148431a203faSVlad Serebrennikov } 148531a203faSVlad Serebrennikov } 148631a203faSVlad Serebrennikov 148731a203faSVlad Serebrennikov return false; 148831a203faSVlad Serebrennikov } 148931a203faSVlad Serebrennikov 14906b755b0cSVlad Serebrennikov bool SemaObjC::isNSStringType(QualType T, bool AllowNSAttributedString) { 14916b755b0cSVlad Serebrennikov const auto *PT = T->getAs<ObjCObjectPointerType>(); 14926b755b0cSVlad Serebrennikov if (!PT) 14936b755b0cSVlad Serebrennikov return false; 14946b755b0cSVlad Serebrennikov 14956b755b0cSVlad Serebrennikov ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); 14966b755b0cSVlad Serebrennikov if (!Cls) 14976b755b0cSVlad Serebrennikov return false; 14986b755b0cSVlad Serebrennikov 14996b755b0cSVlad Serebrennikov IdentifierInfo *ClsName = Cls->getIdentifier(); 15006b755b0cSVlad Serebrennikov 15016b755b0cSVlad Serebrennikov if (AllowNSAttributedString && 15026b755b0cSVlad Serebrennikov ClsName == &getASTContext().Idents.get("NSAttributedString")) 15036b755b0cSVlad Serebrennikov return true; 15046b755b0cSVlad Serebrennikov // FIXME: Should we walk the chain of classes? 15056b755b0cSVlad Serebrennikov return ClsName == &getASTContext().Idents.get("NSString") || 15066b755b0cSVlad Serebrennikov ClsName == &getASTContext().Idents.get("NSMutableString"); 15076b755b0cSVlad Serebrennikov } 15086b755b0cSVlad Serebrennikov 15096b755b0cSVlad Serebrennikov bool SemaObjC::isCFStringType(QualType T) { 15106b755b0cSVlad Serebrennikov const auto *PT = T->getAs<PointerType>(); 15116b755b0cSVlad Serebrennikov if (!PT) 15126b755b0cSVlad Serebrennikov return false; 15136b755b0cSVlad Serebrennikov 15146b755b0cSVlad Serebrennikov const auto *RT = PT->getPointeeType()->getAs<RecordType>(); 15156b755b0cSVlad Serebrennikov if (!RT) 15166b755b0cSVlad Serebrennikov return false; 15176b755b0cSVlad Serebrennikov 15186b755b0cSVlad Serebrennikov const RecordDecl *RD = RT->getDecl(); 15196b755b0cSVlad Serebrennikov if (RD->getTagKind() != TagTypeKind::Struct) 15206b755b0cSVlad Serebrennikov return false; 15216b755b0cSVlad Serebrennikov 15226b755b0cSVlad Serebrennikov return RD->getIdentifier() == &getASTContext().Idents.get("__CFString"); 15236b755b0cSVlad Serebrennikov } 15246b755b0cSVlad Serebrennikov 15256b755b0cSVlad Serebrennikov static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { 15266b755b0cSVlad Serebrennikov // The IBOutlet/IBOutletCollection attributes only apply to instance 15276b755b0cSVlad Serebrennikov // variables or properties of Objective-C classes. The outlet must also 15286b755b0cSVlad Serebrennikov // have an object reference type. 15296b755b0cSVlad Serebrennikov if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) { 15306b755b0cSVlad Serebrennikov if (!VD->getType()->getAs<ObjCObjectPointerType>()) { 15316b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) 15326b755b0cSVlad Serebrennikov << AL << VD->getType() << 0; 15336b755b0cSVlad Serebrennikov return false; 15346b755b0cSVlad Serebrennikov } 15356b755b0cSVlad Serebrennikov } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { 15366b755b0cSVlad Serebrennikov if (!PD->getType()->getAs<ObjCObjectPointerType>()) { 15376b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) 15386b755b0cSVlad Serebrennikov << AL << PD->getType() << 1; 15396b755b0cSVlad Serebrennikov return false; 15406b755b0cSVlad Serebrennikov } 15416b755b0cSVlad Serebrennikov } else { 15426b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL; 15436b755b0cSVlad Serebrennikov return false; 15446b755b0cSVlad Serebrennikov } 15456b755b0cSVlad Serebrennikov 15466b755b0cSVlad Serebrennikov return true; 15476b755b0cSVlad Serebrennikov } 15486b755b0cSVlad Serebrennikov 15496b755b0cSVlad Serebrennikov void SemaObjC::handleIBOutlet(Decl *D, const ParsedAttr &AL) { 15506b755b0cSVlad Serebrennikov if (!checkIBOutletCommon(SemaRef, D, AL)) 15516b755b0cSVlad Serebrennikov return; 15526b755b0cSVlad Serebrennikov 15536b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) IBOutletAttr(getASTContext(), AL)); 15546b755b0cSVlad Serebrennikov } 15556b755b0cSVlad Serebrennikov 15566b755b0cSVlad Serebrennikov void SemaObjC::handleIBOutletCollection(Decl *D, const ParsedAttr &AL) { 15576b755b0cSVlad Serebrennikov 15586b755b0cSVlad Serebrennikov ASTContext &Context = getASTContext(); 15596b755b0cSVlad Serebrennikov // The iboutletcollection attribute can have zero or one arguments. 15606b755b0cSVlad Serebrennikov if (AL.getNumArgs() > 1) { 15616b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; 15626b755b0cSVlad Serebrennikov return; 15636b755b0cSVlad Serebrennikov } 15646b755b0cSVlad Serebrennikov 15656b755b0cSVlad Serebrennikov if (!checkIBOutletCommon(SemaRef, D, AL)) 15666b755b0cSVlad Serebrennikov return; 15676b755b0cSVlad Serebrennikov 15686b755b0cSVlad Serebrennikov ParsedType PT; 15696b755b0cSVlad Serebrennikov 15706b755b0cSVlad Serebrennikov if (AL.hasParsedType()) 15716b755b0cSVlad Serebrennikov PT = AL.getTypeArg(); 15726b755b0cSVlad Serebrennikov else { 15736b755b0cSVlad Serebrennikov PT = SemaRef.getTypeName( 15746b755b0cSVlad Serebrennikov Context.Idents.get("NSObject"), AL.getLoc(), 15756b755b0cSVlad Serebrennikov SemaRef.getScopeForContext(D->getDeclContext()->getParent())); 15766b755b0cSVlad Serebrennikov if (!PT) { 15776b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; 15786b755b0cSVlad Serebrennikov return; 15796b755b0cSVlad Serebrennikov } 15806b755b0cSVlad Serebrennikov } 15816b755b0cSVlad Serebrennikov 15826b755b0cSVlad Serebrennikov TypeSourceInfo *QTLoc = nullptr; 15836b755b0cSVlad Serebrennikov QualType QT = SemaRef.GetTypeFromParser(PT, &QTLoc); 15846b755b0cSVlad Serebrennikov if (!QTLoc) 15856b755b0cSVlad Serebrennikov QTLoc = Context.getTrivialTypeSourceInfo(QT, AL.getLoc()); 15866b755b0cSVlad Serebrennikov 15876b755b0cSVlad Serebrennikov // Diagnose use of non-object type in iboutletcollection attribute. 15886b755b0cSVlad Serebrennikov // FIXME. Gnu attribute extension ignores use of builtin types in 15896b755b0cSVlad Serebrennikov // attributes. So, __attribute__((iboutletcollection(char))) will be 15906b755b0cSVlad Serebrennikov // treated as __attribute__((iboutletcollection())). 15916b755b0cSVlad Serebrennikov if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { 15926b755b0cSVlad Serebrennikov Diag(AL.getLoc(), QT->isBuiltinType() 15936b755b0cSVlad Serebrennikov ? diag::err_iboutletcollection_builtintype 15946b755b0cSVlad Serebrennikov : diag::err_iboutletcollection_type) 15956b755b0cSVlad Serebrennikov << QT; 15966b755b0cSVlad Serebrennikov return; 15976b755b0cSVlad Serebrennikov } 15986b755b0cSVlad Serebrennikov 15996b755b0cSVlad Serebrennikov D->addAttr(::new (Context) IBOutletCollectionAttr(Context, AL, QTLoc)); 16006b755b0cSVlad Serebrennikov } 16016b755b0cSVlad Serebrennikov 16026b755b0cSVlad Serebrennikov void SemaObjC::handleSuppresProtocolAttr(Decl *D, const ParsedAttr &AL) { 16036b755b0cSVlad Serebrennikov if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) { 16046b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition) 16056b755b0cSVlad Serebrennikov << AL << AL.getRange(); 16066b755b0cSVlad Serebrennikov return; 16076b755b0cSVlad Serebrennikov } 16086b755b0cSVlad Serebrennikov 16096b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 16106b755b0cSVlad Serebrennikov ObjCExplicitProtocolImplAttr(getASTContext(), AL)); 16116b755b0cSVlad Serebrennikov } 16126b755b0cSVlad Serebrennikov 16136b755b0cSVlad Serebrennikov void SemaObjC::handleDirectAttr(Decl *D, const ParsedAttr &AL) { 16146b755b0cSVlad Serebrennikov // objc_direct cannot be set on methods declared in the context of a protocol 16156b755b0cSVlad Serebrennikov if (isa<ObjCProtocolDecl>(D->getDeclContext())) { 16166b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false; 16176b755b0cSVlad Serebrennikov return; 16186b755b0cSVlad Serebrennikov } 16196b755b0cSVlad Serebrennikov 16206b755b0cSVlad Serebrennikov if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) { 16216b755b0cSVlad Serebrennikov handleSimpleAttribute<ObjCDirectAttr>(*this, D, AL); 16226b755b0cSVlad Serebrennikov } else { 16236b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; 16246b755b0cSVlad Serebrennikov } 16256b755b0cSVlad Serebrennikov } 16266b755b0cSVlad Serebrennikov 16276b755b0cSVlad Serebrennikov void SemaObjC::handleDirectMembersAttr(Decl *D, const ParsedAttr &AL) { 16286b755b0cSVlad Serebrennikov if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) { 16296b755b0cSVlad Serebrennikov handleSimpleAttribute<ObjCDirectMembersAttr>(*this, D, AL); 16306b755b0cSVlad Serebrennikov } else { 16316b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; 16326b755b0cSVlad Serebrennikov } 16336b755b0cSVlad Serebrennikov } 16346b755b0cSVlad Serebrennikov 16356b755b0cSVlad Serebrennikov void SemaObjC::handleMethodFamilyAttr(Decl *D, const ParsedAttr &AL) { 16366b755b0cSVlad Serebrennikov const auto *M = cast<ObjCMethodDecl>(D); 16376b755b0cSVlad Serebrennikov if (!AL.isArgIdent(0)) { 16386b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 16396b755b0cSVlad Serebrennikov << AL << 1 << AANT_ArgumentIdentifier; 16406b755b0cSVlad Serebrennikov return; 16416b755b0cSVlad Serebrennikov } 16426b755b0cSVlad Serebrennikov 16436b755b0cSVlad Serebrennikov IdentifierLoc *IL = AL.getArgAsIdent(0); 16446b755b0cSVlad Serebrennikov ObjCMethodFamilyAttr::FamilyKind F; 16456b755b0cSVlad Serebrennikov if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { 16466b755b0cSVlad Serebrennikov Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident; 16476b755b0cSVlad Serebrennikov return; 16486b755b0cSVlad Serebrennikov } 16496b755b0cSVlad Serebrennikov 16506b755b0cSVlad Serebrennikov if (F == ObjCMethodFamilyAttr::OMF_init && 16516b755b0cSVlad Serebrennikov !M->getReturnType()->isObjCObjectPointerType()) { 16526b755b0cSVlad Serebrennikov Diag(M->getLocation(), diag::err_init_method_bad_return_type) 16536b755b0cSVlad Serebrennikov << M->getReturnType(); 16546b755b0cSVlad Serebrennikov // Ignore the attribute. 16556b755b0cSVlad Serebrennikov return; 16566b755b0cSVlad Serebrennikov } 16576b755b0cSVlad Serebrennikov 16586b755b0cSVlad Serebrennikov D->addAttr(new (getASTContext()) 16596b755b0cSVlad Serebrennikov ObjCMethodFamilyAttr(getASTContext(), AL, F)); 16606b755b0cSVlad Serebrennikov } 16616b755b0cSVlad Serebrennikov 16626b755b0cSVlad Serebrennikov void SemaObjC::handleNSObject(Decl *D, const ParsedAttr &AL) { 16636b755b0cSVlad Serebrennikov if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { 16646b755b0cSVlad Serebrennikov QualType T = TD->getUnderlyingType(); 16656b755b0cSVlad Serebrennikov if (!T->isCARCBridgableType()) { 16666b755b0cSVlad Serebrennikov Diag(TD->getLocation(), diag::err_nsobject_attribute); 16676b755b0cSVlad Serebrennikov return; 16686b755b0cSVlad Serebrennikov } 16696b755b0cSVlad Serebrennikov } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { 16706b755b0cSVlad Serebrennikov QualType T = PD->getType(); 16716b755b0cSVlad Serebrennikov if (!T->isCARCBridgableType()) { 16726b755b0cSVlad Serebrennikov Diag(PD->getLocation(), diag::err_nsobject_attribute); 16736b755b0cSVlad Serebrennikov return; 16746b755b0cSVlad Serebrennikov } 16756b755b0cSVlad Serebrennikov } else { 16766b755b0cSVlad Serebrennikov // It is okay to include this attribute on properties, e.g.: 16776b755b0cSVlad Serebrennikov // 16786b755b0cSVlad Serebrennikov // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); 16796b755b0cSVlad Serebrennikov // 16806b755b0cSVlad Serebrennikov // In this case it follows tradition and suppresses an error in the above 16816b755b0cSVlad Serebrennikov // case. 16826b755b0cSVlad Serebrennikov Diag(D->getLocation(), diag::warn_nsobject_attribute); 16836b755b0cSVlad Serebrennikov } 16846b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) ObjCNSObjectAttr(getASTContext(), AL)); 16856b755b0cSVlad Serebrennikov } 16866b755b0cSVlad Serebrennikov 16876b755b0cSVlad Serebrennikov void SemaObjC::handleIndependentClass(Decl *D, const ParsedAttr &AL) { 16886b755b0cSVlad Serebrennikov if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { 16896b755b0cSVlad Serebrennikov QualType T = TD->getUnderlyingType(); 16906b755b0cSVlad Serebrennikov if (!T->isObjCObjectPointerType()) { 16916b755b0cSVlad Serebrennikov Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute); 16926b755b0cSVlad Serebrennikov return; 16936b755b0cSVlad Serebrennikov } 16946b755b0cSVlad Serebrennikov } else { 16956b755b0cSVlad Serebrennikov Diag(D->getLocation(), diag::warn_independentclass_attribute); 16966b755b0cSVlad Serebrennikov return; 16976b755b0cSVlad Serebrennikov } 16986b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 16996b755b0cSVlad Serebrennikov ObjCIndependentClassAttr(getASTContext(), AL)); 17006b755b0cSVlad Serebrennikov } 17016b755b0cSVlad Serebrennikov 17026b755b0cSVlad Serebrennikov void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) { 17036b755b0cSVlad Serebrennikov if (!AL.isArgIdent(0)) { 17046b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 17056b755b0cSVlad Serebrennikov << AL << 1 << AANT_ArgumentIdentifier; 17066b755b0cSVlad Serebrennikov return; 17076b755b0cSVlad Serebrennikov } 17086b755b0cSVlad Serebrennikov 17096b755b0cSVlad Serebrennikov IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 17106b755b0cSVlad Serebrennikov BlocksAttr::BlockType type; 17116b755b0cSVlad Serebrennikov if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { 17126b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; 17136b755b0cSVlad Serebrennikov return; 17146b755b0cSVlad Serebrennikov } 17156b755b0cSVlad Serebrennikov 17166b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) BlocksAttr(getASTContext(), AL, type)); 17176b755b0cSVlad Serebrennikov } 17186b755b0cSVlad Serebrennikov 17196b755b0cSVlad Serebrennikov static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) { 17206b755b0cSVlad Serebrennikov return QT->isDependentType() || QT->isObjCRetainableType(); 17216b755b0cSVlad Serebrennikov } 17226b755b0cSVlad Serebrennikov 17236b755b0cSVlad Serebrennikov static bool isValidSubjectOfNSAttribute(QualType QT) { 17246b755b0cSVlad Serebrennikov return QT->isDependentType() || QT->isObjCObjectPointerType() || 17256b755b0cSVlad Serebrennikov QT->isObjCNSObjectType(); 17266b755b0cSVlad Serebrennikov } 17276b755b0cSVlad Serebrennikov 17286b755b0cSVlad Serebrennikov static bool isValidSubjectOfCFAttribute(QualType QT) { 17296b755b0cSVlad Serebrennikov return QT->isDependentType() || QT->isPointerType() || 17306b755b0cSVlad Serebrennikov isValidSubjectOfNSAttribute(QT); 17316b755b0cSVlad Serebrennikov } 17326b755b0cSVlad Serebrennikov 17336b755b0cSVlad Serebrennikov static bool isValidSubjectOfOSAttribute(QualType QT) { 17346b755b0cSVlad Serebrennikov if (QT->isDependentType()) 17356b755b0cSVlad Serebrennikov return true; 17366b755b0cSVlad Serebrennikov QualType PT = QT->getPointeeType(); 17376b755b0cSVlad Serebrennikov return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr; 17386b755b0cSVlad Serebrennikov } 17396b755b0cSVlad Serebrennikov 17406b755b0cSVlad Serebrennikov void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI, 17416b755b0cSVlad Serebrennikov Sema::RetainOwnershipKind K, 17426b755b0cSVlad Serebrennikov bool IsTemplateInstantiation) { 17436b755b0cSVlad Serebrennikov ValueDecl *VD = cast<ValueDecl>(D); 17446b755b0cSVlad Serebrennikov switch (K) { 17456b755b0cSVlad Serebrennikov case Sema::RetainOwnershipKind::OS: 17466b755b0cSVlad Serebrennikov handleSimpleAttributeOrDiagnose<OSConsumedAttr>( 17476b755b0cSVlad Serebrennikov *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()), 17486b755b0cSVlad Serebrennikov diag::warn_ns_attribute_wrong_parameter_type, 17496b755b0cSVlad Serebrennikov /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1); 17506b755b0cSVlad Serebrennikov return; 17516b755b0cSVlad Serebrennikov case Sema::RetainOwnershipKind::NS: 17526b755b0cSVlad Serebrennikov handleSimpleAttributeOrDiagnose<NSConsumedAttr>( 17536b755b0cSVlad Serebrennikov *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()), 17546b755b0cSVlad Serebrennikov 17556b755b0cSVlad Serebrennikov // These attributes are normally just advisory, but in ARC, ns_consumed 17566b755b0cSVlad Serebrennikov // is significant. Allow non-dependent code to contain inappropriate 17576b755b0cSVlad Serebrennikov // attributes even in ARC, but require template instantiations to be 17586b755b0cSVlad Serebrennikov // set up correctly. 17596b755b0cSVlad Serebrennikov ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount) 17606b755b0cSVlad Serebrennikov ? diag::err_ns_attribute_wrong_parameter_type 17616b755b0cSVlad Serebrennikov : diag::warn_ns_attribute_wrong_parameter_type), 17626b755b0cSVlad Serebrennikov /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0); 17636b755b0cSVlad Serebrennikov return; 17646b755b0cSVlad Serebrennikov case Sema::RetainOwnershipKind::CF: 17656b755b0cSVlad Serebrennikov handleSimpleAttributeOrDiagnose<CFConsumedAttr>( 17666b755b0cSVlad Serebrennikov *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()), 17676b755b0cSVlad Serebrennikov diag::warn_ns_attribute_wrong_parameter_type, 17686b755b0cSVlad Serebrennikov /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1); 17696b755b0cSVlad Serebrennikov return; 17706b755b0cSVlad Serebrennikov } 17716b755b0cSVlad Serebrennikov } 17726b755b0cSVlad Serebrennikov 17736b755b0cSVlad Serebrennikov Sema::RetainOwnershipKind 17746b755b0cSVlad Serebrennikov SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) { 17756b755b0cSVlad Serebrennikov switch (AL.getKind()) { 17766b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFConsumed: 17776b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsRetained: 17786b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsNotRetained: 17796b755b0cSVlad Serebrennikov return Sema::RetainOwnershipKind::CF; 17806b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSConsumesThis: 17816b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSConsumed: 17826b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsRetained: 17836b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsNotRetained: 17846b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsRetainedOnZero: 17856b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsRetainedOnNonZero: 17866b755b0cSVlad Serebrennikov return Sema::RetainOwnershipKind::OS; 17876b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSConsumesSelf: 17886b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSConsumed: 17896b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsRetained: 17906b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsNotRetained: 17916b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsAutoreleased: 17926b755b0cSVlad Serebrennikov return Sema::RetainOwnershipKind::NS; 17936b755b0cSVlad Serebrennikov default: 17946b755b0cSVlad Serebrennikov llvm_unreachable("Wrong argument supplied"); 17956b755b0cSVlad Serebrennikov } 17966b755b0cSVlad Serebrennikov } 17976b755b0cSVlad Serebrennikov 17986b755b0cSVlad Serebrennikov bool SemaObjC::checkNSReturnsRetainedReturnType(SourceLocation Loc, 17996b755b0cSVlad Serebrennikov QualType QT) { 18006b755b0cSVlad Serebrennikov if (isValidSubjectOfNSReturnsRetainedAttribute(QT)) 18016b755b0cSVlad Serebrennikov return false; 18026b755b0cSVlad Serebrennikov 18036b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_ns_attribute_wrong_return_type) 18046b755b0cSVlad Serebrennikov << "'ns_returns_retained'" << 0 << 0; 18056b755b0cSVlad Serebrennikov return true; 18066b755b0cSVlad Serebrennikov } 18076b755b0cSVlad Serebrennikov 18086b755b0cSVlad Serebrennikov /// \return whether the parameter is a pointer to OSObject pointer. 18096b755b0cSVlad Serebrennikov bool SemaObjC::isValidOSObjectOutParameter(const Decl *D) { 18106b755b0cSVlad Serebrennikov const auto *PVD = dyn_cast<ParmVarDecl>(D); 18116b755b0cSVlad Serebrennikov if (!PVD) 18126b755b0cSVlad Serebrennikov return false; 18136b755b0cSVlad Serebrennikov QualType QT = PVD->getType(); 18146b755b0cSVlad Serebrennikov QualType PT = QT->getPointeeType(); 18156b755b0cSVlad Serebrennikov return !PT.isNull() && isValidSubjectOfOSAttribute(PT); 18166b755b0cSVlad Serebrennikov } 18176b755b0cSVlad Serebrennikov 18186b755b0cSVlad Serebrennikov void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) { 18196b755b0cSVlad Serebrennikov QualType ReturnType; 18206b755b0cSVlad Serebrennikov Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL); 18216b755b0cSVlad Serebrennikov 18226b755b0cSVlad Serebrennikov if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 18236b755b0cSVlad Serebrennikov ReturnType = MD->getReturnType(); 18246b755b0cSVlad Serebrennikov } else if (getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && 18256b755b0cSVlad Serebrennikov (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) { 18266b755b0cSVlad Serebrennikov return; // ignore: was handled as a type attribute 18276b755b0cSVlad Serebrennikov } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { 18286b755b0cSVlad Serebrennikov ReturnType = PD->getType(); 18296b755b0cSVlad Serebrennikov } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 18306b755b0cSVlad Serebrennikov ReturnType = FD->getReturnType(); 18316b755b0cSVlad Serebrennikov } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) { 18326b755b0cSVlad Serebrennikov // Attributes on parameters are used for out-parameters, 18336b755b0cSVlad Serebrennikov // passed as pointers-to-pointers. 18346b755b0cSVlad Serebrennikov unsigned DiagID = K == Sema::RetainOwnershipKind::CF 18356b755b0cSVlad Serebrennikov ? /*pointer-to-CF-pointer*/ 2 18366b755b0cSVlad Serebrennikov : /*pointer-to-OSObject-pointer*/ 3; 18376b755b0cSVlad Serebrennikov ReturnType = Param->getType()->getPointeeType(); 18386b755b0cSVlad Serebrennikov if (ReturnType.isNull()) { 18396b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) 18406b755b0cSVlad Serebrennikov << AL << DiagID << AL.getRange(); 18416b755b0cSVlad Serebrennikov return; 18426b755b0cSVlad Serebrennikov } 18436b755b0cSVlad Serebrennikov } else if (AL.isUsedAsTypeAttr()) { 18446b755b0cSVlad Serebrennikov return; 18456b755b0cSVlad Serebrennikov } else { 18466b755b0cSVlad Serebrennikov AttributeDeclKind ExpectedDeclKind; 18476b755b0cSVlad Serebrennikov switch (AL.getKind()) { 18486b755b0cSVlad Serebrennikov default: 18496b755b0cSVlad Serebrennikov llvm_unreachable("invalid ownership attribute"); 18506b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsRetained: 18516b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsAutoreleased: 18526b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsNotRetained: 18536b755b0cSVlad Serebrennikov ExpectedDeclKind = ExpectedFunctionOrMethod; 18546b755b0cSVlad Serebrennikov break; 18556b755b0cSVlad Serebrennikov 18566b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsRetained: 18576b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsNotRetained: 18586b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsRetained: 18596b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsNotRetained: 18606b755b0cSVlad Serebrennikov ExpectedDeclKind = ExpectedFunctionMethodOrParameter; 18616b755b0cSVlad Serebrennikov break; 18626b755b0cSVlad Serebrennikov } 18636b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type) 18646b755b0cSVlad Serebrennikov << AL.getRange() << AL << AL.isRegularKeywordAttribute() 18656b755b0cSVlad Serebrennikov << ExpectedDeclKind; 18666b755b0cSVlad Serebrennikov return; 18676b755b0cSVlad Serebrennikov } 18686b755b0cSVlad Serebrennikov 18696b755b0cSVlad Serebrennikov bool TypeOK; 18706b755b0cSVlad Serebrennikov bool Cf; 18716b755b0cSVlad Serebrennikov unsigned ParmDiagID = 2; // Pointer-to-CF-pointer 18726b755b0cSVlad Serebrennikov switch (AL.getKind()) { 18736b755b0cSVlad Serebrennikov default: 18746b755b0cSVlad Serebrennikov llvm_unreachable("invalid ownership attribute"); 18756b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsRetained: 18766b755b0cSVlad Serebrennikov TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType); 18776b755b0cSVlad Serebrennikov Cf = false; 18786b755b0cSVlad Serebrennikov break; 18796b755b0cSVlad Serebrennikov 18806b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsAutoreleased: 18816b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsNotRetained: 18826b755b0cSVlad Serebrennikov TypeOK = isValidSubjectOfNSAttribute(ReturnType); 18836b755b0cSVlad Serebrennikov Cf = false; 18846b755b0cSVlad Serebrennikov break; 18856b755b0cSVlad Serebrennikov 18866b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsRetained: 18876b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsNotRetained: 18886b755b0cSVlad Serebrennikov TypeOK = isValidSubjectOfCFAttribute(ReturnType); 18896b755b0cSVlad Serebrennikov Cf = true; 18906b755b0cSVlad Serebrennikov break; 18916b755b0cSVlad Serebrennikov 18926b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsRetained: 18936b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsNotRetained: 18946b755b0cSVlad Serebrennikov TypeOK = isValidSubjectOfOSAttribute(ReturnType); 18956b755b0cSVlad Serebrennikov Cf = true; 18966b755b0cSVlad Serebrennikov ParmDiagID = 3; // Pointer-to-OSObject-pointer 18976b755b0cSVlad Serebrennikov break; 18986b755b0cSVlad Serebrennikov } 18996b755b0cSVlad Serebrennikov 19006b755b0cSVlad Serebrennikov if (!TypeOK) { 19016b755b0cSVlad Serebrennikov if (AL.isUsedAsTypeAttr()) 19026b755b0cSVlad Serebrennikov return; 19036b755b0cSVlad Serebrennikov 19046b755b0cSVlad Serebrennikov if (isa<ParmVarDecl>(D)) { 19056b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) 19066b755b0cSVlad Serebrennikov << AL << ParmDiagID << AL.getRange(); 19076b755b0cSVlad Serebrennikov } else { 19086b755b0cSVlad Serebrennikov // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. 19096b755b0cSVlad Serebrennikov enum : unsigned { Function, Method, Property } SubjectKind = Function; 19106b755b0cSVlad Serebrennikov if (isa<ObjCMethodDecl>(D)) 19116b755b0cSVlad Serebrennikov SubjectKind = Method; 19126b755b0cSVlad Serebrennikov else if (isa<ObjCPropertyDecl>(D)) 19136b755b0cSVlad Serebrennikov SubjectKind = Property; 19146b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) 19156b755b0cSVlad Serebrennikov << AL << SubjectKind << Cf << AL.getRange(); 19166b755b0cSVlad Serebrennikov } 19176b755b0cSVlad Serebrennikov return; 19186b755b0cSVlad Serebrennikov } 19196b755b0cSVlad Serebrennikov 19206b755b0cSVlad Serebrennikov switch (AL.getKind()) { 19216b755b0cSVlad Serebrennikov default: 19226b755b0cSVlad Serebrennikov llvm_unreachable("invalid ownership attribute"); 19236b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsAutoreleased: 19246b755b0cSVlad Serebrennikov handleSimpleAttribute<NSReturnsAutoreleasedAttr>(*this, D, AL); 19256b755b0cSVlad Serebrennikov return; 19266b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsNotRetained: 19276b755b0cSVlad Serebrennikov handleSimpleAttribute<CFReturnsNotRetainedAttr>(*this, D, AL); 19286b755b0cSVlad Serebrennikov return; 19296b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsNotRetained: 19306b755b0cSVlad Serebrennikov handleSimpleAttribute<NSReturnsNotRetainedAttr>(*this, D, AL); 19316b755b0cSVlad Serebrennikov return; 19326b755b0cSVlad Serebrennikov case ParsedAttr::AT_CFReturnsRetained: 19336b755b0cSVlad Serebrennikov handleSimpleAttribute<CFReturnsRetainedAttr>(*this, D, AL); 19346b755b0cSVlad Serebrennikov return; 19356b755b0cSVlad Serebrennikov case ParsedAttr::AT_NSReturnsRetained: 19366b755b0cSVlad Serebrennikov handleSimpleAttribute<NSReturnsRetainedAttr>(*this, D, AL); 19376b755b0cSVlad Serebrennikov return; 19386b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsRetained: 19396b755b0cSVlad Serebrennikov handleSimpleAttribute<OSReturnsRetainedAttr>(*this, D, AL); 19406b755b0cSVlad Serebrennikov return; 19416b755b0cSVlad Serebrennikov case ParsedAttr::AT_OSReturnsNotRetained: 19426b755b0cSVlad Serebrennikov handleSimpleAttribute<OSReturnsNotRetainedAttr>(*this, D, AL); 19436b755b0cSVlad Serebrennikov return; 19446b755b0cSVlad Serebrennikov }; 19456b755b0cSVlad Serebrennikov } 19466b755b0cSVlad Serebrennikov 19476b755b0cSVlad Serebrennikov void SemaObjC::handleReturnsInnerPointerAttr(Decl *D, const ParsedAttr &Attrs) { 19486b755b0cSVlad Serebrennikov const int EP_ObjCMethod = 1; 19496b755b0cSVlad Serebrennikov const int EP_ObjCProperty = 2; 19506b755b0cSVlad Serebrennikov 19516b755b0cSVlad Serebrennikov SourceLocation loc = Attrs.getLoc(); 19526b755b0cSVlad Serebrennikov QualType resultType; 19536b755b0cSVlad Serebrennikov if (isa<ObjCMethodDecl>(D)) 19546b755b0cSVlad Serebrennikov resultType = cast<ObjCMethodDecl>(D)->getReturnType(); 19556b755b0cSVlad Serebrennikov else 19566b755b0cSVlad Serebrennikov resultType = cast<ObjCPropertyDecl>(D)->getType(); 19576b755b0cSVlad Serebrennikov 19586b755b0cSVlad Serebrennikov if (!resultType->isReferenceType() && 19596b755b0cSVlad Serebrennikov (!resultType->isPointerType() || resultType->isObjCRetainableType())) { 19606b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) 19616b755b0cSVlad Serebrennikov << SourceRange(loc) << Attrs 19626b755b0cSVlad Serebrennikov << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty) 19636b755b0cSVlad Serebrennikov << /*non-retainable pointer*/ 2; 19646b755b0cSVlad Serebrennikov 19656b755b0cSVlad Serebrennikov // Drop the attribute. 19666b755b0cSVlad Serebrennikov return; 19676b755b0cSVlad Serebrennikov } 19686b755b0cSVlad Serebrennikov 19696b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 19706b755b0cSVlad Serebrennikov ObjCReturnsInnerPointerAttr(getASTContext(), Attrs)); 19716b755b0cSVlad Serebrennikov } 19726b755b0cSVlad Serebrennikov 19736b755b0cSVlad Serebrennikov void SemaObjC::handleRequiresSuperAttr(Decl *D, const ParsedAttr &Attrs) { 19746b755b0cSVlad Serebrennikov const auto *Method = cast<ObjCMethodDecl>(D); 19756b755b0cSVlad Serebrennikov 19766b755b0cSVlad Serebrennikov const DeclContext *DC = Method->getDeclContext(); 19776b755b0cSVlad Serebrennikov if (const auto *PDecl = dyn_cast_if_present<ObjCProtocolDecl>(DC)) { 19786b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) 19796b755b0cSVlad Serebrennikov << Attrs << 0; 19806b755b0cSVlad Serebrennikov Diag(PDecl->getLocation(), diag::note_protocol_decl); 19816b755b0cSVlad Serebrennikov return; 19826b755b0cSVlad Serebrennikov } 19836b755b0cSVlad Serebrennikov if (Method->getMethodFamily() == OMF_dealloc) { 19846b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) 19856b755b0cSVlad Serebrennikov << Attrs << 1; 19866b755b0cSVlad Serebrennikov return; 19876b755b0cSVlad Serebrennikov } 19886b755b0cSVlad Serebrennikov 19896b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 19906b755b0cSVlad Serebrennikov ObjCRequiresSuperAttr(getASTContext(), Attrs)); 19916b755b0cSVlad Serebrennikov } 19926b755b0cSVlad Serebrennikov 19936b755b0cSVlad Serebrennikov void SemaObjC::handleNSErrorDomain(Decl *D, const ParsedAttr &Attr) { 19946b755b0cSVlad Serebrennikov if (!isa<TagDecl>(D)) { 19956b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0; 19966b755b0cSVlad Serebrennikov return; 19976b755b0cSVlad Serebrennikov } 19986b755b0cSVlad Serebrennikov 19996b755b0cSVlad Serebrennikov IdentifierLoc *IdentLoc = 20006b755b0cSVlad Serebrennikov Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr; 20016b755b0cSVlad Serebrennikov if (!IdentLoc || !IdentLoc->Ident) { 20026b755b0cSVlad Serebrennikov // Try to locate the argument directly. 20036b755b0cSVlad Serebrennikov SourceLocation Loc = Attr.getLoc(); 20046b755b0cSVlad Serebrennikov if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0)) 20056b755b0cSVlad Serebrennikov Loc = Attr.getArgAsExpr(0)->getBeginLoc(); 20066b755b0cSVlad Serebrennikov 20076b755b0cSVlad Serebrennikov Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0; 20086b755b0cSVlad Serebrennikov return; 20096b755b0cSVlad Serebrennikov } 20106b755b0cSVlad Serebrennikov 20116b755b0cSVlad Serebrennikov // Verify that the identifier is a valid decl in the C decl namespace. 20126b755b0cSVlad Serebrennikov LookupResult Result(SemaRef, DeclarationName(IdentLoc->Ident), 20136b755b0cSVlad Serebrennikov SourceLocation(), 20146b755b0cSVlad Serebrennikov Sema::LookupNameKind::LookupOrdinaryName); 20156b755b0cSVlad Serebrennikov if (!SemaRef.LookupName(Result, SemaRef.TUScope) || 20166b755b0cSVlad Serebrennikov !Result.getAsSingle<VarDecl>()) { 20176b755b0cSVlad Serebrennikov Diag(IdentLoc->Loc, diag::err_nserrordomain_invalid_decl) 20186b755b0cSVlad Serebrennikov << 1 << IdentLoc->Ident; 20196b755b0cSVlad Serebrennikov return; 20206b755b0cSVlad Serebrennikov } 20216b755b0cSVlad Serebrennikov 20226b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 20236b755b0cSVlad Serebrennikov NSErrorDomainAttr(getASTContext(), Attr, IdentLoc->Ident)); 20246b755b0cSVlad Serebrennikov } 20256b755b0cSVlad Serebrennikov 20266b755b0cSVlad Serebrennikov void SemaObjC::handleBridgeAttr(Decl *D, const ParsedAttr &AL) { 20276b755b0cSVlad Serebrennikov IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; 20286b755b0cSVlad Serebrennikov 20296b755b0cSVlad Serebrennikov if (!Parm) { 20306b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; 20316b755b0cSVlad Serebrennikov return; 20326b755b0cSVlad Serebrennikov } 20336b755b0cSVlad Serebrennikov 20346b755b0cSVlad Serebrennikov // Typedefs only allow objc_bridge(id) and have some additional checking. 20356b755b0cSVlad Serebrennikov if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { 20366b755b0cSVlad Serebrennikov if (!Parm->Ident->isStr("id")) { 20376b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL; 20386b755b0cSVlad Serebrennikov return; 20396b755b0cSVlad Serebrennikov } 20406b755b0cSVlad Serebrennikov 20416b755b0cSVlad Serebrennikov // Only allow 'cv void *'. 20426b755b0cSVlad Serebrennikov QualType T = TD->getUnderlyingType(); 20436b755b0cSVlad Serebrennikov if (!T->isVoidPointerType()) { 20446b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer); 20456b755b0cSVlad Serebrennikov return; 20466b755b0cSVlad Serebrennikov } 20476b755b0cSVlad Serebrennikov } 20486b755b0cSVlad Serebrennikov 20496b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 20506b755b0cSVlad Serebrennikov ObjCBridgeAttr(getASTContext(), AL, Parm->Ident)); 20516b755b0cSVlad Serebrennikov } 20526b755b0cSVlad Serebrennikov 20536b755b0cSVlad Serebrennikov void SemaObjC::handleBridgeMutableAttr(Decl *D, const ParsedAttr &AL) { 20546b755b0cSVlad Serebrennikov IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; 20556b755b0cSVlad Serebrennikov 20566b755b0cSVlad Serebrennikov if (!Parm) { 20576b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; 20586b755b0cSVlad Serebrennikov return; 20596b755b0cSVlad Serebrennikov } 20606b755b0cSVlad Serebrennikov 20616b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 20626b755b0cSVlad Serebrennikov ObjCBridgeMutableAttr(getASTContext(), AL, Parm->Ident)); 20636b755b0cSVlad Serebrennikov } 20646b755b0cSVlad Serebrennikov 20656b755b0cSVlad Serebrennikov void SemaObjC::handleBridgeRelatedAttr(Decl *D, const ParsedAttr &AL) { 20666b755b0cSVlad Serebrennikov IdentifierInfo *RelatedClass = 20676b755b0cSVlad Serebrennikov AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr; 20686b755b0cSVlad Serebrennikov if (!RelatedClass) { 20696b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; 20706b755b0cSVlad Serebrennikov return; 20716b755b0cSVlad Serebrennikov } 20726b755b0cSVlad Serebrennikov IdentifierInfo *ClassMethod = 20736b755b0cSVlad Serebrennikov AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr; 20746b755b0cSVlad Serebrennikov IdentifierInfo *InstanceMethod = 20756b755b0cSVlad Serebrennikov AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr; 20766b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) ObjCBridgeRelatedAttr( 20776b755b0cSVlad Serebrennikov getASTContext(), AL, RelatedClass, ClassMethod, InstanceMethod)); 20786b755b0cSVlad Serebrennikov } 20796b755b0cSVlad Serebrennikov 20806b755b0cSVlad Serebrennikov void SemaObjC::handleDesignatedInitializer(Decl *D, const ParsedAttr &AL) { 20816b755b0cSVlad Serebrennikov DeclContext *Ctx = D->getDeclContext(); 20826b755b0cSVlad Serebrennikov 20836b755b0cSVlad Serebrennikov // This attribute can only be applied to methods in interfaces or class 20846b755b0cSVlad Serebrennikov // extensions. 20856b755b0cSVlad Serebrennikov if (!isa<ObjCInterfaceDecl>(Ctx) && 20866b755b0cSVlad Serebrennikov !(isa<ObjCCategoryDecl>(Ctx) && 20876b755b0cSVlad Serebrennikov cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) { 20886b755b0cSVlad Serebrennikov Diag(D->getLocation(), diag::err_designated_init_attr_non_init); 20896b755b0cSVlad Serebrennikov return; 20906b755b0cSVlad Serebrennikov } 20916b755b0cSVlad Serebrennikov 20926b755b0cSVlad Serebrennikov ObjCInterfaceDecl *IFace; 20936b755b0cSVlad Serebrennikov if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx)) 20946b755b0cSVlad Serebrennikov IFace = CatDecl->getClassInterface(); 20956b755b0cSVlad Serebrennikov else 20966b755b0cSVlad Serebrennikov IFace = cast<ObjCInterfaceDecl>(Ctx); 20976b755b0cSVlad Serebrennikov 20986b755b0cSVlad Serebrennikov if (!IFace) 20996b755b0cSVlad Serebrennikov return; 21006b755b0cSVlad Serebrennikov 21016b755b0cSVlad Serebrennikov IFace->setHasDesignatedInitializers(); 21026b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 21036b755b0cSVlad Serebrennikov ObjCDesignatedInitializerAttr(getASTContext(), AL)); 21046b755b0cSVlad Serebrennikov } 21056b755b0cSVlad Serebrennikov 21066b755b0cSVlad Serebrennikov void SemaObjC::handleRuntimeName(Decl *D, const ParsedAttr &AL) { 21076b755b0cSVlad Serebrennikov StringRef MetaDataName; 21086b755b0cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, MetaDataName)) 21096b755b0cSVlad Serebrennikov return; 21106b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 21116b755b0cSVlad Serebrennikov ObjCRuntimeNameAttr(getASTContext(), AL, MetaDataName)); 21126b755b0cSVlad Serebrennikov } 21136b755b0cSVlad Serebrennikov 21146b755b0cSVlad Serebrennikov // When a user wants to use objc_boxable with a union or struct 21156b755b0cSVlad Serebrennikov // but they don't have access to the declaration (legacy/third-party code) 21166b755b0cSVlad Serebrennikov // then they can 'enable' this feature with a typedef: 21176b755b0cSVlad Serebrennikov // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct; 21186b755b0cSVlad Serebrennikov void SemaObjC::handleBoxable(Decl *D, const ParsedAttr &AL) { 21196b755b0cSVlad Serebrennikov bool notify = false; 21206b755b0cSVlad Serebrennikov 21216b755b0cSVlad Serebrennikov auto *RD = dyn_cast<RecordDecl>(D); 21226b755b0cSVlad Serebrennikov if (RD && RD->getDefinition()) { 21236b755b0cSVlad Serebrennikov RD = RD->getDefinition(); 21246b755b0cSVlad Serebrennikov notify = true; 21256b755b0cSVlad Serebrennikov } 21266b755b0cSVlad Serebrennikov 21276b755b0cSVlad Serebrennikov if (RD) { 21286b755b0cSVlad Serebrennikov ObjCBoxableAttr *BoxableAttr = 21296b755b0cSVlad Serebrennikov ::new (getASTContext()) ObjCBoxableAttr(getASTContext(), AL); 21306b755b0cSVlad Serebrennikov RD->addAttr(BoxableAttr); 21316b755b0cSVlad Serebrennikov if (notify) { 21326b755b0cSVlad Serebrennikov // we need to notify ASTReader/ASTWriter about 21336b755b0cSVlad Serebrennikov // modification of existing declaration 21346b755b0cSVlad Serebrennikov if (ASTMutationListener *L = SemaRef.getASTMutationListener()) 21356b755b0cSVlad Serebrennikov L->AddedAttributeToRecord(BoxableAttr, RD); 21366b755b0cSVlad Serebrennikov } 21376b755b0cSVlad Serebrennikov } 21386b755b0cSVlad Serebrennikov } 21396b755b0cSVlad Serebrennikov 21406b755b0cSVlad Serebrennikov void SemaObjC::handleOwnershipAttr(Decl *D, const ParsedAttr &AL) { 21416b755b0cSVlad Serebrennikov if (hasDeclarator(D)) 21426b755b0cSVlad Serebrennikov return; 21436b755b0cSVlad Serebrennikov 21446b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type) 21456b755b0cSVlad Serebrennikov << AL.getRange() << AL << AL.isRegularKeywordAttribute() 21466b755b0cSVlad Serebrennikov << ExpectedVariable; 21476b755b0cSVlad Serebrennikov } 21486b755b0cSVlad Serebrennikov 21496b755b0cSVlad Serebrennikov void SemaObjC::handlePreciseLifetimeAttr(Decl *D, const ParsedAttr &AL) { 21506b755b0cSVlad Serebrennikov const auto *VD = cast<ValueDecl>(D); 21516b755b0cSVlad Serebrennikov QualType QT = VD->getType(); 21526b755b0cSVlad Serebrennikov 21536b755b0cSVlad Serebrennikov if (!QT->isDependentType() && !QT->isObjCLifetimeType()) { 21546b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) << QT; 21556b755b0cSVlad Serebrennikov return; 21566b755b0cSVlad Serebrennikov } 21576b755b0cSVlad Serebrennikov 21586b755b0cSVlad Serebrennikov Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime(); 21596b755b0cSVlad Serebrennikov 21606b755b0cSVlad Serebrennikov // If we have no lifetime yet, check the lifetime we're presumably 21616b755b0cSVlad Serebrennikov // going to infer. 21626b755b0cSVlad Serebrennikov if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType()) 21636b755b0cSVlad Serebrennikov Lifetime = QT->getObjCARCImplicitLifetime(); 21646b755b0cSVlad Serebrennikov 21656b755b0cSVlad Serebrennikov switch (Lifetime) { 21666b755b0cSVlad Serebrennikov case Qualifiers::OCL_None: 21676b755b0cSVlad Serebrennikov assert(QT->isDependentType() && 21686b755b0cSVlad Serebrennikov "didn't infer lifetime for non-dependent type?"); 21696b755b0cSVlad Serebrennikov break; 21706b755b0cSVlad Serebrennikov 21716b755b0cSVlad Serebrennikov case Qualifiers::OCL_Weak: // meaningful 21726b755b0cSVlad Serebrennikov case Qualifiers::OCL_Strong: // meaningful 21736b755b0cSVlad Serebrennikov break; 21746b755b0cSVlad Serebrennikov 21756b755b0cSVlad Serebrennikov case Qualifiers::OCL_ExplicitNone: 21766b755b0cSVlad Serebrennikov case Qualifiers::OCL_Autoreleasing: 21776b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless) 21786b755b0cSVlad Serebrennikov << (Lifetime == Qualifiers::OCL_Autoreleasing); 21796b755b0cSVlad Serebrennikov break; 21806b755b0cSVlad Serebrennikov } 21816b755b0cSVlad Serebrennikov 21826b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 21836b755b0cSVlad Serebrennikov ObjCPreciseLifetimeAttr(getASTContext(), AL)); 21846b755b0cSVlad Serebrennikov } 21856b755b0cSVlad Serebrennikov 21866b755b0cSVlad Serebrennikov static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD, 21876b755b0cSVlad Serebrennikov bool DiagnoseFailure) { 21886b755b0cSVlad Serebrennikov QualType Ty = VD->getType(); 21896b755b0cSVlad Serebrennikov if (!Ty->isObjCRetainableType()) { 21906b755b0cSVlad Serebrennikov if (DiagnoseFailure) { 21916b755b0cSVlad Serebrennikov S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) 21926b755b0cSVlad Serebrennikov << 0; 21936b755b0cSVlad Serebrennikov } 21946b755b0cSVlad Serebrennikov return false; 21956b755b0cSVlad Serebrennikov } 21966b755b0cSVlad Serebrennikov 21976b755b0cSVlad Serebrennikov Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime(); 21986b755b0cSVlad Serebrennikov 21996b755b0cSVlad Serebrennikov // SemaObjC::inferObjCARCLifetime must run after processing decl attributes 22006b755b0cSVlad Serebrennikov // (because __block lowers to an attribute), so if the lifetime hasn't been 22016b755b0cSVlad Serebrennikov // explicitly specified, infer it locally now. 22026b755b0cSVlad Serebrennikov if (LifetimeQual == Qualifiers::OCL_None) 22036b755b0cSVlad Serebrennikov LifetimeQual = Ty->getObjCARCImplicitLifetime(); 22046b755b0cSVlad Serebrennikov 22056b755b0cSVlad Serebrennikov // The attributes only really makes sense for __strong variables; ignore any 22066b755b0cSVlad Serebrennikov // attempts to annotate a parameter with any other lifetime qualifier. 22076b755b0cSVlad Serebrennikov if (LifetimeQual != Qualifiers::OCL_Strong) { 22086b755b0cSVlad Serebrennikov if (DiagnoseFailure) { 22096b755b0cSVlad Serebrennikov S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) 22106b755b0cSVlad Serebrennikov << 1; 22116b755b0cSVlad Serebrennikov } 22126b755b0cSVlad Serebrennikov return false; 22136b755b0cSVlad Serebrennikov } 22146b755b0cSVlad Serebrennikov 22156b755b0cSVlad Serebrennikov // Tampering with the type of a VarDecl here is a bit of a hack, but we need 22166b755b0cSVlad Serebrennikov // to ensure that the variable is 'const' so that we can error on 22176b755b0cSVlad Serebrennikov // modification, which can otherwise over-release. 22186b755b0cSVlad Serebrennikov VD->setType(Ty.withConst()); 22196b755b0cSVlad Serebrennikov VD->setARCPseudoStrong(true); 22206b755b0cSVlad Serebrennikov return true; 22216b755b0cSVlad Serebrennikov } 22226b755b0cSVlad Serebrennikov 22236b755b0cSVlad Serebrennikov void SemaObjC::handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL) { 22246b755b0cSVlad Serebrennikov if (auto *VD = dyn_cast<VarDecl>(D)) { 22256b755b0cSVlad Serebrennikov assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically"); 22266b755b0cSVlad Serebrennikov if (!VD->hasLocalStorage()) { 22276b755b0cSVlad Serebrennikov Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) << 0; 22286b755b0cSVlad Serebrennikov return; 22296b755b0cSVlad Serebrennikov } 22306b755b0cSVlad Serebrennikov 22316b755b0cSVlad Serebrennikov if (!tryMakeVariablePseudoStrong(SemaRef, VD, /*DiagnoseFailure=*/true)) 22326b755b0cSVlad Serebrennikov return; 22336b755b0cSVlad Serebrennikov 22346b755b0cSVlad Serebrennikov handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL); 22356b755b0cSVlad Serebrennikov return; 22366b755b0cSVlad Serebrennikov } 22376b755b0cSVlad Serebrennikov 22386b755b0cSVlad Serebrennikov // If D is a function-like declaration (method, block, or function), then we 22396b755b0cSVlad Serebrennikov // make every parameter psuedo-strong. 22406b755b0cSVlad Serebrennikov unsigned NumParams = 22416b755b0cSVlad Serebrennikov hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0; 22426b755b0cSVlad Serebrennikov for (unsigned I = 0; I != NumParams; ++I) { 22436b755b0cSVlad Serebrennikov auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I)); 22446b755b0cSVlad Serebrennikov QualType Ty = PVD->getType(); 22456b755b0cSVlad Serebrennikov 22466b755b0cSVlad Serebrennikov // If a user wrote a parameter with __strong explicitly, then assume they 22476b755b0cSVlad Serebrennikov // want "real" strong semantics for that parameter. This works because if 22486b755b0cSVlad Serebrennikov // the parameter was written with __strong, then the strong qualifier will 22496b755b0cSVlad Serebrennikov // be non-local. 22506b755b0cSVlad Serebrennikov if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() == 22516b755b0cSVlad Serebrennikov Qualifiers::OCL_Strong) 22526b755b0cSVlad Serebrennikov continue; 22536b755b0cSVlad Serebrennikov 22546b755b0cSVlad Serebrennikov tryMakeVariablePseudoStrong(SemaRef, PVD, /*DiagnoseFailure=*/false); 22556b755b0cSVlad Serebrennikov } 22566b755b0cSVlad Serebrennikov handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL); 22576b755b0cSVlad Serebrennikov } 22586b755b0cSVlad Serebrennikov 2259f1c54d72SVlad Serebrennikov bool SemaObjC::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { 2260f1c54d72SVlad Serebrennikov Sema::FormatStringInfo FSI; 2261f1c54d72SVlad Serebrennikov if ((SemaRef.GetFormatStringType(Format) == Sema::FST_NSString) && 2262f1c54d72SVlad Serebrennikov SemaRef.getFormatStringInfo(Format, false, true, &FSI)) { 2263f1c54d72SVlad Serebrennikov Idx = FSI.FormatIdx; 2264f1c54d72SVlad Serebrennikov return true; 2265f1c54d72SVlad Serebrennikov } 2266f1c54d72SVlad Serebrennikov return false; 2267f1c54d72SVlad Serebrennikov } 2268f1c54d72SVlad Serebrennikov 2269f1c54d72SVlad Serebrennikov /// Diagnose use of %s directive in an NSString which is being passed 2270f1c54d72SVlad Serebrennikov /// as formatting string to formatting method. 2271f1c54d72SVlad Serebrennikov void SemaObjC::DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl, 2272f1c54d72SVlad Serebrennikov Expr **Args, 2273f1c54d72SVlad Serebrennikov unsigned NumArgs) { 2274f1c54d72SVlad Serebrennikov unsigned Idx = 0; 2275f1c54d72SVlad Serebrennikov bool Format = false; 2276f1c54d72SVlad Serebrennikov ObjCStringFormatFamily SFFamily = FDecl->getObjCFStringFormattingFamily(); 2277f1c54d72SVlad Serebrennikov if (SFFamily == ObjCStringFormatFamily::SFF_CFString) { 2278f1c54d72SVlad Serebrennikov Idx = 2; 2279f1c54d72SVlad Serebrennikov Format = true; 2280f1c54d72SVlad Serebrennikov } else 2281f1c54d72SVlad Serebrennikov for (const auto *I : FDecl->specific_attrs<FormatAttr>()) { 2282f1c54d72SVlad Serebrennikov if (GetFormatNSStringIdx(I, Idx)) { 2283f1c54d72SVlad Serebrennikov Format = true; 2284f1c54d72SVlad Serebrennikov break; 2285f1c54d72SVlad Serebrennikov } 2286f1c54d72SVlad Serebrennikov } 2287f1c54d72SVlad Serebrennikov if (!Format || NumArgs <= Idx) 2288f1c54d72SVlad Serebrennikov return; 2289f1c54d72SVlad Serebrennikov const Expr *FormatExpr = Args[Idx]; 2290f1c54d72SVlad Serebrennikov if (const CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(FormatExpr)) 2291f1c54d72SVlad Serebrennikov FormatExpr = CSCE->getSubExpr(); 2292f1c54d72SVlad Serebrennikov const StringLiteral *FormatString; 2293f1c54d72SVlad Serebrennikov if (const ObjCStringLiteral *OSL = 2294f1c54d72SVlad Serebrennikov dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) 2295f1c54d72SVlad Serebrennikov FormatString = OSL->getString(); 2296f1c54d72SVlad Serebrennikov else 2297f1c54d72SVlad Serebrennikov FormatString = dyn_cast<StringLiteral>(FormatExpr->IgnoreParenImpCasts()); 2298f1c54d72SVlad Serebrennikov if (!FormatString) 2299f1c54d72SVlad Serebrennikov return; 2300f1c54d72SVlad Serebrennikov if (SemaRef.FormatStringHasSArg(FormatString)) { 2301f1c54d72SVlad Serebrennikov Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string) 2302f1c54d72SVlad Serebrennikov << "%s" << 1 << 1; 2303f1c54d72SVlad Serebrennikov Diag(FDecl->getLocation(), diag::note_entity_declared_at) 2304f1c54d72SVlad Serebrennikov << FDecl->getDeclName(); 2305f1c54d72SVlad Serebrennikov } 2306f1c54d72SVlad Serebrennikov } 2307f1c54d72SVlad Serebrennikov 2308f1c54d72SVlad Serebrennikov bool SemaObjC::isSignedCharBool(QualType Ty) { 2309f1c54d72SVlad Serebrennikov return Ty->isSpecificBuiltinType(BuiltinType::SChar) && getLangOpts().ObjC && 2310f1c54d72SVlad Serebrennikov NSAPIObj->isObjCBOOLType(Ty); 2311f1c54d72SVlad Serebrennikov } 2312f1c54d72SVlad Serebrennikov 2313f1c54d72SVlad Serebrennikov void SemaObjC::adornBoolConversionDiagWithTernaryFixit( 2314f1c54d72SVlad Serebrennikov Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder) { 2315f1c54d72SVlad Serebrennikov Expr *Ignored = SourceExpr->IgnoreImplicit(); 2316f1c54d72SVlad Serebrennikov if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ignored)) 2317f1c54d72SVlad Serebrennikov Ignored = OVE->getSourceExpr(); 2318f1c54d72SVlad Serebrennikov bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) || 2319f1c54d72SVlad Serebrennikov isa<BinaryOperator>(Ignored) || 2320f1c54d72SVlad Serebrennikov isa<CXXOperatorCallExpr>(Ignored); 2321f1c54d72SVlad Serebrennikov SourceLocation EndLoc = SemaRef.getLocForEndOfToken(SourceExpr->getEndLoc()); 2322f1c54d72SVlad Serebrennikov if (NeedsParens) 2323f1c54d72SVlad Serebrennikov Builder << FixItHint::CreateInsertion(SourceExpr->getBeginLoc(), "(") 2324f1c54d72SVlad Serebrennikov << FixItHint::CreateInsertion(EndLoc, ")"); 2325f1c54d72SVlad Serebrennikov Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO"); 2326f1c54d72SVlad Serebrennikov } 2327f1c54d72SVlad Serebrennikov 2328f1c54d72SVlad Serebrennikov /// Check a single element within a collection literal against the 2329f1c54d72SVlad Serebrennikov /// target element type. 2330f1c54d72SVlad Serebrennikov static void checkCollectionLiteralElement(Sema &S, QualType TargetElementType, 2331f1c54d72SVlad Serebrennikov Expr *Element, unsigned ElementKind) { 2332f1c54d72SVlad Serebrennikov // Skip a bitcast to 'id' or qualified 'id'. 2333f1c54d72SVlad Serebrennikov if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) { 2334f1c54d72SVlad Serebrennikov if (ICE->getCastKind() == CK_BitCast && 2335f1c54d72SVlad Serebrennikov ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>()) 2336f1c54d72SVlad Serebrennikov Element = ICE->getSubExpr(); 2337f1c54d72SVlad Serebrennikov } 2338f1c54d72SVlad Serebrennikov 2339f1c54d72SVlad Serebrennikov QualType ElementType = Element->getType(); 2340f1c54d72SVlad Serebrennikov ExprResult ElementResult(Element); 2341f1c54d72SVlad Serebrennikov if (ElementType->getAs<ObjCObjectPointerType>() && 2342f1c54d72SVlad Serebrennikov S.CheckSingleAssignmentConstraints(TargetElementType, ElementResult, 2343f1c54d72SVlad Serebrennikov false, false) != Sema::Compatible) { 2344f1c54d72SVlad Serebrennikov S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element) 2345f1c54d72SVlad Serebrennikov << ElementType << ElementKind << TargetElementType 2346f1c54d72SVlad Serebrennikov << Element->getSourceRange(); 2347f1c54d72SVlad Serebrennikov } 2348f1c54d72SVlad Serebrennikov 2349f1c54d72SVlad Serebrennikov if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element)) 2350f1c54d72SVlad Serebrennikov S.ObjC().checkArrayLiteral(TargetElementType, ArrayLiteral); 2351f1c54d72SVlad Serebrennikov else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element)) 2352f1c54d72SVlad Serebrennikov S.ObjC().checkDictionaryLiteral(TargetElementType, DictionaryLiteral); 2353f1c54d72SVlad Serebrennikov } 2354f1c54d72SVlad Serebrennikov 2355f1c54d72SVlad Serebrennikov /// Check an Objective-C array literal being converted to the given 2356f1c54d72SVlad Serebrennikov /// target type. 2357f1c54d72SVlad Serebrennikov void SemaObjC::checkArrayLiteral(QualType TargetType, 2358f1c54d72SVlad Serebrennikov ObjCArrayLiteral *ArrayLiteral) { 2359f1c54d72SVlad Serebrennikov if (!NSArrayDecl) 2360f1c54d72SVlad Serebrennikov return; 2361f1c54d72SVlad Serebrennikov 2362f1c54d72SVlad Serebrennikov const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>(); 2363f1c54d72SVlad Serebrennikov if (!TargetObjCPtr) 2364f1c54d72SVlad Serebrennikov return; 2365f1c54d72SVlad Serebrennikov 2366f1c54d72SVlad Serebrennikov if (TargetObjCPtr->isUnspecialized() || 2367f1c54d72SVlad Serebrennikov TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() != 2368f1c54d72SVlad Serebrennikov NSArrayDecl->getCanonicalDecl()) 2369f1c54d72SVlad Serebrennikov return; 2370f1c54d72SVlad Serebrennikov 2371f1c54d72SVlad Serebrennikov auto TypeArgs = TargetObjCPtr->getTypeArgs(); 2372f1c54d72SVlad Serebrennikov if (TypeArgs.size() != 1) 2373f1c54d72SVlad Serebrennikov return; 2374f1c54d72SVlad Serebrennikov 2375f1c54d72SVlad Serebrennikov QualType TargetElementType = TypeArgs[0]; 2376f1c54d72SVlad Serebrennikov for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) { 2377f1c54d72SVlad Serebrennikov checkCollectionLiteralElement(SemaRef, TargetElementType, 2378f1c54d72SVlad Serebrennikov ArrayLiteral->getElement(I), 0); 2379f1c54d72SVlad Serebrennikov } 2380f1c54d72SVlad Serebrennikov } 2381f1c54d72SVlad Serebrennikov 2382f1c54d72SVlad Serebrennikov void SemaObjC::checkDictionaryLiteral( 2383f1c54d72SVlad Serebrennikov QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral) { 2384f1c54d72SVlad Serebrennikov if (!NSDictionaryDecl) 2385f1c54d72SVlad Serebrennikov return; 2386f1c54d72SVlad Serebrennikov 2387f1c54d72SVlad Serebrennikov const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>(); 2388f1c54d72SVlad Serebrennikov if (!TargetObjCPtr) 2389f1c54d72SVlad Serebrennikov return; 2390f1c54d72SVlad Serebrennikov 2391f1c54d72SVlad Serebrennikov if (TargetObjCPtr->isUnspecialized() || 2392f1c54d72SVlad Serebrennikov TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() != 2393f1c54d72SVlad Serebrennikov NSDictionaryDecl->getCanonicalDecl()) 2394f1c54d72SVlad Serebrennikov return; 2395f1c54d72SVlad Serebrennikov 2396f1c54d72SVlad Serebrennikov auto TypeArgs = TargetObjCPtr->getTypeArgs(); 2397f1c54d72SVlad Serebrennikov if (TypeArgs.size() != 2) 2398f1c54d72SVlad Serebrennikov return; 2399f1c54d72SVlad Serebrennikov 2400f1c54d72SVlad Serebrennikov QualType TargetKeyType = TypeArgs[0]; 2401f1c54d72SVlad Serebrennikov QualType TargetObjectType = TypeArgs[1]; 2402f1c54d72SVlad Serebrennikov for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) { 2403f1c54d72SVlad Serebrennikov auto Element = DictionaryLiteral->getKeyValueElement(I); 2404f1c54d72SVlad Serebrennikov checkCollectionLiteralElement(SemaRef, TargetKeyType, Element.Key, 1); 2405f1c54d72SVlad Serebrennikov checkCollectionLiteralElement(SemaRef, TargetObjectType, Element.Value, 2); 2406f1c54d72SVlad Serebrennikov } 2407f1c54d72SVlad Serebrennikov } 2408f1c54d72SVlad Serebrennikov 240931a203faSVlad Serebrennikov } // namespace clang 2410