xref: /llvm-project/clang/lib/Sema/SemaObjC.cpp (revision b9d678d22f74ebd6e34f0a3501fb01d3d80984e7)
131a203faSVlad Serebrennikov //===----- SemaObjC.cpp ---- Semantic Analysis for Objective-C ------------===//
231a203faSVlad Serebrennikov //
331a203faSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
431a203faSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information.
531a203faSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
631a203faSVlad Serebrennikov //
731a203faSVlad Serebrennikov //===----------------------------------------------------------------------===//
831a203faSVlad Serebrennikov /// \file
931a203faSVlad Serebrennikov /// This file implements semantic analysis for Objective-C.
1031a203faSVlad Serebrennikov ///
1131a203faSVlad Serebrennikov //===----------------------------------------------------------------------===//
1231a203faSVlad Serebrennikov 
1331a203faSVlad Serebrennikov #include "clang/Sema/SemaObjC.h"
146b755b0cSVlad Serebrennikov #include "clang/AST/ASTMutationListener.h"
1531a203faSVlad Serebrennikov #include "clang/AST/EvaluatedExprVisitor.h"
1631a203faSVlad Serebrennikov #include "clang/AST/StmtObjC.h"
1731a203faSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h"
1831a203faSVlad Serebrennikov #include "clang/Lex/Preprocessor.h"
196b755b0cSVlad Serebrennikov #include "clang/Sema/Attr.h"
2027d37ee4SVlad Serebrennikov #include "clang/Sema/Lookup.h"
216b755b0cSVlad Serebrennikov #include "clang/Sema/ParsedAttr.h"
2231a203faSVlad Serebrennikov #include "clang/Sema/ScopeInfo.h"
2331a203faSVlad Serebrennikov #include "clang/Sema/Sema.h"
2431a203faSVlad Serebrennikov #include "clang/Sema/TemplateDeduction.h"
2531a203faSVlad Serebrennikov #include "llvm/Support/ConvertUTF.h"
2631a203faSVlad Serebrennikov 
2731a203faSVlad Serebrennikov namespace clang {
2831a203faSVlad Serebrennikov 
2931a203faSVlad Serebrennikov SemaObjC::SemaObjC(Sema &S)
3031a203faSVlad Serebrennikov     : SemaBase(S), NSNumberDecl(nullptr), NSValueDecl(nullptr),
3131a203faSVlad Serebrennikov       NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
3231a203faSVlad Serebrennikov       ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
3331a203faSVlad Serebrennikov       ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
3431a203faSVlad Serebrennikov       DictionaryWithObjectsMethod(nullptr) {}
3531a203faSVlad Serebrennikov 
3631a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
3731a203faSVlad Serebrennikov                                                 Stmt *First, Expr *collection,
3831a203faSVlad Serebrennikov                                                 SourceLocation RParenLoc) {
3931a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
4031a203faSVlad Serebrennikov   SemaRef.setFunctionHasBranchProtectedScope();
4131a203faSVlad Serebrennikov 
4231a203faSVlad Serebrennikov   ExprResult CollectionExprResult =
4331a203faSVlad Serebrennikov       CheckObjCForCollectionOperand(ForLoc, collection);
4431a203faSVlad Serebrennikov 
4531a203faSVlad Serebrennikov   if (First) {
4631a203faSVlad Serebrennikov     QualType FirstType;
4731a203faSVlad Serebrennikov     if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
4831a203faSVlad Serebrennikov       if (!DS->isSingleDecl())
4931a203faSVlad Serebrennikov         return StmtError(Diag((*DS->decl_begin())->getLocation(),
5031a203faSVlad Serebrennikov                               diag::err_toomany_element_decls));
5131a203faSVlad Serebrennikov 
5231a203faSVlad Serebrennikov       VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl());
5331a203faSVlad Serebrennikov       if (!D || D->isInvalidDecl())
5431a203faSVlad Serebrennikov         return StmtError();
5531a203faSVlad Serebrennikov 
5631a203faSVlad Serebrennikov       FirstType = D->getType();
5731a203faSVlad Serebrennikov       // C99 6.8.5p3: The declaration part of a 'for' statement shall only
5831a203faSVlad Serebrennikov       // declare identifiers for objects having storage class 'auto' or
5931a203faSVlad Serebrennikov       // 'register'.
6031a203faSVlad Serebrennikov       if (!D->hasLocalStorage())
6131a203faSVlad Serebrennikov         return StmtError(
6231a203faSVlad Serebrennikov             Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for));
6331a203faSVlad Serebrennikov 
6431a203faSVlad Serebrennikov       // If the type contained 'auto', deduce the 'auto' to 'id'.
6531a203faSVlad Serebrennikov       if (FirstType->getContainedAutoType()) {
6631a203faSVlad Serebrennikov         SourceLocation Loc = D->getLocation();
6731a203faSVlad Serebrennikov         OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue);
6831a203faSVlad Serebrennikov         Expr *DeducedInit = &OpaqueId;
6931a203faSVlad Serebrennikov         sema::TemplateDeductionInfo Info(Loc);
7031a203faSVlad Serebrennikov         FirstType = QualType();
7131a203faSVlad Serebrennikov         TemplateDeductionResult Result = SemaRef.DeduceAutoType(
7231a203faSVlad Serebrennikov             D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info);
7331a203faSVlad Serebrennikov         if (Result != TemplateDeductionResult::Success &&
7431a203faSVlad Serebrennikov             Result != TemplateDeductionResult::AlreadyDiagnosed)
7531a203faSVlad Serebrennikov           SemaRef.DiagnoseAutoDeductionFailure(D, DeducedInit);
7631a203faSVlad Serebrennikov         if (FirstType.isNull()) {
7731a203faSVlad Serebrennikov           D->setInvalidDecl();
7831a203faSVlad Serebrennikov           return StmtError();
7931a203faSVlad Serebrennikov         }
8031a203faSVlad Serebrennikov 
8131a203faSVlad Serebrennikov         D->setType(FirstType);
8231a203faSVlad Serebrennikov 
8331a203faSVlad Serebrennikov         if (!SemaRef.inTemplateInstantiation()) {
8431a203faSVlad Serebrennikov           SourceLocation Loc =
8531a203faSVlad Serebrennikov               D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
8631a203faSVlad Serebrennikov           Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName();
8731a203faSVlad Serebrennikov         }
8831a203faSVlad Serebrennikov       }
8931a203faSVlad Serebrennikov 
9031a203faSVlad Serebrennikov     } else {
9131a203faSVlad Serebrennikov       Expr *FirstE = cast<Expr>(First);
9231a203faSVlad Serebrennikov       if (!FirstE->isTypeDependent() && !FirstE->isLValue())
9331a203faSVlad Serebrennikov         return StmtError(
9431a203faSVlad Serebrennikov             Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue)
9531a203faSVlad Serebrennikov             << First->getSourceRange());
9631a203faSVlad Serebrennikov 
9731a203faSVlad Serebrennikov       FirstType = static_cast<Expr *>(First)->getType();
9831a203faSVlad Serebrennikov       if (FirstType.isConstQualified())
9931a203faSVlad Serebrennikov         Diag(ForLoc, diag::err_selector_element_const_type)
10031a203faSVlad Serebrennikov             << FirstType << First->getSourceRange();
10131a203faSVlad Serebrennikov     }
10231a203faSVlad Serebrennikov     if (!FirstType->isDependentType() &&
10331a203faSVlad Serebrennikov         !FirstType->isObjCObjectPointerType() &&
10431a203faSVlad Serebrennikov         !FirstType->isBlockPointerType())
10531a203faSVlad Serebrennikov       return StmtError(Diag(ForLoc, diag::err_selector_element_type)
10631a203faSVlad Serebrennikov                        << FirstType << First->getSourceRange());
10731a203faSVlad Serebrennikov   }
10831a203faSVlad Serebrennikov 
10931a203faSVlad Serebrennikov   if (CollectionExprResult.isInvalid())
11031a203faSVlad Serebrennikov     return StmtError();
11131a203faSVlad Serebrennikov 
11231a203faSVlad Serebrennikov   CollectionExprResult = SemaRef.ActOnFinishFullExpr(CollectionExprResult.get(),
11331a203faSVlad Serebrennikov                                                      /*DiscardedValue*/ false);
11431a203faSVlad Serebrennikov   if (CollectionExprResult.isInvalid())
11531a203faSVlad Serebrennikov     return StmtError();
11631a203faSVlad Serebrennikov 
11731a203faSVlad Serebrennikov   return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(),
11831a203faSVlad Serebrennikov                                              nullptr, ForLoc, RParenLoc);
11931a203faSVlad Serebrennikov }
12031a203faSVlad Serebrennikov 
12131a203faSVlad Serebrennikov ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc,
12231a203faSVlad Serebrennikov                                                    Expr *collection) {
12331a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
12431a203faSVlad Serebrennikov   if (!collection)
12531a203faSVlad Serebrennikov     return ExprError();
12631a203faSVlad Serebrennikov 
12731a203faSVlad Serebrennikov   ExprResult result = SemaRef.CorrectDelayedTyposInExpr(collection);
12831a203faSVlad Serebrennikov   if (!result.isUsable())
12931a203faSVlad Serebrennikov     return ExprError();
13031a203faSVlad Serebrennikov   collection = result.get();
13131a203faSVlad Serebrennikov 
13231a203faSVlad Serebrennikov   // Bail out early if we've got a type-dependent expression.
13331a203faSVlad Serebrennikov   if (collection->isTypeDependent())
13431a203faSVlad Serebrennikov     return collection;
13531a203faSVlad Serebrennikov 
13631a203faSVlad Serebrennikov   // Perform normal l-value conversion.
13731a203faSVlad Serebrennikov   result = SemaRef.DefaultFunctionArrayLvalueConversion(collection);
13831a203faSVlad Serebrennikov   if (result.isInvalid())
13931a203faSVlad Serebrennikov     return ExprError();
14031a203faSVlad Serebrennikov   collection = result.get();
14131a203faSVlad Serebrennikov 
14231a203faSVlad Serebrennikov   // The operand needs to have object-pointer type.
14331a203faSVlad Serebrennikov   // TODO: should we do a contextual conversion?
14431a203faSVlad Serebrennikov   const ObjCObjectPointerType *pointerType =
14531a203faSVlad Serebrennikov       collection->getType()->getAs<ObjCObjectPointerType>();
14631a203faSVlad Serebrennikov   if (!pointerType)
14731a203faSVlad Serebrennikov     return Diag(forLoc, diag::err_collection_expr_type)
14831a203faSVlad Serebrennikov            << collection->getType() << collection->getSourceRange();
14931a203faSVlad Serebrennikov 
15031a203faSVlad Serebrennikov   // Check that the operand provides
15131a203faSVlad Serebrennikov   //   - countByEnumeratingWithState:objects:count:
15231a203faSVlad Serebrennikov   const ObjCObjectType *objectType = pointerType->getObjectType();
15331a203faSVlad Serebrennikov   ObjCInterfaceDecl *iface = objectType->getInterface();
15431a203faSVlad Serebrennikov 
15531a203faSVlad Serebrennikov   // If we have a forward-declared type, we can't do this check.
15631a203faSVlad Serebrennikov   // Under ARC, it is an error not to have a forward-declared class.
15731a203faSVlad Serebrennikov   if (iface &&
15831a203faSVlad Serebrennikov       (getLangOpts().ObjCAutoRefCount
15931a203faSVlad Serebrennikov            ? SemaRef.RequireCompleteType(forLoc, QualType(objectType, 0),
16031a203faSVlad Serebrennikov                                          diag::err_arc_collection_forward,
16131a203faSVlad Serebrennikov                                          collection)
16231a203faSVlad Serebrennikov            : !SemaRef.isCompleteType(forLoc, QualType(objectType, 0)))) {
16331a203faSVlad Serebrennikov     // Otherwise, if we have any useful type information, check that
16431a203faSVlad Serebrennikov     // the type declares the appropriate method.
16531a203faSVlad Serebrennikov   } else if (iface || !objectType->qual_empty()) {
16631a203faSVlad Serebrennikov     const IdentifierInfo *selectorIdents[] = {
16731a203faSVlad Serebrennikov         &Context.Idents.get("countByEnumeratingWithState"),
16831a203faSVlad Serebrennikov         &Context.Idents.get("objects"), &Context.Idents.get("count")};
16931a203faSVlad Serebrennikov     Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);
17031a203faSVlad Serebrennikov 
17131a203faSVlad Serebrennikov     ObjCMethodDecl *method = nullptr;
17231a203faSVlad Serebrennikov 
17331a203faSVlad Serebrennikov     // If there's an interface, look in both the public and private APIs.
17431a203faSVlad Serebrennikov     if (iface) {
17531a203faSVlad Serebrennikov       method = iface->lookupInstanceMethod(selector);
17631a203faSVlad Serebrennikov       if (!method)
17731a203faSVlad Serebrennikov         method = iface->lookupPrivateMethod(selector);
17831a203faSVlad Serebrennikov     }
17931a203faSVlad Serebrennikov 
18031a203faSVlad Serebrennikov     // Also check protocol qualifiers.
18131a203faSVlad Serebrennikov     if (!method)
18231a203faSVlad Serebrennikov       method = LookupMethodInQualifiedType(selector, pointerType,
18331a203faSVlad Serebrennikov                                            /*instance*/ true);
18431a203faSVlad Serebrennikov 
18531a203faSVlad Serebrennikov     // If we didn't find it anywhere, give up.
18631a203faSVlad Serebrennikov     if (!method) {
18731a203faSVlad Serebrennikov       Diag(forLoc, diag::warn_collection_expr_type)
18831a203faSVlad Serebrennikov           << collection->getType() << selector << collection->getSourceRange();
18931a203faSVlad Serebrennikov     }
19031a203faSVlad Serebrennikov 
19131a203faSVlad Serebrennikov     // TODO: check for an incompatible signature?
19231a203faSVlad Serebrennikov   }
19331a203faSVlad Serebrennikov 
19431a203faSVlad Serebrennikov   // Wrap up any cleanups in the expression.
19531a203faSVlad Serebrennikov   return collection;
19631a203faSVlad Serebrennikov }
19731a203faSVlad Serebrennikov 
19831a203faSVlad Serebrennikov StmtResult SemaObjC::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) {
19931a203faSVlad Serebrennikov   if (!S || !B)
20031a203faSVlad Serebrennikov     return StmtError();
20131a203faSVlad Serebrennikov   ObjCForCollectionStmt *ForStmt = cast<ObjCForCollectionStmt>(S);
20231a203faSVlad Serebrennikov 
20331a203faSVlad Serebrennikov   ForStmt->setBody(B);
20431a203faSVlad Serebrennikov   return S;
20531a203faSVlad Serebrennikov }
20631a203faSVlad Serebrennikov 
20731a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
20831a203faSVlad Serebrennikov                                           SourceLocation RParen, Decl *Parm,
20931a203faSVlad Serebrennikov                                           Stmt *Body) {
21031a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
21131a203faSVlad Serebrennikov   VarDecl *Var = cast_or_null<VarDecl>(Parm);
21231a203faSVlad Serebrennikov   if (Var && Var->isInvalidDecl())
21331a203faSVlad Serebrennikov     return StmtError();
21431a203faSVlad Serebrennikov 
21531a203faSVlad Serebrennikov   return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body);
21631a203faSVlad Serebrennikov }
21731a203faSVlad Serebrennikov 
21831a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
21931a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
22031a203faSVlad Serebrennikov   return new (Context) ObjCAtFinallyStmt(AtLoc, Body);
22131a203faSVlad Serebrennikov }
22231a203faSVlad Serebrennikov 
22331a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
22431a203faSVlad Serebrennikov                                         MultiStmtArg CatchStmts,
22531a203faSVlad Serebrennikov                                         Stmt *Finally) {
22631a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
22731a203faSVlad Serebrennikov   if (!getLangOpts().ObjCExceptions)
22831a203faSVlad Serebrennikov     Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
22931a203faSVlad Serebrennikov 
23031a203faSVlad Serebrennikov   // Objective-C try is incompatible with SEH __try.
23131a203faSVlad Serebrennikov   sema::FunctionScopeInfo *FSI = SemaRef.getCurFunction();
23231a203faSVlad Serebrennikov   if (FSI->FirstSEHTryLoc.isValid()) {
23331a203faSVlad Serebrennikov     Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1;
23431a203faSVlad Serebrennikov     Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
23531a203faSVlad Serebrennikov   }
23631a203faSVlad Serebrennikov 
23731a203faSVlad Serebrennikov   FSI->setHasObjCTry(AtLoc);
23831a203faSVlad Serebrennikov   unsigned NumCatchStmts = CatchStmts.size();
23931a203faSVlad Serebrennikov   return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
24031a203faSVlad Serebrennikov                                NumCatchStmts, Finally);
24131a203faSVlad Serebrennikov }
24231a203faSVlad Serebrennikov 
24331a203faSVlad Serebrennikov StmtResult SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
24431a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
24531a203faSVlad Serebrennikov   if (Throw) {
24631a203faSVlad Serebrennikov     ExprResult Result = SemaRef.DefaultLvalueConversion(Throw);
24731a203faSVlad Serebrennikov     if (Result.isInvalid())
24831a203faSVlad Serebrennikov       return StmtError();
24931a203faSVlad Serebrennikov 
25031a203faSVlad Serebrennikov     Result =
25131a203faSVlad Serebrennikov         SemaRef.ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false);
25231a203faSVlad Serebrennikov     if (Result.isInvalid())
25331a203faSVlad Serebrennikov       return StmtError();
25431a203faSVlad Serebrennikov     Throw = Result.get();
25531a203faSVlad Serebrennikov 
25631a203faSVlad Serebrennikov     QualType ThrowType = Throw->getType();
25731a203faSVlad Serebrennikov     // Make sure the expression type is an ObjC pointer or "void *".
25831a203faSVlad Serebrennikov     if (!ThrowType->isDependentType() &&
25931a203faSVlad Serebrennikov         !ThrowType->isObjCObjectPointerType()) {
26031a203faSVlad Serebrennikov       const PointerType *PT = ThrowType->getAs<PointerType>();
26131a203faSVlad Serebrennikov       if (!PT || !PT->getPointeeType()->isVoidType())
26231a203faSVlad Serebrennikov         return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object)
26331a203faSVlad Serebrennikov                          << Throw->getType() << Throw->getSourceRange());
26431a203faSVlad Serebrennikov     }
26531a203faSVlad Serebrennikov   }
26631a203faSVlad Serebrennikov 
26731a203faSVlad Serebrennikov   return new (Context) ObjCAtThrowStmt(AtLoc, Throw);
26831a203faSVlad Serebrennikov }
26931a203faSVlad Serebrennikov 
27031a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
27131a203faSVlad Serebrennikov                                           Scope *CurScope) {
27231a203faSVlad Serebrennikov   if (!getLangOpts().ObjCExceptions)
27331a203faSVlad Serebrennikov     Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";
27431a203faSVlad Serebrennikov 
27531a203faSVlad Serebrennikov   if (!Throw) {
27631a203faSVlad Serebrennikov     // @throw without an expression designates a rethrow (which must occur
27731a203faSVlad Serebrennikov     // in the context of an @catch clause).
27831a203faSVlad Serebrennikov     Scope *AtCatchParent = CurScope;
27931a203faSVlad Serebrennikov     while (AtCatchParent && !AtCatchParent->isAtCatchScope())
28031a203faSVlad Serebrennikov       AtCatchParent = AtCatchParent->getParent();
28131a203faSVlad Serebrennikov     if (!AtCatchParent)
28231a203faSVlad Serebrennikov       return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch));
28331a203faSVlad Serebrennikov   }
28431a203faSVlad Serebrennikov   return BuildObjCAtThrowStmt(AtLoc, Throw);
28531a203faSVlad Serebrennikov }
28631a203faSVlad Serebrennikov 
28731a203faSVlad Serebrennikov ExprResult SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,
28831a203faSVlad Serebrennikov                                                     Expr *operand) {
28931a203faSVlad Serebrennikov   ExprResult result = SemaRef.DefaultLvalueConversion(operand);
29031a203faSVlad Serebrennikov   if (result.isInvalid())
29131a203faSVlad Serebrennikov     return ExprError();
29231a203faSVlad Serebrennikov   operand = result.get();
29331a203faSVlad Serebrennikov 
29431a203faSVlad Serebrennikov   // Make sure the expression type is an ObjC pointer or "void *".
29531a203faSVlad Serebrennikov   QualType type = operand->getType();
29631a203faSVlad Serebrennikov   if (!type->isDependentType() && !type->isObjCObjectPointerType()) {
29731a203faSVlad Serebrennikov     const PointerType *pointerType = type->getAs<PointerType>();
29831a203faSVlad Serebrennikov     if (!pointerType || !pointerType->getPointeeType()->isVoidType()) {
29931a203faSVlad Serebrennikov       if (getLangOpts().CPlusPlus) {
30031a203faSVlad Serebrennikov         if (SemaRef.RequireCompleteType(atLoc, type,
30131a203faSVlad Serebrennikov                                         diag::err_incomplete_receiver_type))
30231a203faSVlad Serebrennikov           return Diag(atLoc, diag::err_objc_synchronized_expects_object)
30331a203faSVlad Serebrennikov                  << type << operand->getSourceRange();
30431a203faSVlad Serebrennikov 
30531a203faSVlad Serebrennikov         ExprResult result =
30631a203faSVlad Serebrennikov             SemaRef.PerformContextuallyConvertToObjCPointer(operand);
30731a203faSVlad Serebrennikov         if (result.isInvalid())
30831a203faSVlad Serebrennikov           return ExprError();
30931a203faSVlad Serebrennikov         if (!result.isUsable())
31031a203faSVlad Serebrennikov           return Diag(atLoc, diag::err_objc_synchronized_expects_object)
31131a203faSVlad Serebrennikov                  << type << operand->getSourceRange();
31231a203faSVlad Serebrennikov 
31331a203faSVlad Serebrennikov         operand = result.get();
31431a203faSVlad Serebrennikov       } else {
31531a203faSVlad Serebrennikov         return Diag(atLoc, diag::err_objc_synchronized_expects_object)
31631a203faSVlad Serebrennikov                << type << operand->getSourceRange();
31731a203faSVlad Serebrennikov       }
31831a203faSVlad Serebrennikov     }
31931a203faSVlad Serebrennikov   }
32031a203faSVlad Serebrennikov 
32131a203faSVlad Serebrennikov   // The operand to @synchronized is a full-expression.
32231a203faSVlad Serebrennikov   return SemaRef.ActOnFinishFullExpr(operand, /*DiscardedValue*/ false);
32331a203faSVlad Serebrennikov }
32431a203faSVlad Serebrennikov 
32531a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
32631a203faSVlad Serebrennikov                                                  Expr *SyncExpr,
32731a203faSVlad Serebrennikov                                                  Stmt *SyncBody) {
32831a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
32931a203faSVlad Serebrennikov   // We can't jump into or indirect-jump out of a @synchronized block.
33031a203faSVlad Serebrennikov   SemaRef.setFunctionHasBranchProtectedScope();
33131a203faSVlad Serebrennikov   return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
33231a203faSVlad Serebrennikov }
33331a203faSVlad Serebrennikov 
33431a203faSVlad Serebrennikov StmtResult SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc,
33531a203faSVlad Serebrennikov                                                   Stmt *Body) {
33631a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
33731a203faSVlad Serebrennikov   SemaRef.setFunctionHasBranchProtectedScope();
33831a203faSVlad Serebrennikov   return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
33931a203faSVlad Serebrennikov }
34031a203faSVlad Serebrennikov 
34131a203faSVlad Serebrennikov TypeResult SemaObjC::actOnObjCProtocolQualifierType(
34231a203faSVlad Serebrennikov     SourceLocation lAngleLoc, ArrayRef<Decl *> protocols,
34331a203faSVlad Serebrennikov     ArrayRef<SourceLocation> protocolLocs, SourceLocation rAngleLoc) {
34431a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
34531a203faSVlad Serebrennikov   // Form id<protocol-list>.
34631a203faSVlad Serebrennikov   QualType Result = Context.getObjCObjectType(
34731a203faSVlad Serebrennikov       Context.ObjCBuiltinIdTy, {},
34831a203faSVlad Serebrennikov       llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(),
34931a203faSVlad Serebrennikov                      protocols.size()),
35031a203faSVlad Serebrennikov       false);
35131a203faSVlad Serebrennikov   Result = Context.getObjCObjectPointerType(Result);
35231a203faSVlad Serebrennikov 
35331a203faSVlad Serebrennikov   TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
35431a203faSVlad Serebrennikov   TypeLoc ResultTL = ResultTInfo->getTypeLoc();
35531a203faSVlad Serebrennikov 
35631a203faSVlad Serebrennikov   auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>();
35731a203faSVlad Serebrennikov   ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit
35831a203faSVlad Serebrennikov 
35931a203faSVlad Serebrennikov   auto ObjCObjectTL =
36031a203faSVlad Serebrennikov       ObjCObjectPointerTL.getPointeeLoc().castAs<ObjCObjectTypeLoc>();
36131a203faSVlad Serebrennikov   ObjCObjectTL.setHasBaseTypeAsWritten(false);
36231a203faSVlad Serebrennikov   ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation());
36331a203faSVlad Serebrennikov 
36431a203faSVlad Serebrennikov   // No type arguments.
36531a203faSVlad Serebrennikov   ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
36631a203faSVlad Serebrennikov   ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
36731a203faSVlad Serebrennikov 
36831a203faSVlad Serebrennikov   // Fill in protocol qualifiers.
36931a203faSVlad Serebrennikov   ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc);
37031a203faSVlad Serebrennikov   ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc);
37131a203faSVlad Serebrennikov   for (unsigned i = 0, n = protocols.size(); i != n; ++i)
37231a203faSVlad Serebrennikov     ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]);
37331a203faSVlad Serebrennikov 
37431a203faSVlad Serebrennikov   // We're done. Return the completed type to the parser.
37531a203faSVlad Serebrennikov   return SemaRef.CreateParsedType(Result, ResultTInfo);
37631a203faSVlad Serebrennikov }
37731a203faSVlad Serebrennikov 
37831a203faSVlad Serebrennikov TypeResult SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers(
37931a203faSVlad Serebrennikov     Scope *S, SourceLocation Loc, ParsedType BaseType,
38031a203faSVlad Serebrennikov     SourceLocation TypeArgsLAngleLoc, ArrayRef<ParsedType> TypeArgs,
38131a203faSVlad Serebrennikov     SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc,
38231a203faSVlad Serebrennikov     ArrayRef<Decl *> Protocols, ArrayRef<SourceLocation> ProtocolLocs,
38331a203faSVlad Serebrennikov     SourceLocation ProtocolRAngleLoc) {
38431a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
38531a203faSVlad Serebrennikov   TypeSourceInfo *BaseTypeInfo = nullptr;
38631a203faSVlad Serebrennikov   QualType T = SemaRef.GetTypeFromParser(BaseType, &BaseTypeInfo);
38731a203faSVlad Serebrennikov   if (T.isNull())
38831a203faSVlad Serebrennikov     return true;
38931a203faSVlad Serebrennikov 
39031a203faSVlad Serebrennikov   // Handle missing type-source info.
39131a203faSVlad Serebrennikov   if (!BaseTypeInfo)
39231a203faSVlad Serebrennikov     BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc);
39331a203faSVlad Serebrennikov 
39431a203faSVlad Serebrennikov   // Extract type arguments.
39531a203faSVlad Serebrennikov   SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos;
39631a203faSVlad Serebrennikov   for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) {
39731a203faSVlad Serebrennikov     TypeSourceInfo *TypeArgInfo = nullptr;
39831a203faSVlad Serebrennikov     QualType TypeArg = SemaRef.GetTypeFromParser(TypeArgs[i], &TypeArgInfo);
39931a203faSVlad Serebrennikov     if (TypeArg.isNull()) {
40031a203faSVlad Serebrennikov       ActualTypeArgInfos.clear();
40131a203faSVlad Serebrennikov       break;
40231a203faSVlad Serebrennikov     }
40331a203faSVlad Serebrennikov 
40431a203faSVlad Serebrennikov     assert(TypeArgInfo && "No type source info?");
40531a203faSVlad Serebrennikov     ActualTypeArgInfos.push_back(TypeArgInfo);
40631a203faSVlad Serebrennikov   }
40731a203faSVlad Serebrennikov 
40831a203faSVlad Serebrennikov   // Build the object type.
40931a203faSVlad Serebrennikov   QualType Result = BuildObjCObjectType(
41031a203faSVlad Serebrennikov       T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
41131a203faSVlad Serebrennikov       TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
41231a203faSVlad Serebrennikov       ProtocolLAngleLoc,
41331a203faSVlad Serebrennikov       llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(),
41431a203faSVlad Serebrennikov                      Protocols.size()),
41531a203faSVlad Serebrennikov       ProtocolLocs, ProtocolRAngleLoc,
41631a203faSVlad Serebrennikov       /*FailOnError=*/false,
41731a203faSVlad Serebrennikov       /*Rebuilding=*/false);
41831a203faSVlad Serebrennikov 
41931a203faSVlad Serebrennikov   if (Result == T)
42031a203faSVlad Serebrennikov     return BaseType;
42131a203faSVlad Serebrennikov 
42231a203faSVlad Serebrennikov   // Create source information for this type.
42331a203faSVlad Serebrennikov   TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
42431a203faSVlad Serebrennikov   TypeLoc ResultTL = ResultTInfo->getTypeLoc();
42531a203faSVlad Serebrennikov 
42631a203faSVlad Serebrennikov   // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an
42731a203faSVlad Serebrennikov   // object pointer type. Fill in source information for it.
42831a203faSVlad Serebrennikov   if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) {
42931a203faSVlad Serebrennikov     // The '*' is implicit.
43031a203faSVlad Serebrennikov     ObjCObjectPointerTL.setStarLoc(SourceLocation());
43131a203faSVlad Serebrennikov     ResultTL = ObjCObjectPointerTL.getPointeeLoc();
43231a203faSVlad Serebrennikov   }
43331a203faSVlad Serebrennikov 
43431a203faSVlad Serebrennikov   if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {
43531a203faSVlad Serebrennikov     // Protocol qualifier information.
43631a203faSVlad Serebrennikov     if (OTPTL.getNumProtocols() > 0) {
43731a203faSVlad Serebrennikov       assert(OTPTL.getNumProtocols() == Protocols.size());
43831a203faSVlad Serebrennikov       OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
43931a203faSVlad Serebrennikov       OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
44031a203faSVlad Serebrennikov       for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
44131a203faSVlad Serebrennikov         OTPTL.setProtocolLoc(i, ProtocolLocs[i]);
44231a203faSVlad Serebrennikov     }
44331a203faSVlad Serebrennikov 
44431a203faSVlad Serebrennikov     // We're done. Return the completed type to the parser.
44531a203faSVlad Serebrennikov     return SemaRef.CreateParsedType(Result, ResultTInfo);
44631a203faSVlad Serebrennikov   }
44731a203faSVlad Serebrennikov 
44831a203faSVlad Serebrennikov   auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();
44931a203faSVlad Serebrennikov 
45031a203faSVlad Serebrennikov   // Type argument information.
45131a203faSVlad Serebrennikov   if (ObjCObjectTL.getNumTypeArgs() > 0) {
45231a203faSVlad Serebrennikov     assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size());
45331a203faSVlad Serebrennikov     ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc);
45431a203faSVlad Serebrennikov     ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc);
45531a203faSVlad Serebrennikov     for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i)
45631a203faSVlad Serebrennikov       ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]);
45731a203faSVlad Serebrennikov   } else {
45831a203faSVlad Serebrennikov     ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
45931a203faSVlad Serebrennikov     ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
46031a203faSVlad Serebrennikov   }
46131a203faSVlad Serebrennikov 
46231a203faSVlad Serebrennikov   // Protocol qualifier information.
46331a203faSVlad Serebrennikov   if (ObjCObjectTL.getNumProtocols() > 0) {
46431a203faSVlad Serebrennikov     assert(ObjCObjectTL.getNumProtocols() == Protocols.size());
46531a203faSVlad Serebrennikov     ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
46631a203faSVlad Serebrennikov     ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
46731a203faSVlad Serebrennikov     for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
46831a203faSVlad Serebrennikov       ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]);
46931a203faSVlad Serebrennikov   } else {
47031a203faSVlad Serebrennikov     ObjCObjectTL.setProtocolLAngleLoc(SourceLocation());
47131a203faSVlad Serebrennikov     ObjCObjectTL.setProtocolRAngleLoc(SourceLocation());
47231a203faSVlad Serebrennikov   }
47331a203faSVlad Serebrennikov 
47431a203faSVlad Serebrennikov   // Base type.
47531a203faSVlad Serebrennikov   ObjCObjectTL.setHasBaseTypeAsWritten(true);
47631a203faSVlad Serebrennikov   if (ObjCObjectTL.getType() == T)
47731a203faSVlad Serebrennikov     ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc());
47831a203faSVlad Serebrennikov   else
47931a203faSVlad Serebrennikov     ObjCObjectTL.getBaseLoc().initialize(Context, Loc);
48031a203faSVlad Serebrennikov 
48131a203faSVlad Serebrennikov   // We're done. Return the completed type to the parser.
48231a203faSVlad Serebrennikov   return SemaRef.CreateParsedType(Result, ResultTInfo);
48331a203faSVlad Serebrennikov }
48431a203faSVlad Serebrennikov 
48531a203faSVlad Serebrennikov QualType SemaObjC::BuildObjCTypeParamType(
48631a203faSVlad Serebrennikov     const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc,
48731a203faSVlad Serebrennikov     ArrayRef<ObjCProtocolDecl *> Protocols,
48831a203faSVlad Serebrennikov     ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
48931a203faSVlad Serebrennikov     bool FailOnError) {
49031a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
49131a203faSVlad Serebrennikov   QualType Result = QualType(Decl->getTypeForDecl(), 0);
49231a203faSVlad Serebrennikov   if (!Protocols.empty()) {
49331a203faSVlad Serebrennikov     bool HasError;
49431a203faSVlad Serebrennikov     Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError);
49531a203faSVlad Serebrennikov     if (HasError) {
49631a203faSVlad Serebrennikov       Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers)
49731a203faSVlad Serebrennikov           << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
49831a203faSVlad Serebrennikov       if (FailOnError)
49931a203faSVlad Serebrennikov         Result = QualType();
50031a203faSVlad Serebrennikov     }
50131a203faSVlad Serebrennikov     if (FailOnError && Result.isNull())
50231a203faSVlad Serebrennikov       return QualType();
50331a203faSVlad Serebrennikov   }
50431a203faSVlad Serebrennikov 
50531a203faSVlad Serebrennikov   return Result;
50631a203faSVlad Serebrennikov }
50731a203faSVlad Serebrennikov 
50831a203faSVlad Serebrennikov /// Apply Objective-C type arguments to the given type.
50931a203faSVlad Serebrennikov static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
51031a203faSVlad Serebrennikov                                   ArrayRef<TypeSourceInfo *> typeArgs,
51131a203faSVlad Serebrennikov                                   SourceRange typeArgsRange, bool failOnError,
51231a203faSVlad Serebrennikov                                   bool rebuilding) {
51331a203faSVlad Serebrennikov   // We can only apply type arguments to an Objective-C class type.
51431a203faSVlad Serebrennikov   const auto *objcObjectType = type->getAs<ObjCObjectType>();
51531a203faSVlad Serebrennikov   if (!objcObjectType || !objcObjectType->getInterface()) {
51631a203faSVlad Serebrennikov     S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange;
51731a203faSVlad Serebrennikov 
51831a203faSVlad Serebrennikov     if (failOnError)
51931a203faSVlad Serebrennikov       return QualType();
52031a203faSVlad Serebrennikov     return type;
52131a203faSVlad Serebrennikov   }
52231a203faSVlad Serebrennikov 
52331a203faSVlad Serebrennikov   // The class type must be parameterized.
52431a203faSVlad Serebrennikov   ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
52531a203faSVlad Serebrennikov   ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
52631a203faSVlad Serebrennikov   if (!typeParams) {
52731a203faSVlad Serebrennikov     S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
52831a203faSVlad Serebrennikov         << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange);
52931a203faSVlad Serebrennikov 
53031a203faSVlad Serebrennikov     if (failOnError)
53131a203faSVlad Serebrennikov       return QualType();
53231a203faSVlad Serebrennikov 
53331a203faSVlad Serebrennikov     return type;
53431a203faSVlad Serebrennikov   }
53531a203faSVlad Serebrennikov 
53631a203faSVlad Serebrennikov   // The type must not already be specialized.
53731a203faSVlad Serebrennikov   if (objcObjectType->isSpecialized()) {
53831a203faSVlad Serebrennikov     S.Diag(loc, diag::err_objc_type_args_specialized_class)
53931a203faSVlad Serebrennikov         << type << FixItHint::CreateRemoval(typeArgsRange);
54031a203faSVlad Serebrennikov 
54131a203faSVlad Serebrennikov     if (failOnError)
54231a203faSVlad Serebrennikov       return QualType();
54331a203faSVlad Serebrennikov 
54431a203faSVlad Serebrennikov     return type;
54531a203faSVlad Serebrennikov   }
54631a203faSVlad Serebrennikov 
54731a203faSVlad Serebrennikov   // Check the type arguments.
54831a203faSVlad Serebrennikov   SmallVector<QualType, 4> finalTypeArgs;
54931a203faSVlad Serebrennikov   unsigned numTypeParams = typeParams->size();
55031a203faSVlad Serebrennikov   bool anyPackExpansions = false;
55131a203faSVlad Serebrennikov   for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {
55231a203faSVlad Serebrennikov     TypeSourceInfo *typeArgInfo = typeArgs[i];
55331a203faSVlad Serebrennikov     QualType typeArg = typeArgInfo->getType();
55431a203faSVlad Serebrennikov 
55531a203faSVlad Serebrennikov     // Type arguments cannot have explicit qualifiers or nullability.
55631a203faSVlad Serebrennikov     // We ignore indirect sources of these, e.g. behind typedefs or
55731a203faSVlad Serebrennikov     // template arguments.
55831a203faSVlad Serebrennikov     if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {
55931a203faSVlad Serebrennikov       bool diagnosed = false;
56031a203faSVlad Serebrennikov       SourceRange rangeToRemove;
56131a203faSVlad Serebrennikov       if (auto attr = qual.getAs<AttributedTypeLoc>()) {
56231a203faSVlad Serebrennikov         rangeToRemove = attr.getLocalSourceRange();
56331a203faSVlad Serebrennikov         if (attr.getTypePtr()->getImmediateNullability()) {
56431a203faSVlad Serebrennikov           typeArg = attr.getTypePtr()->getModifiedType();
56531a203faSVlad Serebrennikov           S.Diag(attr.getBeginLoc(),
56631a203faSVlad Serebrennikov                  diag::err_objc_type_arg_explicit_nullability)
56731a203faSVlad Serebrennikov               << typeArg << FixItHint::CreateRemoval(rangeToRemove);
56831a203faSVlad Serebrennikov           diagnosed = true;
56931a203faSVlad Serebrennikov         }
57031a203faSVlad Serebrennikov       }
57131a203faSVlad Serebrennikov 
57231a203faSVlad Serebrennikov       // When rebuilding, qualifiers might have gotten here through a
57331a203faSVlad Serebrennikov       // final substitution.
57431a203faSVlad Serebrennikov       if (!rebuilding && !diagnosed) {
57531a203faSVlad Serebrennikov         S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)
57631a203faSVlad Serebrennikov             << typeArg << typeArg.getQualifiers().getAsString()
57731a203faSVlad Serebrennikov             << FixItHint::CreateRemoval(rangeToRemove);
57831a203faSVlad Serebrennikov       }
57931a203faSVlad Serebrennikov     }
58031a203faSVlad Serebrennikov 
58131a203faSVlad Serebrennikov     // Remove qualifiers even if they're non-local.
58231a203faSVlad Serebrennikov     typeArg = typeArg.getUnqualifiedType();
58331a203faSVlad Serebrennikov 
58431a203faSVlad Serebrennikov     finalTypeArgs.push_back(typeArg);
58531a203faSVlad Serebrennikov 
58631a203faSVlad Serebrennikov     if (typeArg->getAs<PackExpansionType>())
58731a203faSVlad Serebrennikov       anyPackExpansions = true;
58831a203faSVlad Serebrennikov 
58931a203faSVlad Serebrennikov     // Find the corresponding type parameter, if there is one.
59031a203faSVlad Serebrennikov     ObjCTypeParamDecl *typeParam = nullptr;
59131a203faSVlad Serebrennikov     if (!anyPackExpansions) {
59231a203faSVlad Serebrennikov       if (i < numTypeParams) {
59331a203faSVlad Serebrennikov         typeParam = typeParams->begin()[i];
59431a203faSVlad Serebrennikov       } else {
59531a203faSVlad Serebrennikov         // Too many arguments.
59631a203faSVlad Serebrennikov         S.Diag(loc, diag::err_objc_type_args_wrong_arity)
59731a203faSVlad Serebrennikov             << false << objcClass->getDeclName() << (unsigned)typeArgs.size()
59831a203faSVlad Serebrennikov             << numTypeParams;
59931a203faSVlad Serebrennikov         S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass;
60031a203faSVlad Serebrennikov 
60131a203faSVlad Serebrennikov         if (failOnError)
60231a203faSVlad Serebrennikov           return QualType();
60331a203faSVlad Serebrennikov 
60431a203faSVlad Serebrennikov         return type;
60531a203faSVlad Serebrennikov       }
60631a203faSVlad Serebrennikov     }
60731a203faSVlad Serebrennikov 
60831a203faSVlad Serebrennikov     // Objective-C object pointer types must be substitutable for the bounds.
60931a203faSVlad Serebrennikov     if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {
61031a203faSVlad Serebrennikov       // If we don't have a type parameter to match against, assume
61131a203faSVlad Serebrennikov       // everything is fine. There was a prior pack expansion that
61231a203faSVlad Serebrennikov       // means we won't be able to match anything.
61331a203faSVlad Serebrennikov       if (!typeParam) {
61431a203faSVlad Serebrennikov         assert(anyPackExpansions && "Too many arguments?");
61531a203faSVlad Serebrennikov         continue;
61631a203faSVlad Serebrennikov       }
61731a203faSVlad Serebrennikov 
61831a203faSVlad Serebrennikov       // Retrieve the bound.
61931a203faSVlad Serebrennikov       QualType bound = typeParam->getUnderlyingType();
62031a203faSVlad Serebrennikov       const auto *boundObjC = bound->castAs<ObjCObjectPointerType>();
62131a203faSVlad Serebrennikov 
62231a203faSVlad Serebrennikov       // Determine whether the type argument is substitutable for the bound.
62331a203faSVlad Serebrennikov       if (typeArgObjC->isObjCIdType()) {
62431a203faSVlad Serebrennikov         // When the type argument is 'id', the only acceptable type
62531a203faSVlad Serebrennikov         // parameter bound is 'id'.
62631a203faSVlad Serebrennikov         if (boundObjC->isObjCIdType())
62731a203faSVlad Serebrennikov           continue;
62831a203faSVlad Serebrennikov       } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
62931a203faSVlad Serebrennikov         // Otherwise, we follow the assignability rules.
63031a203faSVlad Serebrennikov         continue;
63131a203faSVlad Serebrennikov       }
63231a203faSVlad Serebrennikov 
63331a203faSVlad Serebrennikov       // Diagnose the mismatch.
63431a203faSVlad Serebrennikov       S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
63531a203faSVlad Serebrennikov              diag::err_objc_type_arg_does_not_match_bound)
63631a203faSVlad Serebrennikov           << typeArg << bound << typeParam->getDeclName();
63731a203faSVlad Serebrennikov       S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
63831a203faSVlad Serebrennikov           << typeParam->getDeclName();
63931a203faSVlad Serebrennikov 
64031a203faSVlad Serebrennikov       if (failOnError)
64131a203faSVlad Serebrennikov         return QualType();
64231a203faSVlad Serebrennikov 
64331a203faSVlad Serebrennikov       return type;
64431a203faSVlad Serebrennikov     }
64531a203faSVlad Serebrennikov 
64631a203faSVlad Serebrennikov     // Block pointer types are permitted for unqualified 'id' bounds.
64731a203faSVlad Serebrennikov     if (typeArg->isBlockPointerType()) {
64831a203faSVlad Serebrennikov       // If we don't have a type parameter to match against, assume
64931a203faSVlad Serebrennikov       // everything is fine. There was a prior pack expansion that
65031a203faSVlad Serebrennikov       // means we won't be able to match anything.
65131a203faSVlad Serebrennikov       if (!typeParam) {
65231a203faSVlad Serebrennikov         assert(anyPackExpansions && "Too many arguments?");
65331a203faSVlad Serebrennikov         continue;
65431a203faSVlad Serebrennikov       }
65531a203faSVlad Serebrennikov 
65631a203faSVlad Serebrennikov       // Retrieve the bound.
65731a203faSVlad Serebrennikov       QualType bound = typeParam->getUnderlyingType();
65831a203faSVlad Serebrennikov       if (bound->isBlockCompatibleObjCPointerType(S.Context))
65931a203faSVlad Serebrennikov         continue;
66031a203faSVlad Serebrennikov 
66131a203faSVlad Serebrennikov       // Diagnose the mismatch.
66231a203faSVlad Serebrennikov       S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
66331a203faSVlad Serebrennikov              diag::err_objc_type_arg_does_not_match_bound)
66431a203faSVlad Serebrennikov           << typeArg << bound << typeParam->getDeclName();
66531a203faSVlad Serebrennikov       S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
66631a203faSVlad Serebrennikov           << typeParam->getDeclName();
66731a203faSVlad Serebrennikov 
66831a203faSVlad Serebrennikov       if (failOnError)
66931a203faSVlad Serebrennikov         return QualType();
67031a203faSVlad Serebrennikov 
67131a203faSVlad Serebrennikov       return type;
67231a203faSVlad Serebrennikov     }
67331a203faSVlad Serebrennikov 
67431a203faSVlad Serebrennikov     // Types that have __attribute__((NSObject)) are permitted.
67531a203faSVlad Serebrennikov     if (typeArg->isObjCNSObjectType()) {
67631a203faSVlad Serebrennikov       continue;
67731a203faSVlad Serebrennikov     }
67831a203faSVlad Serebrennikov 
67931a203faSVlad Serebrennikov     // Dependent types will be checked at instantiation time.
68031a203faSVlad Serebrennikov     if (typeArg->isDependentType()) {
68131a203faSVlad Serebrennikov       continue;
68231a203faSVlad Serebrennikov     }
68331a203faSVlad Serebrennikov 
68431a203faSVlad Serebrennikov     // Diagnose non-id-compatible type arguments.
68531a203faSVlad Serebrennikov     S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
68631a203faSVlad Serebrennikov            diag::err_objc_type_arg_not_id_compatible)
68731a203faSVlad Serebrennikov         << typeArg << typeArgInfo->getTypeLoc().getSourceRange();
68831a203faSVlad Serebrennikov 
68931a203faSVlad Serebrennikov     if (failOnError)
69031a203faSVlad Serebrennikov       return QualType();
69131a203faSVlad Serebrennikov 
69231a203faSVlad Serebrennikov     return type;
69331a203faSVlad Serebrennikov   }
69431a203faSVlad Serebrennikov 
69531a203faSVlad Serebrennikov   // Make sure we didn't have the wrong number of arguments.
69631a203faSVlad Serebrennikov   if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) {
69731a203faSVlad Serebrennikov     S.Diag(loc, diag::err_objc_type_args_wrong_arity)
69831a203faSVlad Serebrennikov         << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName()
69931a203faSVlad Serebrennikov         << (unsigned)finalTypeArgs.size() << (unsigned)numTypeParams;
70031a203faSVlad Serebrennikov     S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass;
70131a203faSVlad Serebrennikov 
70231a203faSVlad Serebrennikov     if (failOnError)
70331a203faSVlad Serebrennikov       return QualType();
70431a203faSVlad Serebrennikov 
70531a203faSVlad Serebrennikov     return type;
70631a203faSVlad Serebrennikov   }
70731a203faSVlad Serebrennikov 
70831a203faSVlad Serebrennikov   // Success. Form the specialized type.
70931a203faSVlad Serebrennikov   return S.Context.getObjCObjectType(type, finalTypeArgs, {}, false);
71031a203faSVlad Serebrennikov }
71131a203faSVlad Serebrennikov 
71231a203faSVlad Serebrennikov QualType SemaObjC::BuildObjCObjectType(
71331a203faSVlad Serebrennikov     QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
71431a203faSVlad Serebrennikov     ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
71531a203faSVlad Serebrennikov     SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
71631a203faSVlad Serebrennikov     ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
71731a203faSVlad Serebrennikov     bool FailOnError, bool Rebuilding) {
71831a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
71931a203faSVlad Serebrennikov   QualType Result = BaseType;
72031a203faSVlad Serebrennikov   if (!TypeArgs.empty()) {
72131a203faSVlad Serebrennikov     Result =
72231a203faSVlad Serebrennikov         applyObjCTypeArgs(SemaRef, Loc, Result, TypeArgs,
72331a203faSVlad Serebrennikov                           SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc),
72431a203faSVlad Serebrennikov                           FailOnError, Rebuilding);
72531a203faSVlad Serebrennikov     if (FailOnError && Result.isNull())
72631a203faSVlad Serebrennikov       return QualType();
72731a203faSVlad Serebrennikov   }
72831a203faSVlad Serebrennikov 
72931a203faSVlad Serebrennikov   if (!Protocols.empty()) {
73031a203faSVlad Serebrennikov     bool HasError;
73131a203faSVlad Serebrennikov     Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError);
73231a203faSVlad Serebrennikov     if (HasError) {
73331a203faSVlad Serebrennikov       Diag(Loc, diag::err_invalid_protocol_qualifiers)
73431a203faSVlad Serebrennikov           << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
73531a203faSVlad Serebrennikov       if (FailOnError)
73631a203faSVlad Serebrennikov         Result = QualType();
73731a203faSVlad Serebrennikov     }
73831a203faSVlad Serebrennikov     if (FailOnError && Result.isNull())
73931a203faSVlad Serebrennikov       return QualType();
74031a203faSVlad Serebrennikov   }
74131a203faSVlad Serebrennikov 
74231a203faSVlad Serebrennikov   return Result;
74331a203faSVlad Serebrennikov }
74431a203faSVlad Serebrennikov 
74531a203faSVlad Serebrennikov ParsedType SemaObjC::ActOnObjCInstanceType(SourceLocation Loc) {
74631a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
74731a203faSVlad Serebrennikov   QualType T = Context.getObjCInstanceType();
74831a203faSVlad Serebrennikov   TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
74931a203faSVlad Serebrennikov   return SemaRef.CreateParsedType(T, TInfo);
75031a203faSVlad Serebrennikov }
75131a203faSVlad Serebrennikov 
75231a203faSVlad Serebrennikov //===--- CHECK: Objective-C retain cycles ----------------------------------//
75331a203faSVlad Serebrennikov 
75431a203faSVlad Serebrennikov namespace {
75531a203faSVlad Serebrennikov 
75631a203faSVlad Serebrennikov struct RetainCycleOwner {
75731a203faSVlad Serebrennikov   VarDecl *Variable = nullptr;
75831a203faSVlad Serebrennikov   SourceRange Range;
75931a203faSVlad Serebrennikov   SourceLocation Loc;
76031a203faSVlad Serebrennikov   bool Indirect = false;
76131a203faSVlad Serebrennikov 
76231a203faSVlad Serebrennikov   RetainCycleOwner() = default;
76331a203faSVlad Serebrennikov 
76431a203faSVlad Serebrennikov   void setLocsFrom(Expr *e) {
76531a203faSVlad Serebrennikov     Loc = e->getExprLoc();
76631a203faSVlad Serebrennikov     Range = e->getSourceRange();
76731a203faSVlad Serebrennikov   }
76831a203faSVlad Serebrennikov };
76931a203faSVlad Serebrennikov 
77031a203faSVlad Serebrennikov } // namespace
77131a203faSVlad Serebrennikov 
77231a203faSVlad Serebrennikov /// Consider whether capturing the given variable can possibly lead to
77331a203faSVlad Serebrennikov /// a retain cycle.
77431a203faSVlad Serebrennikov static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) {
77531a203faSVlad Serebrennikov   // In ARC, it's captured strongly iff the variable has __strong
77631a203faSVlad Serebrennikov   // lifetime.  In MRR, it's captured strongly if the variable is
77731a203faSVlad Serebrennikov   // __block and has an appropriate type.
77831a203faSVlad Serebrennikov   if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
77931a203faSVlad Serebrennikov     return false;
78031a203faSVlad Serebrennikov 
78131a203faSVlad Serebrennikov   owner.Variable = var;
78231a203faSVlad Serebrennikov   if (ref)
78331a203faSVlad Serebrennikov     owner.setLocsFrom(ref);
78431a203faSVlad Serebrennikov   return true;
78531a203faSVlad Serebrennikov }
78631a203faSVlad Serebrennikov 
78731a203faSVlad Serebrennikov static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) {
78831a203faSVlad Serebrennikov   while (true) {
78931a203faSVlad Serebrennikov     e = e->IgnoreParens();
79031a203faSVlad Serebrennikov     if (CastExpr *cast = dyn_cast<CastExpr>(e)) {
79131a203faSVlad Serebrennikov       switch (cast->getCastKind()) {
79231a203faSVlad Serebrennikov       case CK_BitCast:
79331a203faSVlad Serebrennikov       case CK_LValueBitCast:
79431a203faSVlad Serebrennikov       case CK_LValueToRValue:
79531a203faSVlad Serebrennikov       case CK_ARCReclaimReturnedObject:
79631a203faSVlad Serebrennikov         e = cast->getSubExpr();
79731a203faSVlad Serebrennikov         continue;
79831a203faSVlad Serebrennikov 
79931a203faSVlad Serebrennikov       default:
80031a203faSVlad Serebrennikov         return false;
80131a203faSVlad Serebrennikov       }
80231a203faSVlad Serebrennikov     }
80331a203faSVlad Serebrennikov 
80431a203faSVlad Serebrennikov     if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) {
80531a203faSVlad Serebrennikov       ObjCIvarDecl *ivar = ref->getDecl();
80631a203faSVlad Serebrennikov       if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
80731a203faSVlad Serebrennikov         return false;
80831a203faSVlad Serebrennikov 
80931a203faSVlad Serebrennikov       // Try to find a retain cycle in the base.
81031a203faSVlad Serebrennikov       if (!findRetainCycleOwner(S, ref->getBase(), owner))
81131a203faSVlad Serebrennikov         return false;
81231a203faSVlad Serebrennikov 
81331a203faSVlad Serebrennikov       if (ref->isFreeIvar())
81431a203faSVlad Serebrennikov         owner.setLocsFrom(ref);
81531a203faSVlad Serebrennikov       owner.Indirect = true;
81631a203faSVlad Serebrennikov       return true;
81731a203faSVlad Serebrennikov     }
81831a203faSVlad Serebrennikov 
81931a203faSVlad Serebrennikov     if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
82031a203faSVlad Serebrennikov       VarDecl *var = dyn_cast<VarDecl>(ref->getDecl());
82131a203faSVlad Serebrennikov       if (!var)
82231a203faSVlad Serebrennikov         return false;
82331a203faSVlad Serebrennikov       return considerVariable(var, ref, owner);
82431a203faSVlad Serebrennikov     }
82531a203faSVlad Serebrennikov 
82631a203faSVlad Serebrennikov     if (MemberExpr *member = dyn_cast<MemberExpr>(e)) {
82731a203faSVlad Serebrennikov       if (member->isArrow())
82831a203faSVlad Serebrennikov         return false;
82931a203faSVlad Serebrennikov 
83031a203faSVlad Serebrennikov       // Don't count this as an indirect ownership.
83131a203faSVlad Serebrennikov       e = member->getBase();
83231a203faSVlad Serebrennikov       continue;
83331a203faSVlad Serebrennikov     }
83431a203faSVlad Serebrennikov 
83531a203faSVlad Serebrennikov     if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {
83631a203faSVlad Serebrennikov       // Only pay attention to pseudo-objects on property references.
83731a203faSVlad Serebrennikov       ObjCPropertyRefExpr *pre = dyn_cast<ObjCPropertyRefExpr>(
83831a203faSVlad Serebrennikov           pseudo->getSyntacticForm()->IgnoreParens());
83931a203faSVlad Serebrennikov       if (!pre)
84031a203faSVlad Serebrennikov         return false;
84131a203faSVlad Serebrennikov       if (pre->isImplicitProperty())
84231a203faSVlad Serebrennikov         return false;
84331a203faSVlad Serebrennikov       ObjCPropertyDecl *property = pre->getExplicitProperty();
84431a203faSVlad Serebrennikov       if (!property->isRetaining() &&
84531a203faSVlad Serebrennikov           !(property->getPropertyIvarDecl() &&
84631a203faSVlad Serebrennikov             property->getPropertyIvarDecl()->getType().getObjCLifetime() ==
84731a203faSVlad Serebrennikov                 Qualifiers::OCL_Strong))
84831a203faSVlad Serebrennikov         return false;
84931a203faSVlad Serebrennikov 
85031a203faSVlad Serebrennikov       owner.Indirect = true;
85131a203faSVlad Serebrennikov       if (pre->isSuperReceiver()) {
85231a203faSVlad Serebrennikov         owner.Variable = S.getCurMethodDecl()->getSelfDecl();
85331a203faSVlad Serebrennikov         if (!owner.Variable)
85431a203faSVlad Serebrennikov           return false;
85531a203faSVlad Serebrennikov         owner.Loc = pre->getLocation();
85631a203faSVlad Serebrennikov         owner.Range = pre->getSourceRange();
85731a203faSVlad Serebrennikov         return true;
85831a203faSVlad Serebrennikov       }
85931a203faSVlad Serebrennikov       e = const_cast<Expr *>(
86031a203faSVlad Serebrennikov           cast<OpaqueValueExpr>(pre->getBase())->getSourceExpr());
86131a203faSVlad Serebrennikov       continue;
86231a203faSVlad Serebrennikov     }
86331a203faSVlad Serebrennikov 
86431a203faSVlad Serebrennikov     // Array ivars?
86531a203faSVlad Serebrennikov 
86631a203faSVlad Serebrennikov     return false;
86731a203faSVlad Serebrennikov   }
86831a203faSVlad Serebrennikov }
86931a203faSVlad Serebrennikov 
87031a203faSVlad Serebrennikov namespace {
87131a203faSVlad Serebrennikov 
87231a203faSVlad Serebrennikov struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
87331a203faSVlad Serebrennikov   VarDecl *Variable;
87431a203faSVlad Serebrennikov   Expr *Capturer = nullptr;
87531a203faSVlad Serebrennikov   bool VarWillBeReased = false;
87631a203faSVlad Serebrennikov 
87731a203faSVlad Serebrennikov   FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
87831a203faSVlad Serebrennikov       : EvaluatedExprVisitor<FindCaptureVisitor>(Context), Variable(variable) {}
87931a203faSVlad Serebrennikov 
88031a203faSVlad Serebrennikov   void VisitDeclRefExpr(DeclRefExpr *ref) {
88131a203faSVlad Serebrennikov     if (ref->getDecl() == Variable && !Capturer)
88231a203faSVlad Serebrennikov       Capturer = ref;
88331a203faSVlad Serebrennikov   }
88431a203faSVlad Serebrennikov 
88531a203faSVlad Serebrennikov   void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) {
88631a203faSVlad Serebrennikov     if (Capturer)
88731a203faSVlad Serebrennikov       return;
88831a203faSVlad Serebrennikov     Visit(ref->getBase());
88931a203faSVlad Serebrennikov     if (Capturer && ref->isFreeIvar())
89031a203faSVlad Serebrennikov       Capturer = ref;
89131a203faSVlad Serebrennikov   }
89231a203faSVlad Serebrennikov 
89331a203faSVlad Serebrennikov   void VisitBlockExpr(BlockExpr *block) {
89431a203faSVlad Serebrennikov     // Look inside nested blocks
89531a203faSVlad Serebrennikov     if (block->getBlockDecl()->capturesVariable(Variable))
89631a203faSVlad Serebrennikov       Visit(block->getBlockDecl()->getBody());
89731a203faSVlad Serebrennikov   }
89831a203faSVlad Serebrennikov 
89931a203faSVlad Serebrennikov   void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) {
90031a203faSVlad Serebrennikov     if (Capturer)
90131a203faSVlad Serebrennikov       return;
90231a203faSVlad Serebrennikov     if (OVE->getSourceExpr())
90331a203faSVlad Serebrennikov       Visit(OVE->getSourceExpr());
90431a203faSVlad Serebrennikov   }
90531a203faSVlad Serebrennikov 
90631a203faSVlad Serebrennikov   void VisitBinaryOperator(BinaryOperator *BinOp) {
90731a203faSVlad Serebrennikov     if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign)
90831a203faSVlad Serebrennikov       return;
90931a203faSVlad Serebrennikov     Expr *LHS = BinOp->getLHS();
91031a203faSVlad Serebrennikov     if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) {
91131a203faSVlad Serebrennikov       if (DRE->getDecl() != Variable)
91231a203faSVlad Serebrennikov         return;
91331a203faSVlad Serebrennikov       if (Expr *RHS = BinOp->getRHS()) {
91431a203faSVlad Serebrennikov         RHS = RHS->IgnoreParenCasts();
91531a203faSVlad Serebrennikov         std::optional<llvm::APSInt> Value;
91631a203faSVlad Serebrennikov         VarWillBeReased =
91731a203faSVlad Serebrennikov             (RHS && (Value = RHS->getIntegerConstantExpr(Context)) &&
91831a203faSVlad Serebrennikov              *Value == 0);
91931a203faSVlad Serebrennikov       }
92031a203faSVlad Serebrennikov     }
92131a203faSVlad Serebrennikov   }
92231a203faSVlad Serebrennikov };
92331a203faSVlad Serebrennikov 
92431a203faSVlad Serebrennikov } // namespace
92531a203faSVlad Serebrennikov 
92631a203faSVlad Serebrennikov /// Check whether the given argument is a block which captures a
92731a203faSVlad Serebrennikov /// variable.
92831a203faSVlad Serebrennikov static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
92931a203faSVlad Serebrennikov   assert(owner.Variable && owner.Loc.isValid());
93031a203faSVlad Serebrennikov 
93131a203faSVlad Serebrennikov   e = e->IgnoreParenCasts();
93231a203faSVlad Serebrennikov 
93331a203faSVlad Serebrennikov   // Look through [^{...} copy] and Block_copy(^{...}).
93431a203faSVlad Serebrennikov   if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) {
93531a203faSVlad Serebrennikov     Selector Cmd = ME->getSelector();
93631a203faSVlad Serebrennikov     if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") {
93731a203faSVlad Serebrennikov       e = ME->getInstanceReceiver();
93831a203faSVlad Serebrennikov       if (!e)
93931a203faSVlad Serebrennikov         return nullptr;
94031a203faSVlad Serebrennikov       e = e->IgnoreParenCasts();
94131a203faSVlad Serebrennikov     }
94231a203faSVlad Serebrennikov   } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) {
94331a203faSVlad Serebrennikov     if (CE->getNumArgs() == 1) {
94431a203faSVlad Serebrennikov       FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl());
94531a203faSVlad Serebrennikov       if (Fn) {
94631a203faSVlad Serebrennikov         const IdentifierInfo *FnI = Fn->getIdentifier();
94731a203faSVlad Serebrennikov         if (FnI && FnI->isStr("_Block_copy")) {
94831a203faSVlad Serebrennikov           e = CE->getArg(0)->IgnoreParenCasts();
94931a203faSVlad Serebrennikov         }
95031a203faSVlad Serebrennikov       }
95131a203faSVlad Serebrennikov     }
95231a203faSVlad Serebrennikov   }
95331a203faSVlad Serebrennikov 
95431a203faSVlad Serebrennikov   BlockExpr *block = dyn_cast<BlockExpr>(e);
95531a203faSVlad Serebrennikov   if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
95631a203faSVlad Serebrennikov     return nullptr;
95731a203faSVlad Serebrennikov 
95831a203faSVlad Serebrennikov   FindCaptureVisitor visitor(S.Context, owner.Variable);
95931a203faSVlad Serebrennikov   visitor.Visit(block->getBlockDecl()->getBody());
96031a203faSVlad Serebrennikov   return visitor.VarWillBeReased ? nullptr : visitor.Capturer;
96131a203faSVlad Serebrennikov }
96231a203faSVlad Serebrennikov 
96331a203faSVlad Serebrennikov static void diagnoseRetainCycle(Sema &S, Expr *capturer,
96431a203faSVlad Serebrennikov                                 RetainCycleOwner &owner) {
96531a203faSVlad Serebrennikov   assert(capturer);
96631a203faSVlad Serebrennikov   assert(owner.Variable && owner.Loc.isValid());
96731a203faSVlad Serebrennikov 
96831a203faSVlad Serebrennikov   S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle)
96931a203faSVlad Serebrennikov       << owner.Variable << capturer->getSourceRange();
97031a203faSVlad Serebrennikov   S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner)
97131a203faSVlad Serebrennikov       << owner.Indirect << owner.Range;
97231a203faSVlad Serebrennikov }
97331a203faSVlad Serebrennikov 
97431a203faSVlad Serebrennikov /// Check for a keyword selector that starts with the word 'add' or
97531a203faSVlad Serebrennikov /// 'set'.
97631a203faSVlad Serebrennikov static bool isSetterLikeSelector(Selector sel) {
97731a203faSVlad Serebrennikov   if (sel.isUnarySelector())
97831a203faSVlad Serebrennikov     return false;
97931a203faSVlad Serebrennikov 
98031a203faSVlad Serebrennikov   StringRef str = sel.getNameForSlot(0);
98131a203faSVlad Serebrennikov   str = str.ltrim('_');
98231a203faSVlad Serebrennikov   if (str.starts_with("set"))
98331a203faSVlad Serebrennikov     str = str.substr(3);
98431a203faSVlad Serebrennikov   else if (str.starts_with("add")) {
98531a203faSVlad Serebrennikov     // Specially allow 'addOperationWithBlock:'.
98631a203faSVlad Serebrennikov     if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock"))
98731a203faSVlad Serebrennikov       return false;
98831a203faSVlad Serebrennikov     str = str.substr(3);
98931a203faSVlad Serebrennikov   } else
99031a203faSVlad Serebrennikov     return false;
99131a203faSVlad Serebrennikov 
99231a203faSVlad Serebrennikov   if (str.empty())
99331a203faSVlad Serebrennikov     return true;
99431a203faSVlad Serebrennikov   return !isLowercase(str.front());
99531a203faSVlad Serebrennikov }
99631a203faSVlad Serebrennikov 
99731a203faSVlad Serebrennikov static std::optional<int>
99831a203faSVlad Serebrennikov GetNSMutableArrayArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) {
99931a203faSVlad Serebrennikov   bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass(
100031a203faSVlad Serebrennikov       Message->getReceiverInterface(), NSAPI::ClassId_NSMutableArray);
100131a203faSVlad Serebrennikov   if (!IsMutableArray) {
100231a203faSVlad Serebrennikov     return std::nullopt;
100331a203faSVlad Serebrennikov   }
100431a203faSVlad Serebrennikov 
100531a203faSVlad Serebrennikov   Selector Sel = Message->getSelector();
100631a203faSVlad Serebrennikov 
100731a203faSVlad Serebrennikov   std::optional<NSAPI::NSArrayMethodKind> MKOpt =
100831a203faSVlad Serebrennikov       S.NSAPIObj->getNSArrayMethodKind(Sel);
100931a203faSVlad Serebrennikov   if (!MKOpt) {
101031a203faSVlad Serebrennikov     return std::nullopt;
101131a203faSVlad Serebrennikov   }
101231a203faSVlad Serebrennikov 
101331a203faSVlad Serebrennikov   NSAPI::NSArrayMethodKind MK = *MKOpt;
101431a203faSVlad Serebrennikov 
101531a203faSVlad Serebrennikov   switch (MK) {
101631a203faSVlad Serebrennikov   case NSAPI::NSMutableArr_addObject:
101731a203faSVlad Serebrennikov   case NSAPI::NSMutableArr_insertObjectAtIndex:
101831a203faSVlad Serebrennikov   case NSAPI::NSMutableArr_setObjectAtIndexedSubscript:
101931a203faSVlad Serebrennikov     return 0;
102031a203faSVlad Serebrennikov   case NSAPI::NSMutableArr_replaceObjectAtIndex:
102131a203faSVlad Serebrennikov     return 1;
102231a203faSVlad Serebrennikov 
102331a203faSVlad Serebrennikov   default:
102431a203faSVlad Serebrennikov     return std::nullopt;
102531a203faSVlad Serebrennikov   }
102631a203faSVlad Serebrennikov 
102731a203faSVlad Serebrennikov   return std::nullopt;
102831a203faSVlad Serebrennikov }
102931a203faSVlad Serebrennikov 
103031a203faSVlad Serebrennikov static std::optional<int>
103131a203faSVlad Serebrennikov GetNSMutableDictionaryArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) {
103231a203faSVlad Serebrennikov   bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass(
103331a203faSVlad Serebrennikov       Message->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary);
103431a203faSVlad Serebrennikov   if (!IsMutableDictionary) {
103531a203faSVlad Serebrennikov     return std::nullopt;
103631a203faSVlad Serebrennikov   }
103731a203faSVlad Serebrennikov 
103831a203faSVlad Serebrennikov   Selector Sel = Message->getSelector();
103931a203faSVlad Serebrennikov 
104031a203faSVlad Serebrennikov   std::optional<NSAPI::NSDictionaryMethodKind> MKOpt =
104131a203faSVlad Serebrennikov       S.NSAPIObj->getNSDictionaryMethodKind(Sel);
104231a203faSVlad Serebrennikov   if (!MKOpt) {
104331a203faSVlad Serebrennikov     return std::nullopt;
104431a203faSVlad Serebrennikov   }
104531a203faSVlad Serebrennikov 
104631a203faSVlad Serebrennikov   NSAPI::NSDictionaryMethodKind MK = *MKOpt;
104731a203faSVlad Serebrennikov 
104831a203faSVlad Serebrennikov   switch (MK) {
104931a203faSVlad Serebrennikov   case NSAPI::NSMutableDict_setObjectForKey:
105031a203faSVlad Serebrennikov   case NSAPI::NSMutableDict_setValueForKey:
105131a203faSVlad Serebrennikov   case NSAPI::NSMutableDict_setObjectForKeyedSubscript:
105231a203faSVlad Serebrennikov     return 0;
105331a203faSVlad Serebrennikov 
105431a203faSVlad Serebrennikov   default:
105531a203faSVlad Serebrennikov     return std::nullopt;
105631a203faSVlad Serebrennikov   }
105731a203faSVlad Serebrennikov 
105831a203faSVlad Serebrennikov   return std::nullopt;
105931a203faSVlad Serebrennikov }
106031a203faSVlad Serebrennikov 
106131a203faSVlad Serebrennikov static std::optional<int> GetNSSetArgumentIndex(SemaObjC &S,
106231a203faSVlad Serebrennikov                                                 ObjCMessageExpr *Message) {
106331a203faSVlad Serebrennikov   bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass(
106431a203faSVlad Serebrennikov       Message->getReceiverInterface(), NSAPI::ClassId_NSMutableSet);
106531a203faSVlad Serebrennikov 
106631a203faSVlad Serebrennikov   bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass(
106731a203faSVlad Serebrennikov       Message->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet);
106831a203faSVlad Serebrennikov   if (!IsMutableSet && !IsMutableOrderedSet) {
106931a203faSVlad Serebrennikov     return std::nullopt;
107031a203faSVlad Serebrennikov   }
107131a203faSVlad Serebrennikov 
107231a203faSVlad Serebrennikov   Selector Sel = Message->getSelector();
107331a203faSVlad Serebrennikov 
107431a203faSVlad Serebrennikov   std::optional<NSAPI::NSSetMethodKind> MKOpt =
107531a203faSVlad Serebrennikov       S.NSAPIObj->getNSSetMethodKind(Sel);
107631a203faSVlad Serebrennikov   if (!MKOpt) {
107731a203faSVlad Serebrennikov     return std::nullopt;
107831a203faSVlad Serebrennikov   }
107931a203faSVlad Serebrennikov 
108031a203faSVlad Serebrennikov   NSAPI::NSSetMethodKind MK = *MKOpt;
108131a203faSVlad Serebrennikov 
108231a203faSVlad Serebrennikov   switch (MK) {
108331a203faSVlad Serebrennikov   case NSAPI::NSMutableSet_addObject:
108431a203faSVlad Serebrennikov   case NSAPI::NSOrderedSet_setObjectAtIndex:
108531a203faSVlad Serebrennikov   case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript:
108631a203faSVlad Serebrennikov   case NSAPI::NSOrderedSet_insertObjectAtIndex:
108731a203faSVlad Serebrennikov     return 0;
108831a203faSVlad Serebrennikov   case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject:
108931a203faSVlad Serebrennikov     return 1;
109031a203faSVlad Serebrennikov   }
109131a203faSVlad Serebrennikov 
109231a203faSVlad Serebrennikov   return std::nullopt;
109331a203faSVlad Serebrennikov }
109431a203faSVlad Serebrennikov 
109531a203faSVlad Serebrennikov void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
109631a203faSVlad Serebrennikov   if (!Message->isInstanceMessage()) {
109731a203faSVlad Serebrennikov     return;
109831a203faSVlad Serebrennikov   }
109931a203faSVlad Serebrennikov 
110031a203faSVlad Serebrennikov   std::optional<int> ArgOpt;
110131a203faSVlad Serebrennikov 
110231a203faSVlad Serebrennikov   if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) &&
110331a203faSVlad Serebrennikov       !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) &&
110431a203faSVlad Serebrennikov       !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) {
110531a203faSVlad Serebrennikov     return;
110631a203faSVlad Serebrennikov   }
110731a203faSVlad Serebrennikov 
110831a203faSVlad Serebrennikov   int ArgIndex = *ArgOpt;
110931a203faSVlad Serebrennikov 
111031a203faSVlad Serebrennikov   Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts();
111131a203faSVlad Serebrennikov   if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) {
111231a203faSVlad Serebrennikov     Arg = OE->getSourceExpr()->IgnoreImpCasts();
111331a203faSVlad Serebrennikov   }
111431a203faSVlad Serebrennikov 
111531a203faSVlad Serebrennikov   if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
111631a203faSVlad Serebrennikov     if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
111731a203faSVlad Serebrennikov       if (ArgRE->isObjCSelfExpr()) {
111831a203faSVlad Serebrennikov         Diag(Message->getSourceRange().getBegin(),
111931a203faSVlad Serebrennikov              diag::warn_objc_circular_container)
112031a203faSVlad Serebrennikov             << ArgRE->getDecl() << StringRef("'super'");
112131a203faSVlad Serebrennikov       }
112231a203faSVlad Serebrennikov     }
112331a203faSVlad Serebrennikov   } else {
112431a203faSVlad Serebrennikov     Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts();
112531a203faSVlad Serebrennikov 
112631a203faSVlad Serebrennikov     if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) {
112731a203faSVlad Serebrennikov       Receiver = OE->getSourceExpr()->IgnoreImpCasts();
112831a203faSVlad Serebrennikov     }
112931a203faSVlad Serebrennikov 
113031a203faSVlad Serebrennikov     if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) {
113131a203faSVlad Serebrennikov       if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
113231a203faSVlad Serebrennikov         if (ReceiverRE->getDecl() == ArgRE->getDecl()) {
113331a203faSVlad Serebrennikov           ValueDecl *Decl = ReceiverRE->getDecl();
113431a203faSVlad Serebrennikov           Diag(Message->getSourceRange().getBegin(),
113531a203faSVlad Serebrennikov                diag::warn_objc_circular_container)
113631a203faSVlad Serebrennikov               << Decl << Decl;
113731a203faSVlad Serebrennikov           if (!ArgRE->isObjCSelfExpr()) {
113831a203faSVlad Serebrennikov             Diag(Decl->getLocation(),
113931a203faSVlad Serebrennikov                  diag::note_objc_circular_container_declared_here)
114031a203faSVlad Serebrennikov                 << Decl;
114131a203faSVlad Serebrennikov           }
114231a203faSVlad Serebrennikov         }
114331a203faSVlad Serebrennikov       }
114431a203faSVlad Serebrennikov     } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) {
114531a203faSVlad Serebrennikov       if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) {
114631a203faSVlad Serebrennikov         if (IvarRE->getDecl() == IvarArgRE->getDecl()) {
114731a203faSVlad Serebrennikov           ObjCIvarDecl *Decl = IvarRE->getDecl();
114831a203faSVlad Serebrennikov           Diag(Message->getSourceRange().getBegin(),
114931a203faSVlad Serebrennikov                diag::warn_objc_circular_container)
115031a203faSVlad Serebrennikov               << Decl << Decl;
115131a203faSVlad Serebrennikov           Diag(Decl->getLocation(),
115231a203faSVlad Serebrennikov                diag::note_objc_circular_container_declared_here)
115331a203faSVlad Serebrennikov               << Decl;
115431a203faSVlad Serebrennikov         }
115531a203faSVlad Serebrennikov       }
115631a203faSVlad Serebrennikov     }
115731a203faSVlad Serebrennikov   }
115831a203faSVlad Serebrennikov }
115931a203faSVlad Serebrennikov 
116031a203faSVlad Serebrennikov /// Check a message send to see if it's likely to cause a retain cycle.
116131a203faSVlad Serebrennikov void SemaObjC::checkRetainCycles(ObjCMessageExpr *msg) {
116231a203faSVlad Serebrennikov   // Only check instance methods whose selector looks like a setter.
116331a203faSVlad Serebrennikov   if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector()))
116431a203faSVlad Serebrennikov     return;
116531a203faSVlad Serebrennikov 
116631a203faSVlad Serebrennikov   // Try to find a variable that the receiver is strongly owned by.
116731a203faSVlad Serebrennikov   RetainCycleOwner owner;
116831a203faSVlad Serebrennikov   if (msg->getReceiverKind() == ObjCMessageExpr::Instance) {
116931a203faSVlad Serebrennikov     if (!findRetainCycleOwner(SemaRef, msg->getInstanceReceiver(), owner))
117031a203faSVlad Serebrennikov       return;
117131a203faSVlad Serebrennikov   } else {
117231a203faSVlad Serebrennikov     assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
117331a203faSVlad Serebrennikov     owner.Variable = SemaRef.getCurMethodDecl()->getSelfDecl();
117431a203faSVlad Serebrennikov     owner.Loc = msg->getSuperLoc();
117531a203faSVlad Serebrennikov     owner.Range = msg->getSuperLoc();
117631a203faSVlad Serebrennikov   }
117731a203faSVlad Serebrennikov 
117831a203faSVlad Serebrennikov   // Check whether the receiver is captured by any of the arguments.
117931a203faSVlad Serebrennikov   const ObjCMethodDecl *MD = msg->getMethodDecl();
118031a203faSVlad Serebrennikov   for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) {
118131a203faSVlad Serebrennikov     if (Expr *capturer = findCapturingExpr(SemaRef, msg->getArg(i), owner)) {
118231a203faSVlad Serebrennikov       // noescape blocks should not be retained by the method.
118331a203faSVlad Serebrennikov       if (MD && MD->parameters()[i]->hasAttr<NoEscapeAttr>())
118431a203faSVlad Serebrennikov         continue;
118531a203faSVlad Serebrennikov       return diagnoseRetainCycle(SemaRef, capturer, owner);
118631a203faSVlad Serebrennikov     }
118731a203faSVlad Serebrennikov   }
118831a203faSVlad Serebrennikov }
118931a203faSVlad Serebrennikov 
119031a203faSVlad Serebrennikov /// Check a property assign to see if it's likely to cause a retain cycle.
119131a203faSVlad Serebrennikov void SemaObjC::checkRetainCycles(Expr *receiver, Expr *argument) {
119231a203faSVlad Serebrennikov   RetainCycleOwner owner;
119331a203faSVlad Serebrennikov   if (!findRetainCycleOwner(SemaRef, receiver, owner))
119431a203faSVlad Serebrennikov     return;
119531a203faSVlad Serebrennikov 
119631a203faSVlad Serebrennikov   if (Expr *capturer = findCapturingExpr(SemaRef, argument, owner))
119731a203faSVlad Serebrennikov     diagnoseRetainCycle(SemaRef, capturer, owner);
119831a203faSVlad Serebrennikov }
119931a203faSVlad Serebrennikov 
120031a203faSVlad Serebrennikov void SemaObjC::checkRetainCycles(VarDecl *Var, Expr *Init) {
120131a203faSVlad Serebrennikov   RetainCycleOwner Owner;
120231a203faSVlad Serebrennikov   if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner))
120331a203faSVlad Serebrennikov     return;
120431a203faSVlad Serebrennikov 
120531a203faSVlad Serebrennikov   // Because we don't have an expression for the variable, we have to set the
120631a203faSVlad Serebrennikov   // location explicitly here.
120731a203faSVlad Serebrennikov   Owner.Loc = Var->getLocation();
120831a203faSVlad Serebrennikov   Owner.Range = Var->getSourceRange();
120931a203faSVlad Serebrennikov 
121031a203faSVlad Serebrennikov   if (Expr *Capturer = findCapturingExpr(SemaRef, Init, Owner))
121131a203faSVlad Serebrennikov     diagnoseRetainCycle(SemaRef, Capturer, Owner);
121231a203faSVlad Serebrennikov }
121331a203faSVlad Serebrennikov 
121431a203faSVlad Serebrennikov /// CheckObjCString - Checks that the argument to the builtin
121531a203faSVlad Serebrennikov /// CFString constructor is correct
121631a203faSVlad Serebrennikov /// Note: It might also make sense to do the UTF-16 conversion here (would
121731a203faSVlad Serebrennikov /// simplify the backend).
121831a203faSVlad Serebrennikov bool SemaObjC::CheckObjCString(Expr *Arg) {
121931a203faSVlad Serebrennikov   Arg = Arg->IgnoreParenCasts();
122031a203faSVlad Serebrennikov   StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
122131a203faSVlad Serebrennikov 
122231a203faSVlad Serebrennikov   if (!Literal || !Literal->isOrdinary()) {
122331a203faSVlad Serebrennikov     Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)
122431a203faSVlad Serebrennikov         << Arg->getSourceRange();
122531a203faSVlad Serebrennikov     return true;
122631a203faSVlad Serebrennikov   }
122731a203faSVlad Serebrennikov 
122831a203faSVlad Serebrennikov   if (Literal->containsNonAsciiOrNull()) {
122931a203faSVlad Serebrennikov     StringRef String = Literal->getString();
123031a203faSVlad Serebrennikov     unsigned NumBytes = String.size();
123131a203faSVlad Serebrennikov     SmallVector<llvm::UTF16, 128> ToBuf(NumBytes);
123231a203faSVlad Serebrennikov     const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data();
123331a203faSVlad Serebrennikov     llvm::UTF16 *ToPtr = &ToBuf[0];
123431a203faSVlad Serebrennikov 
123531a203faSVlad Serebrennikov     llvm::ConversionResult Result =
123631a203faSVlad Serebrennikov         llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr,
123731a203faSVlad Serebrennikov                                  ToPtr + NumBytes, llvm::strictConversion);
123831a203faSVlad Serebrennikov     // Check for conversion failure.
123931a203faSVlad Serebrennikov     if (Result != llvm::conversionOK)
124031a203faSVlad Serebrennikov       Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated)
124131a203faSVlad Serebrennikov           << Arg->getSourceRange();
124231a203faSVlad Serebrennikov   }
124331a203faSVlad Serebrennikov   return false;
124431a203faSVlad Serebrennikov }
124531a203faSVlad Serebrennikov 
124631a203faSVlad Serebrennikov bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
124731a203faSVlad Serebrennikov                                    ArrayRef<const Expr *> Args) {
124831a203faSVlad Serebrennikov   Sema::VariadicCallType CallType =
124931a203faSVlad Serebrennikov       Method->isVariadic() ? Sema::VariadicMethod : Sema::VariadicDoesNotApply;
125031a203faSVlad Serebrennikov 
125131a203faSVlad Serebrennikov   SemaRef.checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args,
125231a203faSVlad Serebrennikov                     /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
125331a203faSVlad Serebrennikov                     CallType);
125431a203faSVlad Serebrennikov 
125531a203faSVlad Serebrennikov   SemaRef.CheckTCBEnforcement(lbrac, Method);
125631a203faSVlad Serebrennikov 
125731a203faSVlad Serebrennikov   return false;
125831a203faSVlad Serebrennikov }
125931a203faSVlad Serebrennikov 
126031a203faSVlad Serebrennikov const DeclContext *SemaObjC::getCurObjCLexicalContext() const {
126131a203faSVlad Serebrennikov   const DeclContext *DC = SemaRef.getCurLexicalContext();
126231a203faSVlad Serebrennikov   // A category implicitly has the attribute of the interface.
126331a203faSVlad Serebrennikov   if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))
126431a203faSVlad Serebrennikov     DC = CatD->getClassInterface();
126531a203faSVlad Serebrennikov   return DC;
126631a203faSVlad Serebrennikov }
126731a203faSVlad Serebrennikov 
126831a203faSVlad Serebrennikov /// Retrieve the identifier "NSError".
126931a203faSVlad Serebrennikov IdentifierInfo *SemaObjC::getNSErrorIdent() {
127031a203faSVlad Serebrennikov   if (!Ident_NSError)
127131a203faSVlad Serebrennikov     Ident_NSError = SemaRef.PP.getIdentifierInfo("NSError");
127231a203faSVlad Serebrennikov 
127331a203faSVlad Serebrennikov   return Ident_NSError;
127431a203faSVlad Serebrennikov }
127531a203faSVlad Serebrennikov 
127631a203faSVlad Serebrennikov void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) {
127731a203faSVlad Serebrennikov   assert(
127831a203faSVlad Serebrennikov       IDecl->getLexicalParent() == SemaRef.CurContext &&
127931a203faSVlad Serebrennikov       "The next DeclContext should be lexically contained in the current one.");
128031a203faSVlad Serebrennikov   SemaRef.CurContext = IDecl;
128131a203faSVlad Serebrennikov }
128231a203faSVlad Serebrennikov 
128331a203faSVlad Serebrennikov void SemaObjC::ActOnObjCContainerFinishDefinition() {
128431a203faSVlad Serebrennikov   // Exit this scope of this interface definition.
128531a203faSVlad Serebrennikov   SemaRef.PopDeclContext();
128631a203faSVlad Serebrennikov }
128731a203faSVlad Serebrennikov 
128831a203faSVlad Serebrennikov void SemaObjC::ActOnObjCTemporaryExitContainerContext(
128931a203faSVlad Serebrennikov     ObjCContainerDecl *ObjCCtx) {
129031a203faSVlad Serebrennikov   assert(ObjCCtx == SemaRef.CurContext && "Mismatch of container contexts");
129131a203faSVlad Serebrennikov   SemaRef.OriginalLexicalContext = ObjCCtx;
129231a203faSVlad Serebrennikov   ActOnObjCContainerFinishDefinition();
129331a203faSVlad Serebrennikov }
129431a203faSVlad Serebrennikov 
129531a203faSVlad Serebrennikov void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) {
129631a203faSVlad Serebrennikov   ActOnObjCContainerStartDefinition(ObjCCtx);
129731a203faSVlad Serebrennikov   SemaRef.OriginalLexicalContext = nullptr;
129831a203faSVlad Serebrennikov }
129931a203faSVlad Serebrennikov 
130031a203faSVlad Serebrennikov /// Find the protocol with the given name, if any.
130131a203faSVlad Serebrennikov ObjCProtocolDecl *SemaObjC::LookupProtocol(IdentifierInfo *II,
130231a203faSVlad Serebrennikov                                            SourceLocation IdLoc,
130331a203faSVlad Serebrennikov                                            RedeclarationKind Redecl) {
130431a203faSVlad Serebrennikov   Decl *D = SemaRef.LookupSingleName(SemaRef.TUScope, II, IdLoc,
130531a203faSVlad Serebrennikov                                      Sema::LookupObjCProtocolName, Redecl);
130631a203faSVlad Serebrennikov   return cast_or_null<ObjCProtocolDecl>(D);
130731a203faSVlad Serebrennikov }
130831a203faSVlad Serebrennikov 
130931a203faSVlad Serebrennikov /// Determine whether this is an Objective-C writeback conversion,
131031a203faSVlad Serebrennikov /// used for parameter passing when performing automatic reference counting.
131131a203faSVlad Serebrennikov ///
131231a203faSVlad Serebrennikov /// \param FromType The type we're converting form.
131331a203faSVlad Serebrennikov ///
131431a203faSVlad Serebrennikov /// \param ToType The type we're converting to.
131531a203faSVlad Serebrennikov ///
131631a203faSVlad Serebrennikov /// \param ConvertedType The type that will be produced after applying
131731a203faSVlad Serebrennikov /// this conversion.
131831a203faSVlad Serebrennikov bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType,
131931a203faSVlad Serebrennikov                                          QualType &ConvertedType) {
132031a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
132131a203faSVlad Serebrennikov   if (!getLangOpts().ObjCAutoRefCount ||
132231a203faSVlad Serebrennikov       Context.hasSameUnqualifiedType(FromType, ToType))
132331a203faSVlad Serebrennikov     return false;
132431a203faSVlad Serebrennikov 
132531a203faSVlad Serebrennikov   // Parameter must be a pointer to __autoreleasing (with no other qualifiers).
132631a203faSVlad Serebrennikov   QualType ToPointee;
132731a203faSVlad Serebrennikov   if (const PointerType *ToPointer = ToType->getAs<PointerType>())
132831a203faSVlad Serebrennikov     ToPointee = ToPointer->getPointeeType();
132931a203faSVlad Serebrennikov   else
133031a203faSVlad Serebrennikov     return false;
133131a203faSVlad Serebrennikov 
133231a203faSVlad Serebrennikov   Qualifiers ToQuals = ToPointee.getQualifiers();
133331a203faSVlad Serebrennikov   if (!ToPointee->isObjCLifetimeType() ||
133431a203faSVlad Serebrennikov       ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||
133531a203faSVlad Serebrennikov       !ToQuals.withoutObjCLifetime().empty())
133631a203faSVlad Serebrennikov     return false;
133731a203faSVlad Serebrennikov 
133831a203faSVlad Serebrennikov   // Argument must be a pointer to __strong to __weak.
133931a203faSVlad Serebrennikov   QualType FromPointee;
134031a203faSVlad Serebrennikov   if (const PointerType *FromPointer = FromType->getAs<PointerType>())
134131a203faSVlad Serebrennikov     FromPointee = FromPointer->getPointeeType();
134231a203faSVlad Serebrennikov   else
134331a203faSVlad Serebrennikov     return false;
134431a203faSVlad Serebrennikov 
134531a203faSVlad Serebrennikov   Qualifiers FromQuals = FromPointee.getQualifiers();
134631a203faSVlad Serebrennikov   if (!FromPointee->isObjCLifetimeType() ||
134731a203faSVlad Serebrennikov       (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong &&
134831a203faSVlad Serebrennikov        FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak))
134931a203faSVlad Serebrennikov     return false;
135031a203faSVlad Serebrennikov 
135131a203faSVlad Serebrennikov   // Make sure that we have compatible qualifiers.
135231a203faSVlad Serebrennikov   FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing);
1353*b9d678d2SJoseph Huber   if (!ToQuals.compatiblyIncludes(FromQuals, getASTContext()))
135431a203faSVlad Serebrennikov     return false;
135531a203faSVlad Serebrennikov 
135631a203faSVlad Serebrennikov   // Remove qualifiers from the pointee type we're converting from; they
135731a203faSVlad Serebrennikov   // aren't used in the compatibility check belong, and we'll be adding back
135831a203faSVlad Serebrennikov   // qualifiers (with __autoreleasing) if the compatibility check succeeds.
135931a203faSVlad Serebrennikov   FromPointee = FromPointee.getUnqualifiedType();
136031a203faSVlad Serebrennikov 
136131a203faSVlad Serebrennikov   // The unqualified form of the pointee types must be compatible.
136231a203faSVlad Serebrennikov   ToPointee = ToPointee.getUnqualifiedType();
136331a203faSVlad Serebrennikov   bool IncompatibleObjC;
136431a203faSVlad Serebrennikov   if (Context.typesAreCompatible(FromPointee, ToPointee))
136531a203faSVlad Serebrennikov     FromPointee = ToPointee;
136631a203faSVlad Serebrennikov   else if (!SemaRef.isObjCPointerConversion(FromPointee, ToPointee, FromPointee,
136731a203faSVlad Serebrennikov                                             IncompatibleObjC))
136831a203faSVlad Serebrennikov     return false;
136931a203faSVlad Serebrennikov 
137031a203faSVlad Serebrennikov   /// Construct the type we're converting to, which is a pointer to
137131a203faSVlad Serebrennikov   /// __autoreleasing pointee.
137231a203faSVlad Serebrennikov   FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
137331a203faSVlad Serebrennikov   ConvertedType = Context.getPointerType(FromPointee);
137431a203faSVlad Serebrennikov   return true;
137531a203faSVlad Serebrennikov }
137631a203faSVlad Serebrennikov 
137731a203faSVlad Serebrennikov /// CheckSubscriptingKind - This routine decide what type
137831a203faSVlad Serebrennikov /// of indexing represented by "FromE" is being done.
137931a203faSVlad Serebrennikov SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) {
138031a203faSVlad Serebrennikov   // If the expression already has integral or enumeration type, we're golden.
138131a203faSVlad Serebrennikov   QualType T = FromE->getType();
138231a203faSVlad Serebrennikov   if (T->isIntegralOrEnumerationType())
138331a203faSVlad Serebrennikov     return SemaObjC::OS_Array;
138431a203faSVlad Serebrennikov 
138531a203faSVlad Serebrennikov   // If we don't have a class type in C++, there's no way we can get an
138631a203faSVlad Serebrennikov   // expression of integral or enumeration type.
138731a203faSVlad Serebrennikov   const RecordType *RecordTy = T->getAs<RecordType>();
138831a203faSVlad Serebrennikov   if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType()))
138931a203faSVlad Serebrennikov     // All other scalar cases are assumed to be dictionary indexing which
139031a203faSVlad Serebrennikov     // caller handles, with diagnostics if needed.
139131a203faSVlad Serebrennikov     return SemaObjC::OS_Dictionary;
139231a203faSVlad Serebrennikov   if (!getLangOpts().CPlusPlus || !RecordTy || RecordTy->isIncompleteType()) {
139331a203faSVlad Serebrennikov     // No indexing can be done. Issue diagnostics and quit.
139431a203faSVlad Serebrennikov     const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
139531a203faSVlad Serebrennikov     if (isa<StringLiteral>(IndexExpr))
139631a203faSVlad Serebrennikov       Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
139731a203faSVlad Serebrennikov           << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
139831a203faSVlad Serebrennikov     else
139931a203faSVlad Serebrennikov       Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) << T;
140031a203faSVlad Serebrennikov     return SemaObjC::OS_Error;
140131a203faSVlad Serebrennikov   }
140231a203faSVlad Serebrennikov 
140331a203faSVlad Serebrennikov   // We must have a complete class type.
140431a203faSVlad Serebrennikov   if (SemaRef.RequireCompleteType(FromE->getExprLoc(), T,
140531a203faSVlad Serebrennikov                                   diag::err_objc_index_incomplete_class_type,
140631a203faSVlad Serebrennikov                                   FromE))
140731a203faSVlad Serebrennikov     return SemaObjC::OS_Error;
140831a203faSVlad Serebrennikov 
140931a203faSVlad Serebrennikov   // Look for a conversion to an integral, enumeration type, or
141031a203faSVlad Serebrennikov   // objective-C pointer type.
141131a203faSVlad Serebrennikov   int NoIntegrals = 0, NoObjCIdPointers = 0;
141231a203faSVlad Serebrennikov   SmallVector<CXXConversionDecl *, 4> ConversionDecls;
141331a203faSVlad Serebrennikov 
141431a203faSVlad Serebrennikov   for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
141531a203faSVlad Serebrennikov                           ->getVisibleConversionFunctions()) {
141631a203faSVlad Serebrennikov     if (CXXConversionDecl *Conversion =
141731a203faSVlad Serebrennikov             dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
141831a203faSVlad Serebrennikov       QualType CT = Conversion->getConversionType().getNonReferenceType();
141931a203faSVlad Serebrennikov       if (CT->isIntegralOrEnumerationType()) {
142031a203faSVlad Serebrennikov         ++NoIntegrals;
142131a203faSVlad Serebrennikov         ConversionDecls.push_back(Conversion);
142231a203faSVlad Serebrennikov       } else if (CT->isObjCIdType() || CT->isBlockPointerType()) {
142331a203faSVlad Serebrennikov         ++NoObjCIdPointers;
142431a203faSVlad Serebrennikov         ConversionDecls.push_back(Conversion);
142531a203faSVlad Serebrennikov       }
142631a203faSVlad Serebrennikov     }
142731a203faSVlad Serebrennikov   }
142831a203faSVlad Serebrennikov   if (NoIntegrals == 1 && NoObjCIdPointers == 0)
142931a203faSVlad Serebrennikov     return SemaObjC::OS_Array;
143031a203faSVlad Serebrennikov   if (NoIntegrals == 0 && NoObjCIdPointers == 1)
143131a203faSVlad Serebrennikov     return SemaObjC::OS_Dictionary;
143231a203faSVlad Serebrennikov   if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
143331a203faSVlad Serebrennikov     // No conversion function was found. Issue diagnostic and return.
143431a203faSVlad Serebrennikov     Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
143531a203faSVlad Serebrennikov         << FromE->getType();
143631a203faSVlad Serebrennikov     return SemaObjC::OS_Error;
143731a203faSVlad Serebrennikov   }
143831a203faSVlad Serebrennikov   Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
143931a203faSVlad Serebrennikov       << FromE->getType();
144031a203faSVlad Serebrennikov   for (unsigned int i = 0; i < ConversionDecls.size(); i++)
144131a203faSVlad Serebrennikov     Diag(ConversionDecls[i]->getLocation(),
144231a203faSVlad Serebrennikov          diag::note_conv_function_declared_at);
144331a203faSVlad Serebrennikov 
144431a203faSVlad Serebrennikov   return SemaObjC::OS_Error;
144531a203faSVlad Serebrennikov }
144631a203faSVlad Serebrennikov 
144731a203faSVlad Serebrennikov void SemaObjC::AddCFAuditedAttribute(Decl *D) {
144831a203faSVlad Serebrennikov   ASTContext &Context = getASTContext();
144931a203faSVlad Serebrennikov   IdentifierInfo *Ident;
145031a203faSVlad Serebrennikov   SourceLocation Loc;
145131a203faSVlad Serebrennikov   std::tie(Ident, Loc) = SemaRef.PP.getPragmaARCCFCodeAuditedInfo();
145231a203faSVlad Serebrennikov   if (!Loc.isValid())
145331a203faSVlad Serebrennikov     return;
145431a203faSVlad Serebrennikov 
145531a203faSVlad Serebrennikov   // Don't add a redundant or conflicting attribute.
145631a203faSVlad Serebrennikov   if (D->hasAttr<CFAuditedTransferAttr>() ||
145731a203faSVlad Serebrennikov       D->hasAttr<CFUnknownTransferAttr>())
145831a203faSVlad Serebrennikov     return;
145931a203faSVlad Serebrennikov 
146031a203faSVlad Serebrennikov   AttributeCommonInfo Info(Ident, SourceRange(Loc),
146131a203faSVlad Serebrennikov                            AttributeCommonInfo::Form::Pragma());
146231a203faSVlad Serebrennikov   D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info));
146331a203faSVlad Serebrennikov }
146431a203faSVlad Serebrennikov 
146531a203faSVlad Serebrennikov bool SemaObjC::isCFError(RecordDecl *RD) {
146631a203faSVlad Serebrennikov   // If we already know about CFError, test it directly.
146731a203faSVlad Serebrennikov   if (CFError)
146831a203faSVlad Serebrennikov     return CFError == RD;
146931a203faSVlad Serebrennikov 
147031a203faSVlad Serebrennikov   // Check whether this is CFError, which we identify based on its bridge to
147131a203faSVlad Serebrennikov   // NSError. CFErrorRef used to be declared with "objc_bridge" but is now
147231a203faSVlad Serebrennikov   // declared with "objc_bridge_mutable", so look for either one of the two
147331a203faSVlad Serebrennikov   // attributes.
147431a203faSVlad Serebrennikov   if (RD->getTagKind() == TagTypeKind::Struct) {
147531a203faSVlad Serebrennikov     IdentifierInfo *bridgedType = nullptr;
147631a203faSVlad Serebrennikov     if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>())
147731a203faSVlad Serebrennikov       bridgedType = bridgeAttr->getBridgedType();
147831a203faSVlad Serebrennikov     else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>())
147931a203faSVlad Serebrennikov       bridgedType = bridgeAttr->getBridgedType();
148031a203faSVlad Serebrennikov 
148131a203faSVlad Serebrennikov     if (bridgedType == getNSErrorIdent()) {
148231a203faSVlad Serebrennikov       CFError = RD;
148331a203faSVlad Serebrennikov       return true;
148431a203faSVlad Serebrennikov     }
148531a203faSVlad Serebrennikov   }
148631a203faSVlad Serebrennikov 
148731a203faSVlad Serebrennikov   return false;
148831a203faSVlad Serebrennikov }
148931a203faSVlad Serebrennikov 
14906b755b0cSVlad Serebrennikov bool SemaObjC::isNSStringType(QualType T, bool AllowNSAttributedString) {
14916b755b0cSVlad Serebrennikov   const auto *PT = T->getAs<ObjCObjectPointerType>();
14926b755b0cSVlad Serebrennikov   if (!PT)
14936b755b0cSVlad Serebrennikov     return false;
14946b755b0cSVlad Serebrennikov 
14956b755b0cSVlad Serebrennikov   ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
14966b755b0cSVlad Serebrennikov   if (!Cls)
14976b755b0cSVlad Serebrennikov     return false;
14986b755b0cSVlad Serebrennikov 
14996b755b0cSVlad Serebrennikov   IdentifierInfo *ClsName = Cls->getIdentifier();
15006b755b0cSVlad Serebrennikov 
15016b755b0cSVlad Serebrennikov   if (AllowNSAttributedString &&
15026b755b0cSVlad Serebrennikov       ClsName == &getASTContext().Idents.get("NSAttributedString"))
15036b755b0cSVlad Serebrennikov     return true;
15046b755b0cSVlad Serebrennikov   // FIXME: Should we walk the chain of classes?
15056b755b0cSVlad Serebrennikov   return ClsName == &getASTContext().Idents.get("NSString") ||
15066b755b0cSVlad Serebrennikov          ClsName == &getASTContext().Idents.get("NSMutableString");
15076b755b0cSVlad Serebrennikov }
15086b755b0cSVlad Serebrennikov 
15096b755b0cSVlad Serebrennikov bool SemaObjC::isCFStringType(QualType T) {
15106b755b0cSVlad Serebrennikov   const auto *PT = T->getAs<PointerType>();
15116b755b0cSVlad Serebrennikov   if (!PT)
15126b755b0cSVlad Serebrennikov     return false;
15136b755b0cSVlad Serebrennikov 
15146b755b0cSVlad Serebrennikov   const auto *RT = PT->getPointeeType()->getAs<RecordType>();
15156b755b0cSVlad Serebrennikov   if (!RT)
15166b755b0cSVlad Serebrennikov     return false;
15176b755b0cSVlad Serebrennikov 
15186b755b0cSVlad Serebrennikov   const RecordDecl *RD = RT->getDecl();
15196b755b0cSVlad Serebrennikov   if (RD->getTagKind() != TagTypeKind::Struct)
15206b755b0cSVlad Serebrennikov     return false;
15216b755b0cSVlad Serebrennikov 
15226b755b0cSVlad Serebrennikov   return RD->getIdentifier() == &getASTContext().Idents.get("__CFString");
15236b755b0cSVlad Serebrennikov }
15246b755b0cSVlad Serebrennikov 
15256b755b0cSVlad Serebrennikov static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
15266b755b0cSVlad Serebrennikov   // The IBOutlet/IBOutletCollection attributes only apply to instance
15276b755b0cSVlad Serebrennikov   // variables or properties of Objective-C classes.  The outlet must also
15286b755b0cSVlad Serebrennikov   // have an object reference type.
15296b755b0cSVlad Serebrennikov   if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
15306b755b0cSVlad Serebrennikov     if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
15316b755b0cSVlad Serebrennikov       S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
15326b755b0cSVlad Serebrennikov           << AL << VD->getType() << 0;
15336b755b0cSVlad Serebrennikov       return false;
15346b755b0cSVlad Serebrennikov     }
15356b755b0cSVlad Serebrennikov   } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
15366b755b0cSVlad Serebrennikov     if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
15376b755b0cSVlad Serebrennikov       S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
15386b755b0cSVlad Serebrennikov           << AL << PD->getType() << 1;
15396b755b0cSVlad Serebrennikov       return false;
15406b755b0cSVlad Serebrennikov     }
15416b755b0cSVlad Serebrennikov   } else {
15426b755b0cSVlad Serebrennikov     S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
15436b755b0cSVlad Serebrennikov     return false;
15446b755b0cSVlad Serebrennikov   }
15456b755b0cSVlad Serebrennikov 
15466b755b0cSVlad Serebrennikov   return true;
15476b755b0cSVlad Serebrennikov }
15486b755b0cSVlad Serebrennikov 
15496b755b0cSVlad Serebrennikov void SemaObjC::handleIBOutlet(Decl *D, const ParsedAttr &AL) {
15506b755b0cSVlad Serebrennikov   if (!checkIBOutletCommon(SemaRef, D, AL))
15516b755b0cSVlad Serebrennikov     return;
15526b755b0cSVlad Serebrennikov 
15536b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext()) IBOutletAttr(getASTContext(), AL));
15546b755b0cSVlad Serebrennikov }
15556b755b0cSVlad Serebrennikov 
15566b755b0cSVlad Serebrennikov void SemaObjC::handleIBOutletCollection(Decl *D, const ParsedAttr &AL) {
15576b755b0cSVlad Serebrennikov 
15586b755b0cSVlad Serebrennikov   ASTContext &Context = getASTContext();
15596b755b0cSVlad Serebrennikov   // The iboutletcollection attribute can have zero or one arguments.
15606b755b0cSVlad Serebrennikov   if (AL.getNumArgs() > 1) {
15616b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
15626b755b0cSVlad Serebrennikov     return;
15636b755b0cSVlad Serebrennikov   }
15646b755b0cSVlad Serebrennikov 
15656b755b0cSVlad Serebrennikov   if (!checkIBOutletCommon(SemaRef, D, AL))
15666b755b0cSVlad Serebrennikov     return;
15676b755b0cSVlad Serebrennikov 
15686b755b0cSVlad Serebrennikov   ParsedType PT;
15696b755b0cSVlad Serebrennikov 
15706b755b0cSVlad Serebrennikov   if (AL.hasParsedType())
15716b755b0cSVlad Serebrennikov     PT = AL.getTypeArg();
15726b755b0cSVlad Serebrennikov   else {
15736b755b0cSVlad Serebrennikov     PT = SemaRef.getTypeName(
15746b755b0cSVlad Serebrennikov         Context.Idents.get("NSObject"), AL.getLoc(),
15756b755b0cSVlad Serebrennikov         SemaRef.getScopeForContext(D->getDeclContext()->getParent()));
15766b755b0cSVlad Serebrennikov     if (!PT) {
15776b755b0cSVlad Serebrennikov       Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
15786b755b0cSVlad Serebrennikov       return;
15796b755b0cSVlad Serebrennikov     }
15806b755b0cSVlad Serebrennikov   }
15816b755b0cSVlad Serebrennikov 
15826b755b0cSVlad Serebrennikov   TypeSourceInfo *QTLoc = nullptr;
15836b755b0cSVlad Serebrennikov   QualType QT = SemaRef.GetTypeFromParser(PT, &QTLoc);
15846b755b0cSVlad Serebrennikov   if (!QTLoc)
15856b755b0cSVlad Serebrennikov     QTLoc = Context.getTrivialTypeSourceInfo(QT, AL.getLoc());
15866b755b0cSVlad Serebrennikov 
15876b755b0cSVlad Serebrennikov   // Diagnose use of non-object type in iboutletcollection attribute.
15886b755b0cSVlad Serebrennikov   // FIXME. Gnu attribute extension ignores use of builtin types in
15896b755b0cSVlad Serebrennikov   // attributes. So, __attribute__((iboutletcollection(char))) will be
15906b755b0cSVlad Serebrennikov   // treated as __attribute__((iboutletcollection())).
15916b755b0cSVlad Serebrennikov   if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
15926b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), QT->isBuiltinType()
15936b755b0cSVlad Serebrennikov                           ? diag::err_iboutletcollection_builtintype
15946b755b0cSVlad Serebrennikov                           : diag::err_iboutletcollection_type)
15956b755b0cSVlad Serebrennikov         << QT;
15966b755b0cSVlad Serebrennikov     return;
15976b755b0cSVlad Serebrennikov   }
15986b755b0cSVlad Serebrennikov 
15996b755b0cSVlad Serebrennikov   D->addAttr(::new (Context) IBOutletCollectionAttr(Context, AL, QTLoc));
16006b755b0cSVlad Serebrennikov }
16016b755b0cSVlad Serebrennikov 
16026b755b0cSVlad Serebrennikov void SemaObjC::handleSuppresProtocolAttr(Decl *D, const ParsedAttr &AL) {
16036b755b0cSVlad Serebrennikov   if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
16046b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
16056b755b0cSVlad Serebrennikov         << AL << AL.getRange();
16066b755b0cSVlad Serebrennikov     return;
16076b755b0cSVlad Serebrennikov   }
16086b755b0cSVlad Serebrennikov 
16096b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
16106b755b0cSVlad Serebrennikov                  ObjCExplicitProtocolImplAttr(getASTContext(), AL));
16116b755b0cSVlad Serebrennikov }
16126b755b0cSVlad Serebrennikov 
16136b755b0cSVlad Serebrennikov void SemaObjC::handleDirectAttr(Decl *D, const ParsedAttr &AL) {
16146b755b0cSVlad Serebrennikov   // objc_direct cannot be set on methods declared in the context of a protocol
16156b755b0cSVlad Serebrennikov   if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
16166b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false;
16176b755b0cSVlad Serebrennikov     return;
16186b755b0cSVlad Serebrennikov   }
16196b755b0cSVlad Serebrennikov 
16206b755b0cSVlad Serebrennikov   if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
16216b755b0cSVlad Serebrennikov     handleSimpleAttribute<ObjCDirectAttr>(*this, D, AL);
16226b755b0cSVlad Serebrennikov   } else {
16236b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
16246b755b0cSVlad Serebrennikov   }
16256b755b0cSVlad Serebrennikov }
16266b755b0cSVlad Serebrennikov 
16276b755b0cSVlad Serebrennikov void SemaObjC::handleDirectMembersAttr(Decl *D, const ParsedAttr &AL) {
16286b755b0cSVlad Serebrennikov   if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
16296b755b0cSVlad Serebrennikov     handleSimpleAttribute<ObjCDirectMembersAttr>(*this, D, AL);
16306b755b0cSVlad Serebrennikov   } else {
16316b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
16326b755b0cSVlad Serebrennikov   }
16336b755b0cSVlad Serebrennikov }
16346b755b0cSVlad Serebrennikov 
16356b755b0cSVlad Serebrennikov void SemaObjC::handleMethodFamilyAttr(Decl *D, const ParsedAttr &AL) {
16366b755b0cSVlad Serebrennikov   const auto *M = cast<ObjCMethodDecl>(D);
16376b755b0cSVlad Serebrennikov   if (!AL.isArgIdent(0)) {
16386b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
16396b755b0cSVlad Serebrennikov         << AL << 1 << AANT_ArgumentIdentifier;
16406b755b0cSVlad Serebrennikov     return;
16416b755b0cSVlad Serebrennikov   }
16426b755b0cSVlad Serebrennikov 
16436b755b0cSVlad Serebrennikov   IdentifierLoc *IL = AL.getArgAsIdent(0);
16446b755b0cSVlad Serebrennikov   ObjCMethodFamilyAttr::FamilyKind F;
16456b755b0cSVlad Serebrennikov   if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
16466b755b0cSVlad Serebrennikov     Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident;
16476b755b0cSVlad Serebrennikov     return;
16486b755b0cSVlad Serebrennikov   }
16496b755b0cSVlad Serebrennikov 
16506b755b0cSVlad Serebrennikov   if (F == ObjCMethodFamilyAttr::OMF_init &&
16516b755b0cSVlad Serebrennikov       !M->getReturnType()->isObjCObjectPointerType()) {
16526b755b0cSVlad Serebrennikov     Diag(M->getLocation(), diag::err_init_method_bad_return_type)
16536b755b0cSVlad Serebrennikov         << M->getReturnType();
16546b755b0cSVlad Serebrennikov     // Ignore the attribute.
16556b755b0cSVlad Serebrennikov     return;
16566b755b0cSVlad Serebrennikov   }
16576b755b0cSVlad Serebrennikov 
16586b755b0cSVlad Serebrennikov   D->addAttr(new (getASTContext())
16596b755b0cSVlad Serebrennikov                  ObjCMethodFamilyAttr(getASTContext(), AL, F));
16606b755b0cSVlad Serebrennikov }
16616b755b0cSVlad Serebrennikov 
16626b755b0cSVlad Serebrennikov void SemaObjC::handleNSObject(Decl *D, const ParsedAttr &AL) {
16636b755b0cSVlad Serebrennikov   if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
16646b755b0cSVlad Serebrennikov     QualType T = TD->getUnderlyingType();
16656b755b0cSVlad Serebrennikov     if (!T->isCARCBridgableType()) {
16666b755b0cSVlad Serebrennikov       Diag(TD->getLocation(), diag::err_nsobject_attribute);
16676b755b0cSVlad Serebrennikov       return;
16686b755b0cSVlad Serebrennikov     }
16696b755b0cSVlad Serebrennikov   } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
16706b755b0cSVlad Serebrennikov     QualType T = PD->getType();
16716b755b0cSVlad Serebrennikov     if (!T->isCARCBridgableType()) {
16726b755b0cSVlad Serebrennikov       Diag(PD->getLocation(), diag::err_nsobject_attribute);
16736b755b0cSVlad Serebrennikov       return;
16746b755b0cSVlad Serebrennikov     }
16756b755b0cSVlad Serebrennikov   } else {
16766b755b0cSVlad Serebrennikov     // It is okay to include this attribute on properties, e.g.:
16776b755b0cSVlad Serebrennikov     //
16786b755b0cSVlad Serebrennikov     //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
16796b755b0cSVlad Serebrennikov     //
16806b755b0cSVlad Serebrennikov     // In this case it follows tradition and suppresses an error in the above
16816b755b0cSVlad Serebrennikov     // case.
16826b755b0cSVlad Serebrennikov     Diag(D->getLocation(), diag::warn_nsobject_attribute);
16836b755b0cSVlad Serebrennikov   }
16846b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext()) ObjCNSObjectAttr(getASTContext(), AL));
16856b755b0cSVlad Serebrennikov }
16866b755b0cSVlad Serebrennikov 
16876b755b0cSVlad Serebrennikov void SemaObjC::handleIndependentClass(Decl *D, const ParsedAttr &AL) {
16886b755b0cSVlad Serebrennikov   if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
16896b755b0cSVlad Serebrennikov     QualType T = TD->getUnderlyingType();
16906b755b0cSVlad Serebrennikov     if (!T->isObjCObjectPointerType()) {
16916b755b0cSVlad Serebrennikov       Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
16926b755b0cSVlad Serebrennikov       return;
16936b755b0cSVlad Serebrennikov     }
16946b755b0cSVlad Serebrennikov   } else {
16956b755b0cSVlad Serebrennikov     Diag(D->getLocation(), diag::warn_independentclass_attribute);
16966b755b0cSVlad Serebrennikov     return;
16976b755b0cSVlad Serebrennikov   }
16986b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
16996b755b0cSVlad Serebrennikov                  ObjCIndependentClassAttr(getASTContext(), AL));
17006b755b0cSVlad Serebrennikov }
17016b755b0cSVlad Serebrennikov 
17026b755b0cSVlad Serebrennikov void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) {
17036b755b0cSVlad Serebrennikov   if (!AL.isArgIdent(0)) {
17046b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
17056b755b0cSVlad Serebrennikov         << AL << 1 << AANT_ArgumentIdentifier;
17066b755b0cSVlad Serebrennikov     return;
17076b755b0cSVlad Serebrennikov   }
17086b755b0cSVlad Serebrennikov 
17096b755b0cSVlad Serebrennikov   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
17106b755b0cSVlad Serebrennikov   BlocksAttr::BlockType type;
17116b755b0cSVlad Serebrennikov   if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
17126b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
17136b755b0cSVlad Serebrennikov     return;
17146b755b0cSVlad Serebrennikov   }
17156b755b0cSVlad Serebrennikov 
17166b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext()) BlocksAttr(getASTContext(), AL, type));
17176b755b0cSVlad Serebrennikov }
17186b755b0cSVlad Serebrennikov 
17196b755b0cSVlad Serebrennikov static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
17206b755b0cSVlad Serebrennikov   return QT->isDependentType() || QT->isObjCRetainableType();
17216b755b0cSVlad Serebrennikov }
17226b755b0cSVlad Serebrennikov 
17236b755b0cSVlad Serebrennikov static bool isValidSubjectOfNSAttribute(QualType QT) {
17246b755b0cSVlad Serebrennikov   return QT->isDependentType() || QT->isObjCObjectPointerType() ||
17256b755b0cSVlad Serebrennikov          QT->isObjCNSObjectType();
17266b755b0cSVlad Serebrennikov }
17276b755b0cSVlad Serebrennikov 
17286b755b0cSVlad Serebrennikov static bool isValidSubjectOfCFAttribute(QualType QT) {
17296b755b0cSVlad Serebrennikov   return QT->isDependentType() || QT->isPointerType() ||
17306b755b0cSVlad Serebrennikov          isValidSubjectOfNSAttribute(QT);
17316b755b0cSVlad Serebrennikov }
17326b755b0cSVlad Serebrennikov 
17336b755b0cSVlad Serebrennikov static bool isValidSubjectOfOSAttribute(QualType QT) {
17346b755b0cSVlad Serebrennikov   if (QT->isDependentType())
17356b755b0cSVlad Serebrennikov     return true;
17366b755b0cSVlad Serebrennikov   QualType PT = QT->getPointeeType();
17376b755b0cSVlad Serebrennikov   return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;
17386b755b0cSVlad Serebrennikov }
17396b755b0cSVlad Serebrennikov 
17406b755b0cSVlad Serebrennikov void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
17416b755b0cSVlad Serebrennikov                                 Sema::RetainOwnershipKind K,
17426b755b0cSVlad Serebrennikov                                 bool IsTemplateInstantiation) {
17436b755b0cSVlad Serebrennikov   ValueDecl *VD = cast<ValueDecl>(D);
17446b755b0cSVlad Serebrennikov   switch (K) {
17456b755b0cSVlad Serebrennikov   case Sema::RetainOwnershipKind::OS:
17466b755b0cSVlad Serebrennikov     handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
17476b755b0cSVlad Serebrennikov         *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()),
17486b755b0cSVlad Serebrennikov         diag::warn_ns_attribute_wrong_parameter_type,
17496b755b0cSVlad Serebrennikov         /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1);
17506b755b0cSVlad Serebrennikov     return;
17516b755b0cSVlad Serebrennikov   case Sema::RetainOwnershipKind::NS:
17526b755b0cSVlad Serebrennikov     handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
17536b755b0cSVlad Serebrennikov         *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()),
17546b755b0cSVlad Serebrennikov 
17556b755b0cSVlad Serebrennikov         // These attributes are normally just advisory, but in ARC, ns_consumed
17566b755b0cSVlad Serebrennikov         // is significant.  Allow non-dependent code to contain inappropriate
17576b755b0cSVlad Serebrennikov         // attributes even in ARC, but require template instantiations to be
17586b755b0cSVlad Serebrennikov         // set up correctly.
17596b755b0cSVlad Serebrennikov         ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)
17606b755b0cSVlad Serebrennikov              ? diag::err_ns_attribute_wrong_parameter_type
17616b755b0cSVlad Serebrennikov              : diag::warn_ns_attribute_wrong_parameter_type),
17626b755b0cSVlad Serebrennikov         /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0);
17636b755b0cSVlad Serebrennikov     return;
17646b755b0cSVlad Serebrennikov   case Sema::RetainOwnershipKind::CF:
17656b755b0cSVlad Serebrennikov     handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
17666b755b0cSVlad Serebrennikov         *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()),
17676b755b0cSVlad Serebrennikov         diag::warn_ns_attribute_wrong_parameter_type,
17686b755b0cSVlad Serebrennikov         /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1);
17696b755b0cSVlad Serebrennikov     return;
17706b755b0cSVlad Serebrennikov   }
17716b755b0cSVlad Serebrennikov }
17726b755b0cSVlad Serebrennikov 
17736b755b0cSVlad Serebrennikov Sema::RetainOwnershipKind
17746b755b0cSVlad Serebrennikov SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
17756b755b0cSVlad Serebrennikov   switch (AL.getKind()) {
17766b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFConsumed:
17776b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFReturnsRetained:
17786b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFReturnsNotRetained:
17796b755b0cSVlad Serebrennikov     return Sema::RetainOwnershipKind::CF;
17806b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSConsumesThis:
17816b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSConsumed:
17826b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsRetained:
17836b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsNotRetained:
17846b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsRetainedOnZero:
17856b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
17866b755b0cSVlad Serebrennikov     return Sema::RetainOwnershipKind::OS;
17876b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSConsumesSelf:
17886b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSConsumed:
17896b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsRetained:
17906b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsNotRetained:
17916b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsAutoreleased:
17926b755b0cSVlad Serebrennikov     return Sema::RetainOwnershipKind::NS;
17936b755b0cSVlad Serebrennikov   default:
17946b755b0cSVlad Serebrennikov     llvm_unreachable("Wrong argument supplied");
17956b755b0cSVlad Serebrennikov   }
17966b755b0cSVlad Serebrennikov }
17976b755b0cSVlad Serebrennikov 
17986b755b0cSVlad Serebrennikov bool SemaObjC::checkNSReturnsRetainedReturnType(SourceLocation Loc,
17996b755b0cSVlad Serebrennikov                                                 QualType QT) {
18006b755b0cSVlad Serebrennikov   if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
18016b755b0cSVlad Serebrennikov     return false;
18026b755b0cSVlad Serebrennikov 
18036b755b0cSVlad Serebrennikov   Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
18046b755b0cSVlad Serebrennikov       << "'ns_returns_retained'" << 0 << 0;
18056b755b0cSVlad Serebrennikov   return true;
18066b755b0cSVlad Serebrennikov }
18076b755b0cSVlad Serebrennikov 
18086b755b0cSVlad Serebrennikov /// \return whether the parameter is a pointer to OSObject pointer.
18096b755b0cSVlad Serebrennikov bool SemaObjC::isValidOSObjectOutParameter(const Decl *D) {
18106b755b0cSVlad Serebrennikov   const auto *PVD = dyn_cast<ParmVarDecl>(D);
18116b755b0cSVlad Serebrennikov   if (!PVD)
18126b755b0cSVlad Serebrennikov     return false;
18136b755b0cSVlad Serebrennikov   QualType QT = PVD->getType();
18146b755b0cSVlad Serebrennikov   QualType PT = QT->getPointeeType();
18156b755b0cSVlad Serebrennikov   return !PT.isNull() && isValidSubjectOfOSAttribute(PT);
18166b755b0cSVlad Serebrennikov }
18176b755b0cSVlad Serebrennikov 
18186b755b0cSVlad Serebrennikov void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) {
18196b755b0cSVlad Serebrennikov   QualType ReturnType;
18206b755b0cSVlad Serebrennikov   Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
18216b755b0cSVlad Serebrennikov 
18226b755b0cSVlad Serebrennikov   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
18236b755b0cSVlad Serebrennikov     ReturnType = MD->getReturnType();
18246b755b0cSVlad Serebrennikov   } else if (getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
18256b755b0cSVlad Serebrennikov              (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {
18266b755b0cSVlad Serebrennikov     return; // ignore: was handled as a type attribute
18276b755b0cSVlad Serebrennikov   } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
18286b755b0cSVlad Serebrennikov     ReturnType = PD->getType();
18296b755b0cSVlad Serebrennikov   } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
18306b755b0cSVlad Serebrennikov     ReturnType = FD->getReturnType();
18316b755b0cSVlad Serebrennikov   } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
18326b755b0cSVlad Serebrennikov     // Attributes on parameters are used for out-parameters,
18336b755b0cSVlad Serebrennikov     // passed as pointers-to-pointers.
18346b755b0cSVlad Serebrennikov     unsigned DiagID = K == Sema::RetainOwnershipKind::CF
18356b755b0cSVlad Serebrennikov                           ? /*pointer-to-CF-pointer*/ 2
18366b755b0cSVlad Serebrennikov                           : /*pointer-to-OSObject-pointer*/ 3;
18376b755b0cSVlad Serebrennikov     ReturnType = Param->getType()->getPointeeType();
18386b755b0cSVlad Serebrennikov     if (ReturnType.isNull()) {
18396b755b0cSVlad Serebrennikov       Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
18406b755b0cSVlad Serebrennikov           << AL << DiagID << AL.getRange();
18416b755b0cSVlad Serebrennikov       return;
18426b755b0cSVlad Serebrennikov     }
18436b755b0cSVlad Serebrennikov   } else if (AL.isUsedAsTypeAttr()) {
18446b755b0cSVlad Serebrennikov     return;
18456b755b0cSVlad Serebrennikov   } else {
18466b755b0cSVlad Serebrennikov     AttributeDeclKind ExpectedDeclKind;
18476b755b0cSVlad Serebrennikov     switch (AL.getKind()) {
18486b755b0cSVlad Serebrennikov     default:
18496b755b0cSVlad Serebrennikov       llvm_unreachable("invalid ownership attribute");
18506b755b0cSVlad Serebrennikov     case ParsedAttr::AT_NSReturnsRetained:
18516b755b0cSVlad Serebrennikov     case ParsedAttr::AT_NSReturnsAutoreleased:
18526b755b0cSVlad Serebrennikov     case ParsedAttr::AT_NSReturnsNotRetained:
18536b755b0cSVlad Serebrennikov       ExpectedDeclKind = ExpectedFunctionOrMethod;
18546b755b0cSVlad Serebrennikov       break;
18556b755b0cSVlad Serebrennikov 
18566b755b0cSVlad Serebrennikov     case ParsedAttr::AT_OSReturnsRetained:
18576b755b0cSVlad Serebrennikov     case ParsedAttr::AT_OSReturnsNotRetained:
18586b755b0cSVlad Serebrennikov     case ParsedAttr::AT_CFReturnsRetained:
18596b755b0cSVlad Serebrennikov     case ParsedAttr::AT_CFReturnsNotRetained:
18606b755b0cSVlad Serebrennikov       ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
18616b755b0cSVlad Serebrennikov       break;
18626b755b0cSVlad Serebrennikov     }
18636b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
18646b755b0cSVlad Serebrennikov         << AL.getRange() << AL << AL.isRegularKeywordAttribute()
18656b755b0cSVlad Serebrennikov         << ExpectedDeclKind;
18666b755b0cSVlad Serebrennikov     return;
18676b755b0cSVlad Serebrennikov   }
18686b755b0cSVlad Serebrennikov 
18696b755b0cSVlad Serebrennikov   bool TypeOK;
18706b755b0cSVlad Serebrennikov   bool Cf;
18716b755b0cSVlad Serebrennikov   unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
18726b755b0cSVlad Serebrennikov   switch (AL.getKind()) {
18736b755b0cSVlad Serebrennikov   default:
18746b755b0cSVlad Serebrennikov     llvm_unreachable("invalid ownership attribute");
18756b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsRetained:
18766b755b0cSVlad Serebrennikov     TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
18776b755b0cSVlad Serebrennikov     Cf = false;
18786b755b0cSVlad Serebrennikov     break;
18796b755b0cSVlad Serebrennikov 
18806b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsAutoreleased:
18816b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsNotRetained:
18826b755b0cSVlad Serebrennikov     TypeOK = isValidSubjectOfNSAttribute(ReturnType);
18836b755b0cSVlad Serebrennikov     Cf = false;
18846b755b0cSVlad Serebrennikov     break;
18856b755b0cSVlad Serebrennikov 
18866b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFReturnsRetained:
18876b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFReturnsNotRetained:
18886b755b0cSVlad Serebrennikov     TypeOK = isValidSubjectOfCFAttribute(ReturnType);
18896b755b0cSVlad Serebrennikov     Cf = true;
18906b755b0cSVlad Serebrennikov     break;
18916b755b0cSVlad Serebrennikov 
18926b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsRetained:
18936b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsNotRetained:
18946b755b0cSVlad Serebrennikov     TypeOK = isValidSubjectOfOSAttribute(ReturnType);
18956b755b0cSVlad Serebrennikov     Cf = true;
18966b755b0cSVlad Serebrennikov     ParmDiagID = 3; // Pointer-to-OSObject-pointer
18976b755b0cSVlad Serebrennikov     break;
18986b755b0cSVlad Serebrennikov   }
18996b755b0cSVlad Serebrennikov 
19006b755b0cSVlad Serebrennikov   if (!TypeOK) {
19016b755b0cSVlad Serebrennikov     if (AL.isUsedAsTypeAttr())
19026b755b0cSVlad Serebrennikov       return;
19036b755b0cSVlad Serebrennikov 
19046b755b0cSVlad Serebrennikov     if (isa<ParmVarDecl>(D)) {
19056b755b0cSVlad Serebrennikov       Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
19066b755b0cSVlad Serebrennikov           << AL << ParmDiagID << AL.getRange();
19076b755b0cSVlad Serebrennikov     } else {
19086b755b0cSVlad Serebrennikov       // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
19096b755b0cSVlad Serebrennikov       enum : unsigned { Function, Method, Property } SubjectKind = Function;
19106b755b0cSVlad Serebrennikov       if (isa<ObjCMethodDecl>(D))
19116b755b0cSVlad Serebrennikov         SubjectKind = Method;
19126b755b0cSVlad Serebrennikov       else if (isa<ObjCPropertyDecl>(D))
19136b755b0cSVlad Serebrennikov         SubjectKind = Property;
19146b755b0cSVlad Serebrennikov       Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
19156b755b0cSVlad Serebrennikov           << AL << SubjectKind << Cf << AL.getRange();
19166b755b0cSVlad Serebrennikov     }
19176b755b0cSVlad Serebrennikov     return;
19186b755b0cSVlad Serebrennikov   }
19196b755b0cSVlad Serebrennikov 
19206b755b0cSVlad Serebrennikov   switch (AL.getKind()) {
19216b755b0cSVlad Serebrennikov   default:
19226b755b0cSVlad Serebrennikov     llvm_unreachable("invalid ownership attribute");
19236b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsAutoreleased:
19246b755b0cSVlad Serebrennikov     handleSimpleAttribute<NSReturnsAutoreleasedAttr>(*this, D, AL);
19256b755b0cSVlad Serebrennikov     return;
19266b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFReturnsNotRetained:
19276b755b0cSVlad Serebrennikov     handleSimpleAttribute<CFReturnsNotRetainedAttr>(*this, D, AL);
19286b755b0cSVlad Serebrennikov     return;
19296b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsNotRetained:
19306b755b0cSVlad Serebrennikov     handleSimpleAttribute<NSReturnsNotRetainedAttr>(*this, D, AL);
19316b755b0cSVlad Serebrennikov     return;
19326b755b0cSVlad Serebrennikov   case ParsedAttr::AT_CFReturnsRetained:
19336b755b0cSVlad Serebrennikov     handleSimpleAttribute<CFReturnsRetainedAttr>(*this, D, AL);
19346b755b0cSVlad Serebrennikov     return;
19356b755b0cSVlad Serebrennikov   case ParsedAttr::AT_NSReturnsRetained:
19366b755b0cSVlad Serebrennikov     handleSimpleAttribute<NSReturnsRetainedAttr>(*this, D, AL);
19376b755b0cSVlad Serebrennikov     return;
19386b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsRetained:
19396b755b0cSVlad Serebrennikov     handleSimpleAttribute<OSReturnsRetainedAttr>(*this, D, AL);
19406b755b0cSVlad Serebrennikov     return;
19416b755b0cSVlad Serebrennikov   case ParsedAttr::AT_OSReturnsNotRetained:
19426b755b0cSVlad Serebrennikov     handleSimpleAttribute<OSReturnsNotRetainedAttr>(*this, D, AL);
19436b755b0cSVlad Serebrennikov     return;
19446b755b0cSVlad Serebrennikov   };
19456b755b0cSVlad Serebrennikov }
19466b755b0cSVlad Serebrennikov 
19476b755b0cSVlad Serebrennikov void SemaObjC::handleReturnsInnerPointerAttr(Decl *D, const ParsedAttr &Attrs) {
19486b755b0cSVlad Serebrennikov   const int EP_ObjCMethod = 1;
19496b755b0cSVlad Serebrennikov   const int EP_ObjCProperty = 2;
19506b755b0cSVlad Serebrennikov 
19516b755b0cSVlad Serebrennikov   SourceLocation loc = Attrs.getLoc();
19526b755b0cSVlad Serebrennikov   QualType resultType;
19536b755b0cSVlad Serebrennikov   if (isa<ObjCMethodDecl>(D))
19546b755b0cSVlad Serebrennikov     resultType = cast<ObjCMethodDecl>(D)->getReturnType();
19556b755b0cSVlad Serebrennikov   else
19566b755b0cSVlad Serebrennikov     resultType = cast<ObjCPropertyDecl>(D)->getType();
19576b755b0cSVlad Serebrennikov 
19586b755b0cSVlad Serebrennikov   if (!resultType->isReferenceType() &&
19596b755b0cSVlad Serebrennikov       (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
19606b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
19616b755b0cSVlad Serebrennikov         << SourceRange(loc) << Attrs
19626b755b0cSVlad Serebrennikov         << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
19636b755b0cSVlad Serebrennikov         << /*non-retainable pointer*/ 2;
19646b755b0cSVlad Serebrennikov 
19656b755b0cSVlad Serebrennikov     // Drop the attribute.
19666b755b0cSVlad Serebrennikov     return;
19676b755b0cSVlad Serebrennikov   }
19686b755b0cSVlad Serebrennikov 
19696b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
19706b755b0cSVlad Serebrennikov                  ObjCReturnsInnerPointerAttr(getASTContext(), Attrs));
19716b755b0cSVlad Serebrennikov }
19726b755b0cSVlad Serebrennikov 
19736b755b0cSVlad Serebrennikov void SemaObjC::handleRequiresSuperAttr(Decl *D, const ParsedAttr &Attrs) {
19746b755b0cSVlad Serebrennikov   const auto *Method = cast<ObjCMethodDecl>(D);
19756b755b0cSVlad Serebrennikov 
19766b755b0cSVlad Serebrennikov   const DeclContext *DC = Method->getDeclContext();
19776b755b0cSVlad Serebrennikov   if (const auto *PDecl = dyn_cast_if_present<ObjCProtocolDecl>(DC)) {
19786b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)
19796b755b0cSVlad Serebrennikov         << Attrs << 0;
19806b755b0cSVlad Serebrennikov     Diag(PDecl->getLocation(), diag::note_protocol_decl);
19816b755b0cSVlad Serebrennikov     return;
19826b755b0cSVlad Serebrennikov   }
19836b755b0cSVlad Serebrennikov   if (Method->getMethodFamily() == OMF_dealloc) {
19846b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)
19856b755b0cSVlad Serebrennikov         << Attrs << 1;
19866b755b0cSVlad Serebrennikov     return;
19876b755b0cSVlad Serebrennikov   }
19886b755b0cSVlad Serebrennikov 
19896b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
19906b755b0cSVlad Serebrennikov                  ObjCRequiresSuperAttr(getASTContext(), Attrs));
19916b755b0cSVlad Serebrennikov }
19926b755b0cSVlad Serebrennikov 
19936b755b0cSVlad Serebrennikov void SemaObjC::handleNSErrorDomain(Decl *D, const ParsedAttr &Attr) {
19946b755b0cSVlad Serebrennikov   if (!isa<TagDecl>(D)) {
19956b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
19966b755b0cSVlad Serebrennikov     return;
19976b755b0cSVlad Serebrennikov   }
19986b755b0cSVlad Serebrennikov 
19996b755b0cSVlad Serebrennikov   IdentifierLoc *IdentLoc =
20006b755b0cSVlad Serebrennikov       Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
20016b755b0cSVlad Serebrennikov   if (!IdentLoc || !IdentLoc->Ident) {
20026b755b0cSVlad Serebrennikov     // Try to locate the argument directly.
20036b755b0cSVlad Serebrennikov     SourceLocation Loc = Attr.getLoc();
20046b755b0cSVlad Serebrennikov     if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
20056b755b0cSVlad Serebrennikov       Loc = Attr.getArgAsExpr(0)->getBeginLoc();
20066b755b0cSVlad Serebrennikov 
20076b755b0cSVlad Serebrennikov     Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
20086b755b0cSVlad Serebrennikov     return;
20096b755b0cSVlad Serebrennikov   }
20106b755b0cSVlad Serebrennikov 
20116b755b0cSVlad Serebrennikov   // Verify that the identifier is a valid decl in the C decl namespace.
20126b755b0cSVlad Serebrennikov   LookupResult Result(SemaRef, DeclarationName(IdentLoc->Ident),
20136b755b0cSVlad Serebrennikov                       SourceLocation(),
20146b755b0cSVlad Serebrennikov                       Sema::LookupNameKind::LookupOrdinaryName);
20156b755b0cSVlad Serebrennikov   if (!SemaRef.LookupName(Result, SemaRef.TUScope) ||
20166b755b0cSVlad Serebrennikov       !Result.getAsSingle<VarDecl>()) {
20176b755b0cSVlad Serebrennikov     Diag(IdentLoc->Loc, diag::err_nserrordomain_invalid_decl)
20186b755b0cSVlad Serebrennikov         << 1 << IdentLoc->Ident;
20196b755b0cSVlad Serebrennikov     return;
20206b755b0cSVlad Serebrennikov   }
20216b755b0cSVlad Serebrennikov 
20226b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
20236b755b0cSVlad Serebrennikov                  NSErrorDomainAttr(getASTContext(), Attr, IdentLoc->Ident));
20246b755b0cSVlad Serebrennikov }
20256b755b0cSVlad Serebrennikov 
20266b755b0cSVlad Serebrennikov void SemaObjC::handleBridgeAttr(Decl *D, const ParsedAttr &AL) {
20276b755b0cSVlad Serebrennikov   IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
20286b755b0cSVlad Serebrennikov 
20296b755b0cSVlad Serebrennikov   if (!Parm) {
20306b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
20316b755b0cSVlad Serebrennikov     return;
20326b755b0cSVlad Serebrennikov   }
20336b755b0cSVlad Serebrennikov 
20346b755b0cSVlad Serebrennikov   // Typedefs only allow objc_bridge(id) and have some additional checking.
20356b755b0cSVlad Serebrennikov   if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
20366b755b0cSVlad Serebrennikov     if (!Parm->Ident->isStr("id")) {
20376b755b0cSVlad Serebrennikov       Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;
20386b755b0cSVlad Serebrennikov       return;
20396b755b0cSVlad Serebrennikov     }
20406b755b0cSVlad Serebrennikov 
20416b755b0cSVlad Serebrennikov     // Only allow 'cv void *'.
20426b755b0cSVlad Serebrennikov     QualType T = TD->getUnderlyingType();
20436b755b0cSVlad Serebrennikov     if (!T->isVoidPointerType()) {
20446b755b0cSVlad Serebrennikov       Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
20456b755b0cSVlad Serebrennikov       return;
20466b755b0cSVlad Serebrennikov     }
20476b755b0cSVlad Serebrennikov   }
20486b755b0cSVlad Serebrennikov 
20496b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
20506b755b0cSVlad Serebrennikov                  ObjCBridgeAttr(getASTContext(), AL, Parm->Ident));
20516b755b0cSVlad Serebrennikov }
20526b755b0cSVlad Serebrennikov 
20536b755b0cSVlad Serebrennikov void SemaObjC::handleBridgeMutableAttr(Decl *D, const ParsedAttr &AL) {
20546b755b0cSVlad Serebrennikov   IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
20556b755b0cSVlad Serebrennikov 
20566b755b0cSVlad Serebrennikov   if (!Parm) {
20576b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
20586b755b0cSVlad Serebrennikov     return;
20596b755b0cSVlad Serebrennikov   }
20606b755b0cSVlad Serebrennikov 
20616b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
20626b755b0cSVlad Serebrennikov                  ObjCBridgeMutableAttr(getASTContext(), AL, Parm->Ident));
20636b755b0cSVlad Serebrennikov }
20646b755b0cSVlad Serebrennikov 
20656b755b0cSVlad Serebrennikov void SemaObjC::handleBridgeRelatedAttr(Decl *D, const ParsedAttr &AL) {
20666b755b0cSVlad Serebrennikov   IdentifierInfo *RelatedClass =
20676b755b0cSVlad Serebrennikov       AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
20686b755b0cSVlad Serebrennikov   if (!RelatedClass) {
20696b755b0cSVlad Serebrennikov     Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
20706b755b0cSVlad Serebrennikov     return;
20716b755b0cSVlad Serebrennikov   }
20726b755b0cSVlad Serebrennikov   IdentifierInfo *ClassMethod =
20736b755b0cSVlad Serebrennikov       AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
20746b755b0cSVlad Serebrennikov   IdentifierInfo *InstanceMethod =
20756b755b0cSVlad Serebrennikov       AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
20766b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext()) ObjCBridgeRelatedAttr(
20776b755b0cSVlad Serebrennikov       getASTContext(), AL, RelatedClass, ClassMethod, InstanceMethod));
20786b755b0cSVlad Serebrennikov }
20796b755b0cSVlad Serebrennikov 
20806b755b0cSVlad Serebrennikov void SemaObjC::handleDesignatedInitializer(Decl *D, const ParsedAttr &AL) {
20816b755b0cSVlad Serebrennikov   DeclContext *Ctx = D->getDeclContext();
20826b755b0cSVlad Serebrennikov 
20836b755b0cSVlad Serebrennikov   // This attribute can only be applied to methods in interfaces or class
20846b755b0cSVlad Serebrennikov   // extensions.
20856b755b0cSVlad Serebrennikov   if (!isa<ObjCInterfaceDecl>(Ctx) &&
20866b755b0cSVlad Serebrennikov       !(isa<ObjCCategoryDecl>(Ctx) &&
20876b755b0cSVlad Serebrennikov         cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
20886b755b0cSVlad Serebrennikov     Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
20896b755b0cSVlad Serebrennikov     return;
20906b755b0cSVlad Serebrennikov   }
20916b755b0cSVlad Serebrennikov 
20926b755b0cSVlad Serebrennikov   ObjCInterfaceDecl *IFace;
20936b755b0cSVlad Serebrennikov   if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
20946b755b0cSVlad Serebrennikov     IFace = CatDecl->getClassInterface();
20956b755b0cSVlad Serebrennikov   else
20966b755b0cSVlad Serebrennikov     IFace = cast<ObjCInterfaceDecl>(Ctx);
20976b755b0cSVlad Serebrennikov 
20986b755b0cSVlad Serebrennikov   if (!IFace)
20996b755b0cSVlad Serebrennikov     return;
21006b755b0cSVlad Serebrennikov 
21016b755b0cSVlad Serebrennikov   IFace->setHasDesignatedInitializers();
21026b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
21036b755b0cSVlad Serebrennikov                  ObjCDesignatedInitializerAttr(getASTContext(), AL));
21046b755b0cSVlad Serebrennikov }
21056b755b0cSVlad Serebrennikov 
21066b755b0cSVlad Serebrennikov void SemaObjC::handleRuntimeName(Decl *D, const ParsedAttr &AL) {
21076b755b0cSVlad Serebrennikov   StringRef MetaDataName;
21086b755b0cSVlad Serebrennikov   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
21096b755b0cSVlad Serebrennikov     return;
21106b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
21116b755b0cSVlad Serebrennikov                  ObjCRuntimeNameAttr(getASTContext(), AL, MetaDataName));
21126b755b0cSVlad Serebrennikov }
21136b755b0cSVlad Serebrennikov 
21146b755b0cSVlad Serebrennikov // When a user wants to use objc_boxable with a union or struct
21156b755b0cSVlad Serebrennikov // but they don't have access to the declaration (legacy/third-party code)
21166b755b0cSVlad Serebrennikov // then they can 'enable' this feature with a typedef:
21176b755b0cSVlad Serebrennikov // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
21186b755b0cSVlad Serebrennikov void SemaObjC::handleBoxable(Decl *D, const ParsedAttr &AL) {
21196b755b0cSVlad Serebrennikov   bool notify = false;
21206b755b0cSVlad Serebrennikov 
21216b755b0cSVlad Serebrennikov   auto *RD = dyn_cast<RecordDecl>(D);
21226b755b0cSVlad Serebrennikov   if (RD && RD->getDefinition()) {
21236b755b0cSVlad Serebrennikov     RD = RD->getDefinition();
21246b755b0cSVlad Serebrennikov     notify = true;
21256b755b0cSVlad Serebrennikov   }
21266b755b0cSVlad Serebrennikov 
21276b755b0cSVlad Serebrennikov   if (RD) {
21286b755b0cSVlad Serebrennikov     ObjCBoxableAttr *BoxableAttr =
21296b755b0cSVlad Serebrennikov         ::new (getASTContext()) ObjCBoxableAttr(getASTContext(), AL);
21306b755b0cSVlad Serebrennikov     RD->addAttr(BoxableAttr);
21316b755b0cSVlad Serebrennikov     if (notify) {
21326b755b0cSVlad Serebrennikov       // we need to notify ASTReader/ASTWriter about
21336b755b0cSVlad Serebrennikov       // modification of existing declaration
21346b755b0cSVlad Serebrennikov       if (ASTMutationListener *L = SemaRef.getASTMutationListener())
21356b755b0cSVlad Serebrennikov         L->AddedAttributeToRecord(BoxableAttr, RD);
21366b755b0cSVlad Serebrennikov     }
21376b755b0cSVlad Serebrennikov   }
21386b755b0cSVlad Serebrennikov }
21396b755b0cSVlad Serebrennikov 
21406b755b0cSVlad Serebrennikov void SemaObjC::handleOwnershipAttr(Decl *D, const ParsedAttr &AL) {
21416b755b0cSVlad Serebrennikov   if (hasDeclarator(D))
21426b755b0cSVlad Serebrennikov     return;
21436b755b0cSVlad Serebrennikov 
21446b755b0cSVlad Serebrennikov   Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
21456b755b0cSVlad Serebrennikov       << AL.getRange() << AL << AL.isRegularKeywordAttribute()
21466b755b0cSVlad Serebrennikov       << ExpectedVariable;
21476b755b0cSVlad Serebrennikov }
21486b755b0cSVlad Serebrennikov 
21496b755b0cSVlad Serebrennikov void SemaObjC::handlePreciseLifetimeAttr(Decl *D, const ParsedAttr &AL) {
21506b755b0cSVlad Serebrennikov   const auto *VD = cast<ValueDecl>(D);
21516b755b0cSVlad Serebrennikov   QualType QT = VD->getType();
21526b755b0cSVlad Serebrennikov 
21536b755b0cSVlad Serebrennikov   if (!QT->isDependentType() && !QT->isObjCLifetimeType()) {
21546b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) << QT;
21556b755b0cSVlad Serebrennikov     return;
21566b755b0cSVlad Serebrennikov   }
21576b755b0cSVlad Serebrennikov 
21586b755b0cSVlad Serebrennikov   Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();
21596b755b0cSVlad Serebrennikov 
21606b755b0cSVlad Serebrennikov   // If we have no lifetime yet, check the lifetime we're presumably
21616b755b0cSVlad Serebrennikov   // going to infer.
21626b755b0cSVlad Serebrennikov   if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
21636b755b0cSVlad Serebrennikov     Lifetime = QT->getObjCARCImplicitLifetime();
21646b755b0cSVlad Serebrennikov 
21656b755b0cSVlad Serebrennikov   switch (Lifetime) {
21666b755b0cSVlad Serebrennikov   case Qualifiers::OCL_None:
21676b755b0cSVlad Serebrennikov     assert(QT->isDependentType() &&
21686b755b0cSVlad Serebrennikov            "didn't infer lifetime for non-dependent type?");
21696b755b0cSVlad Serebrennikov     break;
21706b755b0cSVlad Serebrennikov 
21716b755b0cSVlad Serebrennikov   case Qualifiers::OCL_Weak:   // meaningful
21726b755b0cSVlad Serebrennikov   case Qualifiers::OCL_Strong: // meaningful
21736b755b0cSVlad Serebrennikov     break;
21746b755b0cSVlad Serebrennikov 
21756b755b0cSVlad Serebrennikov   case Qualifiers::OCL_ExplicitNone:
21766b755b0cSVlad Serebrennikov   case Qualifiers::OCL_Autoreleasing:
21776b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
21786b755b0cSVlad Serebrennikov         << (Lifetime == Qualifiers::OCL_Autoreleasing);
21796b755b0cSVlad Serebrennikov     break;
21806b755b0cSVlad Serebrennikov   }
21816b755b0cSVlad Serebrennikov 
21826b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
21836b755b0cSVlad Serebrennikov                  ObjCPreciseLifetimeAttr(getASTContext(), AL));
21846b755b0cSVlad Serebrennikov }
21856b755b0cSVlad Serebrennikov 
21866b755b0cSVlad Serebrennikov static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
21876b755b0cSVlad Serebrennikov                                         bool DiagnoseFailure) {
21886b755b0cSVlad Serebrennikov   QualType Ty = VD->getType();
21896b755b0cSVlad Serebrennikov   if (!Ty->isObjCRetainableType()) {
21906b755b0cSVlad Serebrennikov     if (DiagnoseFailure) {
21916b755b0cSVlad Serebrennikov       S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
21926b755b0cSVlad Serebrennikov           << 0;
21936b755b0cSVlad Serebrennikov     }
21946b755b0cSVlad Serebrennikov     return false;
21956b755b0cSVlad Serebrennikov   }
21966b755b0cSVlad Serebrennikov 
21976b755b0cSVlad Serebrennikov   Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();
21986b755b0cSVlad Serebrennikov 
21996b755b0cSVlad Serebrennikov   // SemaObjC::inferObjCARCLifetime must run after processing decl attributes
22006b755b0cSVlad Serebrennikov   // (because __block lowers to an attribute), so if the lifetime hasn't been
22016b755b0cSVlad Serebrennikov   // explicitly specified, infer it locally now.
22026b755b0cSVlad Serebrennikov   if (LifetimeQual == Qualifiers::OCL_None)
22036b755b0cSVlad Serebrennikov     LifetimeQual = Ty->getObjCARCImplicitLifetime();
22046b755b0cSVlad Serebrennikov 
22056b755b0cSVlad Serebrennikov   // The attributes only really makes sense for __strong variables; ignore any
22066b755b0cSVlad Serebrennikov   // attempts to annotate a parameter with any other lifetime qualifier.
22076b755b0cSVlad Serebrennikov   if (LifetimeQual != Qualifiers::OCL_Strong) {
22086b755b0cSVlad Serebrennikov     if (DiagnoseFailure) {
22096b755b0cSVlad Serebrennikov       S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
22106b755b0cSVlad Serebrennikov           << 1;
22116b755b0cSVlad Serebrennikov     }
22126b755b0cSVlad Serebrennikov     return false;
22136b755b0cSVlad Serebrennikov   }
22146b755b0cSVlad Serebrennikov 
22156b755b0cSVlad Serebrennikov   // Tampering with the type of a VarDecl here is a bit of a hack, but we need
22166b755b0cSVlad Serebrennikov   // to ensure that the variable is 'const' so that we can error on
22176b755b0cSVlad Serebrennikov   // modification, which can otherwise over-release.
22186b755b0cSVlad Serebrennikov   VD->setType(Ty.withConst());
22196b755b0cSVlad Serebrennikov   VD->setARCPseudoStrong(true);
22206b755b0cSVlad Serebrennikov   return true;
22216b755b0cSVlad Serebrennikov }
22226b755b0cSVlad Serebrennikov 
22236b755b0cSVlad Serebrennikov void SemaObjC::handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL) {
22246b755b0cSVlad Serebrennikov   if (auto *VD = dyn_cast<VarDecl>(D)) {
22256b755b0cSVlad Serebrennikov     assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");
22266b755b0cSVlad Serebrennikov     if (!VD->hasLocalStorage()) {
22276b755b0cSVlad Serebrennikov       Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) << 0;
22286b755b0cSVlad Serebrennikov       return;
22296b755b0cSVlad Serebrennikov     }
22306b755b0cSVlad Serebrennikov 
22316b755b0cSVlad Serebrennikov     if (!tryMakeVariablePseudoStrong(SemaRef, VD, /*DiagnoseFailure=*/true))
22326b755b0cSVlad Serebrennikov       return;
22336b755b0cSVlad Serebrennikov 
22346b755b0cSVlad Serebrennikov     handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL);
22356b755b0cSVlad Serebrennikov     return;
22366b755b0cSVlad Serebrennikov   }
22376b755b0cSVlad Serebrennikov 
22386b755b0cSVlad Serebrennikov   // If D is a function-like declaration (method, block, or function), then we
22396b755b0cSVlad Serebrennikov   // make every parameter psuedo-strong.
22406b755b0cSVlad Serebrennikov   unsigned NumParams =
22416b755b0cSVlad Serebrennikov       hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0;
22426b755b0cSVlad Serebrennikov   for (unsigned I = 0; I != NumParams; ++I) {
22436b755b0cSVlad Serebrennikov     auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));
22446b755b0cSVlad Serebrennikov     QualType Ty = PVD->getType();
22456b755b0cSVlad Serebrennikov 
22466b755b0cSVlad Serebrennikov     // If a user wrote a parameter with __strong explicitly, then assume they
22476b755b0cSVlad Serebrennikov     // want "real" strong semantics for that parameter. This works because if
22486b755b0cSVlad Serebrennikov     // the parameter was written with __strong, then the strong qualifier will
22496b755b0cSVlad Serebrennikov     // be non-local.
22506b755b0cSVlad Serebrennikov     if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
22516b755b0cSVlad Serebrennikov         Qualifiers::OCL_Strong)
22526b755b0cSVlad Serebrennikov       continue;
22536b755b0cSVlad Serebrennikov 
22546b755b0cSVlad Serebrennikov     tryMakeVariablePseudoStrong(SemaRef, PVD, /*DiagnoseFailure=*/false);
22556b755b0cSVlad Serebrennikov   }
22566b755b0cSVlad Serebrennikov   handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL);
22576b755b0cSVlad Serebrennikov }
22586b755b0cSVlad Serebrennikov 
2259f1c54d72SVlad Serebrennikov bool SemaObjC::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
2260f1c54d72SVlad Serebrennikov   Sema::FormatStringInfo FSI;
2261f1c54d72SVlad Serebrennikov   if ((SemaRef.GetFormatStringType(Format) == Sema::FST_NSString) &&
2262f1c54d72SVlad Serebrennikov       SemaRef.getFormatStringInfo(Format, false, true, &FSI)) {
2263f1c54d72SVlad Serebrennikov     Idx = FSI.FormatIdx;
2264f1c54d72SVlad Serebrennikov     return true;
2265f1c54d72SVlad Serebrennikov   }
2266f1c54d72SVlad Serebrennikov   return false;
2267f1c54d72SVlad Serebrennikov }
2268f1c54d72SVlad Serebrennikov 
2269f1c54d72SVlad Serebrennikov /// Diagnose use of %s directive in an NSString which is being passed
2270f1c54d72SVlad Serebrennikov /// as formatting string to formatting method.
2271f1c54d72SVlad Serebrennikov void SemaObjC::DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl,
2272f1c54d72SVlad Serebrennikov                                                      Expr **Args,
2273f1c54d72SVlad Serebrennikov                                                      unsigned NumArgs) {
2274f1c54d72SVlad Serebrennikov   unsigned Idx = 0;
2275f1c54d72SVlad Serebrennikov   bool Format = false;
2276f1c54d72SVlad Serebrennikov   ObjCStringFormatFamily SFFamily = FDecl->getObjCFStringFormattingFamily();
2277f1c54d72SVlad Serebrennikov   if (SFFamily == ObjCStringFormatFamily::SFF_CFString) {
2278f1c54d72SVlad Serebrennikov     Idx = 2;
2279f1c54d72SVlad Serebrennikov     Format = true;
2280f1c54d72SVlad Serebrennikov   } else
2281f1c54d72SVlad Serebrennikov     for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {
2282f1c54d72SVlad Serebrennikov       if (GetFormatNSStringIdx(I, Idx)) {
2283f1c54d72SVlad Serebrennikov         Format = true;
2284f1c54d72SVlad Serebrennikov         break;
2285f1c54d72SVlad Serebrennikov       }
2286f1c54d72SVlad Serebrennikov     }
2287f1c54d72SVlad Serebrennikov   if (!Format || NumArgs <= Idx)
2288f1c54d72SVlad Serebrennikov     return;
2289f1c54d72SVlad Serebrennikov   const Expr *FormatExpr = Args[Idx];
2290f1c54d72SVlad Serebrennikov   if (const CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(FormatExpr))
2291f1c54d72SVlad Serebrennikov     FormatExpr = CSCE->getSubExpr();
2292f1c54d72SVlad Serebrennikov   const StringLiteral *FormatString;
2293f1c54d72SVlad Serebrennikov   if (const ObjCStringLiteral *OSL =
2294f1c54d72SVlad Serebrennikov           dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts()))
2295f1c54d72SVlad Serebrennikov     FormatString = OSL->getString();
2296f1c54d72SVlad Serebrennikov   else
2297f1c54d72SVlad Serebrennikov     FormatString = dyn_cast<StringLiteral>(FormatExpr->IgnoreParenImpCasts());
2298f1c54d72SVlad Serebrennikov   if (!FormatString)
2299f1c54d72SVlad Serebrennikov     return;
2300f1c54d72SVlad Serebrennikov   if (SemaRef.FormatStringHasSArg(FormatString)) {
2301f1c54d72SVlad Serebrennikov     Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)
2302f1c54d72SVlad Serebrennikov         << "%s" << 1 << 1;
2303f1c54d72SVlad Serebrennikov     Diag(FDecl->getLocation(), diag::note_entity_declared_at)
2304f1c54d72SVlad Serebrennikov         << FDecl->getDeclName();
2305f1c54d72SVlad Serebrennikov   }
2306f1c54d72SVlad Serebrennikov }
2307f1c54d72SVlad Serebrennikov 
2308f1c54d72SVlad Serebrennikov bool SemaObjC::isSignedCharBool(QualType Ty) {
2309f1c54d72SVlad Serebrennikov   return Ty->isSpecificBuiltinType(BuiltinType::SChar) && getLangOpts().ObjC &&
2310f1c54d72SVlad Serebrennikov          NSAPIObj->isObjCBOOLType(Ty);
2311f1c54d72SVlad Serebrennikov }
2312f1c54d72SVlad Serebrennikov 
2313f1c54d72SVlad Serebrennikov void SemaObjC::adornBoolConversionDiagWithTernaryFixit(
2314f1c54d72SVlad Serebrennikov     Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder) {
2315f1c54d72SVlad Serebrennikov   Expr *Ignored = SourceExpr->IgnoreImplicit();
2316f1c54d72SVlad Serebrennikov   if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ignored))
2317f1c54d72SVlad Serebrennikov     Ignored = OVE->getSourceExpr();
2318f1c54d72SVlad Serebrennikov   bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) ||
2319f1c54d72SVlad Serebrennikov                      isa<BinaryOperator>(Ignored) ||
2320f1c54d72SVlad Serebrennikov                      isa<CXXOperatorCallExpr>(Ignored);
2321f1c54d72SVlad Serebrennikov   SourceLocation EndLoc = SemaRef.getLocForEndOfToken(SourceExpr->getEndLoc());
2322f1c54d72SVlad Serebrennikov   if (NeedsParens)
2323f1c54d72SVlad Serebrennikov     Builder << FixItHint::CreateInsertion(SourceExpr->getBeginLoc(), "(")
2324f1c54d72SVlad Serebrennikov             << FixItHint::CreateInsertion(EndLoc, ")");
2325f1c54d72SVlad Serebrennikov   Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO");
2326f1c54d72SVlad Serebrennikov }
2327f1c54d72SVlad Serebrennikov 
2328f1c54d72SVlad Serebrennikov /// Check a single element within a collection literal against the
2329f1c54d72SVlad Serebrennikov /// target element type.
2330f1c54d72SVlad Serebrennikov static void checkCollectionLiteralElement(Sema &S, QualType TargetElementType,
2331f1c54d72SVlad Serebrennikov                                           Expr *Element, unsigned ElementKind) {
2332f1c54d72SVlad Serebrennikov   // Skip a bitcast to 'id' or qualified 'id'.
2333f1c54d72SVlad Serebrennikov   if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) {
2334f1c54d72SVlad Serebrennikov     if (ICE->getCastKind() == CK_BitCast &&
2335f1c54d72SVlad Serebrennikov         ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>())
2336f1c54d72SVlad Serebrennikov       Element = ICE->getSubExpr();
2337f1c54d72SVlad Serebrennikov   }
2338f1c54d72SVlad Serebrennikov 
2339f1c54d72SVlad Serebrennikov   QualType ElementType = Element->getType();
2340f1c54d72SVlad Serebrennikov   ExprResult ElementResult(Element);
2341f1c54d72SVlad Serebrennikov   if (ElementType->getAs<ObjCObjectPointerType>() &&
2342f1c54d72SVlad Serebrennikov       S.CheckSingleAssignmentConstraints(TargetElementType, ElementResult,
2343f1c54d72SVlad Serebrennikov                                          false, false) != Sema::Compatible) {
2344f1c54d72SVlad Serebrennikov     S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element)
2345f1c54d72SVlad Serebrennikov         << ElementType << ElementKind << TargetElementType
2346f1c54d72SVlad Serebrennikov         << Element->getSourceRange();
2347f1c54d72SVlad Serebrennikov   }
2348f1c54d72SVlad Serebrennikov 
2349f1c54d72SVlad Serebrennikov   if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element))
2350f1c54d72SVlad Serebrennikov     S.ObjC().checkArrayLiteral(TargetElementType, ArrayLiteral);
2351f1c54d72SVlad Serebrennikov   else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element))
2352f1c54d72SVlad Serebrennikov     S.ObjC().checkDictionaryLiteral(TargetElementType, DictionaryLiteral);
2353f1c54d72SVlad Serebrennikov }
2354f1c54d72SVlad Serebrennikov 
2355f1c54d72SVlad Serebrennikov /// Check an Objective-C array literal being converted to the given
2356f1c54d72SVlad Serebrennikov /// target type.
2357f1c54d72SVlad Serebrennikov void SemaObjC::checkArrayLiteral(QualType TargetType,
2358f1c54d72SVlad Serebrennikov                                  ObjCArrayLiteral *ArrayLiteral) {
2359f1c54d72SVlad Serebrennikov   if (!NSArrayDecl)
2360f1c54d72SVlad Serebrennikov     return;
2361f1c54d72SVlad Serebrennikov 
2362f1c54d72SVlad Serebrennikov   const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
2363f1c54d72SVlad Serebrennikov   if (!TargetObjCPtr)
2364f1c54d72SVlad Serebrennikov     return;
2365f1c54d72SVlad Serebrennikov 
2366f1c54d72SVlad Serebrennikov   if (TargetObjCPtr->isUnspecialized() ||
2367f1c54d72SVlad Serebrennikov       TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() !=
2368f1c54d72SVlad Serebrennikov           NSArrayDecl->getCanonicalDecl())
2369f1c54d72SVlad Serebrennikov     return;
2370f1c54d72SVlad Serebrennikov 
2371f1c54d72SVlad Serebrennikov   auto TypeArgs = TargetObjCPtr->getTypeArgs();
2372f1c54d72SVlad Serebrennikov   if (TypeArgs.size() != 1)
2373f1c54d72SVlad Serebrennikov     return;
2374f1c54d72SVlad Serebrennikov 
2375f1c54d72SVlad Serebrennikov   QualType TargetElementType = TypeArgs[0];
2376f1c54d72SVlad Serebrennikov   for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) {
2377f1c54d72SVlad Serebrennikov     checkCollectionLiteralElement(SemaRef, TargetElementType,
2378f1c54d72SVlad Serebrennikov                                   ArrayLiteral->getElement(I), 0);
2379f1c54d72SVlad Serebrennikov   }
2380f1c54d72SVlad Serebrennikov }
2381f1c54d72SVlad Serebrennikov 
2382f1c54d72SVlad Serebrennikov void SemaObjC::checkDictionaryLiteral(
2383f1c54d72SVlad Serebrennikov     QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral) {
2384f1c54d72SVlad Serebrennikov   if (!NSDictionaryDecl)
2385f1c54d72SVlad Serebrennikov     return;
2386f1c54d72SVlad Serebrennikov 
2387f1c54d72SVlad Serebrennikov   const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
2388f1c54d72SVlad Serebrennikov   if (!TargetObjCPtr)
2389f1c54d72SVlad Serebrennikov     return;
2390f1c54d72SVlad Serebrennikov 
2391f1c54d72SVlad Serebrennikov   if (TargetObjCPtr->isUnspecialized() ||
2392f1c54d72SVlad Serebrennikov       TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() !=
2393f1c54d72SVlad Serebrennikov           NSDictionaryDecl->getCanonicalDecl())
2394f1c54d72SVlad Serebrennikov     return;
2395f1c54d72SVlad Serebrennikov 
2396f1c54d72SVlad Serebrennikov   auto TypeArgs = TargetObjCPtr->getTypeArgs();
2397f1c54d72SVlad Serebrennikov   if (TypeArgs.size() != 2)
2398f1c54d72SVlad Serebrennikov     return;
2399f1c54d72SVlad Serebrennikov 
2400f1c54d72SVlad Serebrennikov   QualType TargetKeyType = TypeArgs[0];
2401f1c54d72SVlad Serebrennikov   QualType TargetObjectType = TypeArgs[1];
2402f1c54d72SVlad Serebrennikov   for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) {
2403f1c54d72SVlad Serebrennikov     auto Element = DictionaryLiteral->getKeyValueElement(I);
2404f1c54d72SVlad Serebrennikov     checkCollectionLiteralElement(SemaRef, TargetKeyType, Element.Key, 1);
2405f1c54d72SVlad Serebrennikov     checkCollectionLiteralElement(SemaRef, TargetObjectType, Element.Value, 2);
2406f1c54d72SVlad Serebrennikov   }
2407f1c54d72SVlad Serebrennikov }
2408f1c54d72SVlad Serebrennikov 
240931a203faSVlad Serebrennikov } // namespace clang
2410