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