From: Richard Smith Date: Mon, 23 Jul 2018 19:19:08 +0000 (+0000) Subject: Separate out the initialization kind for a statement expression result X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c2add0a67604106d9460c0f6e8169e050f682a71;p=clang Separate out the initialization kind for a statement expression result from that for a return value. No functionality change intended: I don't believe any of the diagnostics affected by this patch are reachable when initializing the result of statement expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337728 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e45f5f3376..c6f263dc8c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1804,7 +1804,8 @@ def err_destructor_template : Error< // C++ initialization def err_init_conversion_failed : Error< - "cannot initialize %select{a variable|a parameter|return object|an " + "cannot initialize %select{a variable|a parameter|return object|" + "statement expression result|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " "block element|a complex element|a lambda capture|a compound literal " @@ -1939,34 +1940,29 @@ def warn_unsequenced_mod_mod : Warning< def warn_unsequenced_mod_use : Warning< "unsequenced modification and access to %0">, InGroup; +def select_initialized_entity_kind : TextSubstitution< + "%select{copying variable|copying parameter|" + "returning object|initializing statement expression result|" + "throwing object|copying member subobject|copying array element|" + "allocating object|copying temporary|initializing base subobject|" + "initializing vector element|capturing value}0">; + def err_temp_copy_no_viable : Error< - "no viable constructor %select{copying variable|copying parameter|" - "returning object|throwing object|copying member subobject|copying array " - "element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element|capturing value}0 of type %1">; + "no viable constructor %sub{select_initialized_entity_kind}0 of type %1">; def ext_rvalue_to_reference_temp_copy_no_viable : Extension< - "no viable constructor %select{copying variable|copying parameter|" - "returning object|throwing object|copying member subobject|copying array " - "element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element|capturing value}0 of type %1; C++98 requires a copy " - "constructor when binding a reference to a temporary">, + "no viable constructor %sub{select_initialized_entity_kind}0 of type %1; " + "C++98 requires a copy constructor when binding a reference to a temporary">, InGroup; def err_temp_copy_ambiguous : Error< - "ambiguous constructor call when %select{copying variable|copying " - "parameter|returning object|throwing object|copying member subobject|copying " - "array element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element|capturing value}0 of type %1">; + "ambiguous constructor call when %sub{select_initialized_entity_kind}0 " + "of type %1">; def err_temp_copy_deleted : Error< - "%select{copying variable|copying parameter|returning object|throwing " - "object|copying member subobject|copying array element|allocating object|" - "copying temporary|initializing base subobject|initializing vector element|" - "capturing value}0 of type %1 invokes deleted constructor">; + "%sub{select_initialized_entity_kind}0 of type %1 " + "invokes deleted constructor">; def err_temp_copy_incomplete : Error< "copying a temporary object of incomplete type %0">; def warn_cxx98_compat_temp_copy : Warning< - "%select{copying variable|copying parameter|returning object|throwing " - "object|copying member subobject|copying array element|allocating object|" - "copying temporary|initializing base subobject|initializing vector element}1 " + "%sub{select_initialized_entity_kind}1 " "of type %2 when binding a reference to a temporary would %select{invoke " "an inaccessible constructor|find no viable constructor|find ambiguous " "constructors|invoke a deleted constructor}0 in C++98">, diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index b7ef8d0f47..7a510f391b 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -59,6 +59,9 @@ public: /// The entity being initialized is the result of a function call. EK_Result, + /// The entity being initialized is the result of a statement expression. + EK_StmtExprResult, + /// The entity being initialized is an exception object that /// is being thrown. EK_Exception, @@ -285,6 +288,11 @@ public: return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO); } + static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc, + QualType Type) { + return InitializedEntity(EK_StmtExprResult, ReturnLoc, Type); + } + static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc, QualType Type, bool NRVO) { return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fc70c882c2..a72f6c3796 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12992,11 +12992,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, LastExpr = rebuiltLastStmt; } else { LastExpr = PerformCopyInitialization( - InitializedEntity::InitializeResult(LPLoc, - Ty, - false), - SourceLocation(), - LastExpr); + InitializedEntity::InitializeStmtExprResult(LPLoc, Ty), + SourceLocation(), LastExpr); } if (LastExpr.isInvalid()) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 6c2c6d143d..e457de4dcc 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1020,6 +1020,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_Binding: + case InitializedEntity::EK_StmtExprResult: llvm_unreachable("unexpected braced scalar init"); } @@ -3000,6 +3001,7 @@ DeclarationName InitializedEntity::getName() const { return DeclarationName(Capture.VarID); case EK_Result: + case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: @@ -3030,6 +3032,7 @@ ValueDecl *InitializedEntity::getDecl() const { return reinterpret_cast(Parameter & ~0x1); case EK_Result: + case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: @@ -3055,6 +3058,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Exception: return LocAndNRVO.NRVO; + case EK_StmtExprResult: case EK_Variable: case EK_Parameter: case EK_Parameter_CF_Audited: @@ -3090,6 +3094,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { case EK_Parameter_CF_Audited: OS << "CF audited function Parameter"; break; case EK_Result: OS << "Result"; break; + case EK_StmtExprResult: OS << "StmtExprResult"; break; case EK_Exception: OS << "Exception"; break; case EK_Member: OS << "Member"; break; case EK_Binding: OS << "Binding"; break; @@ -3534,7 +3539,8 @@ static void MaybeProduceObjCObject(Sema &S, /// retainable type, then returns need to immediately retain the /// object. If an autorelease is required, it will be done at the /// last instant. - } else if (Entity.getKind() == InitializedEntity::EK_Result) { + } else if (Entity.getKind() == InitializedEntity::EK_Result || + Entity.getKind() == InitializedEntity::EK_StmtExprResult) { if (!Entity.getType()->isObjCRetainableType()) return; @@ -5632,6 +5638,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited; case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right. return Sema::AA_Returning; case InitializedEntity::EK_Temporary: @@ -5661,6 +5668,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: @@ -5690,6 +5698,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { static bool shouldDestroyEntity(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: @@ -5721,6 +5730,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, Expr *Initializer) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: return Entity.getReturnLoc(); case InitializedEntity::EK_Exception: @@ -6168,6 +6178,7 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { switch (Top->getKind()) { case InitializedEntity::EK_Variable: case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: @@ -6216,6 +6227,10 @@ enum LifetimeKind { /// the entity is a return object. LK_Return, + /// The lifetime of a temporary bound to this entity ends too soon, because + /// the entity is the result of a statement expression. + LK_StmtExprResult, + /// This is a mem-initializer: if it would extend a temporary (other than via /// a default member initializer), the program is ill-formed. LK_MemInitializer, @@ -6274,6 +6289,11 @@ static LifetimeResult getEntityLifetime( // destroyed at the end of the full-expression in the return statement. return {nullptr, LK_Return}; + case InitializedEntity::EK_StmtExprResult: + // FIXME: Should we lifetime-extend through the result of a statement + // expression? + return {nullptr, LK_StmtExprResult}; + case InitializedEntity::EK_New: // -- A temporary bound to a reference in a new-initializer persists // until the completion of the full-expression containing the @@ -6582,6 +6602,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_Return: + case LK_StmtExprResult: // FIXME: Move -Wreturn-stack-address checks here. return false; } @@ -6660,6 +6681,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_Return: + case LK_StmtExprResult: // FIXME: Move -Wreturn-stack-address checks here. return false; }