[clang] [clang][NFC] Move more functions from `Sema` to `SemaObjC` (PR #97172)

Vlad Serebrennikov via cfe-commits cfe-commits at lists.llvm.org
Sat Jun 29 11:23:20 PDT 2024


https://github.com/Endilll created https://github.com/llvm/llvm-project/pull/97172

This patch continues the effort to split `Sema` up, moving more function to `SemaObjC`. Additional context can be found in https://github.com/llvm/llvm-project/pull/84184 and https://github.com/llvm/llvm-project/pull/92682.

Highlights are `getCurBlock()` and `PushBlockScope()`. 

>From 890d449d9cfa956badc1ba1f97022ffb84281ca3 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 29 Jun 2024 21:14:35 +0300
Subject: [PATCH 1/2] [clang] Move more function from `Sema` to `SemaObjC`

---
 clang/include/clang/Sema/Sema.h               |  41 --
 clang/include/clang/Sema/SemaObjC.h           |  47 ++-
 clang/lib/Parse/ParseExpr.cpp                 |  16 +-
 clang/lib/Sema/Sema.cpp                       |  21 -
 clang/lib/Sema/SemaChecking.cpp               | 118 ------
 clang/lib/Sema/SemaCodeComplete.cpp           |   8 +-
 clang/lib/Sema/SemaDecl.cpp                   |  33 +-
 clang/lib/Sema/SemaDeclObjC.cpp               |   2 +-
 clang/lib/Sema/SemaExpr.cpp                   | 374 +----------------
 clang/lib/Sema/SemaExprObjC.cpp               | 376 +++++++++++++++++-
 clang/lib/Sema/SemaLookup.cpp                 |   3 +-
 clang/lib/Sema/SemaObjC.cpp                   | 188 ++++++++-
 clang/lib/Sema/SemaOpenMP.cpp                 |   4 +-
 clang/lib/Sema/SemaPseudoObject.cpp           |   4 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  10 +-
 clang/lib/Sema/TreeTransform.h                |  10 +-
 16 files changed, 631 insertions(+), 624 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ef4fc47567a7c..422149896fb36 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -694,7 +694,6 @@ class Sema final : public SemaBase {
   Scope *getScopeForContext(DeclContext *Ctx);
 
   void PushFunctionScope();
-  void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
   sema::LambdaScopeInfo *PushLambdaScope();
 
   /// This is used to inform Sema what the current TemplateParameterDepth
@@ -736,9 +735,6 @@ class Sema final : public SemaBase {
 
   bool hasAnyUnrecoverableErrorsInThisFunction() const;
 
-  /// Retrieve the current block, if any.
-  sema::BlockScopeInfo *getCurBlock();
-
   /// Get the innermost lambda enclosing the current location, if any. This
   /// looks through intervening non-lambda scopes such as local functions and
   /// blocks.
@@ -2182,14 +2178,6 @@ class Sema final : public SemaBase {
 
   void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
 
-  /// checkUnsafeAssigns - Check whether +1 expr is being assigned
-  /// to weak/__unsafe_unretained type.
-  bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
-
-  /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
-  /// to weak/__unsafe_unretained expression.
-  void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
-
   /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null
   /// statement as a \p Body, and it is located on the same line.
   ///
@@ -3853,8 +3841,6 @@ class Sema final : public SemaBase {
   void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
                            Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
 
-  enum class RetainOwnershipKind { NS, CF, OS };
-
   UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
                           StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
 
@@ -5833,26 +5819,6 @@ class Sema final : public SemaBase {
 
   bool CheckCaseExpression(Expr *E);
 
-  //===------------------------- "Block" Extension ------------------------===//
-
-  /// ActOnBlockStart - This callback is invoked when a block literal is
-  /// started.
-  void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
-
-  /// ActOnBlockArguments - This callback allows processing of block arguments.
-  /// If there are no arguments, this is still invoked.
-  void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
-                           Scope *CurScope);
-
-  /// ActOnBlockError - If there is an error parsing a block, this callback
-  /// is invoked to pop the information about the block from the action impl.
-  void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
-
-  /// ActOnBlockStmtExpr - This is called when the body of a block statement
-  /// literal was successfully completed.  ^(int x){...}
-  ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
-                                Scope *CurScope);
-
   //===---------------------------- Clang Extensions ----------------------===//
 
   /// __builtin_convertvector(...)
@@ -6571,13 +6537,6 @@ class Sema final : public SemaBase {
   // Set of failed immediate invocations to avoid double diagnosing.
   llvm::SmallPtrSet<ConstantExpr *, 4> FailedImmediateInvocations;
 
-  /// List of SourceLocations where 'self' is implicitly retained inside a
-  /// block.
-  llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1>
-      ImplicitlyRetainedSelfLocs;
-
-  void maybeExtendBlockObject(ExprResult &E);
-
 private:
   static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
 
diff --git a/clang/include/clang/Sema/SemaObjC.h b/clang/include/clang/Sema/SemaObjC.h
index 07c3c1a06be16..2ea0cc303d56a 100644
--- a/clang/include/clang/Sema/SemaObjC.h
+++ b/clang/include/clang/Sema/SemaObjC.h
@@ -179,6 +179,13 @@ class SemaObjC : public SemaBase {
   /// target type.
   void checkArrayLiteral(QualType TargetType, ObjCArrayLiteral *ArrayLiteral);
 
+  /// Retrieve the current block, if any.
+  sema::BlockScopeInfo *getCurBlock();
+
+  void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+
+  void diagnoseImplicitlyRetainedSelf();
+
 private:
   IdentifierInfo *Ident_NSError = nullptr;
 
@@ -571,6 +578,21 @@ class SemaObjC : public SemaBase {
 
   ObjCContainerDecl *getObjCDeclContext() const;
 
+  /// List of SourceLocations where 'self' is implicitly retained inside a
+  /// block.
+  llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1>
+      ImplicitlyRetainedSelfLocs;
+
+  /// checkUnsafeAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained type.
+  bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
+
+  /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained expression.
+  void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
+
+  enum class RetainOwnershipKind { NS, CF, OS };
+
 private:
   /// AddMethodToGlobalPool - Add an instance or factory method to the global
   /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
@@ -925,6 +947,27 @@ class SemaObjC : public SemaBase {
   };
   ObjCLiteralKind CheckLiteralKind(Expr *FromE);
 
+  /// Do an explicit extend of the given block pointer if we're in ARC.
+  void maybeExtendBlockObject(ExprResult &E);
+
+  /// ActOnBlockStart - This callback is invoked when a block literal is
+  /// started.
+  void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+
+  /// ActOnBlockArguments - This callback allows processing of block arguments.
+  /// If there are no arguments, this is still invoked.
+  void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
+                           Scope *CurScope);
+
+  /// ActOnBlockError - If there is an error parsing a block, this callback
+  /// is invoked to pop the information about the block from the action impl.
+  void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
+
+  /// ActOnBlockStmtExpr - This is called when the body of a block statement
+  /// literal was successfully completed.  ^(int x){...}
+  ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
+                                Scope *CurScope);
+
   ///@}
 
   //
@@ -1067,14 +1110,14 @@ class SemaObjC : public SemaBase {
   void handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL);
 
   void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        Sema::RetainOwnershipKind K,
+                        RetainOwnershipKind K,
                         bool IsTemplateInstantiation);
 
   /// \return whether the parameter is a pointer to OSObject pointer.
   bool isValidOSObjectOutParameter(const Decl *D);
   bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
 
-  Sema::RetainOwnershipKind
+  RetainOwnershipKind
   parsedAttrToRetainOwnershipKind(const ParsedAttr &AL);
 
   ///@}
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 9fc3cd73f73a0..166b74c0ce9e5 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -3733,7 +3733,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
   MaybeParseGNUAttributes(DeclaratorInfo);
 
   // Inform sema that we are starting a block.
-  Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope());
+  Actions.ObjC().ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope());
 }
 
 /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
@@ -3761,7 +3761,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
                                   Scope::CompoundStmtScope | Scope::DeclScope);
 
   // Inform sema that we are starting a block.
-  Actions.ActOnBlockStart(CaretLoc, getCurScope());
+  Actions.ObjC().ActOnBlockStart(CaretLoc, getCurScope());
 
   // Parse the return type if present.
   DeclSpec DS(AttrFactory);
@@ -3786,14 +3786,14 @@ ExprResult Parser::ParseBlockLiteralExpression() {
       // If there was an error parsing the arguments, they may have
       // tried to use ^(x+y) which requires an argument list.  Just
       // skip the whole block literal.
-      Actions.ActOnBlockError(CaretLoc, getCurScope());
+      Actions.ObjC().ActOnBlockError(CaretLoc, getCurScope());
       return ExprError();
     }
 
     MaybeParseGNUAttributes(ParamInfo);
 
     // Inform sema that we are starting a block.
-    Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
+    Actions.ObjC().ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
   } else if (!Tok.is(tok::l_brace)) {
     ParseBlockId(CaretLoc);
   } else {
@@ -3823,7 +3823,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
     MaybeParseGNUAttributes(ParamInfo);
 
     // Inform sema that we are starting a block.
-    Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
+    Actions.ObjC().ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
   }
 
 
@@ -3831,16 +3831,16 @@ ExprResult Parser::ParseBlockLiteralExpression() {
   if (!Tok.is(tok::l_brace)) {
     // Saw something like: ^expr
     Diag(Tok, diag::err_expected_expression);
-    Actions.ActOnBlockError(CaretLoc, getCurScope());
+    Actions.ObjC().ActOnBlockError(CaretLoc, getCurScope());
     return ExprError();
   }
 
   StmtResult Stmt(ParseCompoundStatementBody());
   BlockScope.Exit();
   if (!Stmt.isInvalid())
-    Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());
+    Result = Actions.ObjC().ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());
   else
-    Actions.ActOnBlockError(CaretLoc, getCurScope());
+    Actions.ObjC().ActOnBlockError(CaretLoc, getCurScope());
   return Result;
 }
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 3f8f2f027172d..e32192af436cf 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2204,12 +2204,6 @@ void Sema::PushFunctionScope() {
     OpenMP().pushOpenMPFunctionRegion();
 }
 
-void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
-  FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
-                                              BlockScope, Block));
-  CapturingFunctionScopes++;
-}
-
 LambdaScopeInfo *Sema::PushLambdaScope() {
   LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics());
   FunctionScopes.push_back(LSI);
@@ -2382,21 +2376,6 @@ void Sema::setFunctionHasMustTail() {
     FunctionScopes.back()->setHasMustTail();
 }
 
-BlockScopeInfo *Sema::getCurBlock() {
-  if (FunctionScopes.empty())
-    return nullptr;
-
-  auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
-  if (CurBSI && CurBSI->TheDecl &&
-      !CurBSI->TheDecl->Encloses(CurContext)) {
-    // We have switched contexts due to template instantiation.
-    assert(!CodeSynthesisContexts.empty());
-    return nullptr;
-  }
-
-  return CurBSI;
-}
-
 FunctionScopeInfo *Sema::getEnclosingFunction() const {
   if (FunctionScopes.empty())
     return nullptr;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 005fbfd42a8ab..784606368b3ae 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -13457,124 +13457,6 @@ void Sema::CheckArrayAccess(const Expr *expr) {
   }
 }
 
-static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
-                                     Expr *RHS, bool isProperty) {
-  // Check if RHS is an Objective-C object literal, which also can get
-  // immediately zapped in a weak reference.  Note that we explicitly
-  // allow ObjCStringLiterals, since those are designed to never really die.
-  RHS = RHS->IgnoreParenImpCasts();
-
-  // This enum needs to match with the 'select' in
-  // warn_objc_arc_literal_assign (off-by-1).
-  SemaObjC::ObjCLiteralKind Kind = S.ObjC().CheckLiteralKind(RHS);
-  if (Kind == SemaObjC::LK_String || Kind == SemaObjC::LK_None)
-    return false;
-
-  S.Diag(Loc, diag::warn_arc_literal_assign)
-    << (unsigned) Kind
-    << (isProperty ? 0 : 1)
-    << RHS->getSourceRange();
-
-  return true;
-}
-
-static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
-                                    Qualifiers::ObjCLifetime LT,
-                                    Expr *RHS, bool isProperty) {
-  // Strip off any implicit cast added to get to the one ARC-specific.
-  while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
-    if (cast->getCastKind() == CK_ARCConsumeObject) {
-      S.Diag(Loc, diag::warn_arc_retained_assign)
-        << (LT == Qualifiers::OCL_ExplicitNone)
-        << (isProperty ? 0 : 1)
-        << RHS->getSourceRange();
-      return true;
-    }
-    RHS = cast->getSubExpr();
-  }
-
-  if (LT == Qualifiers::OCL_Weak &&
-      checkUnsafeAssignLiteral(S, Loc, RHS, isProperty))
-    return true;
-
-  return false;
-}
-
-bool Sema::checkUnsafeAssigns(SourceLocation Loc,
-                              QualType LHS, Expr *RHS) {
-  Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
-
-  if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
-    return false;
-
-  if (checkUnsafeAssignObject(*this, Loc, LT, RHS, false))
-    return true;
-
-  return false;
-}
-
-void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
-                              Expr *LHS, Expr *RHS) {
-  QualType LHSType;
-  // PropertyRef on LHS type need be directly obtained from
-  // its declaration as it has a PseudoType.
-  ObjCPropertyRefExpr *PRE
-    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
-  if (PRE && !PRE->isImplicitProperty()) {
-    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
-    if (PD)
-      LHSType = PD->getType();
-  }
-
-  if (LHSType.isNull())
-    LHSType = LHS->getType();
-
-  Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
-
-  if (LT == Qualifiers::OCL_Weak) {
-    if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
-      getCurFunction()->markSafeWeakUse(LHS);
-  }
-
-  if (checkUnsafeAssigns(Loc, LHSType, RHS))
-    return;
-
-  // FIXME. Check for other life times.
-  if (LT != Qualifiers::OCL_None)
-    return;
-
-  if (PRE) {
-    if (PRE->isImplicitProperty())
-      return;
-    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
-    if (!PD)
-      return;
-
-    unsigned Attributes = PD->getPropertyAttributes();
-    if (Attributes & ObjCPropertyAttribute::kind_assign) {
-      // when 'assign' attribute was not explicitly specified
-      // by user, ignore it and rely on property type itself
-      // for lifetime info.
-      unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten();
-      if (!(AsWrittenAttr & ObjCPropertyAttribute::kind_assign) &&
-          LHSType->isObjCRetainableType())
-        return;
-
-      while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
-        if (cast->getCastKind() == CK_ARCConsumeObject) {
-          Diag(Loc, diag::warn_arc_retained_property_assign)
-          << RHS->getSourceRange();
-          return;
-        }
-        RHS = cast->getSubExpr();
-      }
-    } else if (Attributes & ObjCPropertyAttribute::kind_weak) {
-      if (checkUnsafeAssignObject(*this, Loc, Qualifiers::OCL_Weak, RHS, true))
-        return;
-    }
-  }
-}
-
 //===--- CHECK: Empty statement body (-Wempty-body) ---------------------===//
 
 static bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index cd1c5f9391ccd..bb010cb07cc6d 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -413,7 +413,7 @@ void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
   if (!Enabled)
     return;
   if (isa<BlockDecl>(S.CurContext)) {
-    if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
+    if (sema::BlockScopeInfo *BSI = S.ObjC().getCurBlock()) {
       ComputeType = nullptr;
       Type = BSI->ReturnType;
       ExpectedLoc = Tok;
@@ -2473,9 +2473,9 @@ AddOrdinaryNameResults(SemaCodeCompletion::ParserCompletionContext CCC,
       ReturnType = Function->getReturnType();
     else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
       ReturnType = Method->getReturnType();
-    else if (SemaRef.getCurBlock() &&
-             !SemaRef.getCurBlock()->ReturnType.isNull())
-      ReturnType = SemaRef.getCurBlock()->ReturnType;;
+    else if (SemaRef.ObjC().getCurBlock() &&
+             !SemaRef.ObjC().getCurBlock()->ReturnType.isNull())
+      ReturnType = SemaRef.ObjC().getCurBlock()->ReturnType;;
     if (ReturnType.isNull() || ReturnType->isVoidType()) {
       Builder.AddTypedTextChunk("return");
       Builder.AddChunk(CodeCompletionString::CK_SemiColon);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 029ccf944c513..deb161ee352be 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13782,7 +13782,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
     VDecl->setType(DclT);
 
   if (!VDecl->isInvalidDecl()) {
-    checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
+    ObjC().checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
 
     if (VDecl->hasAttr<BlocksAttr>())
       ObjC().checkRetainCycles(VDecl, Init);
@@ -16016,35 +16016,6 @@ class ExitFunctionBodyRAII {
   bool IsLambda = false;
 };
 
-static void diagnoseImplicitlyRetainedSelf(Sema &S) {
-  llvm::DenseMap<const BlockDecl *, bool> EscapeInfo;
-
-  auto IsOrNestedInEscapingBlock = [&](const BlockDecl *BD) {
-    if (EscapeInfo.count(BD))
-      return EscapeInfo[BD];
-
-    bool R = false;
-    const BlockDecl *CurBD = BD;
-
-    do {
-      R = !CurBD->doesNotEscape();
-      if (R)
-        break;
-      CurBD = CurBD->getParent()->getInnermostBlockDecl();
-    } while (CurBD);
-
-    return EscapeInfo[BD] = R;
-  };
-
-  // If the location where 'self' is implicitly retained is inside a escaping
-  // block, emit a diagnostic.
-  for (const std::pair<SourceLocation, const BlockDecl *> &P :
-       S.ImplicitlyRetainedSelfLocs)
-    if (IsOrNestedInEscapingBlock(P.second))
-      S.Diag(P.first, diag::warn_implicitly_retains_self)
-          << FixItHint::CreateInsertion(P.first, "self->");
-}
-
 static bool methodHasName(const FunctionDecl *FD, StringRef Name) {
   return isa<CXXMethodDecl>(FD) && FD->param_empty() &&
          FD->getDeclName().isIdentifier() && FD->getName() == Name;
@@ -16392,7 +16363,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
         FSI->ObjCWarnForNoInitDelegation = false;
       }
 
-      diagnoseImplicitlyRetainedSelf(*this);
+      ObjC().diagnoseImplicitlyRetainedSelf();
     } else {
       // Parsing the function declaration failed in some way. Pop the fake scope
       // we pushed on.
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 807453400abdd..d60d9968b7957 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -368,7 +368,7 @@ HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {
 /// and user declared, in the method definition's AST.
 void SemaObjC::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
   ASTContext &Context = getASTContext();
-  SemaRef.ImplicitlyRetainedSelfLocs.clear();
+  ImplicitlyRetainedSelfLocs.clear();
   assert((SemaRef.getCurMethodDecl() == nullptr) && "Methodparsing confused");
   ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index db44cfe1288b6..9bc771a34073a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1070,7 +1070,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
 
   // Copy blocks to the heap.
   if (ExprRes.get()->getType()->isBlockPointerType())
-    maybeExtendBlockObject(ExprRes);
+    ObjC().maybeExtendBlockObject(ExprRes);
 
   E = ExprRes.get();
 
@@ -7306,20 +7306,6 @@ Sema::BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
   return E;
 }
 
-/// Do an explicit extend of the given block pointer if we're in ARC.
-void Sema::maybeExtendBlockObject(ExprResult &E) {
-  assert(E.get()->getType()->isBlockPointerType());
-  assert(E.get()->isPRValue());
-
-  // Only do this in an r-value context.
-  if (!getLangOpts().ObjCAutoRefCount) return;
-
-  E = ImplicitCastExpr::Create(
-      Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(),
-      /*base path*/ nullptr, VK_PRValue, FPOptionsOverride());
-  Cleanup.setExprNeedsCleanups(true);
-}
-
 /// Prepares for a scalar cast, performing all the necessary stages
 /// except the final cast and returning the kind required.
 CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
@@ -7356,7 +7342,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
         return CK_BitCast;
       if (SrcKind == Type::STK_CPointer)
         return CK_CPointerToObjCPointerCast;
-      maybeExtendBlockObject(Src);
+      ObjC().maybeExtendBlockObject(Src);
       return CK_BlockPointerToObjCPointerCast;
     case Type::STK_Bool:
       return CK_PointerToBoolean;
@@ -9545,7 +9531,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
     if (RHSType->isBlockPointerType() &&
         LHSType->isBlockCompatibleObjCPointerType(Context)) {
       if (ConvertRHS)
-        maybeExtendBlockObject(RHS);
+        ObjC().maybeExtendBlockObject(RHS);
       Kind = CK_BlockPointerToObjCPointerCast;
       return Compatible;
     }
@@ -13764,7 +13750,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
           getCurFunction()->markSafeWeakUse(RHS.get());
 
       } else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) {
-        checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get());
+        ObjC().checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get());
       }
     }
   } else {
@@ -16081,358 +16067,6 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
 // Clang Extensions.
 //===----------------------------------------------------------------------===//
 
-/// ActOnBlockStart - This callback is invoked when a block literal is started.
-void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
-  BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
-
-  if (LangOpts.CPlusPlus) {
-    MangleNumberingContext *MCtx;
-    Decl *ManglingContextDecl;
-    std::tie(MCtx, ManglingContextDecl) =
-        getCurrentMangleNumberContext(Block->getDeclContext());
-    if (MCtx) {
-      unsigned ManglingNumber = MCtx->getManglingNumber(Block);
-      Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
-    }
-  }
-
-  PushBlockScope(CurScope, Block);
-  CurContext->addDecl(Block);
-  if (CurScope)
-    PushDeclContext(CurScope, Block);
-  else
-    CurContext = Block;
-
-  getCurBlock()->HasImplicitReturnType = true;
-
-  // Enter a new evaluation context to insulate the block from any
-  // cleanups from the enclosing full-expression.
-  PushExpressionEvaluationContext(
-      ExpressionEvaluationContext::PotentiallyEvaluated);
-}
-
-void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
-                               Scope *CurScope) {
-  assert(ParamInfo.getIdentifier() == nullptr &&
-         "block-id should have no identifier!");
-  assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteral);
-  BlockScopeInfo *CurBlock = getCurBlock();
-
-  TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo);
-  QualType T = Sig->getType();
-
-  // FIXME: We should allow unexpanded parameter packs here, but that would,
-  // in turn, make the block expression contain unexpanded parameter packs.
-  if (DiagnoseUnexpandedParameterPack(CaretLoc, Sig, UPPC_Block)) {
-    // Drop the parameters.
-    FunctionProtoType::ExtProtoInfo EPI;
-    EPI.HasTrailingReturn = false;
-    EPI.TypeQuals.addConst();
-    T = Context.getFunctionType(Context.DependentTy, std::nullopt, EPI);
-    Sig = Context.getTrivialTypeSourceInfo(T);
-  }
-
-  // GetTypeForDeclarator always produces a function type for a block
-  // literal signature.  Furthermore, it is always a FunctionProtoType
-  // unless the function was written with a typedef.
-  assert(T->isFunctionType() &&
-         "GetTypeForDeclarator made a non-function block signature");
-
-  // Look for an explicit signature in that function type.
-  FunctionProtoTypeLoc ExplicitSignature;
-
-  if ((ExplicitSignature = Sig->getTypeLoc()
-                               .getAsAdjusted<FunctionProtoTypeLoc>())) {
-
-    // Check whether that explicit signature was synthesized by
-    // GetTypeForDeclarator.  If so, don't save that as part of the
-    // written signature.
-    if (ExplicitSignature.getLocalRangeBegin() ==
-        ExplicitSignature.getLocalRangeEnd()) {
-      // This would be much cheaper if we stored TypeLocs instead of
-      // TypeSourceInfos.
-      TypeLoc Result = ExplicitSignature.getReturnLoc();
-      unsigned Size = Result.getFullDataSize();
-      Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
-      Sig->getTypeLoc().initializeFullCopy(Result, Size);
-
-      ExplicitSignature = FunctionProtoTypeLoc();
-    }
-  }
-
-  CurBlock->TheDecl->setSignatureAsWritten(Sig);
-  CurBlock->FunctionType = T;
-
-  const auto *Fn = T->castAs<FunctionType>();
-  QualType RetTy = Fn->getReturnType();
-  bool isVariadic =
-      (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
-
-  CurBlock->TheDecl->setIsVariadic(isVariadic);
-
-  // Context.DependentTy is used as a placeholder for a missing block
-  // return type.  TODO:  what should we do with declarators like:
-  //   ^ * { ... }
-  // If the answer is "apply template argument deduction"....
-  if (RetTy != Context.DependentTy) {
-    CurBlock->ReturnType = RetTy;
-    CurBlock->TheDecl->setBlockMissingReturnType(false);
-    CurBlock->HasImplicitReturnType = false;
-  }
-
-  // Push block parameters from the declarator if we had them.
-  SmallVector<ParmVarDecl*, 8> Params;
-  if (ExplicitSignature) {
-    for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
-      ParmVarDecl *Param = ExplicitSignature.getParam(I);
-      if (Param->getIdentifier() == nullptr && !Param->isImplicit() &&
-          !Param->isInvalidDecl() && !getLangOpts().CPlusPlus) {
-        // Diagnose this as an extension in C17 and earlier.
-        if (!getLangOpts().C23)
-          Diag(Param->getLocation(), diag::ext_parameter_name_omitted_c23);
-      }
-      Params.push_back(Param);
-    }
-
-  // Fake up parameter variables if we have a typedef, like
-  //   ^ fntype { ... }
-  } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
-    for (const auto &I : Fn->param_types()) {
-      ParmVarDecl *Param = BuildParmVarDeclForTypedef(
-          CurBlock->TheDecl, ParamInfo.getBeginLoc(), I);
-      Params.push_back(Param);
-    }
-  }
-
-  // Set the parameters on the block decl.
-  if (!Params.empty()) {
-    CurBlock->TheDecl->setParams(Params);
-    CheckParmsForFunctionDef(CurBlock->TheDecl->parameters(),
-                             /*CheckParameterNames=*/false);
-  }
-
-  // Finally we can process decl attributes.
-  ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
-
-  // Put the parameter variables in scope.
-  for (auto *AI : CurBlock->TheDecl->parameters()) {
-    AI->setOwningFunction(CurBlock->TheDecl);
-
-    // If this has an identifier, add it to the scope stack.
-    if (AI->getIdentifier()) {
-      CheckShadow(CurBlock->TheScope, AI);
-
-      PushOnScopeChains(AI, CurBlock->TheScope);
-    }
-
-    if (AI->isInvalidDecl())
-      CurBlock->TheDecl->setInvalidDecl();
-  }
-}
-
-/// ActOnBlockError - If there is an error parsing a block, this callback
-/// is invoked to pop the information about the block from the action impl.
-void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
-  // Leave the expression-evaluation context.
-  DiscardCleanupsInEvaluationContext();
-  PopExpressionEvaluationContext();
-
-  // Pop off CurBlock, handle nested blocks.
-  PopDeclContext();
-  PopFunctionScopeInfo();
-}
-
-/// ActOnBlockStmtExpr - This is called when the body of a block statement
-/// literal was successfully completed.  ^(int x){...}
-ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
-                                    Stmt *Body, Scope *CurScope) {
-  // If blocks are disabled, emit an error.
-  if (!LangOpts.Blocks)
-    Diag(CaretLoc, diag::err_blocks_disable) << LangOpts.OpenCL;
-
-  // Leave the expression-evaluation context.
-  if (hasAnyUnrecoverableErrorsInThisFunction())
-    DiscardCleanupsInEvaluationContext();
-  assert(!Cleanup.exprNeedsCleanups() &&
-         "cleanups within block not correctly bound!");
-  PopExpressionEvaluationContext();
-
-  BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back());
-  BlockDecl *BD = BSI->TheDecl;
-
-  if (BSI->HasImplicitReturnType)
-    deduceClosureReturnType(*BSI);
-
-  QualType RetTy = Context.VoidTy;
-  if (!BSI->ReturnType.isNull())
-    RetTy = BSI->ReturnType;
-
-  bool NoReturn = BD->hasAttr<NoReturnAttr>();
-  QualType BlockTy;
-
-  // If the user wrote a function type in some form, try to use that.
-  if (!BSI->FunctionType.isNull()) {
-    const FunctionType *FTy = BSI->FunctionType->castAs<FunctionType>();
-
-    FunctionType::ExtInfo Ext = FTy->getExtInfo();
-    if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
-
-    // Turn protoless block types into nullary block types.
-    if (isa<FunctionNoProtoType>(FTy)) {
-      FunctionProtoType::ExtProtoInfo EPI;
-      EPI.ExtInfo = Ext;
-      BlockTy = Context.getFunctionType(RetTy, std::nullopt, EPI);
-
-      // Otherwise, if we don't need to change anything about the function type,
-      // preserve its sugar structure.
-    } else if (FTy->getReturnType() == RetTy &&
-               (!NoReturn || FTy->getNoReturnAttr())) {
-      BlockTy = BSI->FunctionType;
-
-    // Otherwise, make the minimal modifications to the function type.
-    } else {
-      const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
-      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
-      EPI.TypeQuals = Qualifiers();
-      EPI.ExtInfo = Ext;
-      BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
-    }
-
-  // If we don't have a function type, just build one from nothing.
-  } else {
-    FunctionProtoType::ExtProtoInfo EPI;
-    EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
-    BlockTy = Context.getFunctionType(RetTy, std::nullopt, EPI);
-  }
-
-  DiagnoseUnusedParameters(BD->parameters());
-  BlockTy = Context.getBlockPointerType(BlockTy);
-
-  // If needed, diagnose invalid gotos and switches in the block.
-  if (getCurFunction()->NeedsScopeChecking() &&
-      !PP.isCodeCompletionEnabled())
-    DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
-
-  BD->setBody(cast<CompoundStmt>(Body));
-
-  if (Body && getCurFunction()->HasPotentialAvailabilityViolations)
-    DiagnoseUnguardedAvailabilityViolations(BD);
-
-  // Try to apply the named return value optimization. We have to check again
-  // if we can do this, though, because blocks keep return statements around
-  // to deduce an implicit return type.
-  if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
-      !BD->isDependentContext())
-    computeNRVO(Body, BSI);
-
-  if (RetTy.hasNonTrivialToPrimitiveDestructCUnion() ||
-      RetTy.hasNonTrivialToPrimitiveCopyCUnion())
-    checkNonTrivialCUnion(RetTy, BD->getCaretLocation(), NTCUC_FunctionReturn,
-                          NTCUK_Destruct|NTCUK_Copy);
-
-  PopDeclContext();
-
-  // Set the captured variables on the block.
-  SmallVector<BlockDecl::Capture, 4> Captures;
-  for (Capture &Cap : BSI->Captures) {
-    if (Cap.isInvalid() || Cap.isThisCapture())
-      continue;
-    // Cap.getVariable() is always a VarDecl because
-    // blocks cannot capture structured bindings or other ValueDecl kinds.
-    auto *Var = cast<VarDecl>(Cap.getVariable());
-    Expr *CopyExpr = nullptr;
-    if (getLangOpts().CPlusPlus && Cap.isCopyCapture()) {
-      if (const RecordType *Record =
-              Cap.getCaptureType()->getAs<RecordType>()) {
-        // The capture logic needs the destructor, so make sure we mark it.
-        // Usually this is unnecessary because most local variables have
-        // their destructors marked at declaration time, but parameters are
-        // an exception because it's technically only the call site that
-        // actually requires the destructor.
-        if (isa<ParmVarDecl>(Var))
-          FinalizeVarWithDestructor(Var, Record);
-
-        // Enter a separate potentially-evaluated context while building block
-        // initializers to isolate their cleanups from those of the block
-        // itself.
-        // FIXME: Is this appropriate even when the block itself occurs in an
-        // unevaluated operand?
-        EnterExpressionEvaluationContext EvalContext(
-            *this, ExpressionEvaluationContext::PotentiallyEvaluated);
-
-        SourceLocation Loc = Cap.getLocation();
-
-        ExprResult Result = BuildDeclarationNameExpr(
-            CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
-
-        // According to the blocks spec, the capture of a variable from
-        // the stack requires a const copy constructor.  This is not true
-        // of the copy/move done to move a __block variable to the heap.
-        if (!Result.isInvalid() &&
-            !Result.get()->getType().isConstQualified()) {
-          Result = ImpCastExprToType(Result.get(),
-                                     Result.get()->getType().withConst(),
-                                     CK_NoOp, VK_LValue);
-        }
-
-        if (!Result.isInvalid()) {
-          Result = PerformCopyInitialization(
-              InitializedEntity::InitializeBlock(Var->getLocation(),
-                                                 Cap.getCaptureType()),
-              Loc, Result.get());
-        }
-
-        // Build a full-expression copy expression if initialization
-        // succeeded and used a non-trivial constructor.  Recover from
-        // errors by pretending that the copy isn't necessary.
-        if (!Result.isInvalid() &&
-            !cast<CXXConstructExpr>(Result.get())->getConstructor()
-                ->isTrivial()) {
-          Result = MaybeCreateExprWithCleanups(Result);
-          CopyExpr = Result.get();
-        }
-      }
-    }
-
-    BlockDecl::Capture NewCap(Var, Cap.isBlockCapture(), Cap.isNested(),
-                              CopyExpr);
-    Captures.push_back(NewCap);
-  }
-  BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
-
-  // Pop the block scope now but keep it alive to the end of this function.
-  AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
-  PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy);
-
-  BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy);
-
-  // If the block isn't obviously global, i.e. it captures anything at
-  // all, then we need to do a few things in the surrounding context:
-  if (Result->getBlockDecl()->hasCaptures()) {
-    // First, this expression has a new cleanup object.
-    ExprCleanupObjects.push_back(Result->getBlockDecl());
-    Cleanup.setExprNeedsCleanups(true);
-
-    // It also gets a branch-protected scope if any of the captured
-    // variables needs destruction.
-    for (const auto &CI : Result->getBlockDecl()->captures()) {
-      const VarDecl *var = CI.getVariable();
-      if (var->getType().isDestructedType() != QualType::DK_none) {
-        setFunctionHasBranchProtectedScope();
-        break;
-      }
-    }
-  }
-
-  if (getCurFunction())
-    getCurFunction()->addBlock(BD);
-
-  if (BD->isInvalidDecl())
-    return CreateRecoveryExpr(Result->getBeginLoc(), Result->getEndLoc(),
-                              {Result}, Result->getType());
-  return Result;
-}
-
 ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
                             SourceLocation RPLoc) {
   TypeSourceInfo *TInfo;
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 7ccecf055feed..2cf4cb6f46b72 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -21,6 +21,7 @@
 #include "clang/Edit/Commit.h"
 #include "clang/Edit/Rewriters.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Scope.h"
@@ -1893,7 +1894,7 @@ bool SemaObjC::CheckMessageArgumentTypes(
           Args[i]->getType()->isBlockPointerType() &&
           origParamType->isObjCObjectPointerType()) {
         ExprResult arg = Args[i];
-        SemaRef.maybeExtendBlockObject(arg);
+        maybeExtendBlockObject(arg);
         Args[i] = arg.get();
       }
     }
@@ -4923,7 +4924,7 @@ ExprResult SemaObjC::BuildIvarRefExpr(Scope *S, SourceLocation Loc,
   }
   if (getLangOpts().ObjCAutoRefCount && !SemaRef.isUnevaluatedContext())
     if (const BlockDecl *BD = SemaRef.CurContext->getInnermostBlockDecl())
-      SemaRef.ImplicitlyRetainedSelfLocs.push_back({Loc, BD});
+      ImplicitlyRetainedSelfLocs.push_back({Loc, BD});
 
   return Result;
 }
@@ -5197,7 +5198,7 @@ CastKind SemaObjC::PrepareCastToObjCObjectPointer(ExprResult &E) {
   if (type->isObjCObjectPointerType()) {
     return CK_BitCast;
   } else if (type->isBlockPointerType()) {
-    SemaRef.maybeExtendBlockObject(E);
+    maybeExtendBlockObject(E);
     return CK_BlockPointerToObjCPointerCast;
   } else {
     assert(type->isPointerType());
@@ -5246,3 +5247,372 @@ SemaObjC::ObjCLiteralKind SemaObjC::CheckLiteralKind(Expr *FromE) {
   }
   return LK_None;
 }
+
+void SemaObjC::maybeExtendBlockObject(ExprResult &E) {
+  assert(E.get()->getType()->isBlockPointerType());
+  assert(E.get()->isPRValue());
+
+  // Only do this in an r-value context.
+  if (!getLangOpts().ObjCAutoRefCount) return;
+
+  E = ImplicitCastExpr::Create(
+      getASTContext(), E.get()->getType(), CK_ARCExtendBlockObject, E.get(),
+      /*base path*/ nullptr, VK_PRValue, FPOptionsOverride());
+  SemaRef.Cleanup.setExprNeedsCleanups(true);
+}
+
+/// ActOnBlockStart - This callback is invoked when a block literal is started.
+void SemaObjC::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
+  ASTContext &Context = getASTContext();
+  BlockDecl *Block = BlockDecl::Create(Context, SemaRef.CurContext, CaretLoc);
+
+  if (getLangOpts().CPlusPlus) {
+    MangleNumberingContext *MCtx;
+    Decl *ManglingContextDecl;
+    std::tie(MCtx, ManglingContextDecl) =
+        SemaRef.getCurrentMangleNumberContext(Block->getDeclContext());
+    if (MCtx) {
+      unsigned ManglingNumber = MCtx->getManglingNumber(Block);
+      Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
+    }
+  }
+
+  PushBlockScope(CurScope, Block);
+  SemaRef.CurContext->addDecl(Block);
+  if (CurScope)
+    SemaRef.PushDeclContext(CurScope, Block);
+  else
+    SemaRef.CurContext = Block;
+
+  getCurBlock()->HasImplicitReturnType = true;
+
+  // Enter a new evaluation context to insulate the block from any
+  // cleanups from the enclosing full-expression.
+  SemaRef.PushExpressionEvaluationContext(
+      Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+}
+
+void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
+                               Scope *CurScope) {
+  assert(ParamInfo.getIdentifier() == nullptr &&
+         "block-id should have no identifier!");
+  assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteral);
+  ASTContext &Context = getASTContext();
+  BlockScopeInfo *CurBlock = getCurBlock();
+
+  TypeSourceInfo *Sig = SemaRef.GetTypeForDeclarator(ParamInfo);
+  QualType T = Sig->getType();
+
+  // FIXME: We should allow unexpanded parameter packs here, but that would,
+  // in turn, make the block expression contain unexpanded parameter packs.
+  if (SemaRef.DiagnoseUnexpandedParameterPack(CaretLoc, Sig, Sema::UPPC_Block)) {
+    // Drop the parameters.
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.HasTrailingReturn = false;
+    EPI.TypeQuals.addConst();
+    T = Context.getFunctionType(Context.DependentTy, std::nullopt, EPI);
+    Sig = Context.getTrivialTypeSourceInfo(T);
+  }
+
+  // GetTypeForDeclarator always produces a function type for a block
+  // literal signature.  Furthermore, it is always a FunctionProtoType
+  // unless the function was written with a typedef.
+  assert(T->isFunctionType() &&
+         "GetTypeForDeclarator made a non-function block signature");
+
+  // Look for an explicit signature in that function type.
+  FunctionProtoTypeLoc ExplicitSignature;
+
+  if ((ExplicitSignature = Sig->getTypeLoc()
+                               .getAsAdjusted<FunctionProtoTypeLoc>())) {
+
+    // Check whether that explicit signature was synthesized by
+    // GetTypeForDeclarator.  If so, don't save that as part of the
+    // written signature.
+    if (ExplicitSignature.getLocalRangeBegin() ==
+        ExplicitSignature.getLocalRangeEnd()) {
+      // This would be much cheaper if we stored TypeLocs instead of
+      // TypeSourceInfos.
+      TypeLoc Result = ExplicitSignature.getReturnLoc();
+      unsigned Size = Result.getFullDataSize();
+      Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
+      Sig->getTypeLoc().initializeFullCopy(Result, Size);
+
+      ExplicitSignature = FunctionProtoTypeLoc();
+    }
+  }
+
+  CurBlock->TheDecl->setSignatureAsWritten(Sig);
+  CurBlock->FunctionType = T;
+
+  const auto *Fn = T->castAs<FunctionType>();
+  QualType RetTy = Fn->getReturnType();
+  bool isVariadic =
+      (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
+
+  CurBlock->TheDecl->setIsVariadic(isVariadic);
+
+  // Context.DependentTy is used as a placeholder for a missing block
+  // return type.  TODO:  what should we do with declarators like:
+  //   ^ * { ... }
+  // If the answer is "apply template argument deduction"....
+  if (RetTy != Context.DependentTy) {
+    CurBlock->ReturnType = RetTy;
+    CurBlock->TheDecl->setBlockMissingReturnType(false);
+    CurBlock->HasImplicitReturnType = false;
+  }
+
+  // Push block parameters from the declarator if we had them.
+  SmallVector<ParmVarDecl*, 8> Params;
+  if (ExplicitSignature) {
+    for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
+      ParmVarDecl *Param = ExplicitSignature.getParam(I);
+      if (Param->getIdentifier() == nullptr && !Param->isImplicit() &&
+          !Param->isInvalidDecl() && !getLangOpts().CPlusPlus) {
+        // Diagnose this as an extension in C17 and earlier.
+        if (!getLangOpts().C23)
+          Diag(Param->getLocation(), diag::ext_parameter_name_omitted_c23);
+      }
+      Params.push_back(Param);
+    }
+
+  // Fake up parameter variables if we have a typedef, like
+  //   ^ fntype { ... }
+  } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
+    for (const auto &I : Fn->param_types()) {
+      ParmVarDecl *Param = SemaRef.BuildParmVarDeclForTypedef(
+          CurBlock->TheDecl, ParamInfo.getBeginLoc(), I);
+      Params.push_back(Param);
+    }
+  }
+
+  // Set the parameters on the block decl.
+  if (!Params.empty()) {
+    CurBlock->TheDecl->setParams(Params);
+    SemaRef.CheckParmsForFunctionDef(CurBlock->TheDecl->parameters(),
+                             /*CheckParameterNames=*/false);
+  }
+
+  // Finally we can process decl attributes.
+  SemaRef.ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+
+  // Put the parameter variables in scope.
+  for (auto *AI : CurBlock->TheDecl->parameters()) {
+    AI->setOwningFunction(CurBlock->TheDecl);
+
+    // If this has an identifier, add it to the scope stack.
+    if (AI->getIdentifier()) {
+      SemaRef.CheckShadow(CurBlock->TheScope, AI);
+
+      SemaRef.PushOnScopeChains(AI, CurBlock->TheScope);
+    }
+
+    if (AI->isInvalidDecl())
+      CurBlock->TheDecl->setInvalidDecl();
+  }
+}
+
+/// ActOnBlockError - If there is an error parsing a block, this callback
+/// is invoked to pop the information about the block from the action impl.
+void SemaObjC::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
+  // Leave the expression-evaluation context.
+  SemaRef.DiscardCleanupsInEvaluationContext();
+  SemaRef.PopExpressionEvaluationContext();
+
+  // Pop off CurBlock, handle nested blocks.
+  SemaRef.PopDeclContext();
+  SemaRef.PopFunctionScopeInfo();
+}
+
+/// ActOnBlockStmtExpr - This is called when the body of a block statement
+/// literal was successfully completed.  ^(int x){...}
+ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
+                                    Stmt *Body, Scope *CurScope) {
+  // If blocks are disabled, emit an error.
+  if (!getLangOpts().Blocks)
+    Diag(CaretLoc, diag::err_blocks_disable) << getLangOpts().OpenCL;
+
+  ASTContext &Context = getASTContext();
+
+  // Leave the expression-evaluation context.
+  if (SemaRef.hasAnyUnrecoverableErrorsInThisFunction())
+    SemaRef.DiscardCleanupsInEvaluationContext();
+  assert(!SemaRef.Cleanup.exprNeedsCleanups() &&
+         "cleanups within block not correctly bound!");
+  SemaRef.PopExpressionEvaluationContext();
+
+  BlockScopeInfo *BSI = cast<BlockScopeInfo>(SemaRef.FunctionScopes.back());
+  BlockDecl *BD = BSI->TheDecl;
+
+  if (BSI->HasImplicitReturnType)
+    SemaRef.deduceClosureReturnType(*BSI);
+
+  QualType RetTy = Context.VoidTy;
+  if (!BSI->ReturnType.isNull())
+    RetTy = BSI->ReturnType;
+
+  bool NoReturn = BD->hasAttr<NoReturnAttr>();
+  QualType BlockTy;
+
+  // If the user wrote a function type in some form, try to use that.
+  if (!BSI->FunctionType.isNull()) {
+    const FunctionType *FTy = BSI->FunctionType->castAs<FunctionType>();
+
+    FunctionType::ExtInfo Ext = FTy->getExtInfo();
+    if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
+
+    // Turn protoless block types into nullary block types.
+    if (isa<FunctionNoProtoType>(FTy)) {
+      FunctionProtoType::ExtProtoInfo EPI;
+      EPI.ExtInfo = Ext;
+      BlockTy = Context.getFunctionType(RetTy, std::nullopt, EPI);
+
+      // Otherwise, if we don't need to change anything about the function type,
+      // preserve its sugar structure.
+    } else if (FTy->getReturnType() == RetTy &&
+               (!NoReturn || FTy->getNoReturnAttr())) {
+      BlockTy = BSI->FunctionType;
+
+    // Otherwise, make the minimal modifications to the function type.
+    } else {
+      const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
+      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+      EPI.TypeQuals = Qualifiers();
+      EPI.ExtInfo = Ext;
+      BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
+    }
+
+  // If we don't have a function type, just build one from nothing.
+  } else {
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
+    BlockTy = Context.getFunctionType(RetTy, std::nullopt, EPI);
+  }
+
+  SemaRef.DiagnoseUnusedParameters(BD->parameters());
+  BlockTy = Context.getBlockPointerType(BlockTy);
+
+  // If needed, diagnose invalid gotos and switches in the block.
+  if (SemaRef.getCurFunction()->NeedsScopeChecking() &&
+      !SemaRef.PP.isCodeCompletionEnabled())
+    SemaRef.DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
+
+  BD->setBody(cast<CompoundStmt>(Body));
+
+  if (Body && SemaRef.getCurFunction()->HasPotentialAvailabilityViolations)
+    SemaRef.DiagnoseUnguardedAvailabilityViolations(BD);
+
+  // Try to apply the named return value optimization. We have to check again
+  // if we can do this, though, because blocks keep return statements around
+  // to deduce an implicit return type.
+  if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
+      !BD->isDependentContext())
+    SemaRef.computeNRVO(Body, BSI);
+
+  if (RetTy.hasNonTrivialToPrimitiveDestructCUnion() ||
+      RetTy.hasNonTrivialToPrimitiveCopyCUnion())
+    SemaRef.checkNonTrivialCUnion(RetTy, BD->getCaretLocation(), Sema::NTCUC_FunctionReturn,
+                          Sema::NTCUK_Destruct|Sema::NTCUK_Copy);
+
+  SemaRef.PopDeclContext();
+
+  // Set the captured variables on the block.
+  SmallVector<BlockDecl::Capture, 4> Captures;
+  for (Capture &Cap : BSI->Captures) {
+    if (Cap.isInvalid() || Cap.isThisCapture())
+      continue;
+    // Cap.getVariable() is always a VarDecl because
+    // blocks cannot capture structured bindings or other ValueDecl kinds.
+    auto *Var = cast<VarDecl>(Cap.getVariable());
+    Expr *CopyExpr = nullptr;
+    if (getLangOpts().CPlusPlus && Cap.isCopyCapture()) {
+      if (const RecordType *Record =
+              Cap.getCaptureType()->getAs<RecordType>()) {
+        // The capture logic needs the destructor, so make sure we mark it.
+        // Usually this is unnecessary because most local variables have
+        // their destructors marked at declaration time, but parameters are
+        // an exception because it's technically only the call site that
+        // actually requires the destructor.
+        if (isa<ParmVarDecl>(Var))
+          SemaRef.FinalizeVarWithDestructor(Var, Record);
+
+        // Enter a separate potentially-evaluated context while building block
+        // initializers to isolate their cleanups from those of the block
+        // itself.
+        // FIXME: Is this appropriate even when the block itself occurs in an
+        // unevaluated operand?
+        EnterExpressionEvaluationContext EvalContext(
+            SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+
+        SourceLocation Loc = Cap.getLocation();
+
+        ExprResult Result = SemaRef.BuildDeclarationNameExpr(
+            CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
+
+        // According to the blocks spec, the capture of a variable from
+        // the stack requires a const copy constructor.  This is not true
+        // of the copy/move done to move a __block variable to the heap.
+        if (!Result.isInvalid() &&
+            !Result.get()->getType().isConstQualified()) {
+          Result = SemaRef.ImpCastExprToType(Result.get(),
+                                     Result.get()->getType().withConst(),
+                                     CK_NoOp, VK_LValue);
+        }
+
+        if (!Result.isInvalid()) {
+          Result = SemaRef.PerformCopyInitialization(
+              InitializedEntity::InitializeBlock(Var->getLocation(),
+                                                 Cap.getCaptureType()),
+              Loc, Result.get());
+        }
+
+        // Build a full-expression copy expression if initialization
+        // succeeded and used a non-trivial constructor.  Recover from
+        // errors by pretending that the copy isn't necessary.
+        if (!Result.isInvalid() &&
+            !cast<CXXConstructExpr>(Result.get())->getConstructor()
+                ->isTrivial()) {
+          Result = SemaRef.MaybeCreateExprWithCleanups(Result);
+          CopyExpr = Result.get();
+        }
+      }
+    }
+
+    BlockDecl::Capture NewCap(Var, Cap.isBlockCapture(), Cap.isNested(),
+                              CopyExpr);
+    Captures.push_back(NewCap);
+  }
+  BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
+
+  // Pop the block scope now but keep it alive to the end of this function.
+  AnalysisBasedWarnings::Policy WP = SemaRef.AnalysisWarnings.getDefaultPolicy();
+  Sema::PoppedFunctionScopePtr ScopeRAII = SemaRef.PopFunctionScopeInfo(&WP, BD, BlockTy);
+
+  BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy);
+
+  // If the block isn't obviously global, i.e. it captures anything at
+  // all, then we need to do a few things in the surrounding context:
+  if (Result->getBlockDecl()->hasCaptures()) {
+    // First, this expression has a new cleanup object.
+    SemaRef.ExprCleanupObjects.push_back(Result->getBlockDecl());
+    SemaRef.Cleanup.setExprNeedsCleanups(true);
+
+    // It also gets a branch-protected scope if any of the captured
+    // variables needs destruction.
+    for (const auto &CI : Result->getBlockDecl()->captures()) {
+      const VarDecl *var = CI.getVariable();
+      if (var->getType().isDestructedType() != QualType::DK_none) {
+        SemaRef.setFunctionHasBranchProtectedScope();
+        break;
+      }
+    }
+  }
+
+  if (SemaRef.getCurFunction())
+    SemaRef.getCurFunction()->addBlock(BD);
+
+  if (BD->isInvalidDecl())
+    return SemaRef.CreateRecoveryExpr(Result->getBeginLoc(), Result->getEndLoc(),
+                              {Result}, Result->getType());
+  return Result;
+}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 9a3fabc5933ee..14ad80f448924 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaRISCV.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/Sema/TypoCorrection.h"
@@ -5191,7 +5192,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
   }
 
   if (CCC.WantRemainingKeywords) {
-    if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
+    if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.ObjC().getCurBlock()) {
       // Statements.
       static const char *const CStmts[] = {
         "do", "else", "for", "goto", "if", "return", "switch", "while" };
diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp
index 75233689769c5..4804a4e45aeff 100644
--- a/clang/lib/Sema/SemaObjC.cpp
+++ b/clang/lib/Sema/SemaObjC.cpp
@@ -1737,17 +1737,17 @@ static bool isValidSubjectOfOSAttribute(QualType QT) {
 }
 
 void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                                Sema::RetainOwnershipKind K,
+                                RetainOwnershipKind K,
                                 bool IsTemplateInstantiation) {
   ValueDecl *VD = cast<ValueDecl>(D);
   switch (K) {
-  case Sema::RetainOwnershipKind::OS:
+  case RetainOwnershipKind::OS:
     handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
         *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()),
         diag::warn_ns_attribute_wrong_parameter_type,
         /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1);
     return;
-  case Sema::RetainOwnershipKind::NS:
+  case RetainOwnershipKind::NS:
     handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
         *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()),
 
@@ -1760,7 +1760,7 @@ void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
              : diag::warn_ns_attribute_wrong_parameter_type),
         /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0);
     return;
-  case Sema::RetainOwnershipKind::CF:
+  case RetainOwnershipKind::CF:
     handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
         *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()),
         diag::warn_ns_attribute_wrong_parameter_type,
@@ -1769,26 +1769,26 @@ void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
   }
 }
 
-Sema::RetainOwnershipKind
+SemaObjC::RetainOwnershipKind
 SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
   switch (AL.getKind()) {
   case ParsedAttr::AT_CFConsumed:
   case ParsedAttr::AT_CFReturnsRetained:
   case ParsedAttr::AT_CFReturnsNotRetained:
-    return Sema::RetainOwnershipKind::CF;
+    return RetainOwnershipKind::CF;
   case ParsedAttr::AT_OSConsumesThis:
   case ParsedAttr::AT_OSConsumed:
   case ParsedAttr::AT_OSReturnsRetained:
   case ParsedAttr::AT_OSReturnsNotRetained:
   case ParsedAttr::AT_OSReturnsRetainedOnZero:
   case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
-    return Sema::RetainOwnershipKind::OS;
+    return RetainOwnershipKind::OS;
   case ParsedAttr::AT_NSConsumesSelf:
   case ParsedAttr::AT_NSConsumed:
   case ParsedAttr::AT_NSReturnsRetained:
   case ParsedAttr::AT_NSReturnsNotRetained:
   case ParsedAttr::AT_NSReturnsAutoreleased:
-    return Sema::RetainOwnershipKind::NS;
+    return RetainOwnershipKind::NS;
   default:
     llvm_unreachable("Wrong argument supplied");
   }
@@ -1816,7 +1816,7 @@ bool SemaObjC::isValidOSObjectOutParameter(const Decl *D) {
 
 void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) {
   QualType ReturnType;
-  Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
+  RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
 
   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
     ReturnType = MD->getReturnType();
@@ -1830,7 +1830,7 @@ void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) {
   } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
     // Attributes on parameters are used for out-parameters,
     // passed as pointers-to-pointers.
-    unsigned DiagID = K == Sema::RetainOwnershipKind::CF
+    unsigned DiagID = K == RetainOwnershipKind::CF
                           ? /*pointer-to-CF-pointer*/ 2
                           : /*pointer-to-OSObject-pointer*/ 3;
     ReturnType = Param->getType()->getPointeeType();
@@ -2405,4 +2405,172 @@ void SemaObjC::checkDictionaryLiteral(
   }
 }
 
+sema::BlockScopeInfo *SemaObjC::getCurBlock() {
+  if (SemaRef.FunctionScopes.empty())
+    return nullptr;
+
+  auto CurBSI = dyn_cast<sema::BlockScopeInfo>(SemaRef.FunctionScopes.back());
+  if (CurBSI && CurBSI->TheDecl &&
+      !CurBSI->TheDecl->Encloses(SemaRef.CurContext)) {
+    // We have switched contexts due to template instantiation.
+    assert(!SemaRef.CodeSynthesisContexts.empty());
+    return nullptr;
+  }
+
+  return CurBSI;
+}
+
+static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
+                                     Expr *RHS, bool isProperty) {
+  // Check if RHS is an Objective-C object literal, which also can get
+  // immediately zapped in a weak reference.  Note that we explicitly
+  // allow ObjCStringLiterals, since those are designed to never really die.
+  RHS = RHS->IgnoreParenImpCasts();
+
+  // This enum needs to match with the 'select' in
+  // warn_objc_arc_literal_assign (off-by-1).
+  SemaObjC::ObjCLiteralKind Kind = S.ObjC().CheckLiteralKind(RHS);
+  if (Kind == SemaObjC::LK_String || Kind == SemaObjC::LK_None)
+    return false;
+
+  S.Diag(Loc, diag::warn_arc_literal_assign)
+    << (unsigned) Kind
+    << (isProperty ? 0 : 1)
+    << RHS->getSourceRange();
+
+  return true;
+}
+
+static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
+                                    Qualifiers::ObjCLifetime LT,
+                                    Expr *RHS, bool isProperty) {
+  // Strip off any implicit cast added to get to the one ARC-specific.
+  while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
+    if (cast->getCastKind() == CK_ARCConsumeObject) {
+      S.Diag(Loc, diag::warn_arc_retained_assign)
+        << (LT == Qualifiers::OCL_ExplicitNone)
+        << (isProperty ? 0 : 1)
+        << RHS->getSourceRange();
+      return true;
+    }
+    RHS = cast->getSubExpr();
+  }
+
+  if (LT == Qualifiers::OCL_Weak &&
+      checkUnsafeAssignLiteral(S, Loc, RHS, isProperty))
+    return true;
+
+  return false;
+}
+
+bool SemaObjC::checkUnsafeAssigns(SourceLocation Loc,
+                              QualType LHS, Expr *RHS) {
+  Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
+
+  if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
+    return false;
+
+  if (checkUnsafeAssignObject(SemaRef, Loc, LT, RHS, false))
+    return true;
+
+  return false;
+}
+
+void SemaObjC::checkUnsafeExprAssigns(SourceLocation Loc,
+                              Expr *LHS, Expr *RHS) {
+  QualType LHSType;
+  // PropertyRef on LHS type need be directly obtained from
+  // its declaration as it has a PseudoType.
+  ObjCPropertyRefExpr *PRE
+    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
+  if (PRE && !PRE->isImplicitProperty()) {
+    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
+    if (PD)
+      LHSType = PD->getType();
+  }
+
+  if (LHSType.isNull())
+    LHSType = LHS->getType();
+
+  Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
+
+  if (LT == Qualifiers::OCL_Weak) {
+    if (!getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
+      SemaRef.getCurFunction()->markSafeWeakUse(LHS);
+  }
+
+  if (checkUnsafeAssigns(Loc, LHSType, RHS))
+    return;
+
+  // FIXME. Check for other life times.
+  if (LT != Qualifiers::OCL_None)
+    return;
+
+  if (PRE) {
+    if (PRE->isImplicitProperty())
+      return;
+    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
+    if (!PD)
+      return;
+
+    unsigned Attributes = PD->getPropertyAttributes();
+    if (Attributes & ObjCPropertyAttribute::kind_assign) {
+      // when 'assign' attribute was not explicitly specified
+      // by user, ignore it and rely on property type itself
+      // for lifetime info.
+      unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten();
+      if (!(AsWrittenAttr & ObjCPropertyAttribute::kind_assign) &&
+          LHSType->isObjCRetainableType())
+        return;
+
+      while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
+        if (cast->getCastKind() == CK_ARCConsumeObject) {
+          Diag(Loc, diag::warn_arc_retained_property_assign)
+          << RHS->getSourceRange();
+          return;
+        }
+        RHS = cast->getSubExpr();
+      }
+    } else if (Attributes & ObjCPropertyAttribute::kind_weak) {
+      if (checkUnsafeAssignObject(SemaRef, Loc, Qualifiers::OCL_Weak, RHS, true))
+        return;
+    }
+  }
+}
+
+void SemaObjC::diagnoseImplicitlyRetainedSelf() {
+  llvm::DenseMap<const BlockDecl *, bool> EscapeInfo;
+
+  auto IsOrNestedInEscapingBlock = [&](const BlockDecl *BD) {
+    if (EscapeInfo.count(BD))
+      return EscapeInfo[BD];
+
+    bool R = false;
+    const BlockDecl *CurBD = BD;
+
+    do {
+      R = !CurBD->doesNotEscape();
+      if (R)
+        break;
+      CurBD = CurBD->getParent()->getInnermostBlockDecl();
+    } while (CurBD);
+
+    return EscapeInfo[BD] = R;
+  };
+
+  // If the location where 'self' is implicitly retained is inside a escaping
+  // block, emit a diagnostic.
+  for (const std::pair<SourceLocation, const BlockDecl *> &P :
+       ImplicitlyRetainedSelfLocs)
+    if (IsOrNestedInEscapingBlock(P.second))
+      Diag(P.first, diag::warn_implicitly_retains_self)
+          << FixItHint::CreateInsertion(P.first, "self->");
+}
+
+void SemaObjC::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
+  SemaRef.FunctionScopes.push_back(new sema::BlockScopeInfo(getDiagnostics(),
+                                              BlockScope, Block));
+  SemaRef.CapturingFunctionScopes++;
+}
+
 } // namespace clang
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 3e6c6c94a47cd..0b50f5a10b582 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -2372,7 +2372,7 @@ VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
   // 'target' we return true so that this global is also mapped to the device.
   //
   if (VD && !VD->hasLocalStorage() &&
-      (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
+      (SemaRef.getCurCapturedRegion() || SemaRef.ObjC().getCurBlock() ||
        SemaRef.getCurLambda())) {
     if (isInOpenMPTargetExecutionDirective()) {
       DSAStackTy::DSAVarData DVarTop =
@@ -22986,7 +22986,7 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
       OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
   if (SemaRef.LangOpts.OpenMP >= 50 &&
       (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
-       SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
+       SemaRef.ObjC().getCurBlock() || SemaRef.getCurCapturedRegion()) &&
       VD->hasGlobalStorage()) {
     if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
                    *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index fdb584ceb8105..fe39ec6bfa631 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -928,7 +928,7 @@ ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
   // Various warnings about property assignments in ARC.
   if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
     S.ObjC().checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
-    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
+    S.ObjC().checkUnsafeExprAssigns(opcLoc, LHS, RHS);
   }
 
   return result;
@@ -1017,7 +1017,7 @@ ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
   // Various warnings about objc Index'ed assignments in ARC.
   if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
     S.ObjC().checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
-    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
+    S.ObjC().checkUnsafeExprAssigns(opcLoc, LHS, RHS);
   }
 
   return result;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 0681520764d9a..36ccc744a7484 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -725,15 +725,15 @@ void Sema::InstantiateAttrsForDecl(
   }
 }
 
-static Sema::RetainOwnershipKind
+static SemaObjC::RetainOwnershipKind
 attrToRetainOwnershipKind(const Attr *A) {
   switch (A->getKind()) {
   case clang::attr::CFConsumed:
-    return Sema::RetainOwnershipKind::CF;
+    return SemaObjC::RetainOwnershipKind::CF;
   case clang::attr::OSConsumed:
-    return Sema::RetainOwnershipKind::OS;
+    return SemaObjC::RetainOwnershipKind::OS;
   case clang::attr::NSConsumed:
-    return Sema::RetainOwnershipKind::NS;
+    return SemaObjC::RetainOwnershipKind::NS;
   default:
     llvm_unreachable("Wrong argument supplied");
   }
@@ -1238,7 +1238,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
     if (auto *F = dyn_cast<FunctionDecl>(DC))
       RT = F->getReturnType();
     else if (isa<BlockDecl>(DC))
-      RT = cast<FunctionType>(SemaRef.getCurBlock()->FunctionType)
+      RT = cast<FunctionType>(SemaRef.ObjC().getCurBlock()->FunctionType)
                ->getReturnType();
     else
       llvm_unreachable("Unknown context type");
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 51ba22f99e3a3..7c57ebce5bbe2 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -15817,8 +15817,8 @@ ExprResult
 TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
   BlockDecl *oldBlock = E->getBlockDecl();
 
-  SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/nullptr);
-  BlockScopeInfo *blockScope = SemaRef.getCurBlock();
+  SemaRef.ObjC().ActOnBlockStart(E->getCaretLocation(), /*Scope=*/nullptr);
+  BlockScopeInfo *blockScope = SemaRef.ObjC().getCurBlock();
 
   blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
   blockScope->TheDecl->setBlockMissingReturnType(
@@ -15835,7 +15835,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
           E->getCaretLocation(), oldBlock->parameters(), nullptr,
           exprFunctionType->getExtParameterInfosOrNull(), paramTypes, &params,
           extParamInfos)) {
-    getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
+    getSema().ObjC().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
     return ExprError();
   }
 
@@ -15861,7 +15861,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
   // Transform the body
   StmtResult body = getDerived().TransformStmt(E->getBody());
   if (body.isInvalid()) {
-    getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
+    getSema().ObjC().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr);
     return ExprError();
   }
 
@@ -15890,7 +15890,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
   }
 #endif
 
-  return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
+  return SemaRef.ObjC().ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
                                     /*Scope=*/nullptr);
 }
 

>From 0eb68971e27555d1ebc7784ade3a8350d54d6eb9 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 29 Jun 2024 21:15:28 +0300
Subject: [PATCH 2/2] Run clang-format

---
 clang/include/clang/Sema/SemaObjC.h           |  6 +-
 clang/lib/Parse/ParseExpr.cpp                 |  3 +-
 clang/lib/Sema/SemaCodeComplete.cpp           |  3 +-
 clang/lib/Sema/SemaExprObjC.cpp               | 61 +++++++++++--------
 clang/lib/Sema/SemaObjC.cpp                   | 36 +++++------
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  3 +-
 clang/lib/Sema/TreeTransform.h                |  2 +-
 7 files changed, 58 insertions(+), 56 deletions(-)

diff --git a/clang/include/clang/Sema/SemaObjC.h b/clang/include/clang/Sema/SemaObjC.h
index 2ea0cc303d56a..c962d48799ec5 100644
--- a/clang/include/clang/Sema/SemaObjC.h
+++ b/clang/include/clang/Sema/SemaObjC.h
@@ -1110,15 +1110,13 @@ class SemaObjC : public SemaBase {
   void handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL);
 
   void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        RetainOwnershipKind K,
-                        bool IsTemplateInstantiation);
+                        RetainOwnershipKind K, bool IsTemplateInstantiation);
 
   /// \return whether the parameter is a pointer to OSObject pointer.
   bool isValidOSObjectOutParameter(const Decl *D);
   bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
 
-  RetainOwnershipKind
-  parsedAttrToRetainOwnershipKind(const ParsedAttr &AL);
+  RetainOwnershipKind parsedAttrToRetainOwnershipKind(const ParsedAttr &AL);
 
   ///@}
 };
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 166b74c0ce9e5..ab744c68872d3 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -3838,7 +3838,8 @@ ExprResult Parser::ParseBlockLiteralExpression() {
   StmtResult Stmt(ParseCompoundStatementBody());
   BlockScope.Exit();
   if (!Stmt.isInvalid())
-    Result = Actions.ObjC().ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());
+    Result =
+        Actions.ObjC().ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());
   else
     Actions.ObjC().ActOnBlockError(CaretLoc, getCurScope());
   return Result;
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index bb010cb07cc6d..0801cedf675fe 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -2475,7 +2475,8 @@ AddOrdinaryNameResults(SemaCodeCompletion::ParserCompletionContext CCC,
       ReturnType = Method->getReturnType();
     else if (SemaRef.ObjC().getCurBlock() &&
              !SemaRef.ObjC().getCurBlock()->ReturnType.isNull())
-      ReturnType = SemaRef.ObjC().getCurBlock()->ReturnType;;
+      ReturnType = SemaRef.ObjC().getCurBlock()->ReturnType;
+    ;
     if (ReturnType.isNull() || ReturnType->isVoidType()) {
       Builder.AddTypedTextChunk("return");
       Builder.AddChunk(CodeCompletionString::CK_SemiColon);
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 2cf4cb6f46b72..b7aa09b78cc4a 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -5253,7 +5253,8 @@ void SemaObjC::maybeExtendBlockObject(ExprResult &E) {
   assert(E.get()->isPRValue());
 
   // Only do this in an r-value context.
-  if (!getLangOpts().ObjCAutoRefCount) return;
+  if (!getLangOpts().ObjCAutoRefCount)
+    return;
 
   E = ImplicitCastExpr::Create(
       getASTContext(), E.get()->getType(), CK_ARCExtendBlockObject, E.get(),
@@ -5292,8 +5293,8 @@ void SemaObjC::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
 }
 
-void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
-                               Scope *CurScope) {
+void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc,
+                                   Declarator &ParamInfo, Scope *CurScope) {
   assert(ParamInfo.getIdentifier() == nullptr &&
          "block-id should have no identifier!");
   assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteral);
@@ -5305,7 +5306,8 @@ void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInf
 
   // FIXME: We should allow unexpanded parameter packs here, but that would,
   // in turn, make the block expression contain unexpanded parameter packs.
-  if (SemaRef.DiagnoseUnexpandedParameterPack(CaretLoc, Sig, Sema::UPPC_Block)) {
+  if (SemaRef.DiagnoseUnexpandedParameterPack(CaretLoc, Sig,
+                                              Sema::UPPC_Block)) {
     // Drop the parameters.
     FunctionProtoType::ExtProtoInfo EPI;
     EPI.HasTrailingReturn = false;
@@ -5323,8 +5325,8 @@ void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInf
   // Look for an explicit signature in that function type.
   FunctionProtoTypeLoc ExplicitSignature;
 
-  if ((ExplicitSignature = Sig->getTypeLoc()
-                               .getAsAdjusted<FunctionProtoTypeLoc>())) {
+  if ((ExplicitSignature =
+           Sig->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>())) {
 
     // Check whether that explicit signature was synthesized by
     // GetTypeForDeclarator.  If so, don't save that as part of the
@@ -5363,7 +5365,7 @@ void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInf
   }
 
   // Push block parameters from the declarator if we had them.
-  SmallVector<ParmVarDecl*, 8> Params;
+  SmallVector<ParmVarDecl *, 8> Params;
   if (ExplicitSignature) {
     for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
       ParmVarDecl *Param = ExplicitSignature.getParam(I);
@@ -5376,8 +5378,8 @@ void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInf
       Params.push_back(Param);
     }
 
-  // Fake up parameter variables if we have a typedef, like
-  //   ^ fntype { ... }
+    // Fake up parameter variables if we have a typedef, like
+    //   ^ fntype { ... }
   } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
     for (const auto &I : Fn->param_types()) {
       ParmVarDecl *Param = SemaRef.BuildParmVarDeclForTypedef(
@@ -5390,7 +5392,7 @@ void SemaObjC::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInf
   if (!Params.empty()) {
     CurBlock->TheDecl->setParams(Params);
     SemaRef.CheckParmsForFunctionDef(CurBlock->TheDecl->parameters(),
-                             /*CheckParameterNames=*/false);
+                                     /*CheckParameterNames=*/false);
   }
 
   // Finally we can process decl attributes.
@@ -5426,8 +5428,8 @@ void SemaObjC::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
 
 /// ActOnBlockStmtExpr - This is called when the body of a block statement
 /// literal was successfully completed.  ^(int x){...}
-ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
-                                    Stmt *Body, Scope *CurScope) {
+ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
+                                        Scope *CurScope) {
   // If blocks are disabled, emit an error.
   if (!getLangOpts().Blocks)
     Diag(CaretLoc, diag::err_blocks_disable) << getLangOpts().OpenCL;
@@ -5459,7 +5461,8 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
     const FunctionType *FTy = BSI->FunctionType->castAs<FunctionType>();
 
     FunctionType::ExtInfo Ext = FTy->getExtInfo();
-    if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
+    if (NoReturn && !Ext.getNoReturn())
+      Ext = Ext.withNoReturn(true);
 
     // Turn protoless block types into nullary block types.
     if (isa<FunctionNoProtoType>(FTy)) {
@@ -5473,7 +5476,7 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
                (!NoReturn || FTy->getNoReturnAttr())) {
       BlockTy = BSI->FunctionType;
 
-    // Otherwise, make the minimal modifications to the function type.
+      // Otherwise, make the minimal modifications to the function type.
     } else {
       const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
       FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
@@ -5482,7 +5485,7 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
       BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
     }
 
-  // If we don't have a function type, just build one from nothing.
+    // If we don't have a function type, just build one from nothing.
   } else {
     FunctionProtoType::ExtProtoInfo EPI;
     EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
@@ -5511,8 +5514,9 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
 
   if (RetTy.hasNonTrivialToPrimitiveDestructCUnion() ||
       RetTy.hasNonTrivialToPrimitiveCopyCUnion())
-    SemaRef.checkNonTrivialCUnion(RetTy, BD->getCaretLocation(), Sema::NTCUC_FunctionReturn,
-                          Sema::NTCUK_Destruct|Sema::NTCUK_Copy);
+    SemaRef.checkNonTrivialCUnion(RetTy, BD->getCaretLocation(),
+                                  Sema::NTCUC_FunctionReturn,
+                                  Sema::NTCUK_Destruct | Sema::NTCUK_Copy);
 
   SemaRef.PopDeclContext();
 
@@ -5554,9 +5558,9 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
         // of the copy/move done to move a __block variable to the heap.
         if (!Result.isInvalid() &&
             !Result.get()->getType().isConstQualified()) {
-          Result = SemaRef.ImpCastExprToType(Result.get(),
-                                     Result.get()->getType().withConst(),
-                                     CK_NoOp, VK_LValue);
+          Result = SemaRef.ImpCastExprToType(
+              Result.get(), Result.get()->getType().withConst(), CK_NoOp,
+              VK_LValue);
         }
 
         if (!Result.isInvalid()) {
@@ -5569,9 +5573,9 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
         // Build a full-expression copy expression if initialization
         // succeeded and used a non-trivial constructor.  Recover from
         // errors by pretending that the copy isn't necessary.
-        if (!Result.isInvalid() &&
-            !cast<CXXConstructExpr>(Result.get())->getConstructor()
-                ->isTrivial()) {
+        if (!Result.isInvalid() && !cast<CXXConstructExpr>(Result.get())
+                                        ->getConstructor()
+                                        ->isTrivial()) {
           Result = SemaRef.MaybeCreateExprWithCleanups(Result);
           CopyExpr = Result.get();
         }
@@ -5585,8 +5589,10 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
   BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
 
   // Pop the block scope now but keep it alive to the end of this function.
-  AnalysisBasedWarnings::Policy WP = SemaRef.AnalysisWarnings.getDefaultPolicy();
-  Sema::PoppedFunctionScopePtr ScopeRAII = SemaRef.PopFunctionScopeInfo(&WP, BD, BlockTy);
+  AnalysisBasedWarnings::Policy WP =
+      SemaRef.AnalysisWarnings.getDefaultPolicy();
+  Sema::PoppedFunctionScopePtr ScopeRAII =
+      SemaRef.PopFunctionScopeInfo(&WP, BD, BlockTy);
 
   BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy);
 
@@ -5612,7 +5618,8 @@ ExprResult SemaObjC::ActOnBlockStmtExpr(SourceLocation CaretLoc,
     SemaRef.getCurFunction()->addBlock(BD);
 
   if (BD->isInvalidDecl())
-    return SemaRef.CreateRecoveryExpr(Result->getBeginLoc(), Result->getEndLoc(),
-                              {Result}, Result->getType());
+    return SemaRef.CreateRecoveryExpr(Result->getBeginLoc(),
+                                      Result->getEndLoc(), {Result},
+                                      Result->getType());
   return Result;
 }
diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp
index 4804a4e45aeff..6cfea25c53855 100644
--- a/clang/lib/Sema/SemaObjC.cpp
+++ b/clang/lib/Sema/SemaObjC.cpp
@@ -2420,8 +2420,8 @@ sema::BlockScopeInfo *SemaObjC::getCurBlock() {
   return CurBSI;
 }
 
-static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
-                                     Expr *RHS, bool isProperty) {
+static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc, Expr *RHS,
+                                     bool isProperty) {
   // Check if RHS is an Objective-C object literal, which also can get
   // immediately zapped in a weak reference.  Note that we explicitly
   // allow ObjCStringLiterals, since those are designed to never really die.
@@ -2434,23 +2434,20 @@ static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
     return false;
 
   S.Diag(Loc, diag::warn_arc_literal_assign)
-    << (unsigned) Kind
-    << (isProperty ? 0 : 1)
-    << RHS->getSourceRange();
+      << (unsigned)Kind << (isProperty ? 0 : 1) << RHS->getSourceRange();
 
   return true;
 }
 
 static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
-                                    Qualifiers::ObjCLifetime LT,
-                                    Expr *RHS, bool isProperty) {
+                                    Qualifiers::ObjCLifetime LT, Expr *RHS,
+                                    bool isProperty) {
   // Strip off any implicit cast added to get to the one ARC-specific.
   while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
     if (cast->getCastKind() == CK_ARCConsumeObject) {
       S.Diag(Loc, diag::warn_arc_retained_assign)
-        << (LT == Qualifiers::OCL_ExplicitNone)
-        << (isProperty ? 0 : 1)
-        << RHS->getSourceRange();
+          << (LT == Qualifiers::OCL_ExplicitNone) << (isProperty ? 0 : 1)
+          << RHS->getSourceRange();
       return true;
     }
     RHS = cast->getSubExpr();
@@ -2463,8 +2460,7 @@ static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
   return false;
 }
 
-bool SemaObjC::checkUnsafeAssigns(SourceLocation Loc,
-                              QualType LHS, Expr *RHS) {
+bool SemaObjC::checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS) {
   Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
 
   if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
@@ -2476,13 +2472,12 @@ bool SemaObjC::checkUnsafeAssigns(SourceLocation Loc,
   return false;
 }
 
-void SemaObjC::checkUnsafeExprAssigns(SourceLocation Loc,
-                              Expr *LHS, Expr *RHS) {
+void SemaObjC::checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS,
+                                      Expr *RHS) {
   QualType LHSType;
   // PropertyRef on LHS type need be directly obtained from
   // its declaration as it has a PseudoType.
-  ObjCPropertyRefExpr *PRE
-    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
+  ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
   if (PRE && !PRE->isImplicitProperty()) {
     const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
     if (PD)
@@ -2526,13 +2521,14 @@ void SemaObjC::checkUnsafeExprAssigns(SourceLocation Loc,
       while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
         if (cast->getCastKind() == CK_ARCConsumeObject) {
           Diag(Loc, diag::warn_arc_retained_property_assign)
-          << RHS->getSourceRange();
+              << RHS->getSourceRange();
           return;
         }
         RHS = cast->getSubExpr();
       }
     } else if (Attributes & ObjCPropertyAttribute::kind_weak) {
-      if (checkUnsafeAssignObject(SemaRef, Loc, Qualifiers::OCL_Weak, RHS, true))
+      if (checkUnsafeAssignObject(SemaRef, Loc, Qualifiers::OCL_Weak, RHS,
+                                  true))
         return;
     }
   }
@@ -2568,8 +2564,8 @@ void SemaObjC::diagnoseImplicitlyRetainedSelf() {
 }
 
 void SemaObjC::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
-  SemaRef.FunctionScopes.push_back(new sema::BlockScopeInfo(getDiagnostics(),
-                                              BlockScope, Block));
+  SemaRef.FunctionScopes.push_back(
+      new sema::BlockScopeInfo(getDiagnostics(), BlockScope, Block));
   SemaRef.CapturingFunctionScopes++;
 }
 
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 36ccc744a7484..2b6622562c222 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -725,8 +725,7 @@ void Sema::InstantiateAttrsForDecl(
   }
 }
 
-static SemaObjC::RetainOwnershipKind
-attrToRetainOwnershipKind(const Attr *A) {
+static SemaObjC::RetainOwnershipKind attrToRetainOwnershipKind(const Attr *A) {
   switch (A->getKind()) {
   case clang::attr::CFConsumed:
     return SemaObjC::RetainOwnershipKind::CF;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7c57ebce5bbe2..7de40c416b87c 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -15891,7 +15891,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
 #endif
 
   return SemaRef.ObjC().ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
-                                    /*Scope=*/nullptr);
+                                           /*Scope=*/nullptr);
 }
 
 template<typename Derived>



More information about the cfe-commits mailing list