diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/CheckExprLifetime.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/Sema/CheckExprLifetime.h | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 1 |
4 files changed, 34 insertions, 2 deletions
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index c98fbca849fa..e9e39c11ffba 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -34,6 +34,10 @@ enum LifetimeKind { LK_Return, /// The lifetime of a temporary bound to this entity ends too soon, because + /// the entity passed to a musttail function call. + LK_MustTail, + + /// The lifetime of a temporary bound to this entity ends too soon, because /// the entity is the result of a statement expression. LK_StmtExprResult, @@ -1150,6 +1154,7 @@ static void checkExprLifetimeImpl(Sema &SemaRef, break; case LK_Return: + case LK_MustTail: case LK_StmtExprResult: if (auto *DRE = dyn_cast<DeclRefExpr>(L)) { // We can't determine if the local variable outlives the statement @@ -1158,7 +1163,8 @@ static void checkExprLifetimeImpl(Sema &SemaRef, return false; SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref) << InitEntity->getType()->isReferenceType() << DRE->getDecl() - << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange; + << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail) + << DiagRange; } else if (isa<BlockExpr>(L)) { SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; } else if (isa<AddrLabelExpr>(L)) { @@ -1170,7 +1176,7 @@ static void checkExprLifetimeImpl(Sema &SemaRef, } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) { SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref) << InitEntity->getType()->isReferenceType() << CLE->getInitializer() - << 2 << DiagRange; + << 2 << (LK == LK_MustTail) << DiagRange; } else { // P2748R5: Disallow Binding a Returned Glvalue to a Temporary. // [stmt.return]/p6: In a function whose return type is a reference, @@ -1181,6 +1187,9 @@ static void checkExprLifetimeImpl(Sema &SemaRef, InitEntity->getType()->isReferenceType()) SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref) << InitEntity->getType()->isReferenceType() << DiagRange; + else if (LK == LK_MustTail) + SemaRef.Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref) + << InitEntity->getType()->isReferenceType() << DiagRange; else SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) << InitEntity->getType()->isReferenceType() << DiagRange; @@ -1265,6 +1274,12 @@ void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity, /*AEntity*/ nullptr, Init); } +void checkExprLifetimeMustTailArg(Sema &SemaRef, + const InitializedEntity &Entity, Expr *Init) { + checkExprLifetimeImpl(SemaRef, &Entity, nullptr, LK_MustTail, + /*AEntity*/ nullptr, Init); +} + void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init) { bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics().isIgnored( diff --git a/clang/lib/Sema/CheckExprLifetime.h b/clang/lib/Sema/CheckExprLifetime.h index 8c8d0806dee0..903f312f3533 100644 --- a/clang/lib/Sema/CheckExprLifetime.h +++ b/clang/lib/Sema/CheckExprLifetime.h @@ -35,6 +35,12 @@ void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity, /// sufficient for assigning to the entity. void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init); +/// Check that the lifetime of the given expr (and its subobjects) is +/// sufficient, assuming that it is passed as an argument to a musttail +/// function. +void checkExprLifetimeMustTailArg(Sema &SemaRef, + const InitializedEntity &Entity, Expr *Init); + } // namespace clang::sema #endif // LLVM_CLANG_SEMA_CHECK_EXPR_LIFETIME_H diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 9664287b9a3f..9e235a46707c 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "CheckExprLifetime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" @@ -889,6 +890,15 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { return false; } + // The lifetimes of locals and incoming function parameters must end before + // the call, because we can't have a stack frame to store them, so diagnose + // any pointers or references to them passed into the musttail call. + for (auto ArgExpr : CE->arguments()) { + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, ArgExpr->getType(), false); + checkExprLifetimeMustTailArg(*this, Entity, const_cast<Expr *>(ArgExpr)); + } + return true; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 92274cda15e0..99423b01114c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8631,6 +8631,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( return SkipBody->Previous; Specialization->setInvalidDecl(Invalid); + inferGslOwnerPointerAttribute(Specialization); return Specialization; } |
