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