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