[llvm-branch-commits] [clang] [Clang] Extend lifetime bound analysis to support assignments (PR #96475)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jun 26 05:42:30 PDT 2024
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff 2b5d1fb889fca7287858db0791bfecc1465f23e1 43ffbc27fe7d128586b54dbd33fd676532233032 --extensions 'c,cpp,h' -- clang/lib/Sema/CheckExprLifetime.cpp clang/lib/Sema/CheckExprLifetime.h clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaInit.cpp clang/test/Parser/compound_literal.c clang/test/SemaCXX/attr-lifetimebound.cpp clang/test/SemaCXX/warn-dangling-local.cpp
``````````
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index 73b3fd2d3a..bbca1b209f 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -42,21 +42,20 @@ enum LifetimeKind {
};
using LifetimeResult =
llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
-}
+} // namespace
/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
-static LifetimeResult getEntityLifetime(
- const InitializedEntity *Entity,
- const InitializedEntity *InitField = nullptr) {
+static LifetimeResult
+getEntityLifetime(const InitializedEntity *Entity,
+ const InitializedEntity *InitField = nullptr) {
// C++11 [class.temporary]p5:
switch (Entity->getKind()) {
case InitializedEntity::EK_Variable:
// The temporary [...] persists for the lifetime of the reference
return {Entity, LK_Extended};
-
case InitializedEntity::EK_Member:
// For subobjects, we look at the complete object.
if (Entity->getParent())
@@ -90,7 +89,8 @@ static LifetimeResult getEntityLifetime(
return {nullptr, LK_FullExpression};
case InitializedEntity::EK_TemplateParameter:
- // FIXME: This will always be ill-formed; should we eagerly diagnose it here?
+ // FIXME: This will always be ill-formed; should we eagerly diagnose it
+ // here?
return {nullptr, LK_FullExpression};
case InitializedEntity::EK_Result:
@@ -171,7 +171,7 @@ enum ReferenceKind {
/// * A DeclRefExpr whose declaration is a local.
/// * An AddrLabelExpr.
/// * A BlockExpr for a block with captures.
-using Local = Expr*;
+using Local = Expr *;
/// Expressions we stepped over when looking for the local state. Any steps
/// that would inhibit lifetime extension or take us out of subexpressions of
@@ -359,9 +359,9 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
} else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
FunctionDecl *Callee = OCE->getDirectCallee();
if (Callee && Callee->isCXXInstanceMember() &&
- shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
+ shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
VisitPointerArg(Callee, OCE->getArg(0),
- !Callee->getReturnType()->isReferenceType());
+ !Callee->getReturnType()->isReferenceType());
return;
} else if (auto *CE = dyn_cast<CallExpr>(Call)) {
FunctionDecl *Callee = CE->getDirectCallee();
@@ -419,7 +419,7 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
LocalVisitor Visit) {
const FunctionDecl *Callee;
- ArrayRef<Expr*> Args;
+ ArrayRef<Expr *> Args;
if (auto *CE = dyn_cast<CallExpr>(Call)) {
Callee = CE->getDirectCallee();
@@ -610,7 +610,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
break;
}
- // FIXME: Visit the left-hand side of an -> or ->*.
+ // FIXME: Visit the left-hand side of an -> or ->*.
default:
break;
@@ -632,7 +632,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
// Step into CXXDefaultInitExprs so we can diagnose cases where a
// constructor inherits one as an implicit mem-initializer.
if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
- Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
+ Path.push_back(
+ {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
Init = DIE->getExpr();
}
@@ -657,21 +658,23 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
return visitLocalsRetainedByReferenceBinding(
Path, Init, RK_ReferenceBinding,
[&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
- if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
- auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
- if (VD && VD->getType().isConstQualified() && VD->getInit() &&
- !isVarOnPath(Path, VD)) {
- Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
- visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true,
- EnableLifetimeWarnings);
- }
- } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
- if (MTE->getType().isConstQualified())
- visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit,
- true, EnableLifetimeWarnings);
- }
- return false;
- }, EnableLifetimeWarnings);
+ if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (VD && VD->getType().isConstQualified() && VD->getInit() &&
+ !isVarOnPath(Path, VD)) {
+ Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
+ visitLocalsRetainedByInitializer(
+ Path, VD->getInit(), Visit, true, EnableLifetimeWarnings);
+ }
+ } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
+ if (MTE->getType().isConstQualified())
+ visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
+ Visit, true,
+ EnableLifetimeWarnings);
+ }
+ return false;
+ },
+ EnableLifetimeWarnings);
// We assume that objects can be retained by pointers cast to integers,
// but not if the integer is cast to floating-point type or to _Complex.
@@ -771,9 +774,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
// This might be either aggregate-initialization of a member or
// initialization of a std::initializer_list object. Regardless,
// we should recursively lifetime-extend that initializer.
- visitLocalsRetainedByInitializer(Path, SubInit, Visit,
- RevisitSubinits,
- EnableLifetimeWarnings);
+ visitLocalsRetainedByInitializer(
+ Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);
++Index;
}
}
@@ -813,7 +815,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
CCE->getConstructor()});
visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
- /*EnableLifetimeWarnings*/false);
+ /*EnableLifetimeWarnings*/ false);
Path.pop_back();
}
}
@@ -1002,8 +1004,8 @@ void checkExprLifetime(Sema &SemaRef, const CheckingEntity &CEntity,
bool IsLocalGslOwner = false;
if (pathOnlyInitializesGslPointer(Path)) {
if (isa<DeclRefExpr>(L)) {
- // We do not want to follow the references when returning a pointer originating
- // from a local owner to avoid the following false positive:
+ // We do not want to follow the references when returning a pointer
+ // originating from a local owner to avoid the following false positive:
// int &p = *localUniquePtr;
// someContainer.add(std::move(localUniquePtr));
// return p;
@@ -1011,8 +1013,9 @@ void checkExprLifetime(Sema &SemaRef, const CheckingEntity &CEntity,
if (pathContainsInit(Path) || !IsLocalGslOwner)
return false;
} else {
- IsGslPtrInitWithGslTempOwner = MTE && !MTE->getExtendingDecl() &&
- isRecordWithAttr<OwnerAttr>(MTE->getType());
+ IsGslPtrInitWithGslTempOwner =
+ MTE && !MTE->getExtendingDecl() &&
+ isRecordWithAttr<OwnerAttr>(MTE->getType());
// Skipping a chain of initializing gsl::Pointer annotated objects.
// We are looking only for the final source to find out if it was
// a local or temporary owner or the address of a local variable/param.
@@ -1097,15 +1100,15 @@ void checkExprLifetime(Sema &SemaRef, const CheckingEntity &CEntity,
SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
<< ExtendingDecl << DiagRange;
SemaRef.Diag(ExtendingDecl->getLocation(),
- diag::note_ref_or_ptr_member_declared_here)
+ diag::note_ref_or_ptr_member_declared_here)
<< true;
return false;
}
bool IsSubobjectMember = ExtendingEntity != InitEntity;
SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
- PathLifetimeKind::NoExtend
- ? diag::err_dangling_member
- : diag::warn_dangling_member)
+ PathLifetimeKind::NoExtend
+ ? diag::err_dangling_member
+ : diag::warn_dangling_member)
<< ExtendingDecl << IsSubobjectMember << RK << DiagRange;
// Don't bother adding a note pointing to the field if we're inside
// its default member initializer; our primary diagnostic points to
@@ -1113,7 +1116,7 @@ void checkExprLifetime(Sema &SemaRef, const CheckingEntity &CEntity,
if (Path.empty() ||
Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
SemaRef.Diag(ExtendingDecl->getLocation(),
- diag::note_lifetime_extending_member_declared_here)
+ diag::note_lifetime_extending_member_declared_here)
<< RK << IsSubobjectMember;
}
} else {
@@ -1153,7 +1156,7 @@ void checkExprLifetime(Sema &SemaRef, const CheckingEntity &CEntity,
: diag::warn_bind_ref_member_to_parameter)
<< Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
SemaRef.Diag(Member->getLocation(),
- diag::note_ref_or_ptr_member_declared_here)
+ diag::note_ref_or_ptr_member_declared_here)
<< (unsigned)IsPointer;
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0cf974dc56..3a6bf0f0b9 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13778,7 +13778,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
return QualType();
CheckForNullPointerDereference(*this, LHSExpr);
-
+
AssignedEntity AE{LHSExpr};
checkExprLifetime(*this, &AE, RHS.get());
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 065d078eab..ff28c420a3 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7285,7 +7285,6 @@ PerformConstructorInitialization(Sema &S,
return CurInit;
}
-
void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
Expr *Init) {
sema::CheckingEntity CEntity(&Entity);
``````````
</details>
https://github.com/llvm/llvm-project/pull/96475
More information about the llvm-branch-commits
mailing list