[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, ¶ms,
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