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