1 //===----- SemaObjC.cpp ---- Semantic Analysis for Objective-C ------------===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements semantic analysis for Objective-C.
11 //===----------------------------------------------------------------------===//
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"
29 SemaObjC::SemaObjC(Sema
&S
)
30 : SemaBase(S
), NSNumberDecl(nullptr), NSValueDecl(nullptr),
31 NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
32 ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
33 ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
34 DictionaryWithObjectsMethod(nullptr) {}
36 StmtResult
SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc
,
37 Stmt
*First
, Expr
*collection
,
38 SourceLocation RParenLoc
) {
39 ASTContext
&Context
= getASTContext();
40 SemaRef
.setFunctionHasBranchProtectedScope();
42 ExprResult CollectionExprResult
=
43 CheckObjCForCollectionOperand(ForLoc
, collection
);
47 if (DeclStmt
*DS
= dyn_cast
<DeclStmt
>(First
)) {
48 if (!DS
->isSingleDecl())
49 return StmtError(Diag((*DS
->decl_begin())->getLocation(),
50 diag::err_toomany_element_decls
));
52 VarDecl
*D
= dyn_cast
<VarDecl
>(DS
->getSingleDecl());
53 if (!D
|| D
->isInvalidDecl())
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
60 if (!D
->hasLocalStorage())
62 Diag(D
->getLocation(), diag::err_non_local_variable_decl_in_for
));
64 // If the type contained 'auto', deduce the 'auto' to 'id'.
65 if (FirstType
->getContainedAutoType()) {
66 SourceLocation Loc
= D
->getLocation();
67 OpaqueValueExpr
OpaqueId(Loc
, Context
.getObjCIdType(), VK_PRValue
);
68 Expr
*DeducedInit
= &OpaqueId
;
69 sema::TemplateDeductionInfo
Info(Loc
);
70 FirstType
= QualType();
71 TemplateDeductionResult Result
= SemaRef
.DeduceAutoType(
72 D
->getTypeSourceInfo()->getTypeLoc(), DeducedInit
, FirstType
, Info
);
73 if (Result
!= TemplateDeductionResult::Success
&&
74 Result
!= TemplateDeductionResult::AlreadyDiagnosed
)
75 SemaRef
.DiagnoseAutoDeductionFailure(D
, DeducedInit
);
76 if (FirstType
.isNull()) {
81 D
->setType(FirstType
);
83 if (!SemaRef
.inTemplateInstantiation()) {
85 D
->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
86 Diag(Loc
, diag::warn_auto_var_is_id
) << D
->getDeclName();
91 Expr
*FirstE
= cast
<Expr
>(First
);
92 if (!FirstE
->isTypeDependent() && !FirstE
->isLValue())
94 Diag(First
->getBeginLoc(), diag::err_selector_element_not_lvalue
)
95 << First
->getSourceRange());
97 FirstType
= static_cast<Expr
*>(First
)->getType();
98 if (FirstType
.isConstQualified())
99 Diag(ForLoc
, diag::err_selector_element_const_type
)
100 << FirstType
<< First
->getSourceRange();
102 if (!FirstType
->isDependentType() &&
103 !FirstType
->isObjCObjectPointerType() &&
104 !FirstType
->isBlockPointerType())
105 return StmtError(Diag(ForLoc
, diag::err_selector_element_type
)
106 << FirstType
<< First
->getSourceRange());
109 if (CollectionExprResult
.isInvalid())
112 CollectionExprResult
= SemaRef
.ActOnFinishFullExpr(CollectionExprResult
.get(),
113 /*DiscardedValue*/ false);
114 if (CollectionExprResult
.isInvalid())
117 return new (Context
) ObjCForCollectionStmt(First
, CollectionExprResult
.get(),
118 nullptr, ForLoc
, RParenLoc
);
121 ExprResult
SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc
,
123 ASTContext
&Context
= getASTContext();
127 ExprResult result
= SemaRef
.CorrectDelayedTyposInExpr(collection
);
128 if (!result
.isUsable())
130 collection
= result
.get();
132 // Bail out early if we've got a type-dependent expression.
133 if (collection
->isTypeDependent())
136 // Perform normal l-value conversion.
137 result
= SemaRef
.DefaultFunctionArrayLvalueConversion(collection
);
138 if (result
.isInvalid())
140 collection
= result
.get();
142 // The operand needs to have object-pointer type.
143 // TODO: should we do a contextual conversion?
144 const ObjCObjectPointerType
*pointerType
=
145 collection
->getType()->getAs
<ObjCObjectPointerType
>();
147 return Diag(forLoc
, diag::err_collection_expr_type
)
148 << collection
->getType() << collection
->getSourceRange();
150 // Check that the operand provides
151 // - countByEnumeratingWithState:objects:count:
152 const ObjCObjectType
*objectType
= pointerType
->getObjectType();
153 ObjCInterfaceDecl
*iface
= objectType
->getInterface();
155 // If we have a forward-declared type, we can't do this check.
156 // Under ARC, it is an error not to have a forward-declared class.
158 (getLangOpts().ObjCAutoRefCount
159 ? SemaRef
.RequireCompleteType(forLoc
, QualType(objectType
, 0),
160 diag::err_arc_collection_forward
,
162 : !SemaRef
.isCompleteType(forLoc
, QualType(objectType
, 0)))) {
163 // Otherwise, if we have any useful type information, check that
164 // the type declares the appropriate method.
165 } else if (iface
|| !objectType
->qual_empty()) {
166 const IdentifierInfo
*selectorIdents
[] = {
167 &Context
.Idents
.get("countByEnumeratingWithState"),
168 &Context
.Idents
.get("objects"), &Context
.Idents
.get("count")};
169 Selector selector
= Context
.Selectors
.getSelector(3, &selectorIdents
[0]);
171 ObjCMethodDecl
*method
= nullptr;
173 // If there's an interface, look in both the public and private APIs.
175 method
= iface
->lookupInstanceMethod(selector
);
177 method
= iface
->lookupPrivateMethod(selector
);
180 // Also check protocol qualifiers.
182 method
= LookupMethodInQualifiedType(selector
, pointerType
,
185 // If we didn't find it anywhere, give up.
187 Diag(forLoc
, diag::warn_collection_expr_type
)
188 << collection
->getType() << selector
<< collection
->getSourceRange();
191 // TODO: check for an incompatible signature?
194 // Wrap up any cleanups in the expression.
198 StmtResult
SemaObjC::FinishObjCForCollectionStmt(Stmt
*S
, Stmt
*B
) {
201 ObjCForCollectionStmt
*ForStmt
= cast
<ObjCForCollectionStmt
>(S
);
207 StmtResult
SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc
,
208 SourceLocation RParen
, Decl
*Parm
,
210 ASTContext
&Context
= getASTContext();
211 VarDecl
*Var
= cast_or_null
<VarDecl
>(Parm
);
212 if (Var
&& Var
->isInvalidDecl())
215 return new (Context
) ObjCAtCatchStmt(AtLoc
, RParen
, Var
, Body
);
218 StmtResult
SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc
, Stmt
*Body
) {
219 ASTContext
&Context
= getASTContext();
220 return new (Context
) ObjCAtFinallyStmt(AtLoc
, Body
);
223 StmtResult
SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc
, Stmt
*Try
,
224 MultiStmtArg CatchStmts
,
226 ASTContext
&Context
= getASTContext();
227 if (!getLangOpts().ObjCExceptions
)
228 Diag(AtLoc
, diag::err_objc_exceptions_disabled
) << "@try";
230 // Objective-C try is incompatible with SEH __try.
231 sema::FunctionScopeInfo
*FSI
= SemaRef
.getCurFunction();
232 if (FSI
->FirstSEHTryLoc
.isValid()) {
233 Diag(AtLoc
, diag::err_mixing_cxx_try_seh_try
) << 1;
234 Diag(FSI
->FirstSEHTryLoc
, diag::note_conflicting_try_here
) << "'__try'";
237 FSI
->setHasObjCTry(AtLoc
);
238 unsigned NumCatchStmts
= CatchStmts
.size();
239 return ObjCAtTryStmt::Create(Context
, AtLoc
, Try
, CatchStmts
.data(),
240 NumCatchStmts
, Finally
);
243 StmtResult
SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc
, Expr
*Throw
) {
244 ASTContext
&Context
= getASTContext();
246 ExprResult Result
= SemaRef
.DefaultLvalueConversion(Throw
);
247 if (Result
.isInvalid())
251 SemaRef
.ActOnFinishFullExpr(Result
.get(), /*DiscardedValue*/ false);
252 if (Result
.isInvalid())
254 Throw
= Result
.get();
256 QualType ThrowType
= Throw
->getType();
257 // Make sure the expression type is an ObjC pointer or "void *".
258 if (!ThrowType
->isDependentType() &&
259 !ThrowType
->isObjCObjectPointerType()) {
260 const PointerType
*PT
= ThrowType
->getAs
<PointerType
>();
261 if (!PT
|| !PT
->getPointeeType()->isVoidType())
262 return StmtError(Diag(AtLoc
, diag::err_objc_throw_expects_object
)
263 << Throw
->getType() << Throw
->getSourceRange());
267 return new (Context
) ObjCAtThrowStmt(AtLoc
, Throw
);
270 StmtResult
SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc
, Expr
*Throw
,
272 if (!getLangOpts().ObjCExceptions
)
273 Diag(AtLoc
, diag::err_objc_exceptions_disabled
) << "@throw";
276 // @throw without an expression designates a rethrow (which must occur
277 // in the context of an @catch clause).
278 Scope
*AtCatchParent
= CurScope
;
279 while (AtCatchParent
&& !AtCatchParent
->isAtCatchScope())
280 AtCatchParent
= AtCatchParent
->getParent();
282 return StmtError(Diag(AtLoc
, diag::err_rethrow_used_outside_catch
));
284 return BuildObjCAtThrowStmt(AtLoc
, Throw
);
287 ExprResult
SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc
,
289 ExprResult result
= SemaRef
.DefaultLvalueConversion(operand
);
290 if (result
.isInvalid())
292 operand
= result
.get();
294 // Make sure the expression type is an ObjC pointer or "void *".
295 QualType type
= operand
->getType();
296 if (!type
->isDependentType() && !type
->isObjCObjectPointerType()) {
297 const PointerType
*pointerType
= type
->getAs
<PointerType
>();
298 if (!pointerType
|| !pointerType
->getPointeeType()->isVoidType()) {
299 if (getLangOpts().CPlusPlus
) {
300 if (SemaRef
.RequireCompleteType(atLoc
, type
,
301 diag::err_incomplete_receiver_type
))
302 return Diag(atLoc
, diag::err_objc_synchronized_expects_object
)
303 << type
<< operand
->getSourceRange();
306 SemaRef
.PerformContextuallyConvertToObjCPointer(operand
);
307 if (result
.isInvalid())
309 if (!result
.isUsable())
310 return Diag(atLoc
, diag::err_objc_synchronized_expects_object
)
311 << type
<< operand
->getSourceRange();
313 operand
= result
.get();
315 return Diag(atLoc
, diag::err_objc_synchronized_expects_object
)
316 << type
<< operand
->getSourceRange();
321 // The operand to @synchronized is a full-expression.
322 return SemaRef
.ActOnFinishFullExpr(operand
, /*DiscardedValue*/ false);
325 StmtResult
SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc
,
328 ASTContext
&Context
= getASTContext();
329 // We can't jump into or indirect-jump out of a @synchronized block.
330 SemaRef
.setFunctionHasBranchProtectedScope();
331 return new (Context
) ObjCAtSynchronizedStmt(AtLoc
, SyncExpr
, SyncBody
);
334 StmtResult
SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc
,
336 ASTContext
&Context
= getASTContext();
337 SemaRef
.setFunctionHasBranchProtectedScope();
338 return new (Context
) ObjCAutoreleasePoolStmt(AtLoc
, Body
);
341 TypeResult
SemaObjC::actOnObjCProtocolQualifierType(
342 SourceLocation lAngleLoc
, ArrayRef
<Decl
*> protocols
,
343 ArrayRef
<SourceLocation
> protocolLocs
, SourceLocation rAngleLoc
) {
344 ASTContext
&Context
= getASTContext();
345 // Form id<protocol-list>.
346 QualType Result
= Context
.getObjCObjectType(
347 Context
.ObjCBuiltinIdTy
, {},
348 llvm::ArrayRef((ObjCProtocolDecl
*const *)protocols
.data(),
351 Result
= Context
.getObjCObjectPointerType(Result
);
353 TypeSourceInfo
*ResultTInfo
= Context
.CreateTypeSourceInfo(Result
);
354 TypeLoc ResultTL
= ResultTInfo
->getTypeLoc();
356 auto ObjCObjectPointerTL
= ResultTL
.castAs
<ObjCObjectPointerTypeLoc
>();
357 ObjCObjectPointerTL
.setStarLoc(SourceLocation()); // implicit
360 ObjCObjectPointerTL
.getPointeeLoc().castAs
<ObjCObjectTypeLoc
>();
361 ObjCObjectTL
.setHasBaseTypeAsWritten(false);
362 ObjCObjectTL
.getBaseLoc().initialize(Context
, SourceLocation());
364 // No type arguments.
365 ObjCObjectTL
.setTypeArgsLAngleLoc(SourceLocation());
366 ObjCObjectTL
.setTypeArgsRAngleLoc(SourceLocation());
368 // Fill in protocol qualifiers.
369 ObjCObjectTL
.setProtocolLAngleLoc(lAngleLoc
);
370 ObjCObjectTL
.setProtocolRAngleLoc(rAngleLoc
);
371 for (unsigned i
= 0, n
= protocols
.size(); i
!= n
; ++i
)
372 ObjCObjectTL
.setProtocolLoc(i
, protocolLocs
[i
]);
374 // We're done. Return the completed type to the parser.
375 return SemaRef
.CreateParsedType(Result
, ResultTInfo
);
378 TypeResult
SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers(
379 Scope
*S
, SourceLocation Loc
, ParsedType BaseType
,
380 SourceLocation TypeArgsLAngleLoc
, ArrayRef
<ParsedType
> TypeArgs
,
381 SourceLocation TypeArgsRAngleLoc
, SourceLocation ProtocolLAngleLoc
,
382 ArrayRef
<Decl
*> Protocols
, ArrayRef
<SourceLocation
> ProtocolLocs
,
383 SourceLocation ProtocolRAngleLoc
) {
384 ASTContext
&Context
= getASTContext();
385 TypeSourceInfo
*BaseTypeInfo
= nullptr;
386 QualType T
= SemaRef
.GetTypeFromParser(BaseType
, &BaseTypeInfo
);
390 // Handle missing type-source info.
392 BaseTypeInfo
= Context
.getTrivialTypeSourceInfo(T
, Loc
);
394 // Extract type arguments.
395 SmallVector
<TypeSourceInfo
*, 4> ActualTypeArgInfos
;
396 for (unsigned i
= 0, n
= TypeArgs
.size(); i
!= n
; ++i
) {
397 TypeSourceInfo
*TypeArgInfo
= nullptr;
398 QualType TypeArg
= SemaRef
.GetTypeFromParser(TypeArgs
[i
], &TypeArgInfo
);
399 if (TypeArg
.isNull()) {
400 ActualTypeArgInfos
.clear();
404 assert(TypeArgInfo
&& "No type source info?");
405 ActualTypeArgInfos
.push_back(TypeArgInfo
);
408 // Build the object type.
409 QualType Result
= BuildObjCObjectType(
410 T
, BaseTypeInfo
->getTypeLoc().getSourceRange().getBegin(),
411 TypeArgsLAngleLoc
, ActualTypeArgInfos
, TypeArgsRAngleLoc
,
413 llvm::ArrayRef((ObjCProtocolDecl
*const *)Protocols
.data(),
415 ProtocolLocs
, ProtocolRAngleLoc
,
416 /*FailOnError=*/false,
417 /*Rebuilding=*/false);
422 // Create source information for this type.
423 TypeSourceInfo
*ResultTInfo
= Context
.CreateTypeSourceInfo(Result
);
424 TypeLoc ResultTL
= ResultTInfo
->getTypeLoc();
426 // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an
427 // object pointer type. Fill in source information for it.
428 if (auto ObjCObjectPointerTL
= ResultTL
.getAs
<ObjCObjectPointerTypeLoc
>()) {
429 // The '*' is implicit.
430 ObjCObjectPointerTL
.setStarLoc(SourceLocation());
431 ResultTL
= ObjCObjectPointerTL
.getPointeeLoc();
434 if (auto OTPTL
= ResultTL
.getAs
<ObjCTypeParamTypeLoc
>()) {
435 // Protocol qualifier information.
436 if (OTPTL
.getNumProtocols() > 0) {
437 assert(OTPTL
.getNumProtocols() == Protocols
.size());
438 OTPTL
.setProtocolLAngleLoc(ProtocolLAngleLoc
);
439 OTPTL
.setProtocolRAngleLoc(ProtocolRAngleLoc
);
440 for (unsigned i
= 0, n
= Protocols
.size(); i
!= n
; ++i
)
441 OTPTL
.setProtocolLoc(i
, ProtocolLocs
[i
]);
444 // We're done. Return the completed type to the parser.
445 return SemaRef
.CreateParsedType(Result
, ResultTInfo
);
448 auto ObjCObjectTL
= ResultTL
.castAs
<ObjCObjectTypeLoc
>();
450 // Type argument information.
451 if (ObjCObjectTL
.getNumTypeArgs() > 0) {
452 assert(ObjCObjectTL
.getNumTypeArgs() == ActualTypeArgInfos
.size());
453 ObjCObjectTL
.setTypeArgsLAngleLoc(TypeArgsLAngleLoc
);
454 ObjCObjectTL
.setTypeArgsRAngleLoc(TypeArgsRAngleLoc
);
455 for (unsigned i
= 0, n
= ActualTypeArgInfos
.size(); i
!= n
; ++i
)
456 ObjCObjectTL
.setTypeArgTInfo(i
, ActualTypeArgInfos
[i
]);
458 ObjCObjectTL
.setTypeArgsLAngleLoc(SourceLocation());
459 ObjCObjectTL
.setTypeArgsRAngleLoc(SourceLocation());
462 // Protocol qualifier information.
463 if (ObjCObjectTL
.getNumProtocols() > 0) {
464 assert(ObjCObjectTL
.getNumProtocols() == Protocols
.size());
465 ObjCObjectTL
.setProtocolLAngleLoc(ProtocolLAngleLoc
);
466 ObjCObjectTL
.setProtocolRAngleLoc(ProtocolRAngleLoc
);
467 for (unsigned i
= 0, n
= Protocols
.size(); i
!= n
; ++i
)
468 ObjCObjectTL
.setProtocolLoc(i
, ProtocolLocs
[i
]);
470 ObjCObjectTL
.setProtocolLAngleLoc(SourceLocation());
471 ObjCObjectTL
.setProtocolRAngleLoc(SourceLocation());
475 ObjCObjectTL
.setHasBaseTypeAsWritten(true);
476 if (ObjCObjectTL
.getType() == T
)
477 ObjCObjectTL
.getBaseLoc().initializeFullCopy(BaseTypeInfo
->getTypeLoc());
479 ObjCObjectTL
.getBaseLoc().initialize(Context
, Loc
);
481 // We're done. Return the completed type to the parser.
482 return SemaRef
.CreateParsedType(Result
, ResultTInfo
);
485 QualType
SemaObjC::BuildObjCTypeParamType(
486 const ObjCTypeParamDecl
*Decl
, SourceLocation ProtocolLAngleLoc
,
487 ArrayRef
<ObjCProtocolDecl
*> Protocols
,
488 ArrayRef
<SourceLocation
> ProtocolLocs
, SourceLocation ProtocolRAngleLoc
,
490 ASTContext
&Context
= getASTContext();
491 QualType Result
= QualType(Decl
->getTypeForDecl(), 0);
492 if (!Protocols
.empty()) {
494 Result
= Context
.applyObjCProtocolQualifiers(Result
, Protocols
, HasError
);
496 Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers
)
497 << SourceRange(ProtocolLAngleLoc
, ProtocolRAngleLoc
);
501 if (FailOnError
&& Result
.isNull())
508 /// Apply Objective-C type arguments to the given type.
509 static QualType
applyObjCTypeArgs(Sema
&S
, SourceLocation loc
, QualType type
,
510 ArrayRef
<TypeSourceInfo
*> typeArgs
,
511 SourceRange typeArgsRange
, bool failOnError
,
513 // We can only apply type arguments to an Objective-C class type.
514 const auto *objcObjectType
= type
->getAs
<ObjCObjectType
>();
515 if (!objcObjectType
|| !objcObjectType
->getInterface()) {
516 S
.Diag(loc
, diag::err_objc_type_args_non_class
) << type
<< typeArgsRange
;
523 // The class type must be parameterized.
524 ObjCInterfaceDecl
*objcClass
= objcObjectType
->getInterface();
525 ObjCTypeParamList
*typeParams
= objcClass
->getTypeParamList();
527 S
.Diag(loc
, diag::err_objc_type_args_non_parameterized_class
)
528 << objcClass
->getDeclName() << FixItHint::CreateRemoval(typeArgsRange
);
536 // The type must not already be specialized.
537 if (objcObjectType
->isSpecialized()) {
538 S
.Diag(loc
, diag::err_objc_type_args_specialized_class
)
539 << type
<< FixItHint::CreateRemoval(typeArgsRange
);
547 // Check the type arguments.
548 SmallVector
<QualType
, 4> finalTypeArgs
;
549 unsigned numTypeParams
= typeParams
->size();
550 bool anyPackExpansions
= false;
551 for (unsigned i
= 0, n
= typeArgs
.size(); i
!= n
; ++i
) {
552 TypeSourceInfo
*typeArgInfo
= typeArgs
[i
];
553 QualType typeArg
= typeArgInfo
->getType();
555 // Type arguments cannot have explicit qualifiers or nullability.
556 // We ignore indirect sources of these, e.g. behind typedefs or
557 // template arguments.
558 if (TypeLoc qual
= typeArgInfo
->getTypeLoc().findExplicitQualifierLoc()) {
559 bool diagnosed
= false;
560 SourceRange rangeToRemove
;
561 if (auto attr
= qual
.getAs
<AttributedTypeLoc
>()) {
562 rangeToRemove
= attr
.getLocalSourceRange();
563 if (attr
.getTypePtr()->getImmediateNullability()) {
564 typeArg
= attr
.getTypePtr()->getModifiedType();
565 S
.Diag(attr
.getBeginLoc(),
566 diag::err_objc_type_arg_explicit_nullability
)
567 << typeArg
<< FixItHint::CreateRemoval(rangeToRemove
);
572 // When rebuilding, qualifiers might have gotten here through a
573 // final substitution.
574 if (!rebuilding
&& !diagnosed
) {
575 S
.Diag(qual
.getBeginLoc(), diag::err_objc_type_arg_qualified
)
576 << typeArg
<< typeArg
.getQualifiers().getAsString()
577 << FixItHint::CreateRemoval(rangeToRemove
);
581 // Remove qualifiers even if they're non-local.
582 typeArg
= typeArg
.getUnqualifiedType();
584 finalTypeArgs
.push_back(typeArg
);
586 if (typeArg
->getAs
<PackExpansionType
>())
587 anyPackExpansions
= true;
589 // Find the corresponding type parameter, if there is one.
590 ObjCTypeParamDecl
*typeParam
= nullptr;
591 if (!anyPackExpansions
) {
592 if (i
< numTypeParams
) {
593 typeParam
= typeParams
->begin()[i
];
595 // Too many arguments.
596 S
.Diag(loc
, diag::err_objc_type_args_wrong_arity
)
597 << false << objcClass
->getDeclName() << (unsigned)typeArgs
.size()
599 S
.Diag(objcClass
->getLocation(), diag::note_previous_decl
) << objcClass
;
608 // Objective-C object pointer types must be substitutable for the bounds.
609 if (const auto *typeArgObjC
= typeArg
->getAs
<ObjCObjectPointerType
>()) {
610 // If we don't have a type parameter to match against, assume
611 // everything is fine. There was a prior pack expansion that
612 // means we won't be able to match anything.
614 assert(anyPackExpansions
&& "Too many arguments?");
618 // Retrieve the bound.
619 QualType bound
= typeParam
->getUnderlyingType();
620 const auto *boundObjC
= bound
->castAs
<ObjCObjectPointerType
>();
622 // Determine whether the type argument is substitutable for the bound.
623 if (typeArgObjC
->isObjCIdType()) {
624 // When the type argument is 'id', the only acceptable type
625 // parameter bound is 'id'.
626 if (boundObjC
->isObjCIdType())
628 } else if (S
.Context
.canAssignObjCInterfaces(boundObjC
, typeArgObjC
)) {
629 // Otherwise, we follow the assignability rules.
633 // Diagnose the mismatch.
634 S
.Diag(typeArgInfo
->getTypeLoc().getBeginLoc(),
635 diag::err_objc_type_arg_does_not_match_bound
)
636 << typeArg
<< bound
<< typeParam
->getDeclName();
637 S
.Diag(typeParam
->getLocation(), diag::note_objc_type_param_here
)
638 << typeParam
->getDeclName();
646 // Block pointer types are permitted for unqualified 'id' bounds.
647 if (typeArg
->isBlockPointerType()) {
648 // If we don't have a type parameter to match against, assume
649 // everything is fine. There was a prior pack expansion that
650 // means we won't be able to match anything.
652 assert(anyPackExpansions
&& "Too many arguments?");
656 // Retrieve the bound.
657 QualType bound
= typeParam
->getUnderlyingType();
658 if (bound
->isBlockCompatibleObjCPointerType(S
.Context
))
661 // Diagnose the mismatch.
662 S
.Diag(typeArgInfo
->getTypeLoc().getBeginLoc(),
663 diag::err_objc_type_arg_does_not_match_bound
)
664 << typeArg
<< bound
<< typeParam
->getDeclName();
665 S
.Diag(typeParam
->getLocation(), diag::note_objc_type_param_here
)
666 << typeParam
->getDeclName();
674 // Types that have __attribute__((NSObject)) are permitted.
675 if (typeArg
->isObjCNSObjectType()) {
679 // Dependent types will be checked at instantiation time.
680 if (typeArg
->isDependentType()) {
684 // Diagnose non-id-compatible type arguments.
685 S
.Diag(typeArgInfo
->getTypeLoc().getBeginLoc(),
686 diag::err_objc_type_arg_not_id_compatible
)
687 << typeArg
<< typeArgInfo
->getTypeLoc().getSourceRange();
695 // Make sure we didn't have the wrong number of arguments.
696 if (!anyPackExpansions
&& finalTypeArgs
.size() != numTypeParams
) {
697 S
.Diag(loc
, diag::err_objc_type_args_wrong_arity
)
698 << (typeArgs
.size() < typeParams
->size()) << objcClass
->getDeclName()
699 << (unsigned)finalTypeArgs
.size() << (unsigned)numTypeParams
;
700 S
.Diag(objcClass
->getLocation(), diag::note_previous_decl
) << objcClass
;
708 // Success. Form the specialized type.
709 return S
.Context
.getObjCObjectType(type
, finalTypeArgs
, {}, false);
712 QualType
SemaObjC::BuildObjCObjectType(
713 QualType BaseType
, SourceLocation Loc
, SourceLocation TypeArgsLAngleLoc
,
714 ArrayRef
<TypeSourceInfo
*> TypeArgs
, SourceLocation TypeArgsRAngleLoc
,
715 SourceLocation ProtocolLAngleLoc
, ArrayRef
<ObjCProtocolDecl
*> Protocols
,
716 ArrayRef
<SourceLocation
> ProtocolLocs
, SourceLocation ProtocolRAngleLoc
,
717 bool FailOnError
, bool Rebuilding
) {
718 ASTContext
&Context
= getASTContext();
719 QualType Result
= BaseType
;
720 if (!TypeArgs
.empty()) {
722 applyObjCTypeArgs(SemaRef
, Loc
, Result
, TypeArgs
,
723 SourceRange(TypeArgsLAngleLoc
, TypeArgsRAngleLoc
),
724 FailOnError
, Rebuilding
);
725 if (FailOnError
&& Result
.isNull())
729 if (!Protocols
.empty()) {
731 Result
= Context
.applyObjCProtocolQualifiers(Result
, Protocols
, HasError
);
733 Diag(Loc
, diag::err_invalid_protocol_qualifiers
)
734 << SourceRange(ProtocolLAngleLoc
, ProtocolRAngleLoc
);
738 if (FailOnError
&& Result
.isNull())
745 ParsedType
SemaObjC::ActOnObjCInstanceType(SourceLocation Loc
) {
746 ASTContext
&Context
= getASTContext();
747 QualType T
= Context
.getObjCInstanceType();
748 TypeSourceInfo
*TInfo
= Context
.getTrivialTypeSourceInfo(T
, Loc
);
749 return SemaRef
.CreateParsedType(T
, TInfo
);
752 //===--- CHECK: Objective-C retain cycles ----------------------------------//
756 struct RetainCycleOwner
{
757 VarDecl
*Variable
= nullptr;
760 bool Indirect
= false;
762 RetainCycleOwner() = default;
764 void setLocsFrom(Expr
*e
) {
765 Loc
= e
->getExprLoc();
766 Range
= e
->getSourceRange();
772 /// Consider whether capturing the given variable can possibly lead to
774 static bool considerVariable(VarDecl
*var
, Expr
*ref
, RetainCycleOwner
&owner
) {
775 // In ARC, it's captured strongly iff the variable has __strong
776 // lifetime. In MRR, it's captured strongly if the variable is
777 // __block and has an appropriate type.
778 if (var
->getType().getObjCLifetime() != Qualifiers::OCL_Strong
)
781 owner
.Variable
= var
;
783 owner
.setLocsFrom(ref
);
787 static bool findRetainCycleOwner(Sema
&S
, Expr
*e
, RetainCycleOwner
&owner
) {
789 e
= e
->IgnoreParens();
790 if (CastExpr
*cast
= dyn_cast
<CastExpr
>(e
)) {
791 switch (cast
->getCastKind()) {
793 case CK_LValueBitCast
:
794 case CK_LValueToRValue
:
795 case CK_ARCReclaimReturnedObject
:
796 e
= cast
->getSubExpr();
804 if (ObjCIvarRefExpr
*ref
= dyn_cast
<ObjCIvarRefExpr
>(e
)) {
805 ObjCIvarDecl
*ivar
= ref
->getDecl();
806 if (ivar
->getType().getObjCLifetime() != Qualifiers::OCL_Strong
)
809 // Try to find a retain cycle in the base.
810 if (!findRetainCycleOwner(S
, ref
->getBase(), owner
))
813 if (ref
->isFreeIvar())
814 owner
.setLocsFrom(ref
);
815 owner
.Indirect
= true;
819 if (DeclRefExpr
*ref
= dyn_cast
<DeclRefExpr
>(e
)) {
820 VarDecl
*var
= dyn_cast
<VarDecl
>(ref
->getDecl());
823 return considerVariable(var
, ref
, owner
);
826 if (MemberExpr
*member
= dyn_cast
<MemberExpr
>(e
)) {
827 if (member
->isArrow())
830 // Don't count this as an indirect ownership.
831 e
= member
->getBase();
835 if (PseudoObjectExpr
*pseudo
= dyn_cast
<PseudoObjectExpr
>(e
)) {
836 // Only pay attention to pseudo-objects on property references.
837 ObjCPropertyRefExpr
*pre
= dyn_cast
<ObjCPropertyRefExpr
>(
838 pseudo
->getSyntacticForm()->IgnoreParens());
841 if (pre
->isImplicitProperty())
843 ObjCPropertyDecl
*property
= pre
->getExplicitProperty();
844 if (!property
->isRetaining() &&
845 !(property
->getPropertyIvarDecl() &&
846 property
->getPropertyIvarDecl()->getType().getObjCLifetime() ==
847 Qualifiers::OCL_Strong
))
850 owner
.Indirect
= true;
851 if (pre
->isSuperReceiver()) {
852 owner
.Variable
= S
.getCurMethodDecl()->getSelfDecl();
855 owner
.Loc
= pre
->getLocation();
856 owner
.Range
= pre
->getSourceRange();
859 e
= const_cast<Expr
*>(
860 cast
<OpaqueValueExpr
>(pre
->getBase())->getSourceExpr());
872 struct FindCaptureVisitor
: EvaluatedExprVisitor
<FindCaptureVisitor
> {
874 Expr
*Capturer
= nullptr;
875 bool VarWillBeReased
= false;
877 FindCaptureVisitor(ASTContext
&Context
, VarDecl
*variable
)
878 : EvaluatedExprVisitor
<FindCaptureVisitor
>(Context
), Variable(variable
) {}
880 void VisitDeclRefExpr(DeclRefExpr
*ref
) {
881 if (ref
->getDecl() == Variable
&& !Capturer
)
885 void VisitObjCIvarRefExpr(ObjCIvarRefExpr
*ref
) {
888 Visit(ref
->getBase());
889 if (Capturer
&& ref
->isFreeIvar())
893 void VisitBlockExpr(BlockExpr
*block
) {
894 // Look inside nested blocks
895 if (block
->getBlockDecl()->capturesVariable(Variable
))
896 Visit(block
->getBlockDecl()->getBody());
899 void VisitOpaqueValueExpr(OpaqueValueExpr
*OVE
) {
902 if (OVE
->getSourceExpr())
903 Visit(OVE
->getSourceExpr());
906 void VisitBinaryOperator(BinaryOperator
*BinOp
) {
907 if (!Variable
|| VarWillBeReased
|| BinOp
->getOpcode() != BO_Assign
)
909 Expr
*LHS
= BinOp
->getLHS();
910 if (const DeclRefExpr
*DRE
= dyn_cast_or_null
<DeclRefExpr
>(LHS
)) {
911 if (DRE
->getDecl() != Variable
)
913 if (Expr
*RHS
= BinOp
->getRHS()) {
914 RHS
= RHS
->IgnoreParenCasts();
915 std::optional
<llvm::APSInt
> Value
;
917 (RHS
&& (Value
= RHS
->getIntegerConstantExpr(Context
)) &&
926 /// Check whether the given argument is a block which captures a
928 static Expr
*findCapturingExpr(Sema
&S
, Expr
*e
, RetainCycleOwner
&owner
) {
929 assert(owner
.Variable
&& owner
.Loc
.isValid());
931 e
= e
->IgnoreParenCasts();
933 // Look through [^{...} copy] and Block_copy(^{...}).
934 if (ObjCMessageExpr
*ME
= dyn_cast
<ObjCMessageExpr
>(e
)) {
935 Selector Cmd
= ME
->getSelector();
936 if (Cmd
.isUnarySelector() && Cmd
.getNameForSlot(0) == "copy") {
937 e
= ME
->getInstanceReceiver();
940 e
= e
->IgnoreParenCasts();
942 } else if (CallExpr
*CE
= dyn_cast
<CallExpr
>(e
)) {
943 if (CE
->getNumArgs() == 1) {
944 FunctionDecl
*Fn
= dyn_cast_or_null
<FunctionDecl
>(CE
->getCalleeDecl());
946 const IdentifierInfo
*FnI
= Fn
->getIdentifier();
947 if (FnI
&& FnI
->isStr("_Block_copy")) {
948 e
= CE
->getArg(0)->IgnoreParenCasts();
954 BlockExpr
*block
= dyn_cast
<BlockExpr
>(e
);
955 if (!block
|| !block
->getBlockDecl()->capturesVariable(owner
.Variable
))
958 FindCaptureVisitor
visitor(S
.Context
, owner
.Variable
);
959 visitor
.Visit(block
->getBlockDecl()->getBody());
960 return visitor
.VarWillBeReased
? nullptr : visitor
.Capturer
;
963 static void diagnoseRetainCycle(Sema
&S
, Expr
*capturer
,
964 RetainCycleOwner
&owner
) {
966 assert(owner
.Variable
&& owner
.Loc
.isValid());
968 S
.Diag(capturer
->getExprLoc(), diag::warn_arc_retain_cycle
)
969 << owner
.Variable
<< capturer
->getSourceRange();
970 S
.Diag(owner
.Loc
, diag::note_arc_retain_cycle_owner
)
971 << owner
.Indirect
<< owner
.Range
;
974 /// Check for a keyword selector that starts with the word 'add' or
976 static bool isSetterLikeSelector(Selector sel
) {
977 if (sel
.isUnarySelector())
980 StringRef str
= sel
.getNameForSlot(0);
981 str
= str
.ltrim('_');
982 if (str
.starts_with("set"))
984 else if (str
.starts_with("add")) {
985 // Specially allow 'addOperationWithBlock:'.
986 if (sel
.getNumArgs() == 1 && str
.starts_with("addOperationWithBlock"))
994 return !isLowercase(str
.front());
997 static std::optional
<int>
998 GetNSMutableArrayArgumentIndex(SemaObjC
&S
, ObjCMessageExpr
*Message
) {
999 bool IsMutableArray
= S
.NSAPIObj
->isSubclassOfNSClass(
1000 Message
->getReceiverInterface(), NSAPI::ClassId_NSMutableArray
);
1001 if (!IsMutableArray
) {
1002 return std::nullopt
;
1005 Selector Sel
= Message
->getSelector();
1007 std::optional
<NSAPI::NSArrayMethodKind
> MKOpt
=
1008 S
.NSAPIObj
->getNSArrayMethodKind(Sel
);
1010 return std::nullopt
;
1013 NSAPI::NSArrayMethodKind MK
= *MKOpt
;
1016 case NSAPI::NSMutableArr_addObject
:
1017 case NSAPI::NSMutableArr_insertObjectAtIndex
:
1018 case NSAPI::NSMutableArr_setObjectAtIndexedSubscript
:
1020 case NSAPI::NSMutableArr_replaceObjectAtIndex
:
1024 return std::nullopt
;
1027 return std::nullopt
;
1030 static std::optional
<int>
1031 GetNSMutableDictionaryArgumentIndex(SemaObjC
&S
, ObjCMessageExpr
*Message
) {
1032 bool IsMutableDictionary
= S
.NSAPIObj
->isSubclassOfNSClass(
1033 Message
->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary
);
1034 if (!IsMutableDictionary
) {
1035 return std::nullopt
;
1038 Selector Sel
= Message
->getSelector();
1040 std::optional
<NSAPI::NSDictionaryMethodKind
> MKOpt
=
1041 S
.NSAPIObj
->getNSDictionaryMethodKind(Sel
);
1043 return std::nullopt
;
1046 NSAPI::NSDictionaryMethodKind MK
= *MKOpt
;
1049 case NSAPI::NSMutableDict_setObjectForKey
:
1050 case NSAPI::NSMutableDict_setValueForKey
:
1051 case NSAPI::NSMutableDict_setObjectForKeyedSubscript
:
1055 return std::nullopt
;
1058 return std::nullopt
;
1061 static std::optional
<int> GetNSSetArgumentIndex(SemaObjC
&S
,
1062 ObjCMessageExpr
*Message
) {
1063 bool IsMutableSet
= S
.NSAPIObj
->isSubclassOfNSClass(
1064 Message
->getReceiverInterface(), NSAPI::ClassId_NSMutableSet
);
1066 bool IsMutableOrderedSet
= S
.NSAPIObj
->isSubclassOfNSClass(
1067 Message
->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet
);
1068 if (!IsMutableSet
&& !IsMutableOrderedSet
) {
1069 return std::nullopt
;
1072 Selector Sel
= Message
->getSelector();
1074 std::optional
<NSAPI::NSSetMethodKind
> MKOpt
=
1075 S
.NSAPIObj
->getNSSetMethodKind(Sel
);
1077 return std::nullopt
;
1080 NSAPI::NSSetMethodKind MK
= *MKOpt
;
1083 case NSAPI::NSMutableSet_addObject
:
1084 case NSAPI::NSOrderedSet_setObjectAtIndex
:
1085 case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript
:
1086 case NSAPI::NSOrderedSet_insertObjectAtIndex
:
1088 case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject
:
1092 return std::nullopt
;
1095 void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr
*Message
) {
1096 if (!Message
->isInstanceMessage()) {
1100 std::optional
<int> ArgOpt
;
1102 if (!(ArgOpt
= GetNSMutableArrayArgumentIndex(*this, Message
)) &&
1103 !(ArgOpt
= GetNSMutableDictionaryArgumentIndex(*this, Message
)) &&
1104 !(ArgOpt
= GetNSSetArgumentIndex(*this, Message
))) {
1108 int ArgIndex
= *ArgOpt
;
1110 Expr
*Arg
= Message
->getArg(ArgIndex
)->IgnoreImpCasts();
1111 if (OpaqueValueExpr
*OE
= dyn_cast
<OpaqueValueExpr
>(Arg
)) {
1112 Arg
= OE
->getSourceExpr()->IgnoreImpCasts();
1115 if (Message
->getReceiverKind() == ObjCMessageExpr::SuperInstance
) {
1116 if (DeclRefExpr
*ArgRE
= dyn_cast
<DeclRefExpr
>(Arg
)) {
1117 if (ArgRE
->isObjCSelfExpr()) {
1118 Diag(Message
->getSourceRange().getBegin(),
1119 diag::warn_objc_circular_container
)
1120 << ArgRE
->getDecl() << StringRef("'super'");
1124 Expr
*Receiver
= Message
->getInstanceReceiver()->IgnoreImpCasts();
1126 if (OpaqueValueExpr
*OE
= dyn_cast
<OpaqueValueExpr
>(Receiver
)) {
1127 Receiver
= OE
->getSourceExpr()->IgnoreImpCasts();
1130 if (DeclRefExpr
*ReceiverRE
= dyn_cast
<DeclRefExpr
>(Receiver
)) {
1131 if (DeclRefExpr
*ArgRE
= dyn_cast
<DeclRefExpr
>(Arg
)) {
1132 if (ReceiverRE
->getDecl() == ArgRE
->getDecl()) {
1133 ValueDecl
*Decl
= ReceiverRE
->getDecl();
1134 Diag(Message
->getSourceRange().getBegin(),
1135 diag::warn_objc_circular_container
)
1137 if (!ArgRE
->isObjCSelfExpr()) {
1138 Diag(Decl
->getLocation(),
1139 diag::note_objc_circular_container_declared_here
)
1144 } else if (ObjCIvarRefExpr
*IvarRE
= dyn_cast
<ObjCIvarRefExpr
>(Receiver
)) {
1145 if (ObjCIvarRefExpr
*IvarArgRE
= dyn_cast
<ObjCIvarRefExpr
>(Arg
)) {
1146 if (IvarRE
->getDecl() == IvarArgRE
->getDecl()) {
1147 ObjCIvarDecl
*Decl
= IvarRE
->getDecl();
1148 Diag(Message
->getSourceRange().getBegin(),
1149 diag::warn_objc_circular_container
)
1151 Diag(Decl
->getLocation(),
1152 diag::note_objc_circular_container_declared_here
)
1160 /// Check a message send to see if it's likely to cause a retain cycle.
1161 void SemaObjC::checkRetainCycles(ObjCMessageExpr
*msg
) {
1162 // Only check instance methods whose selector looks like a setter.
1163 if (!msg
->isInstanceMessage() || !isSetterLikeSelector(msg
->getSelector()))
1166 // Try to find a variable that the receiver is strongly owned by.
1167 RetainCycleOwner owner
;
1168 if (msg
->getReceiverKind() == ObjCMessageExpr::Instance
) {
1169 if (!findRetainCycleOwner(SemaRef
, msg
->getInstanceReceiver(), owner
))
1172 assert(msg
->getReceiverKind() == ObjCMessageExpr::SuperInstance
);
1173 owner
.Variable
= SemaRef
.getCurMethodDecl()->getSelfDecl();
1174 owner
.Loc
= msg
->getSuperLoc();
1175 owner
.Range
= msg
->getSuperLoc();
1178 // Check whether the receiver is captured by any of the arguments.
1179 const ObjCMethodDecl
*MD
= msg
->getMethodDecl();
1180 for (unsigned i
= 0, e
= msg
->getNumArgs(); i
!= e
; ++i
) {
1181 if (Expr
*capturer
= findCapturingExpr(SemaRef
, msg
->getArg(i
), owner
)) {
1182 // noescape blocks should not be retained by the method.
1183 if (MD
&& MD
->parameters()[i
]->hasAttr
<NoEscapeAttr
>())
1185 return diagnoseRetainCycle(SemaRef
, capturer
, owner
);
1190 /// Check a property assign to see if it's likely to cause a retain cycle.
1191 void SemaObjC::checkRetainCycles(Expr
*receiver
, Expr
*argument
) {
1192 RetainCycleOwner owner
;
1193 if (!findRetainCycleOwner(SemaRef
, receiver
, owner
))
1196 if (Expr
*capturer
= findCapturingExpr(SemaRef
, argument
, owner
))
1197 diagnoseRetainCycle(SemaRef
, capturer
, owner
);
1200 void SemaObjC::checkRetainCycles(VarDecl
*Var
, Expr
*Init
) {
1201 RetainCycleOwner Owner
;
1202 if (!considerVariable(Var
, /*DeclRefExpr=*/nullptr, Owner
))
1205 // Because we don't have an expression for the variable, we have to set the
1206 // location explicitly here.
1207 Owner
.Loc
= Var
->getLocation();
1208 Owner
.Range
= Var
->getSourceRange();
1210 if (Expr
*Capturer
= findCapturingExpr(SemaRef
, Init
, Owner
))
1211 diagnoseRetainCycle(SemaRef
, Capturer
, Owner
);
1214 /// CheckObjCString - Checks that the argument to the builtin
1215 /// CFString constructor is correct
1216 /// Note: It might also make sense to do the UTF-16 conversion here (would
1217 /// simplify the backend).
1218 bool SemaObjC::CheckObjCString(Expr
*Arg
) {
1219 Arg
= Arg
->IgnoreParenCasts();
1220 StringLiteral
*Literal
= dyn_cast
<StringLiteral
>(Arg
);
1222 if (!Literal
|| !Literal
->isOrdinary()) {
1223 Diag(Arg
->getBeginLoc(), diag::err_cfstring_literal_not_string_constant
)
1224 << Arg
->getSourceRange();
1228 if (Literal
->containsNonAsciiOrNull()) {
1229 StringRef String
= Literal
->getString();
1230 unsigned NumBytes
= String
.size();
1231 SmallVector
<llvm::UTF16
, 128> ToBuf(NumBytes
);
1232 const llvm::UTF8
*FromPtr
= (const llvm::UTF8
*)String
.data();
1233 llvm::UTF16
*ToPtr
= &ToBuf
[0];
1235 llvm::ConversionResult Result
=
1236 llvm::ConvertUTF8toUTF16(&FromPtr
, FromPtr
+ NumBytes
, &ToPtr
,
1237 ToPtr
+ NumBytes
, llvm::strictConversion
);
1238 // Check for conversion failure.
1239 if (Result
!= llvm::conversionOK
)
1240 Diag(Arg
->getBeginLoc(), diag::warn_cfstring_truncated
)
1241 << Arg
->getSourceRange();
1246 bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl
*Method
, SourceLocation lbrac
,
1247 ArrayRef
<const Expr
*> Args
) {
1248 Sema::VariadicCallType CallType
=
1249 Method
->isVariadic() ? Sema::VariadicMethod
: Sema::VariadicDoesNotApply
;
1251 SemaRef
.checkCall(Method
, nullptr, /*ThisArg=*/nullptr, Args
,
1252 /*IsMemberFunction=*/false, lbrac
, Method
->getSourceRange(),
1255 SemaRef
.CheckTCBEnforcement(lbrac
, Method
);
1260 const DeclContext
*SemaObjC::getCurObjCLexicalContext() const {
1261 const DeclContext
*DC
= SemaRef
.getCurLexicalContext();
1262 // A category implicitly has the attribute of the interface.
1263 if (const ObjCCategoryDecl
*CatD
= dyn_cast
<ObjCCategoryDecl
>(DC
))
1264 DC
= CatD
->getClassInterface();
1268 /// Retrieve the identifier "NSError".
1269 IdentifierInfo
*SemaObjC::getNSErrorIdent() {
1271 Ident_NSError
= SemaRef
.PP
.getIdentifierInfo("NSError");
1273 return Ident_NSError
;
1276 void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl
*IDecl
) {
1278 IDecl
->getLexicalParent() == SemaRef
.CurContext
&&
1279 "The next DeclContext should be lexically contained in the current one.");
1280 SemaRef
.CurContext
= IDecl
;
1283 void SemaObjC::ActOnObjCContainerFinishDefinition() {
1284 // Exit this scope of this interface definition.
1285 SemaRef
.PopDeclContext();
1288 void SemaObjC::ActOnObjCTemporaryExitContainerContext(
1289 ObjCContainerDecl
*ObjCCtx
) {
1290 assert(ObjCCtx
== SemaRef
.CurContext
&& "Mismatch of container contexts");
1291 SemaRef
.OriginalLexicalContext
= ObjCCtx
;
1292 ActOnObjCContainerFinishDefinition();
1295 void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl
*ObjCCtx
) {
1296 ActOnObjCContainerStartDefinition(ObjCCtx
);
1297 SemaRef
.OriginalLexicalContext
= nullptr;
1300 /// Find the protocol with the given name, if any.
1301 ObjCProtocolDecl
*SemaObjC::LookupProtocol(IdentifierInfo
*II
,
1302 SourceLocation IdLoc
,
1303 RedeclarationKind Redecl
) {
1304 Decl
*D
= SemaRef
.LookupSingleName(SemaRef
.TUScope
, II
, IdLoc
,
1305 Sema::LookupObjCProtocolName
, Redecl
);
1306 return cast_or_null
<ObjCProtocolDecl
>(D
);
1309 /// Determine whether this is an Objective-C writeback conversion,
1310 /// used for parameter passing when performing automatic reference counting.
1312 /// \param FromType The type we're converting form.
1314 /// \param ToType The type we're converting to.
1316 /// \param ConvertedType The type that will be produced after applying
1317 /// this conversion.
1318 bool SemaObjC::isObjCWritebackConversion(QualType FromType
, QualType ToType
,
1319 QualType
&ConvertedType
) {
1320 ASTContext
&Context
= getASTContext();
1321 if (!getLangOpts().ObjCAutoRefCount
||
1322 Context
.hasSameUnqualifiedType(FromType
, ToType
))
1325 // Parameter must be a pointer to __autoreleasing (with no other qualifiers).
1327 if (const PointerType
*ToPointer
= ToType
->getAs
<PointerType
>())
1328 ToPointee
= ToPointer
->getPointeeType();
1332 Qualifiers ToQuals
= ToPointee
.getQualifiers();
1333 if (!ToPointee
->isObjCLifetimeType() ||
1334 ToQuals
.getObjCLifetime() != Qualifiers::OCL_Autoreleasing
||
1335 !ToQuals
.withoutObjCLifetime().empty())
1338 // Argument must be a pointer to __strong to __weak.
1339 QualType FromPointee
;
1340 if (const PointerType
*FromPointer
= FromType
->getAs
<PointerType
>())
1341 FromPointee
= FromPointer
->getPointeeType();
1345 Qualifiers FromQuals
= FromPointee
.getQualifiers();
1346 if (!FromPointee
->isObjCLifetimeType() ||
1347 (FromQuals
.getObjCLifetime() != Qualifiers::OCL_Strong
&&
1348 FromQuals
.getObjCLifetime() != Qualifiers::OCL_Weak
))
1351 // Make sure that we have compatible qualifiers.
1352 FromQuals
.setObjCLifetime(Qualifiers::OCL_Autoreleasing
);
1353 if (!ToQuals
.compatiblyIncludes(FromQuals
, getASTContext()))
1356 // Remove qualifiers from the pointee type we're converting from; they
1357 // aren't used in the compatibility check belong, and we'll be adding back
1358 // qualifiers (with __autoreleasing) if the compatibility check succeeds.
1359 FromPointee
= FromPointee
.getUnqualifiedType();
1361 // The unqualified form of the pointee types must be compatible.
1362 ToPointee
= ToPointee
.getUnqualifiedType();
1363 bool IncompatibleObjC
;
1364 if (Context
.typesAreCompatible(FromPointee
, ToPointee
))
1365 FromPointee
= ToPointee
;
1366 else if (!SemaRef
.isObjCPointerConversion(FromPointee
, ToPointee
, FromPointee
,
1370 /// Construct the type we're converting to, which is a pointer to
1371 /// __autoreleasing pointee.
1372 FromPointee
= Context
.getQualifiedType(FromPointee
, FromQuals
);
1373 ConvertedType
= Context
.getPointerType(FromPointee
);
1377 /// CheckSubscriptingKind - This routine decide what type
1378 /// of indexing represented by "FromE" is being done.
1379 SemaObjC::ObjCSubscriptKind
SemaObjC::CheckSubscriptingKind(Expr
*FromE
) {
1380 // If the expression already has integral or enumeration type, we're golden.
1381 QualType T
= FromE
->getType();
1382 if (T
->isIntegralOrEnumerationType())
1383 return SemaObjC::OS_Array
;
1385 // If we don't have a class type in C++, there's no way we can get an
1386 // expression of integral or enumeration type.
1387 const RecordType
*RecordTy
= T
->getAs
<RecordType
>();
1388 if (!RecordTy
&& (T
->isObjCObjectPointerType() || T
->isVoidPointerType()))
1389 // All other scalar cases are assumed to be dictionary indexing which
1390 // caller handles, with diagnostics if needed.
1391 return SemaObjC::OS_Dictionary
;
1392 if (!getLangOpts().CPlusPlus
|| !RecordTy
|| RecordTy
->isIncompleteType()) {
1393 // No indexing can be done. Issue diagnostics and quit.
1394 const Expr
*IndexExpr
= FromE
->IgnoreParenImpCasts();
1395 if (isa
<StringLiteral
>(IndexExpr
))
1396 Diag(FromE
->getExprLoc(), diag::err_objc_subscript_pointer
)
1397 << T
<< FixItHint::CreateInsertion(FromE
->getExprLoc(), "@");
1399 Diag(FromE
->getExprLoc(), diag::err_objc_subscript_type_conversion
) << T
;
1400 return SemaObjC::OS_Error
;
1403 // We must have a complete class type.
1404 if (SemaRef
.RequireCompleteType(FromE
->getExprLoc(), T
,
1405 diag::err_objc_index_incomplete_class_type
,
1407 return SemaObjC::OS_Error
;
1409 // Look for a conversion to an integral, enumeration type, or
1410 // objective-C pointer type.
1411 int NoIntegrals
= 0, NoObjCIdPointers
= 0;
1412 SmallVector
<CXXConversionDecl
*, 4> ConversionDecls
;
1414 for (NamedDecl
*D
: cast
<CXXRecordDecl
>(RecordTy
->getDecl())
1415 ->getVisibleConversionFunctions()) {
1416 if (CXXConversionDecl
*Conversion
=
1417 dyn_cast
<CXXConversionDecl
>(D
->getUnderlyingDecl())) {
1418 QualType CT
= Conversion
->getConversionType().getNonReferenceType();
1419 if (CT
->isIntegralOrEnumerationType()) {
1421 ConversionDecls
.push_back(Conversion
);
1422 } else if (CT
->isObjCIdType() || CT
->isBlockPointerType()) {
1424 ConversionDecls
.push_back(Conversion
);
1428 if (NoIntegrals
== 1 && NoObjCIdPointers
== 0)
1429 return SemaObjC::OS_Array
;
1430 if (NoIntegrals
== 0 && NoObjCIdPointers
== 1)
1431 return SemaObjC::OS_Dictionary
;
1432 if (NoIntegrals
== 0 && NoObjCIdPointers
== 0) {
1433 // No conversion function was found. Issue diagnostic and return.
1434 Diag(FromE
->getExprLoc(), diag::err_objc_subscript_type_conversion
)
1435 << FromE
->getType();
1436 return SemaObjC::OS_Error
;
1438 Diag(FromE
->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion
)
1439 << FromE
->getType();
1440 for (unsigned int i
= 0; i
< ConversionDecls
.size(); i
++)
1441 Diag(ConversionDecls
[i
]->getLocation(),
1442 diag::note_conv_function_declared_at
);
1444 return SemaObjC::OS_Error
;
1447 void SemaObjC::AddCFAuditedAttribute(Decl
*D
) {
1448 ASTContext
&Context
= getASTContext();
1449 IdentifierInfo
*Ident
;
1451 std::tie(Ident
, Loc
) = SemaRef
.PP
.getPragmaARCCFCodeAuditedInfo();
1455 // Don't add a redundant or conflicting attribute.
1456 if (D
->hasAttr
<CFAuditedTransferAttr
>() ||
1457 D
->hasAttr
<CFUnknownTransferAttr
>())
1460 AttributeCommonInfo
Info(Ident
, SourceRange(Loc
),
1461 AttributeCommonInfo::Form::Pragma());
1462 D
->addAttr(CFAuditedTransferAttr::CreateImplicit(Context
, Info
));
1465 bool SemaObjC::isCFError(RecordDecl
*RD
) {
1466 // If we already know about CFError, test it directly.
1468 return CFError
== RD
;
1470 // Check whether this is CFError, which we identify based on its bridge to
1471 // NSError. CFErrorRef used to be declared with "objc_bridge" but is now
1472 // declared with "objc_bridge_mutable", so look for either one of the two
1474 if (RD
->getTagKind() == TagTypeKind::Struct
) {
1475 IdentifierInfo
*bridgedType
= nullptr;
1476 if (auto bridgeAttr
= RD
->getAttr
<ObjCBridgeAttr
>())
1477 bridgedType
= bridgeAttr
->getBridgedType();
1478 else if (auto bridgeAttr
= RD
->getAttr
<ObjCBridgeMutableAttr
>())
1479 bridgedType
= bridgeAttr
->getBridgedType();
1481 if (bridgedType
== getNSErrorIdent()) {
1490 bool SemaObjC::isNSStringType(QualType T
, bool AllowNSAttributedString
) {
1491 const auto *PT
= T
->getAs
<ObjCObjectPointerType
>();
1495 ObjCInterfaceDecl
*Cls
= PT
->getObjectType()->getInterface();
1499 IdentifierInfo
*ClsName
= Cls
->getIdentifier();
1501 if (AllowNSAttributedString
&&
1502 ClsName
== &getASTContext().Idents
.get("NSAttributedString"))
1504 // FIXME: Should we walk the chain of classes?
1505 return ClsName
== &getASTContext().Idents
.get("NSString") ||
1506 ClsName
== &getASTContext().Idents
.get("NSMutableString");
1509 bool SemaObjC::isCFStringType(QualType T
) {
1510 const auto *PT
= T
->getAs
<PointerType
>();
1514 const auto *RT
= PT
->getPointeeType()->getAs
<RecordType
>();
1518 const RecordDecl
*RD
= RT
->getDecl();
1519 if (RD
->getTagKind() != TagTypeKind::Struct
)
1522 return RD
->getIdentifier() == &getASTContext().Idents
.get("__CFString");
1525 static bool checkIBOutletCommon(Sema
&S
, Decl
*D
, const ParsedAttr
&AL
) {
1526 // The IBOutlet/IBOutletCollection attributes only apply to instance
1527 // variables or properties of Objective-C classes. The outlet must also
1528 // have an object reference type.
1529 if (const auto *VD
= dyn_cast
<ObjCIvarDecl
>(D
)) {
1530 if (!VD
->getType()->getAs
<ObjCObjectPointerType
>()) {
1531 S
.Diag(AL
.getLoc(), diag::warn_iboutlet_object_type
)
1532 << AL
<< VD
->getType() << 0;
1535 } else if (const auto *PD
= dyn_cast
<ObjCPropertyDecl
>(D
)) {
1536 if (!PD
->getType()->getAs
<ObjCObjectPointerType
>()) {
1537 S
.Diag(AL
.getLoc(), diag::warn_iboutlet_object_type
)
1538 << AL
<< PD
->getType() << 1;
1542 S
.Diag(AL
.getLoc(), diag::warn_attribute_iboutlet
) << AL
;
1549 void SemaObjC::handleIBOutlet(Decl
*D
, const ParsedAttr
&AL
) {
1550 if (!checkIBOutletCommon(SemaRef
, D
, AL
))
1553 D
->addAttr(::new (getASTContext()) IBOutletAttr(getASTContext(), AL
));
1556 void SemaObjC::handleIBOutletCollection(Decl
*D
, const ParsedAttr
&AL
) {
1558 ASTContext
&Context
= getASTContext();
1559 // The iboutletcollection attribute can have zero or one arguments.
1560 if (AL
.getNumArgs() > 1) {
1561 Diag(AL
.getLoc(), diag::err_attribute_wrong_number_arguments
) << AL
<< 1;
1565 if (!checkIBOutletCommon(SemaRef
, D
, AL
))
1570 if (AL
.hasParsedType())
1571 PT
= AL
.getTypeArg();
1573 PT
= SemaRef
.getTypeName(
1574 Context
.Idents
.get("NSObject"), AL
.getLoc(),
1575 SemaRef
.getScopeForContext(D
->getDeclContext()->getParent()));
1577 Diag(AL
.getLoc(), diag::err_iboutletcollection_type
) << "NSObject";
1582 TypeSourceInfo
*QTLoc
= nullptr;
1583 QualType QT
= SemaRef
.GetTypeFromParser(PT
, &QTLoc
);
1585 QTLoc
= Context
.getTrivialTypeSourceInfo(QT
, AL
.getLoc());
1587 // Diagnose use of non-object type in iboutletcollection attribute.
1588 // FIXME. Gnu attribute extension ignores use of builtin types in
1589 // attributes. So, __attribute__((iboutletcollection(char))) will be
1590 // treated as __attribute__((iboutletcollection())).
1591 if (!QT
->isObjCIdType() && !QT
->isObjCObjectType()) {
1592 Diag(AL
.getLoc(), QT
->isBuiltinType()
1593 ? diag::err_iboutletcollection_builtintype
1594 : diag::err_iboutletcollection_type
)
1599 D
->addAttr(::new (Context
) IBOutletCollectionAttr(Context
, AL
, QTLoc
));
1602 void SemaObjC::handleSuppresProtocolAttr(Decl
*D
, const ParsedAttr
&AL
) {
1603 if (!cast
<ObjCProtocolDecl
>(D
)->isThisDeclarationADefinition()) {
1604 Diag(AL
.getLoc(), diag::err_objc_attr_protocol_requires_definition
)
1605 << AL
<< AL
.getRange();
1609 D
->addAttr(::new (getASTContext())
1610 ObjCExplicitProtocolImplAttr(getASTContext(), AL
));
1613 void SemaObjC::handleDirectAttr(Decl
*D
, const ParsedAttr
&AL
) {
1614 // objc_direct cannot be set on methods declared in the context of a protocol
1615 if (isa
<ObjCProtocolDecl
>(D
->getDeclContext())) {
1616 Diag(AL
.getLoc(), diag::err_objc_direct_on_protocol
) << false;
1620 if (getLangOpts().ObjCRuntime
.allowsDirectDispatch()) {
1621 handleSimpleAttribute
<ObjCDirectAttr
>(*this, D
, AL
);
1623 Diag(AL
.getLoc(), diag::warn_objc_direct_ignored
) << AL
;
1627 void SemaObjC::handleDirectMembersAttr(Decl
*D
, const ParsedAttr
&AL
) {
1628 if (getLangOpts().ObjCRuntime
.allowsDirectDispatch()) {
1629 handleSimpleAttribute
<ObjCDirectMembersAttr
>(*this, D
, AL
);
1631 Diag(AL
.getLoc(), diag::warn_objc_direct_ignored
) << AL
;
1635 void SemaObjC::handleMethodFamilyAttr(Decl
*D
, const ParsedAttr
&AL
) {
1636 const auto *M
= cast
<ObjCMethodDecl
>(D
);
1637 if (!AL
.isArgIdent(0)) {
1638 Diag(AL
.getLoc(), diag::err_attribute_argument_n_type
)
1639 << AL
<< 1 << AANT_ArgumentIdentifier
;
1643 IdentifierLoc
*IL
= AL
.getArgAsIdent(0);
1644 ObjCMethodFamilyAttr::FamilyKind F
;
1645 if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL
->Ident
->getName(), F
)) {
1646 Diag(IL
->Loc
, diag::warn_attribute_type_not_supported
) << AL
<< IL
->Ident
;
1650 if (F
== ObjCMethodFamilyAttr::OMF_init
&&
1651 !M
->getReturnType()->isObjCObjectPointerType()) {
1652 Diag(M
->getLocation(), diag::err_init_method_bad_return_type
)
1653 << M
->getReturnType();
1654 // Ignore the attribute.
1658 D
->addAttr(new (getASTContext())
1659 ObjCMethodFamilyAttr(getASTContext(), AL
, F
));
1662 void SemaObjC::handleNSObject(Decl
*D
, const ParsedAttr
&AL
) {
1663 if (const auto *TD
= dyn_cast
<TypedefNameDecl
>(D
)) {
1664 QualType T
= TD
->getUnderlyingType();
1665 if (!T
->isCARCBridgableType()) {
1666 Diag(TD
->getLocation(), diag::err_nsobject_attribute
);
1669 } else if (const auto *PD
= dyn_cast
<ObjCPropertyDecl
>(D
)) {
1670 QualType T
= PD
->getType();
1671 if (!T
->isCARCBridgableType()) {
1672 Diag(PD
->getLocation(), diag::err_nsobject_attribute
);
1676 // It is okay to include this attribute on properties, e.g.:
1678 // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
1680 // In this case it follows tradition and suppresses an error in the above
1682 Diag(D
->getLocation(), diag::warn_nsobject_attribute
);
1684 D
->addAttr(::new (getASTContext()) ObjCNSObjectAttr(getASTContext(), AL
));
1687 void SemaObjC::handleIndependentClass(Decl
*D
, const ParsedAttr
&AL
) {
1688 if (const auto *TD
= dyn_cast
<TypedefNameDecl
>(D
)) {
1689 QualType T
= TD
->getUnderlyingType();
1690 if (!T
->isObjCObjectPointerType()) {
1691 Diag(TD
->getLocation(), diag::warn_ptr_independentclass_attribute
);
1695 Diag(D
->getLocation(), diag::warn_independentclass_attribute
);
1698 D
->addAttr(::new (getASTContext())
1699 ObjCIndependentClassAttr(getASTContext(), AL
));
1702 void SemaObjC::handleBlocksAttr(Decl
*D
, const ParsedAttr
&AL
) {
1703 if (!AL
.isArgIdent(0)) {
1704 Diag(AL
.getLoc(), diag::err_attribute_argument_n_type
)
1705 << AL
<< 1 << AANT_ArgumentIdentifier
;
1709 IdentifierInfo
*II
= AL
.getArgAsIdent(0)->Ident
;
1710 BlocksAttr::BlockType type
;
1711 if (!BlocksAttr::ConvertStrToBlockType(II
->getName(), type
)) {
1712 Diag(AL
.getLoc(), diag::warn_attribute_type_not_supported
) << AL
<< II
;
1716 D
->addAttr(::new (getASTContext()) BlocksAttr(getASTContext(), AL
, type
));
1719 static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT
) {
1720 return QT
->isDependentType() || QT
->isObjCRetainableType();
1723 static bool isValidSubjectOfNSAttribute(QualType QT
) {
1724 return QT
->isDependentType() || QT
->isObjCObjectPointerType() ||
1725 QT
->isObjCNSObjectType();
1728 static bool isValidSubjectOfCFAttribute(QualType QT
) {
1729 return QT
->isDependentType() || QT
->isPointerType() ||
1730 isValidSubjectOfNSAttribute(QT
);
1733 static bool isValidSubjectOfOSAttribute(QualType QT
) {
1734 if (QT
->isDependentType())
1736 QualType PT
= QT
->getPointeeType();
1737 return !PT
.isNull() && PT
->getAsCXXRecordDecl() != nullptr;
1740 void SemaObjC::AddXConsumedAttr(Decl
*D
, const AttributeCommonInfo
&CI
,
1741 Sema::RetainOwnershipKind K
,
1742 bool IsTemplateInstantiation
) {
1743 ValueDecl
*VD
= cast
<ValueDecl
>(D
);
1745 case Sema::RetainOwnershipKind::OS
:
1746 handleSimpleAttributeOrDiagnose
<OSConsumedAttr
>(
1747 *this, VD
, CI
, isValidSubjectOfOSAttribute(VD
->getType()),
1748 diag::warn_ns_attribute_wrong_parameter_type
,
1749 /*ExtraArgs=*/CI
.getRange(), "os_consumed", /*pointers*/ 1);
1751 case Sema::RetainOwnershipKind::NS
:
1752 handleSimpleAttributeOrDiagnose
<NSConsumedAttr
>(
1753 *this, VD
, CI
, isValidSubjectOfNSAttribute(VD
->getType()),
1755 // These attributes are normally just advisory, but in ARC, ns_consumed
1756 // is significant. Allow non-dependent code to contain inappropriate
1757 // attributes even in ARC, but require template instantiations to be
1758 // set up correctly.
1759 ((IsTemplateInstantiation
&& getLangOpts().ObjCAutoRefCount
)
1760 ? diag::err_ns_attribute_wrong_parameter_type
1761 : diag::warn_ns_attribute_wrong_parameter_type
),
1762 /*ExtraArgs=*/CI
.getRange(), "ns_consumed", /*objc pointers*/ 0);
1764 case Sema::RetainOwnershipKind::CF
:
1765 handleSimpleAttributeOrDiagnose
<CFConsumedAttr
>(
1766 *this, VD
, CI
, isValidSubjectOfCFAttribute(VD
->getType()),
1767 diag::warn_ns_attribute_wrong_parameter_type
,
1768 /*ExtraArgs=*/CI
.getRange(), "cf_consumed", /*pointers*/ 1);
1773 Sema::RetainOwnershipKind
1774 SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr
&AL
) {
1775 switch (AL
.getKind()) {
1776 case ParsedAttr::AT_CFConsumed
:
1777 case ParsedAttr::AT_CFReturnsRetained
:
1778 case ParsedAttr::AT_CFReturnsNotRetained
:
1779 return Sema::RetainOwnershipKind::CF
;
1780 case ParsedAttr::AT_OSConsumesThis
:
1781 case ParsedAttr::AT_OSConsumed
:
1782 case ParsedAttr::AT_OSReturnsRetained
:
1783 case ParsedAttr::AT_OSReturnsNotRetained
:
1784 case ParsedAttr::AT_OSReturnsRetainedOnZero
:
1785 case ParsedAttr::AT_OSReturnsRetainedOnNonZero
:
1786 return Sema::RetainOwnershipKind::OS
;
1787 case ParsedAttr::AT_NSConsumesSelf
:
1788 case ParsedAttr::AT_NSConsumed
:
1789 case ParsedAttr::AT_NSReturnsRetained
:
1790 case ParsedAttr::AT_NSReturnsNotRetained
:
1791 case ParsedAttr::AT_NSReturnsAutoreleased
:
1792 return Sema::RetainOwnershipKind::NS
;
1794 llvm_unreachable("Wrong argument supplied");
1798 bool SemaObjC::checkNSReturnsRetainedReturnType(SourceLocation Loc
,
1800 if (isValidSubjectOfNSReturnsRetainedAttribute(QT
))
1803 Diag(Loc
, diag::warn_ns_attribute_wrong_return_type
)
1804 << "'ns_returns_retained'" << 0 << 0;
1808 /// \return whether the parameter is a pointer to OSObject pointer.
1809 bool SemaObjC::isValidOSObjectOutParameter(const Decl
*D
) {
1810 const auto *PVD
= dyn_cast
<ParmVarDecl
>(D
);
1813 QualType QT
= PVD
->getType();
1814 QualType PT
= QT
->getPointeeType();
1815 return !PT
.isNull() && isValidSubjectOfOSAttribute(PT
);
1818 void SemaObjC::handleXReturnsXRetainedAttr(Decl
*D
, const ParsedAttr
&AL
) {
1819 QualType ReturnType
;
1820 Sema::RetainOwnershipKind K
= parsedAttrToRetainOwnershipKind(AL
);
1822 if (const auto *MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
1823 ReturnType
= MD
->getReturnType();
1824 } else if (getLangOpts().ObjCAutoRefCount
&& hasDeclarator(D
) &&
1825 (AL
.getKind() == ParsedAttr::AT_NSReturnsRetained
)) {
1826 return; // ignore: was handled as a type attribute
1827 } else if (const auto *PD
= dyn_cast
<ObjCPropertyDecl
>(D
)) {
1828 ReturnType
= PD
->getType();
1829 } else if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
1830 ReturnType
= FD
->getReturnType();
1831 } else if (const auto *Param
= dyn_cast
<ParmVarDecl
>(D
)) {
1832 // Attributes on parameters are used for out-parameters,
1833 // passed as pointers-to-pointers.
1834 unsigned DiagID
= K
== Sema::RetainOwnershipKind::CF
1835 ? /*pointer-to-CF-pointer*/ 2
1836 : /*pointer-to-OSObject-pointer*/ 3;
1837 ReturnType
= Param
->getType()->getPointeeType();
1838 if (ReturnType
.isNull()) {
1839 Diag(D
->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type
)
1840 << AL
<< DiagID
<< AL
.getRange();
1843 } else if (AL
.isUsedAsTypeAttr()) {
1846 AttributeDeclKind ExpectedDeclKind
;
1847 switch (AL
.getKind()) {
1849 llvm_unreachable("invalid ownership attribute");
1850 case ParsedAttr::AT_NSReturnsRetained
:
1851 case ParsedAttr::AT_NSReturnsAutoreleased
:
1852 case ParsedAttr::AT_NSReturnsNotRetained
:
1853 ExpectedDeclKind
= ExpectedFunctionOrMethod
;
1856 case ParsedAttr::AT_OSReturnsRetained
:
1857 case ParsedAttr::AT_OSReturnsNotRetained
:
1858 case ParsedAttr::AT_CFReturnsRetained
:
1859 case ParsedAttr::AT_CFReturnsNotRetained
:
1860 ExpectedDeclKind
= ExpectedFunctionMethodOrParameter
;
1863 Diag(D
->getBeginLoc(), diag::warn_attribute_wrong_decl_type
)
1864 << AL
.getRange() << AL
<< AL
.isRegularKeywordAttribute()
1865 << ExpectedDeclKind
;
1871 unsigned ParmDiagID
= 2; // Pointer-to-CF-pointer
1872 switch (AL
.getKind()) {
1874 llvm_unreachable("invalid ownership attribute");
1875 case ParsedAttr::AT_NSReturnsRetained
:
1876 TypeOK
= isValidSubjectOfNSReturnsRetainedAttribute(ReturnType
);
1880 case ParsedAttr::AT_NSReturnsAutoreleased
:
1881 case ParsedAttr::AT_NSReturnsNotRetained
:
1882 TypeOK
= isValidSubjectOfNSAttribute(ReturnType
);
1886 case ParsedAttr::AT_CFReturnsRetained
:
1887 case ParsedAttr::AT_CFReturnsNotRetained
:
1888 TypeOK
= isValidSubjectOfCFAttribute(ReturnType
);
1892 case ParsedAttr::AT_OSReturnsRetained
:
1893 case ParsedAttr::AT_OSReturnsNotRetained
:
1894 TypeOK
= isValidSubjectOfOSAttribute(ReturnType
);
1896 ParmDiagID
= 3; // Pointer-to-OSObject-pointer
1901 if (AL
.isUsedAsTypeAttr())
1904 if (isa
<ParmVarDecl
>(D
)) {
1905 Diag(D
->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type
)
1906 << AL
<< ParmDiagID
<< AL
.getRange();
1908 // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
1909 enum : unsigned { Function
, Method
, Property
} SubjectKind
= Function
;
1910 if (isa
<ObjCMethodDecl
>(D
))
1911 SubjectKind
= Method
;
1912 else if (isa
<ObjCPropertyDecl
>(D
))
1913 SubjectKind
= Property
;
1914 Diag(D
->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type
)
1915 << AL
<< SubjectKind
<< Cf
<< AL
.getRange();
1920 switch (AL
.getKind()) {
1922 llvm_unreachable("invalid ownership attribute");
1923 case ParsedAttr::AT_NSReturnsAutoreleased
:
1924 handleSimpleAttribute
<NSReturnsAutoreleasedAttr
>(*this, D
, AL
);
1926 case ParsedAttr::AT_CFReturnsNotRetained
:
1927 handleSimpleAttribute
<CFReturnsNotRetainedAttr
>(*this, D
, AL
);
1929 case ParsedAttr::AT_NSReturnsNotRetained
:
1930 handleSimpleAttribute
<NSReturnsNotRetainedAttr
>(*this, D
, AL
);
1932 case ParsedAttr::AT_CFReturnsRetained
:
1933 handleSimpleAttribute
<CFReturnsRetainedAttr
>(*this, D
, AL
);
1935 case ParsedAttr::AT_NSReturnsRetained
:
1936 handleSimpleAttribute
<NSReturnsRetainedAttr
>(*this, D
, AL
);
1938 case ParsedAttr::AT_OSReturnsRetained
:
1939 handleSimpleAttribute
<OSReturnsRetainedAttr
>(*this, D
, AL
);
1941 case ParsedAttr::AT_OSReturnsNotRetained
:
1942 handleSimpleAttribute
<OSReturnsNotRetainedAttr
>(*this, D
, AL
);
1947 void SemaObjC::handleReturnsInnerPointerAttr(Decl
*D
, const ParsedAttr
&Attrs
) {
1948 const int EP_ObjCMethod
= 1;
1949 const int EP_ObjCProperty
= 2;
1951 SourceLocation loc
= Attrs
.getLoc();
1952 QualType resultType
;
1953 if (isa
<ObjCMethodDecl
>(D
))
1954 resultType
= cast
<ObjCMethodDecl
>(D
)->getReturnType();
1956 resultType
= cast
<ObjCPropertyDecl
>(D
)->getType();
1958 if (!resultType
->isReferenceType() &&
1959 (!resultType
->isPointerType() || resultType
->isObjCRetainableType())) {
1960 Diag(D
->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type
)
1961 << SourceRange(loc
) << Attrs
1962 << (isa
<ObjCMethodDecl
>(D
) ? EP_ObjCMethod
: EP_ObjCProperty
)
1963 << /*non-retainable pointer*/ 2;
1965 // Drop the attribute.
1969 D
->addAttr(::new (getASTContext())
1970 ObjCReturnsInnerPointerAttr(getASTContext(), Attrs
));
1973 void SemaObjC::handleRequiresSuperAttr(Decl
*D
, const ParsedAttr
&Attrs
) {
1974 const auto *Method
= cast
<ObjCMethodDecl
>(D
);
1976 const DeclContext
*DC
= Method
->getDeclContext();
1977 if (const auto *PDecl
= dyn_cast_if_present
<ObjCProtocolDecl
>(DC
)) {
1978 Diag(D
->getBeginLoc(), diag::warn_objc_requires_super_protocol
)
1980 Diag(PDecl
->getLocation(), diag::note_protocol_decl
);
1983 if (Method
->getMethodFamily() == OMF_dealloc
) {
1984 Diag(D
->getBeginLoc(), diag::warn_objc_requires_super_protocol
)
1989 D
->addAttr(::new (getASTContext())
1990 ObjCRequiresSuperAttr(getASTContext(), Attrs
));
1993 void SemaObjC::handleNSErrorDomain(Decl
*D
, const ParsedAttr
&Attr
) {
1994 if (!isa
<TagDecl
>(D
)) {
1995 Diag(D
->getBeginLoc(), diag::err_nserrordomain_invalid_decl
) << 0;
1999 IdentifierLoc
*IdentLoc
=
2000 Attr
.isArgIdent(0) ? Attr
.getArgAsIdent(0) : nullptr;
2001 if (!IdentLoc
|| !IdentLoc
->Ident
) {
2002 // Try to locate the argument directly.
2003 SourceLocation Loc
= Attr
.getLoc();
2004 if (Attr
.isArgExpr(0) && Attr
.getArgAsExpr(0))
2005 Loc
= Attr
.getArgAsExpr(0)->getBeginLoc();
2007 Diag(Loc
, diag::err_nserrordomain_invalid_decl
) << 0;
2011 // Verify that the identifier is a valid decl in the C decl namespace.
2012 LookupResult
Result(SemaRef
, DeclarationName(IdentLoc
->Ident
),
2014 Sema::LookupNameKind::LookupOrdinaryName
);
2015 if (!SemaRef
.LookupName(Result
, SemaRef
.TUScope
) ||
2016 !Result
.getAsSingle
<VarDecl
>()) {
2017 Diag(IdentLoc
->Loc
, diag::err_nserrordomain_invalid_decl
)
2018 << 1 << IdentLoc
->Ident
;
2022 D
->addAttr(::new (getASTContext())
2023 NSErrorDomainAttr(getASTContext(), Attr
, IdentLoc
->Ident
));
2026 void SemaObjC::handleBridgeAttr(Decl
*D
, const ParsedAttr
&AL
) {
2027 IdentifierLoc
*Parm
= AL
.isArgIdent(0) ? AL
.getArgAsIdent(0) : nullptr;
2030 Diag(D
->getBeginLoc(), diag::err_objc_attr_not_id
) << AL
<< 0;
2034 // Typedefs only allow objc_bridge(id) and have some additional checking.
2035 if (const auto *TD
= dyn_cast
<TypedefNameDecl
>(D
)) {
2036 if (!Parm
->Ident
->isStr("id")) {
2037 Diag(AL
.getLoc(), diag::err_objc_attr_typedef_not_id
) << AL
;
2041 // Only allow 'cv void *'.
2042 QualType T
= TD
->getUnderlyingType();
2043 if (!T
->isVoidPointerType()) {
2044 Diag(AL
.getLoc(), diag::err_objc_attr_typedef_not_void_pointer
);
2049 D
->addAttr(::new (getASTContext())
2050 ObjCBridgeAttr(getASTContext(), AL
, Parm
->Ident
));
2053 void SemaObjC::handleBridgeMutableAttr(Decl
*D
, const ParsedAttr
&AL
) {
2054 IdentifierLoc
*Parm
= AL
.isArgIdent(0) ? AL
.getArgAsIdent(0) : nullptr;
2057 Diag(D
->getBeginLoc(), diag::err_objc_attr_not_id
) << AL
<< 0;
2061 D
->addAttr(::new (getASTContext())
2062 ObjCBridgeMutableAttr(getASTContext(), AL
, Parm
->Ident
));
2065 void SemaObjC::handleBridgeRelatedAttr(Decl
*D
, const ParsedAttr
&AL
) {
2066 IdentifierInfo
*RelatedClass
=
2067 AL
.isArgIdent(0) ? AL
.getArgAsIdent(0)->Ident
: nullptr;
2068 if (!RelatedClass
) {
2069 Diag(D
->getBeginLoc(), diag::err_objc_attr_not_id
) << AL
<< 0;
2072 IdentifierInfo
*ClassMethod
=
2073 AL
.getArgAsIdent(1) ? AL
.getArgAsIdent(1)->Ident
: nullptr;
2074 IdentifierInfo
*InstanceMethod
=
2075 AL
.getArgAsIdent(2) ? AL
.getArgAsIdent(2)->Ident
: nullptr;
2076 D
->addAttr(::new (getASTContext()) ObjCBridgeRelatedAttr(
2077 getASTContext(), AL
, RelatedClass
, ClassMethod
, InstanceMethod
));
2080 void SemaObjC::handleDesignatedInitializer(Decl
*D
, const ParsedAttr
&AL
) {
2081 DeclContext
*Ctx
= D
->getDeclContext();
2083 // This attribute can only be applied to methods in interfaces or class
2085 if (!isa
<ObjCInterfaceDecl
>(Ctx
) &&
2086 !(isa
<ObjCCategoryDecl
>(Ctx
) &&
2087 cast
<ObjCCategoryDecl
>(Ctx
)->IsClassExtension())) {
2088 Diag(D
->getLocation(), diag::err_designated_init_attr_non_init
);
2092 ObjCInterfaceDecl
*IFace
;
2093 if (auto *CatDecl
= dyn_cast
<ObjCCategoryDecl
>(Ctx
))
2094 IFace
= CatDecl
->getClassInterface();
2096 IFace
= cast
<ObjCInterfaceDecl
>(Ctx
);
2101 IFace
->setHasDesignatedInitializers();
2102 D
->addAttr(::new (getASTContext())
2103 ObjCDesignatedInitializerAttr(getASTContext(), AL
));
2106 void SemaObjC::handleRuntimeName(Decl
*D
, const ParsedAttr
&AL
) {
2107 StringRef MetaDataName
;
2108 if (!SemaRef
.checkStringLiteralArgumentAttr(AL
, 0, MetaDataName
))
2110 D
->addAttr(::new (getASTContext())
2111 ObjCRuntimeNameAttr(getASTContext(), AL
, MetaDataName
));
2114 // When a user wants to use objc_boxable with a union or struct
2115 // but they don't have access to the declaration (legacy/third-party code)
2116 // then they can 'enable' this feature with a typedef:
2117 // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
2118 void SemaObjC::handleBoxable(Decl
*D
, const ParsedAttr
&AL
) {
2119 bool notify
= false;
2121 auto *RD
= dyn_cast
<RecordDecl
>(D
);
2122 if (RD
&& RD
->getDefinition()) {
2123 RD
= RD
->getDefinition();
2128 ObjCBoxableAttr
*BoxableAttr
=
2129 ::new (getASTContext()) ObjCBoxableAttr(getASTContext(), AL
);
2130 RD
->addAttr(BoxableAttr
);
2132 // we need to notify ASTReader/ASTWriter about
2133 // modification of existing declaration
2134 if (ASTMutationListener
*L
= SemaRef
.getASTMutationListener())
2135 L
->AddedAttributeToRecord(BoxableAttr
, RD
);
2140 void SemaObjC::handleOwnershipAttr(Decl
*D
, const ParsedAttr
&AL
) {
2141 if (hasDeclarator(D
))
2144 Diag(D
->getBeginLoc(), diag::err_attribute_wrong_decl_type
)
2145 << AL
.getRange() << AL
<< AL
.isRegularKeywordAttribute()
2146 << ExpectedVariable
;
2149 void SemaObjC::handlePreciseLifetimeAttr(Decl
*D
, const ParsedAttr
&AL
) {
2150 const auto *VD
= cast
<ValueDecl
>(D
);
2151 QualType QT
= VD
->getType();
2153 if (!QT
->isDependentType() && !QT
->isObjCLifetimeType()) {
2154 Diag(AL
.getLoc(), diag::err_objc_precise_lifetime_bad_type
) << QT
;
2158 Qualifiers::ObjCLifetime Lifetime
= QT
.getObjCLifetime();
2160 // If we have no lifetime yet, check the lifetime we're presumably
2162 if (Lifetime
== Qualifiers::OCL_None
&& !QT
->isDependentType())
2163 Lifetime
= QT
->getObjCARCImplicitLifetime();
2166 case Qualifiers::OCL_None
:
2167 assert(QT
->isDependentType() &&
2168 "didn't infer lifetime for non-dependent type?");
2171 case Qualifiers::OCL_Weak
: // meaningful
2172 case Qualifiers::OCL_Strong
: // meaningful
2175 case Qualifiers::OCL_ExplicitNone
:
2176 case Qualifiers::OCL_Autoreleasing
:
2177 Diag(AL
.getLoc(), diag::warn_objc_precise_lifetime_meaningless
)
2178 << (Lifetime
== Qualifiers::OCL_Autoreleasing
);
2182 D
->addAttr(::new (getASTContext())
2183 ObjCPreciseLifetimeAttr(getASTContext(), AL
));
2186 static bool tryMakeVariablePseudoStrong(Sema
&S
, VarDecl
*VD
,
2187 bool DiagnoseFailure
) {
2188 QualType Ty
= VD
->getType();
2189 if (!Ty
->isObjCRetainableType()) {
2190 if (DiagnoseFailure
) {
2191 S
.Diag(VD
->getBeginLoc(), diag::warn_ignored_objc_externally_retained
)
2197 Qualifiers::ObjCLifetime LifetimeQual
= Ty
.getQualifiers().getObjCLifetime();
2199 // SemaObjC::inferObjCARCLifetime must run after processing decl attributes
2200 // (because __block lowers to an attribute), so if the lifetime hasn't been
2201 // explicitly specified, infer it locally now.
2202 if (LifetimeQual
== Qualifiers::OCL_None
)
2203 LifetimeQual
= Ty
->getObjCARCImplicitLifetime();
2205 // The attributes only really makes sense for __strong variables; ignore any
2206 // attempts to annotate a parameter with any other lifetime qualifier.
2207 if (LifetimeQual
!= Qualifiers::OCL_Strong
) {
2208 if (DiagnoseFailure
) {
2209 S
.Diag(VD
->getBeginLoc(), diag::warn_ignored_objc_externally_retained
)
2215 // Tampering with the type of a VarDecl here is a bit of a hack, but we need
2216 // to ensure that the variable is 'const' so that we can error on
2217 // modification, which can otherwise over-release.
2218 VD
->setType(Ty
.withConst());
2219 VD
->setARCPseudoStrong(true);
2223 void SemaObjC::handleExternallyRetainedAttr(Decl
*D
, const ParsedAttr
&AL
) {
2224 if (auto *VD
= dyn_cast
<VarDecl
>(D
)) {
2225 assert(!isa
<ParmVarDecl
>(VD
) && "should be diagnosed automatically");
2226 if (!VD
->hasLocalStorage()) {
2227 Diag(D
->getBeginLoc(), diag::warn_ignored_objc_externally_retained
) << 0;
2231 if (!tryMakeVariablePseudoStrong(SemaRef
, VD
, /*DiagnoseFailure=*/true))
2234 handleSimpleAttribute
<ObjCExternallyRetainedAttr
>(*this, D
, AL
);
2238 // If D is a function-like declaration (method, block, or function), then we
2239 // make every parameter psuedo-strong.
2240 unsigned NumParams
=
2241 hasFunctionProto(D
) ? getFunctionOrMethodNumParams(D
) : 0;
2242 for (unsigned I
= 0; I
!= NumParams
; ++I
) {
2243 auto *PVD
= const_cast<ParmVarDecl
*>(getFunctionOrMethodParam(D
, I
));
2244 QualType Ty
= PVD
->getType();
2246 // If a user wrote a parameter with __strong explicitly, then assume they
2247 // want "real" strong semantics for that parameter. This works because if
2248 // the parameter was written with __strong, then the strong qualifier will
2250 if (Ty
.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
2251 Qualifiers::OCL_Strong
)
2254 tryMakeVariablePseudoStrong(SemaRef
, PVD
, /*DiagnoseFailure=*/false);
2256 handleSimpleAttribute
<ObjCExternallyRetainedAttr
>(*this, D
, AL
);
2259 bool SemaObjC::GetFormatNSStringIdx(const FormatAttr
*Format
, unsigned &Idx
) {
2260 Sema::FormatStringInfo FSI
;
2261 if ((SemaRef
.GetFormatStringType(Format
) == Sema::FST_NSString
) &&
2262 SemaRef
.getFormatStringInfo(Format
, false, true, &FSI
)) {
2263 Idx
= FSI
.FormatIdx
;
2269 /// Diagnose use of %s directive in an NSString which is being passed
2270 /// as formatting string to formatting method.
2271 void SemaObjC::DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl
*FDecl
,
2275 bool Format
= false;
2276 ObjCStringFormatFamily SFFamily
= FDecl
->getObjCFStringFormattingFamily();
2277 if (SFFamily
== ObjCStringFormatFamily::SFF_CFString
) {
2281 for (const auto *I
: FDecl
->specific_attrs
<FormatAttr
>()) {
2282 if (GetFormatNSStringIdx(I
, Idx
)) {
2287 if (!Format
|| NumArgs
<= Idx
)
2289 const Expr
*FormatExpr
= Args
[Idx
];
2290 if (const CStyleCastExpr
*CSCE
= dyn_cast
<CStyleCastExpr
>(FormatExpr
))
2291 FormatExpr
= CSCE
->getSubExpr();
2292 const StringLiteral
*FormatString
;
2293 if (const ObjCStringLiteral
*OSL
=
2294 dyn_cast
<ObjCStringLiteral
>(FormatExpr
->IgnoreParenImpCasts()))
2295 FormatString
= OSL
->getString();
2297 FormatString
= dyn_cast
<StringLiteral
>(FormatExpr
->IgnoreParenImpCasts());
2300 if (SemaRef
.FormatStringHasSArg(FormatString
)) {
2301 Diag(FormatExpr
->getExprLoc(), diag::warn_objc_cdirective_format_string
)
2303 Diag(FDecl
->getLocation(), diag::note_entity_declared_at
)
2304 << FDecl
->getDeclName();
2308 bool SemaObjC::isSignedCharBool(QualType Ty
) {
2309 return Ty
->isSpecificBuiltinType(BuiltinType::SChar
) && getLangOpts().ObjC
&&
2310 NSAPIObj
->isObjCBOOLType(Ty
);
2313 void SemaObjC::adornBoolConversionDiagWithTernaryFixit(
2314 Expr
*SourceExpr
, const Sema::SemaDiagnosticBuilder
&Builder
) {
2315 Expr
*Ignored
= SourceExpr
->IgnoreImplicit();
2316 if (const auto *OVE
= dyn_cast
<OpaqueValueExpr
>(Ignored
))
2317 Ignored
= OVE
->getSourceExpr();
2318 bool NeedsParens
= isa
<AbstractConditionalOperator
>(Ignored
) ||
2319 isa
<BinaryOperator
>(Ignored
) ||
2320 isa
<CXXOperatorCallExpr
>(Ignored
);
2321 SourceLocation EndLoc
= SemaRef
.getLocForEndOfToken(SourceExpr
->getEndLoc());
2323 Builder
<< FixItHint::CreateInsertion(SourceExpr
->getBeginLoc(), "(")
2324 << FixItHint::CreateInsertion(EndLoc
, ")");
2325 Builder
<< FixItHint::CreateInsertion(EndLoc
, " ? YES : NO");
2328 /// Check a single element within a collection literal against the
2329 /// target element type.
2330 static void checkCollectionLiteralElement(Sema
&S
, QualType TargetElementType
,
2331 Expr
*Element
, unsigned ElementKind
) {
2332 // Skip a bitcast to 'id' or qualified 'id'.
2333 if (auto ICE
= dyn_cast
<ImplicitCastExpr
>(Element
)) {
2334 if (ICE
->getCastKind() == CK_BitCast
&&
2335 ICE
->getSubExpr()->getType()->getAs
<ObjCObjectPointerType
>())
2336 Element
= ICE
->getSubExpr();
2339 QualType ElementType
= Element
->getType();
2340 ExprResult
ElementResult(Element
);
2341 if (ElementType
->getAs
<ObjCObjectPointerType
>() &&
2342 S
.CheckSingleAssignmentConstraints(TargetElementType
, ElementResult
,
2343 false, false) != Sema::Compatible
) {
2344 S
.Diag(Element
->getBeginLoc(), diag::warn_objc_collection_literal_element
)
2345 << ElementType
<< ElementKind
<< TargetElementType
2346 << Element
->getSourceRange();
2349 if (auto ArrayLiteral
= dyn_cast
<ObjCArrayLiteral
>(Element
))
2350 S
.ObjC().checkArrayLiteral(TargetElementType
, ArrayLiteral
);
2351 else if (auto DictionaryLiteral
= dyn_cast
<ObjCDictionaryLiteral
>(Element
))
2352 S
.ObjC().checkDictionaryLiteral(TargetElementType
, DictionaryLiteral
);
2355 /// Check an Objective-C array literal being converted to the given
2357 void SemaObjC::checkArrayLiteral(QualType TargetType
,
2358 ObjCArrayLiteral
*ArrayLiteral
) {
2362 const auto *TargetObjCPtr
= TargetType
->getAs
<ObjCObjectPointerType
>();
2366 if (TargetObjCPtr
->isUnspecialized() ||
2367 TargetObjCPtr
->getInterfaceDecl()->getCanonicalDecl() !=
2368 NSArrayDecl
->getCanonicalDecl())
2371 auto TypeArgs
= TargetObjCPtr
->getTypeArgs();
2372 if (TypeArgs
.size() != 1)
2375 QualType TargetElementType
= TypeArgs
[0];
2376 for (unsigned I
= 0, N
= ArrayLiteral
->getNumElements(); I
!= N
; ++I
) {
2377 checkCollectionLiteralElement(SemaRef
, TargetElementType
,
2378 ArrayLiteral
->getElement(I
), 0);
2382 void SemaObjC::checkDictionaryLiteral(
2383 QualType TargetType
, ObjCDictionaryLiteral
*DictionaryLiteral
) {
2384 if (!NSDictionaryDecl
)
2387 const auto *TargetObjCPtr
= TargetType
->getAs
<ObjCObjectPointerType
>();
2391 if (TargetObjCPtr
->isUnspecialized() ||
2392 TargetObjCPtr
->getInterfaceDecl()->getCanonicalDecl() !=
2393 NSDictionaryDecl
->getCanonicalDecl())
2396 auto TypeArgs
= TargetObjCPtr
->getTypeArgs();
2397 if (TypeArgs
.size() != 2)
2400 QualType TargetKeyType
= TypeArgs
[0];
2401 QualType TargetObjectType
= TypeArgs
[1];
2402 for (unsigned I
= 0, N
= DictionaryLiteral
->getNumElements(); I
!= N
; ++I
) {
2403 auto Element
= DictionaryLiteral
->getKeyValueElement(I
);
2404 checkCollectionLiteralElement(SemaRef
, TargetKeyType
, Element
.Key
, 1);
2405 checkCollectionLiteralElement(SemaRef
, TargetObjectType
, Element
.Value
, 2);
2409 } // namespace clang