<div dir="ltr">Thank you. I added an 'alignas(8)' and reapplied in r337329.<br></div><br><div class="gmail_quote"><div dir="ltr">On Tue, 17 Jul 2018 at 02:28, Florian Hahn via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: fhahn<br>
Date: Tue Jul 17 02:23:31 2018<br>
New Revision: 337255<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=337255&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=337255&view=rev</a><br>
Log:<br>
Temporarily revert r337226 "Restructure checking for, and warning on, lifetime extension."<br>
<br>
This change breaks on ARM because pointers to clang::InitializedEntity are only<br>
4 byte aligned and do not have 3 bits to store values. A possible solution<br>
would be to change the fields in clang::InitializedEntity to enforce a bigger<br>
alignment requirement.<br>
<br>
The error message is<br>
<br>
llvm/include/llvm/ADT/PointerIntPair.h:132:3: error: static_assert failed "PointerIntPair with integer size too large for pointer"<br>
static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,<br>
include/llvm/ADT/PointerIntPair.h:73:13: note: in instantiation of template class 'llvm::PointerIntPairInfo<const clang::InitializedEntity *, 3, llvm::PointerLikeTypeTraits<const clang::InitializedEntity *> >' requested here<br>
Value = Info::updateInt(Info::updatePointer(0, PtrVal),<br>
llvm/include/llvm/ADT/PointerIntPair.h:51:5: note: in instantiation of member function 'llvm::PointerIntPair<const clang::InitializedEntity *, 3, (anonymous namespace)::LifetimeKind, llvm::PointerLikeTypeTraits<const clang::InitializedEntity *>, llvm::PointerIntPairInfo<const clang::InitializedEntity *, 3, llvm::PointerLikeTypeTraits<const clang::InitializedEntity *> > >::setPointerAndInt' requested here<br>
setPointerAndInt(PtrVal, IntVal);<br>
^<br>
llvm/tools/clang/lib/Sema/SemaInit.cpp:6237:12: note: in instantiation of member function 'llvm::PointerIntPair<const clang::InitializedEntity *, 3, (anonymous namespace)::LifetimeKind, llvm::PointerLikeTypeTraits<const clang::InitializedEntity *>, llvm::PointerIntPairInfo<const clang::InitializedEntity *, 3, llvm::PointerLikeTypeTraits<const clang::InitializedEntity *> > >::PointerIntPair' requested here<br>
return {Entity, LK_Extended};<br>
<br>
Full log here:<br>
<a href="http://lab.llvm.org:8011/builders/clang-cmake-armv7-global-isel/builds/1330" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/builders/clang-cmake-armv7-global-isel/builds/1330</a><br>
<a href="http://lab.llvm.org:8011/builders/clang-cmake-armv7-full/builds/1394" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/builders/clang-cmake-armv7-full/builds/1394</a><br>
<br>
<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
cfe/trunk/include/clang/Sema/Initialization.h<br>
cfe/trunk/include/clang/Sema/Sema.h<br>
cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
cfe/trunk/lib/Sema/SemaInit.cpp<br>
cfe/trunk/test/Analysis/initializer.cpp<br>
cfe/trunk/test/CXX/drs/dr16xx.cpp<br>
cfe/trunk/test/CXX/drs/dr18xx.cpp<br>
cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp<br>
cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp<br>
cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp<br>
cfe/trunk/test/CXX/temp/temp.param/p5.cpp<br>
cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp<br>
cfe/trunk/test/CodeGenCXX/temporaries.cpp<br>
cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp<br>
cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp<br>
cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp<br>
cfe/trunk/test/SemaCXX/eval-crashes.cpp<br>
cfe/trunk/test/SemaCXX/member-init.cpp<br>
cfe/trunk/test/SemaCXX/warn-dangling-field.cpp<br>
cfe/trunk/www/cxx_dr_status.html<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Jul 17 02:23:31 2018<br>
@@ -272,7 +272,6 @@ def ShiftOpParentheses: DiagGroup<"shift<br>
def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;<br>
def DanglingElse: DiagGroup<"dangling-else">;<br>
def DanglingField : DiagGroup<"dangling-field">;<br>
-def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;<br>
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;<br>
def ExpansionToDefined : DiagGroup<"expansion-to-defined">;<br>
def FlagEnum : DiagGroup<"flag-enum">;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jul 17 02:23:31 2018<br>
@@ -2049,6 +2049,10 @@ def err_implied_std_initializer_list_not<br>
"not found; include <initializer_list>">;<br>
def err_malformed_std_initializer_list : Error<<br>
"std::initializer_list must be a class template with a single type parameter">;<br>
+def warn_dangling_std_initializer_list : Warning<<br>
+ "array backing the initializer list will be destroyed at the end of "<br>
+ "%select{the full-expression|the constructor}0">,<br>
+ InGroup<DiagGroup<"dangling-initializer-list">>;<br>
def err_auto_init_list_from_c : Error<<br>
"cannot use __auto_type with initializer list in C">;<br>
def err_auto_bitfield : Error<<br>
@@ -7840,39 +7844,13 @@ def warn_bind_ref_member_to_parameter :<br>
def warn_init_ptr_member_to_parameter_addr : Warning<<br>
"initializing pointer member %0 with the stack address of parameter %1">,<br>
InGroup<DanglingField>;<br>
+def warn_bind_ref_member_to_temporary : Warning<<br>
+ "binding reference %select{|subobject of }1member %0 to a temporary value">,<br>
+ InGroup<DanglingField>;<br>
def note_ref_or_ptr_member_declared_here : Note<<br>
"%select{reference|pointer}0 member declared here">;<br>
-<br>
-def err_bind_ref_member_to_temporary : Error<<br>
- "%select{reference|backing array for 'std::initializer_list'}2 "<br>
- "%select{|subobject of }1member %0 "<br>
- "%select{binds to|is}2 a temporary object "<br>
- "whose lifetime would be shorter than the constructed object">;<br>
-def note_lifetime_extending_member_declared_here : Note<<br>
- "%select{%select{reference|'std::initializer_list'}0 member|"<br>
- "member with %select{reference|'std::initializer_list'}0 subobject}1 "<br>
- "declared here">;<br>
-def warn_new_dangling_reference : Warning<<br>
- "temporary bound to reference member of allocated object "<br>
- "will be destroyed at the end of the full-expression">,<br>
- InGroup<DanglingField>;<br>
-def warn_new_dangling_initializer_list : Warning<<br>
- "array backing "<br>
- "%select{initializer list subobject of the allocated object|"<br>
- "the allocated initializer list}0 "<br>
- "will be destroyed at the end of the full-expression">,<br>
- InGroup<DanglingInitializerList>;<br>
-def warn_default_member_init_temporary_not_extended : Warning<<br>
- "sorry, lifetime extension of temporary created by aggregate initialization "<br>
- "using default member initializer is not supported; lifetime of temporary "<br>
- "will end at the end of the full-expression">, InGroup<DanglingField>;<br>
-def warn_default_member_init_init_list_not_extended : Warning<<br>
- "sorry, lifetime extension of backing array of initializer list "<br>
- "created by aggregate initialization using default member initializer "<br>
- "is not supported; lifetime of backing array will end at the end of the "<br>
- "full-expression">, InGroup<DanglingInitializerList>;<br>
-def note_in_default_member_initalizer_here : Note<<br>
- "in default member initializer for field %0 used here">;<br>
+def note_ref_subobject_of_member_declared_here : Note<<br>
+ "member with reference subobject declared here">;<br>
<br>
// For non-floating point, expressions of the form x == x or x != x<br>
// should result in a warning, since these always evaluate to a constant.<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Initialization.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Initialization.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Initialization.h Tue Jul 17 02:23:31 2018<br>
@@ -63,7 +63,7 @@ public:<br>
/// is being thrown.<br>
EK_Exception,<br>
<br>
- /// The entity being initialized is a non-static data member<br>
+ /// The entity being initialized is a non-static data member <br>
/// subobject.<br>
EK_Member,<br>
<br>
@@ -123,7 +123,7 @@ public:<br>
// enum as an index for its first %select. When modifying this list,<br>
// that diagnostic text needs to be updated as well.<br>
};<br>
-<br>
+ <br>
private:<br>
/// The kind of entity being initialized.<br>
EntityKind Kind;<br>
@@ -158,10 +158,6 @@ private:<br>
/// initialization in a copy or move constructor. These can perform array<br>
/// copies.<br>
bool IsImplicitFieldInit;<br>
-<br>
- /// When Kind == EK_Member, whether this is the initial initialization<br>
- /// check for a default member initializer.<br>
- bool IsDefaultMemberInit;<br>
};<br>
<br>
struct C {<br>
@@ -207,7 +203,7 @@ private:<br>
<br>
/// Create the initialization entity for a variable.<br>
InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)<br>
- : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}<br>
+ : Kind(EK), Type(Var->getType()), Variable{Var, false} {}<br>
<br>
/// Create the initialization entity for the result of a<br>
/// function, throwing an object, performing an explicit cast, or<br>
@@ -221,9 +217,9 @@ private:<br>
<br>
/// Create the initialization entity for a member subobject.<br>
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,<br>
- bool Implicit, bool DefaultMemberInit)<br>
+ bool Implicit) <br>
: Kind(EK_Member), Parent(Parent), Type(Member->getType()),<br>
- Variable{Member, Implicit, DefaultMemberInit} {}<br>
+ Variable{Member, Implicit} {}<br>
<br>
/// Create the initialization entity for an array element.<br>
InitializedEntity(ASTContext &Context, unsigned Index, <br>
@@ -343,27 +339,21 @@ public:<br>
static InitializedEntity InitializeDelegation(QualType Type) {<br>
return InitializedEntity(EK_Delegating, SourceLocation(), Type);<br>
}<br>
-<br>
+ <br>
/// Create the initialization entity for a member subobject.<br>
static InitializedEntity<br>
InitializeMember(FieldDecl *Member,<br>
const InitializedEntity *Parent = nullptr,<br>
bool Implicit = false) {<br>
- return InitializedEntity(Member, Parent, Implicit, false);<br>
+ return InitializedEntity(Member, Parent, Implicit);<br>
}<br>
-<br>
+ <br>
/// Create the initialization entity for a member subobject.<br>
static InitializedEntity<br>
InitializeMember(IndirectFieldDecl *Member,<br>
const InitializedEntity *Parent = nullptr,<br>
bool Implicit = false) {<br>
- return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);<br>
- }<br>
-<br>
- /// Create the initialization entity for a default member initializer.<br>
- static InitializedEntity<br>
- InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {<br>
- return InitializedEntity(Member, nullptr, false, true);<br>
+ return InitializedEntity(Member->getAnonField(), Parent, Implicit);<br>
}<br>
<br>
/// Create the initialization entity for an array element.<br>
@@ -463,12 +453,6 @@ public:<br>
return getKind() == EK_Member && Variable.IsImplicitFieldInit;<br>
}<br>
<br>
- /// Is this the default member initializer of a member (specified inside<br>
- /// the class definition)?<br>
- bool isDefaultMemberInitializer() const {<br>
- return getKind() == EK_Member && Variable.IsDefaultMemberInit;<br>
- }<br>
-<br>
/// Determine the location of the 'return' keyword when initializing<br>
/// the result of a function call.<br>
SourceLocation getReturnLoc() const {<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jul 17 02:23:31 2018<br>
@@ -2582,11 +2582,6 @@ public:<br>
NamedDecl *FoundDecl,<br>
CXXMethodDecl *Method);<br>
<br>
- /// Check that the lifetime of the initializer (and its subobjects) is<br>
- /// sufficient for initializing the entity, and perform lifetime extension<br>
- /// (when permitted) if not.<br>
- void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);<br>
-<br>
ExprResult PerformContextuallyConvertToBool(Expr *From);<br>
ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jul 17 02:23:31 2018<br>
@@ -3621,8 +3621,7 @@ void Sema::ActOnFinishCXXInClassMemberIn<br>
<br>
ExprResult Init = InitExpr;<br>
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {<br>
- InitializedEntity Entity =<br>
- InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);<br>
+ InitializedEntity Entity = InitializedEntity::InitializeMember(FD);<br>
InitializationKind Kind =<br>
FD->getInClassInitStyle() == ICIS_ListInit<br>
? InitializationKind::CreateDirectList(InitExpr->getLocStart(),<br>
@@ -4647,10 +4646,6 @@ static bool CollectFieldInitializer(Sema<br>
SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);<br>
if (DIE.isInvalid())<br>
return true;<br>
-<br>
- auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);<br>
- SemaRef.checkInitializerLifetime(Entity, DIE.get());<br>
-<br>
CXXCtorInitializer *Init;<br>
if (Indirect)<br>
Init = new (SemaRef.Context)<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Jul 17 02:23:31 2018<br>
@@ -1864,6 +1864,13 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))<br>
return ExprError();<br>
<br>
+ if (initStyle == CXXNewExpr::ListInit &&<br>
+ isStdInitializerList(AllocType, nullptr)) {<br>
+ Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),<br>
+ diag::warn_dangling_std_initializer_list)<br>
+ << /*at end of FE*/0 << Inits[0]->getSourceRange();<br>
+ }<br>
+<br>
// In ARC, infer 'retaining' for the allocated<br>
if (getLangOpts().ObjCAutoRefCount &&<br>
AllocType.getObjCLifetime() == Qualifiers::OCL_None &&<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jul 17 02:23:31 2018<br>
@@ -572,7 +572,6 @@ void InitListChecker::FillInEmptyInitFor<br>
hadError = true;<br>
return;<br>
}<br>
- SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());<br>
if (Init < NumInits)<br>
ILE->setInit(Init, DIE.get());<br>
else {<br>
@@ -6198,43 +6197,17 @@ InitializedEntityOutlivesFullExpression(<br>
llvm_unreachable("unknown entity kind");<br>
}<br>
<br>
-namespace {<br>
-enum LifetimeKind {<br>
- /// The lifetime of a temporary bound to this entity ends at the end of the<br>
- /// full-expression, and that's (probably) fine.<br>
- LK_FullExpression,<br>
-<br>
- /// The lifetime of a temporary bound to this entity is extended to the<br>
- /// lifeitme of the entity itself.<br>
- LK_Extended,<br>
-<br>
- /// The lifetime of a temporary bound to this entity probably ends too soon,<br>
- /// because the entity is allocated in a new-expression.<br>
- LK_New,<br>
-<br>
- /// The lifetime of a temporary bound to this entity ends too soon, because<br>
- /// the entity is a return object.<br>
- LK_Return,<br>
-<br>
- /// This is a mem-initializer: if it would extend a temporary (other than via<br>
- /// a default member initializer), the program is ill-formed.<br>
- LK_MemInitializer,<br>
-};<br>
-using LifetimeResult =<br>
- llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;<br>
-}<br>
-<br>
/// Determine the declaration which an initialized entity ultimately refers to,<br>
/// for the purpose of lifetime-extending a temporary bound to a reference in<br>
/// the initialization of \p Entity.<br>
-static LifetimeResult getEntityForTemporaryLifetimeExtension(<br>
+static const InitializedEntity *getEntityForTemporaryLifetimeExtension(<br>
const InitializedEntity *Entity,<br>
- const InitializedEntity *InitField = nullptr) {<br>
+ const InitializedEntity *FallbackDecl = nullptr) {<br>
// C++11 [class.temporary]p5:<br>
switch (Entity->getKind()) {<br>
case InitializedEntity::EK_Variable:<br>
// The temporary [...] persists for the lifetime of the reference<br>
- return {Entity, LK_Extended};<br>
+ return Entity;<br>
<br>
case InitializedEntity::EK_Member:<br>
// For subobjects, we look at the complete object.<br>
@@ -6243,43 +6216,29 @@ static LifetimeResult getEntityForTempor<br>
Entity);<br>
<br>
// except:<br>
- // C++17 [class.base.init]p8:<br>
- // A temporary expression bound to a reference member in a<br>
- // mem-initializer is ill-formed.<br>
- // C++17 [class.base.init]p11:<br>
- // A temporary expression bound to a reference member from a<br>
- // default member initializer is ill-formed.<br>
- //<br>
- // The context of p11 and its example suggest that it's only the use of a<br>
- // default member initializer from a constructor that makes the program<br>
- // ill-formed, not its mere existence, and that it can even be used by<br>
- // aggregate initialization.<br>
- return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended<br>
- : LK_MemInitializer};<br>
+ // -- A temporary bound to a reference member in a constructor's<br>
+ // ctor-initializer persists until the constructor exits.<br>
+ return Entity;<br>
<br>
case InitializedEntity::EK_Binding:<br>
// Per [dcl.decomp]p3, the binding is treated as a variable of reference<br>
// type.<br>
- return {Entity, LK_Extended};<br>
+ return Entity;<br>
<br>
case InitializedEntity::EK_Parameter:<br>
case InitializedEntity::EK_Parameter_CF_Audited:<br>
// -- A temporary bound to a reference parameter in a function call<br>
// persists until the completion of the full-expression containing<br>
// the call.<br>
- return {nullptr, LK_FullExpression};<br>
-<br>
case InitializedEntity::EK_Result:<br>
// -- The lifetime of a temporary bound to the returned value in a<br>
// function return statement is not extended; the temporary is<br>
// destroyed at the end of the full-expression in the return statement.<br>
- return {nullptr, LK_Return};<br>
-<br>
case InitializedEntity::EK_New:<br>
// -- A temporary bound to a reference in a new-initializer persists<br>
// until the completion of the full-expression containing the<br>
// new-initializer.<br>
- return {nullptr, LK_New};<br>
+ return nullptr;<br>
<br>
case InitializedEntity::EK_Temporary:<br>
case InitializedEntity::EK_CompoundLiteralInit:<br>
@@ -6287,26 +6246,25 @@ static LifetimeResult getEntityForTempor<br>
// We don't yet know the storage duration of the surrounding temporary.<br>
// Assume it's got full-expression duration for now, it will patch up our<br>
// storage duration if that's not correct.<br>
- return {nullptr, LK_FullExpression};<br>
+ return nullptr;<br>
<br>
case InitializedEntity::EK_ArrayElement:<br>
// For subobjects, we look at the complete object.<br>
return getEntityForTemporaryLifetimeExtension(Entity->getParent(),<br>
- InitField);<br>
+ FallbackDecl);<br>
<br>
case InitializedEntity::EK_Base:<br>
// For subobjects, we look at the complete object.<br>
if (Entity->getParent())<br>
return getEntityForTemporaryLifetimeExtension(Entity->getParent(),<br>
- InitField);<br>
- return {InitField, LK_MemInitializer};<br>
-<br>
+ Entity);<br>
+ LLVM_FALLTHROUGH;<br>
case InitializedEntity::EK_Delegating:<br>
// We can reach this case for aggregate initialization in a constructor:<br>
// struct A { int &&r; };<br>
// struct B : A { B() : A{0} {} };<br>
- // In this case, use the outermost field decl as the context.<br>
- return {InitField, LK_MemInitializer};<br>
+ // In this case, use the innermost field decl as the context.<br>
+ return FallbackDecl;<br>
<br>
case InitializedEntity::EK_BlockElement:<br>
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:<br>
@@ -6314,54 +6272,30 @@ static LifetimeResult getEntityForTempor<br>
case InitializedEntity::EK_Exception:<br>
case InitializedEntity::EK_VectorElement:<br>
case InitializedEntity::EK_ComplexElement:<br>
- return {nullptr, LK_FullExpression};<br>
+ return nullptr;<br>
}<br>
llvm_unreachable("unknown entity kind");<br>
}<br>
<br>
-namespace {<br>
-enum ExtensionKind {<br>
- /// Lifetime would be extended by a reference binding to a temporary.<br>
- EK_ReferenceBinding,<br>
- /// Lifetime would be extended by a std::initializer_list object binding to<br>
- /// its backing array.<br>
- EK_StdInitializerList,<br>
-};<br>
-using IndirectTemporaryPathEntry =<br>
- llvm::PointerUnion<CXXDefaultInitExpr *, ValueDecl *>;<br>
-using IndirectTemporaryPath = llvm::SmallVectorImpl<IndirectTemporaryPathEntry>;<br>
-<br>
-struct RevertToOldSizeRAII {<br>
- IndirectTemporaryPath &Path;<br>
- unsigned OldSize = Path.size();<br>
- RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {}<br>
- ~RevertToOldSizeRAII() { Path.resize(OldSize); }<br>
-};<br>
-}<br>
-<br>
-template <typename TemporaryVisitor><br>
-static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,<br>
- Expr *Init,<br>
- TemporaryVisitor Visit);<br>
-<br>
-/// Visit the temporaries whose lifetimes would be extended by binding a<br>
-/// reference to the glvalue expression \c Init.<br>
-template <typename TemporaryVisitor><br>
-static void<br>
-visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path,<br>
- Expr *Init, ExtensionKind EK,<br>
- TemporaryVisitor Visit) {<br>
- RevertToOldSizeRAII RAII(Path);<br>
+static void performLifetimeExtension(Expr *Init,<br>
+ const InitializedEntity *ExtendingEntity);<br>
<br>
+/// Update a glvalue expression that is used as the initializer of a reference<br>
+/// to note that its lifetime is extended.<br>
+/// \return \c true if any temporary had its lifetime extended.<br>
+static bool<br>
+performReferenceExtension(Expr *Init,<br>
+ const InitializedEntity *ExtendingEntity) {<br>
// Walk past any constructs which we can lifetime-extend across.<br>
Expr *Old;<br>
do {<br>
Old = Init;<br>
<br>
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {<br>
- // If this is just redundant braces around an initializer, step over it.<br>
- if (ILE->isTransparent())<br>
+ if (ILE->getNumInits() == 1 && ILE->isGLValue()) {<br>
+ // This is just redundant braces around an initializer. Step over it.<br>
Init = ILE->getInit(0);<br>
+ }<br>
}<br>
<br>
// Step over any subobject adjustments; we may have a materialized<br>
@@ -6378,65 +6312,40 @@ visitTemporariesExtendedByReferenceBindi<br>
// when performing lifetime extension.<br>
if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init))<br>
Init = ASE->getBase();<br>
-<br>
- // Step into CXXDefaultInitExprs so we can diagnose cases where a<br>
- // constructor inherits one as an implicit mem-initializer.<br>
- if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {<br>
- Path.push_back(DIE);<br>
- Init = DIE->getExpr();<br>
-<br>
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))<br>
- Init = EWC->getSubExpr();<br>
- }<br>
} while (Init != Old);<br>
<br>
- if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {<br>
- if (Visit(Path, MTE, EK))<br>
- visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(),<br>
- Visit);<br>
+ if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {<br>
+ // Update the storage duration of the materialized temporary.<br>
+ // FIXME: Rebuild the expression instead of mutating it.<br>
+ ME->setExtendingDecl(ExtendingEntity->getDecl(),<br>
+ ExtendingEntity->allocateManglingNumber());<br>
+ performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);<br>
+ return true;<br>
}<br>
-}<br>
<br>
-/// Visit the temporaries whose lifetimes would be extended by<br>
-/// lifetime-extending the object initialized by the prvalue expression \c<br>
-/// Init.<br>
-template <typename TemporaryVisitor><br>
-static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,<br>
- Expr *Init,<br>
- TemporaryVisitor Visit) {<br>
- RevertToOldSizeRAII RAII(Path);<br>
-<br>
- // Step into CXXDefaultInitExprs so we can diagnose cases where a<br>
- // constructor inherits one as an implicit mem-initializer.<br>
- if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {<br>
- Path.push_back(DIE);<br>
- Init = DIE->getExpr();<br>
-<br>
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))<br>
- Init = EWC->getSubExpr();<br>
- }<br>
+ return false;<br>
+}<br>
<br>
+/// Update a prvalue expression that is going to be materialized as a<br>
+/// lifetime-extended temporary.<br>
+static void performLifetimeExtension(Expr *Init,<br>
+ const InitializedEntity *ExtendingEntity) {<br>
// Dig out the expression which constructs the extended temporary.<br>
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());<br>
<br>
if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))<br>
Init = BTE->getSubExpr();<br>
<br>
- // C++17 [dcl.init.list]p6:<br>
- // initializing an initializer_list object from the array extends the<br>
- // lifetime of the array exactly like binding a reference to a temporary.<br>
- if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))<br>
- return visitTemporariesExtendedByReferenceBinding(<br>
- Path, ILE->getSubExpr(), EK_StdInitializerList, Visit);<br>
+ if (CXXStdInitializerListExpr *ILE =<br>
+ dyn_cast<CXXStdInitializerListExpr>(Init)) {<br>
+ performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);<br>
+ return;<br>
+ }<br>
<br>
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {<br>
- if (ILE->isTransparent())<br>
- return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0),<br>
- Visit);<br>
-<br>
if (ILE->getType()->isArrayType()) {<br>
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)<br>
- visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit);<br>
+ performLifetimeExtension(ILE->getInit(I), ExtendingEntity);<br>
return;<br>
}<br>
<br>
@@ -6448,8 +6357,7 @@ static void visitTemporariesExtendedByIn<br>
// bound to temporaries, those temporaries are also lifetime-extended.<br>
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&<br>
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())<br>
- visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0),<br>
- EK_ReferenceBinding, Visit);<br>
+ performReferenceExtension(ILE->getInit(0), ExtendingEntity);<br>
else {<br>
unsigned Index = 0;<br>
for (const auto *I : RD->fields()) {<br>
@@ -6459,13 +6367,13 @@ static void visitTemporariesExtendedByIn<br>
continue;<br>
Expr *SubInit = ILE->getInit(Index);<br>
if (I->getType()->isReferenceType())<br>
- visitTemporariesExtendedByReferenceBinding(<br>
- Path, SubInit, EK_ReferenceBinding, Visit);<br>
- else<br>
- // This might be either aggregate-initialization of a member or<br>
- // initialization of a std::initializer_list object. Regardless,<br>
+ performReferenceExtension(SubInit, ExtendingEntity);<br>
+ else if (isa<InitListExpr>(SubInit) ||<br>
+ isa<CXXStdInitializerListExpr>(SubInit))<br>
+ // This may be either aggregate-initialization of a member or<br>
+ // initialization of a std::initializer_list object. Either way,<br>
// we should recursively lifetime-extend that initializer.<br>
- visitTemporariesExtendedByInitializer(Path, SubInit, Visit);<br>
+ performLifetimeExtension(SubInit, ExtendingEntity);<br>
++Index;<br>
}<br>
}<br>
@@ -6473,123 +6381,37 @@ static void visitTemporariesExtendedByIn<br>
}<br>
}<br>
<br>
-/// Determine whether this is an indirect path to a temporary that we are<br>
-/// supposed to lifetime-extend along (but don't).<br>
-static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) {<br>
- for (auto Elem : Path) {<br>
- if (!Elem.is<CXXDefaultInitExpr*>())<br>
- return false;<br>
- }<br>
- return true;<br>
-}<br>
-<br>
-void Sema::checkInitializerLifetime(const InitializedEntity &Entity,<br>
- Expr *Init) {<br>
- LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity);<br>
- LifetimeKind LK = LR.getInt();<br>
- const InitializedEntity *ExtendingEntity = LR.getPointer();<br>
-<br>
- // If this entity doesn't have an interesting lifetime, don't bother looking<br>
- // for temporaries within its initializer.<br>
- if (LK == LK_FullExpression)<br>
- return;<br>
-<br>
- auto TemporaryVisitor = [&](IndirectTemporaryPath &Path,<br>
- MaterializeTemporaryExpr *MTE,<br>
- ExtensionKind EK) -> bool {<br>
- switch (LK) {<br>
- case LK_FullExpression:<br>
- llvm_unreachable("already handled this");<br>
-<br>
- case LK_Extended:<br>
- // Lifetime-extend the temporary.<br>
- if (Path.empty()) {<br>
- // Update the storage duration of the materialized temporary.<br>
- // FIXME: Rebuild the expression instead of mutating it.<br>
- MTE->setExtendingDecl(ExtendingEntity->getDecl(),<br>
- ExtendingEntity->allocateManglingNumber());<br>
- // Also visit the temporaries lifetime-extended by this initializer.<br>
- return true;<br>
- }<br>
-<br>
- if (shouldLifetimeExtendThroughPath(Path)) {<br>
- // We're supposed to lifetime-extend the temporary along this path (per<br>
- // the resolution of DR1815), but we don't support that yet.<br>
- //<br>
- // FIXME: Properly handle this situation. Perhaps the easiest approach<br>
- // would be to clone the initializer expression on each use that would<br>
- // lifetime extend its temporaries.<br>
- Diag(MTE->getExprLoc(),<br>
- EK == EK_ReferenceBinding<br>
- ? diag::warn_default_member_init_temporary_not_extended<br>
- : diag::warn_default_member_init_init_list_not_extended);<br>
- } else {<br>
- llvm_unreachable("unexpected indirect temporary path");<br>
- }<br>
- break;<br>
-<br>
- case LK_MemInitializer:<br>
- // Under C++ DR1696, if a mem-initializer (or a default member<br>
- // initializer used by the absence of one) would lifetime-extend a<br>
- // temporary, the program is ill-formed.<br>
- if (auto *ExtendingDecl = ExtendingEntity->getDecl()) {<br>
- bool IsSubobjectMember = ExtendingEntity != &Entity;<br>
- Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary)<br>
- << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember<br>
- << EK;<br>
- // Don't bother adding a note pointing to the field if we're inside its<br>
- // default member initializer; our primary diagnostic points to the<br>
- // same place in that case.<br>
- if (Path.empty() || !Path.back().is<CXXDefaultInitExpr*>()) {<br>
- Diag(ExtendingDecl->getLocation(),<br>
- diag::note_lifetime_extending_member_declared_here)<br>
- << EK << IsSubobjectMember;<br>
- }<br>
- } else {<br>
- // We have a mem-initializer but no particular field within it; this<br>
- // is either a base class or a delegating initializer directly<br>
- // initializing the base-class from something that doesn't live long<br>
- // enough. Either way, that can't happen.<br>
- // FIXME: Move CheckForDanglingReferenceOrPointer checks here.<br>
- llvm_unreachable(<br>
- "temporary initializer for base class / delegating ctor");<br>
- }<br>
- break;<br>
-<br>
- case LK_New:<br>
- if (EK == EK_ReferenceBinding) {<br>
- Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference);<br>
- } else {<br>
- Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list)<br>
- << (ExtendingEntity != &Entity);<br>
- }<br>
- break;<br>
-<br>
- case LK_Return:<br>
- // FIXME: Move -Wreturn-stack-address checks here.<br>
- return false;<br>
+static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,<br>
+ const Expr *Init, bool IsInitializerList,<br>
+ const ValueDecl *ExtendingDecl) {<br>
+ // Warn if a field lifetime-extends a temporary.<br>
+ if (isa<FieldDecl>(ExtendingDecl)) {<br>
+ if (IsInitializerList) {<br>
+ S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)<br>
+ << /*at end of constructor*/true;<br>
+ return;<br>
}<br>
<br>
- // FIXME: Model these as CodeSynthesisContexts to fix the note emission<br>
- // order.<br>
- for (auto Elem : llvm::reverse(Path)) {<br>
- if (auto *DIE = Elem.dyn_cast<CXXDefaultInitExpr*>()) {<br>
- Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here)<br>
- << DIE->getField();<br>
+ bool IsSubobjectMember = false;<br>
+ for (const InitializedEntity *Ent = Entity.getParent(); Ent;<br>
+ Ent = Ent->getParent()) {<br>
+ if (Ent->getKind() != InitializedEntity::EK_Base) {<br>
+ IsSubobjectMember = true;<br>
+ break;<br>
}<br>
}<br>
-<br>
- // We didn't lifetime-extend, so don't go any further; we don't need more<br>
- // warnings or errors on inner temporaries within this one's initializer.<br>
- return false;<br>
- };<br>
-<br>
- llvm::SmallVector<IndirectTemporaryPathEntry, 8> Path;<br>
- if (Init->isGLValue())<br>
- visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding,<br>
- TemporaryVisitor);<br>
- else<br>
- visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor);<br>
+ S.Diag(Init->getExprLoc(),<br>
+ diag::warn_bind_ref_member_to_temporary)<br>
+ << ExtendingDecl << Init->getSourceRange()<br>
+ << IsSubobjectMember << IsInitializerList;<br>
+ if (IsSubobjectMember)<br>
+ S.Diag(ExtendingDecl->getLocation(),<br>
+ diag::note_ref_subobject_of_member_declared_here);<br>
+ else<br>
+ S.Diag(ExtendingDecl->getLocation(),<br>
+ diag::note_ref_or_ptr_member_declared_here)<br>
+ << /*is pointer*/false;<br>
+ }<br>
}<br>
<br>
static void DiagnoseNarrowingInInitList(Sema &S,<br>
@@ -7016,9 +6838,14 @@ InitializationSequence::Perform(Sema &S,<br>
}<br>
<br>
// Even though we didn't materialize a temporary, the binding may still<br>
- // extend the lifetime of a temporary. This happens if we bind a<br>
- // reference to the result of a cast to reference type.<br>
- S.checkInitializerLifetime(Entity, CurInit.get());<br>
+ // extend the lifetime of a temporary. This happens if we bind a reference<br>
+ // to the result of a cast to reference type.<br>
+ if (const InitializedEntity *ExtendingEntity =<br>
+ getEntityForTemporaryLifetimeExtension(&Entity))<br>
+ if (performReferenceExtension(CurInit.get(), ExtendingEntity))<br>
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),<br>
+ /*IsInitializerList=*/false,<br>
+ ExtendingEntity->getDecl());<br>
<br>
CheckForNullPointerDereference(S, CurInit.get());<br>
break;<br>
@@ -7034,17 +6861,23 @@ InitializationSequence::Perform(Sema &S,<br>
// Materialize the temporary into memory.<br>
MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(<br>
Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());<br>
- CurInit = MTE;<br>
<br>
// Maybe lifetime-extend the temporary's subobjects to match the<br>
// entity's lifetime.<br>
- S.checkInitializerLifetime(Entity, CurInit.get());<br>
+ if (const InitializedEntity *ExtendingEntity =<br>
+ getEntityForTemporaryLifetimeExtension(&Entity))<br>
+ if (performReferenceExtension(MTE, ExtendingEntity))<br>
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),<br>
+ /*IsInitializerList=*/false,<br>
+ ExtendingEntity->getDecl());<br>
<br>
// If we're extending this temporary to automatic storage duration -- we<br>
// need to register its cleanup during the full-expression's cleanups.<br>
if (MTE->getStorageDuration() == SD_Automatic &&<br>
MTE->getType().isDestructedType())<br>
S.Cleanup.setExprNeedsCleanups(true);<br>
+<br>
+ CurInit = MTE;<br>
break;<br>
}<br>
<br>
@@ -7487,12 +7320,17 @@ InitializationSequence::Perform(Sema &S,<br>
CurInit.get()->getType(), CurInit.get(),<br>
/*BoundToLvalueReference=*/false);<br>
<br>
- // Wrap it in a construction of a std::initializer_list<T>.<br>
- CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);<br>
-<br>
// Maybe lifetime-extend the array temporary's subobjects to match the<br>
// entity's lifetime.<br>
- S.checkInitializerLifetime(Entity, CurInit.get());<br>
+ if (const InitializedEntity *ExtendingEntity =<br>
+ getEntityForTemporaryLifetimeExtension(&Entity))<br>
+ if (performReferenceExtension(MTE, ExtendingEntity))<br>
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),<br>
+ /*IsInitializerList=*/true,<br>
+ ExtendingEntity->getDecl());<br>
+<br>
+ // Wrap it in a construction of a std::initializer_list<T>.<br>
+ CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);<br>
<br>
// Bind the result, in case the library has given initializer_list a<br>
// non-trivial destructor.<br>
<br>
Modified: cfe/trunk/test/Analysis/initializer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/initializer.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/initializer.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Analysis/initializer.cpp (original)<br>
+++ cfe/trunk/test/Analysis/initializer.cpp Tue Jul 17 02:23:31 2018<br>
@@ -178,6 +178,29 @@ namespace ReferenceInitialization {<br>
const MyStruct &myStruct(OtherStruct(5));<br>
myStruct.method(); // no-warning<br>
}<br>
+<br>
+ struct HasMyStruct {<br>
+ const MyStruct &ms; // expected-note {{reference member declared here}}<br>
+ const MyStruct &msWithCleanups; // expected-note {{reference member declared here}}<br>
+<br>
+ // clang's Sema issues a warning when binding a reference member to a<br>
+ // temporary value.<br>
+ HasMyStruct() : ms(5), msWithCleanups(OtherStruct(5)) {<br>
+ // expected-warning@-1 {{binding reference member 'ms' to a temporary value}}<br>
+ // expected-warning@-2 {{binding reference member 'msWithCleanups' to a temporary value}}<br>
+<br>
+ // At this point the members are not garbage so we should not expect an<br>
+ // analyzer warning here even though binding a reference member<br>
+ // to a member is a terrible idea.<br>
+ ms.method(); // no-warning<br>
+ msWithCleanups.method(); // no-warning<br>
+ }<br>
+ };<br>
+<br>
+ void referenceInitializeField() {<br>
+ HasMyStruct hms;<br>
+ }<br>
+<br>
};<br>
<br>
namespace PR31592 {<br>
<br>
Modified: cfe/trunk/test/CXX/drs/dr16xx.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr16xx.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr16xx.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/drs/dr16xx.cpp (original)<br>
+++ cfe/trunk/test/CXX/drs/dr16xx.cpp Tue Jul 17 02:23:31 2018<br>
@@ -9,20 +9,6 @@<br>
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)<br>
#endif<br>
<br>
-#if __cplusplus >= 201103L<br>
-namespace std {<br>
- typedef decltype(sizeof(int)) size_t;<br>
-<br>
- template<typename E> class initializer_list {<br>
- const E *begin;<br>
- size_t size;<br>
-<br>
- public:<br>
- initializer_list();<br>
- };<br>
-} // std<br>
-#endif<br>
-<br>
namespace dr1611 { // dr1611: dup 1658<br>
struct A { A(int); };<br>
struct B : virtual A { virtual void f() = 0; };<br>
@@ -283,83 +269,3 @@ namespace dr1687 { // dr1687: 7<br>
auto c = To<E1>() <=> To<E2>(); // expected-error {{invalid operands to binary expression ('To<dr1687::E1>' and 'To<dr1687::E2>')}}<br>
#endif<br>
}<br>
-<br>
-namespace dr1696 { // dr1696: 7<br>
- namespace std_examples {<br>
-#if __cplusplus >= 201402L<br>
- extern struct A a;<br>
- struct A {<br>
- const A &x = { A{a, a} };<br>
- const A &y = { A{} }; // expected-error {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} expected-note {{here}}<br>
- };<br>
- A a{a, a};<br>
-#endif<br>
- }<br>
-<br>
- struct A { A(); ~A(); };<br>
-#if __cplusplus >= 201103L<br>
- struct B {<br>
- A &&a; // expected-note {{declared here}}<br>
- B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}<br>
- } b;<br>
-#endif<br>
-<br>
- struct C {<br>
- C();<br>
- const A &a; // expected-note {{declared here}}<br>
- };<br>
- C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}<br>
-<br>
-#if __cplusplus >= 201103L<br>
- // This is OK in C++14 onwards, per DR1815, though we don't support that yet:<br>
- // D1 d1 = {};<br>
- // is equivalent to<br>
- // D1 d1 = {A()};<br>
- // ... which lifetime-extends the A temporary.<br>
- struct D1 {<br>
- const A &a = A();<br>
-#if __cplusplus < 201402L<br>
- // expected-error@-2 {{binds to a temporary}}<br>
- // expected-note@-4 {{here}}<br>
-#else<br>
- // expected-warning-re@-5 {{sorry, lifetime extension {{.*}} not supported}}<br>
-#endif<br>
- };<br>
- D1 d1 = {}; // expected-note {{here}}<br>
-<br>
- struct D2 {<br>
- const A &a = A(); // expected-error {{binds to a temporary}}<br>
- D2() {} // expected-note {{used here}}<br>
- };<br>
-<br>
- struct D3 { // expected-note {{used here}}<br>
- const A &a = A(); // expected-error {{binds to a temporary}}<br>
- };<br>
- D3 d3; // expected-note {{first required here}}<br>
-<br>
- struct haslist1 {<br>
- std::initializer_list<int> il; // expected-note {{'std::initializer_list' member}}<br>
- haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}<br>
- };<br>
-<br>
- struct haslist2 {<br>
- std::initializer_list<int> il; // expected-note {{'std::initializer_list' member}}<br>
- haslist2();<br>
- };<br>
- haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}<br>
-<br>
- struct haslist3 {<br>
- std::initializer_list<int> il = {1, 2, 3};<br>
- };<br>
-<br>
- struct haslist4 { // expected-note {{in default member initializer}}<br>
- std::initializer_list<int> il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}<br>
- };<br>
- haslist4 hl4; // expected-note {{in implicit default constructor}}<br>
-<br>
- struct haslist5 {<br>
- std::initializer_list<int> il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}<br>
- haslist5() {} // expected-note {{in default member initializer}}<br>
- };<br>
-#endif<br>
-}<br>
<br>
Modified: cfe/trunk/test/CXX/drs/dr18xx.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr18xx.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr18xx.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/drs/dr18xx.cpp (original)<br>
+++ cfe/trunk/test/CXX/drs/dr18xx.cpp Tue Jul 17 02:23:31 2018<br>
@@ -30,17 +30,6 @@ namespace dr1813 { // dr1813: 7<br>
static_assert(!__is_standard_layout(U), "");<br>
}<br>
<br>
-namespace dr1815 { // dr1815: no<br>
-#if __cplusplus >= 201402L<br>
- // FIXME: needs codegen test<br>
- struct A { int &&r = 0; }; // FIXME expected-warning {{not supported}}<br>
- A a = {}; // expected-note {{here}}<br>
-<br>
- struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{here}}<br>
- B b; // expected-note {{here}}<br>
-#endif<br>
-}<br>
-<br>
namespace dr1881 { // dr1881: 7<br>
struct A { int a : 4; };<br>
struct B : A { int b : 3; };<br>
<br>
Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp (original)<br>
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp Tue Jul 17 02:23:31 2018<br>
@@ -121,22 +121,13 @@ extern HasNoAccessDtorBase HNADBa;<br>
HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}<br>
<br>
// -- a non-static data member of rvalue reference type<br>
-int some_int;<br>
struct RValue {<br>
- int && ri = static_cast<int&&>(some_int); // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}<br>
+ int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}<br>
+ // expected-warning@-1{{binding reference member 'ri' to a temporary}} expected-note@-1 {{here}}<br>
};<br>
RValue RVa;<br>
RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}<br>
<br>
-// FIXME: The note on the class-name is attached to the location of the<br>
-// constructor. This is not especially clear.<br>
-struct RValueTmp { // expected-note {{used here}}<br>
- int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}<br>
- // expected-error@-1 {{reference member 'ri' binds to a temporary}}<br>
-};<br>
-RValueTmp RVTa; // expected-note {{implicit default constructor for 'RValueTmp' first required here}}<br>
-RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy constructor}}<br>
-<br>
namespace PR13381 {<br>
struct S {<br>
S(const S&);<br>
<br>
Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp (original)<br>
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp Tue Jul 17 02:23:31 2018<br>
@@ -145,7 +145,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // e<br>
// The restriction on rvalue reference members applies to only the copy<br>
// constructor.<br>
struct RValue {<br>
- int &&ri = 1;<br>
+ int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}<br>
RValue(RValue&&);<br>
};<br>
RValue::RValue(RValue&&) = default;<br>
<br>
Modified: cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (original)<br>
+++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Tue Jul 17 02:23:31 2018<br>
@@ -43,12 +43,8 @@ class NotDeleted2a { int &a = n; };<br>
NotDeleted2a nd2a;<br>
class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}<br>
NotDeleted2b nd2b;<br>
-class NotDeleted2c { int &&a = static_cast<int&&>(n); };<br>
+class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding reference member 'a' to a temporary}} expected-note {{here}}<br>
NotDeleted2c nd2c;<br>
-// Note: this one does not have a deleted default constructor even though the<br>
-// implicit default constructor is ill-formed!<br>
-class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{here}}<br>
-NotDeleted2d nd2d; // expected-note {{first required here}}<br>
<br>
// - any non-variant non-static data member of const qualified type (or array<br>
// thereof) with no brace-or-equal-initializer does not have a user-provided<br>
<br>
Modified: cfe/trunk/test/CXX/temp/temp.param/p5.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p5.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p5.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/temp/temp.param/p5.cpp (original)<br>
+++ cfe/trunk/test/CXX/temp/temp.param/p5.cpp Tue Jul 17 02:23:31 2018<br>
@@ -1,13 +1,13 @@<br>
// RUN: %clang_cc1 -verify %s -std=c++14<br>
<br>
-template<const int I> struct S { // expected-note {{in default member initializer}}<br>
+template<const int I> struct S {<br>
decltype(I) n;<br>
- int &&r = I; // expected-error {{reference member 'r' binds to a temporary object}}<br>
+ int &&r = I; // expected-warning 2{{binding reference member 'r' to a temporary value}} expected-note 2{{declared here}}<br>
};<br>
-S<5> s; // expected-note {{implicit default constructor}}<br>
+S<5> s; // expected-note {{instantiation}}<br>
<br>
-template<typename T, T v> struct U { // expected-note {{in default member initializer}}<br>
+template<typename T, T v> struct U {<br>
decltype(v) n;<br>
- int &&r = v; // expected-error {{reference member 'r' binds to a temporary object}}<br>
+ int &&r = v; // expected-warning {{binding reference member 'r' to a temporary value}} expected-note {{declared here}}<br>
};<br>
-U<const int, 6> u; // expected-note {{implicit default constructor}}<br>
+U<const int, 6> u; // expected-note {{instantiation}}<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Tue Jul 17 02:23:31 2018<br>
@@ -236,6 +236,36 @@ void fn9() {<br>
// CHECK: ret void<br>
}<br>
<br>
+struct haslist1 {<br>
+ std::initializer_list<int> il;<br>
+ haslist1(int i);<br>
+};<br>
+<br>
+// CHECK-LABEL: define void @_ZN8haslist1C2Ei<br>
+haslist1::haslist1(int i)<br>
+// CHECK: alloca [3 x i32]<br>
+// CHECK: store i32 %<br>
+// CHECK: store i32 2<br>
+// CHECK: store i32 3<br>
+ : il{i, 2, 3}<br>
+{<br>
+ destroyme2 dm2;<br>
+}<br>
+<br>
+struct haslist2 {<br>
+ std::initializer_list<destroyme1> il;<br>
+ haslist2();<br>
+};<br>
+<br>
+// CHECK-LABEL: define void @_ZN8haslist2C2Ev<br>
+haslist2::haslist2()<br>
+ : il{destroyme1(), destroyme1()}<br>
+{<br>
+ destroyme2 dm2;<br>
+ // CHECK: call void @_ZN10destroyme2D1Ev<br>
+ // CHECK: call void @_ZN10destroyme1D1Ev<br>
+}<br>
+<br>
void fn10(int i) {<br>
// CHECK-LABEL: define void @_Z4fn10i<br>
// CHECK: alloca [3 x i32]<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/temporaries.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/temporaries.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/temporaries.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/temporaries.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/temporaries.cpp Tue Jul 17 02:23:31 2018<br>
@@ -198,6 +198,20 @@ B::B()<br>
f();<br>
}<br>
<br>
+struct C {<br>
+ C();<br>
+ <br>
+ const B& b;<br>
+};<br>
+<br>
+C::C() <br>
+ // CHECK: call void @_ZN6PR50771BC1Ev<br>
+ : b(B()) {<br>
+ // CHECK: call void @_ZN6PR50771fEv<br>
+ f();<br>
+ <br>
+ // CHECK: call void @_ZN6PR50771BD1Ev<br>
+}<br>
}<br>
<br>
A f8() {<br>
@@ -802,3 +816,16 @@ namespace PR14130 {<br>
// CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)<br>
// CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE<br>
}<br>
+<br>
+namespace Ctor {<br>
+ struct A { A(); ~A(); };<br>
+ void f();<br>
+ struct B {<br>
+ A &&a;<br>
+ B() : a{} { f(); }<br>
+ } b;<br>
+ // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(<br>
+ // CHECK: call void @_ZN4Ctor1AC1Ev(<br>
+ // CHECK: call void @_ZN4Ctor1fEv(<br>
+ // CHECK: call void @_ZN4Ctor1AD1Ev(<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue Jul 17 02:23:31 2018<br>
@@ -1892,15 +1892,14 @@ namespace Lifetime {<br>
}<br>
<br>
constexpr int &get(int &&n) { return n; }<br>
- constexpr int &&get_rv(int &&n) { return static_cast<int&&>(n); }<br>
struct S {<br>
- int &&r;<br>
+ int &&r; // expected-note 2{{declared here}}<br>
int &s;<br>
int t;<br>
- constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note {{read of object outside its lifetime}}<br>
- constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{read of object outside its lifetime}}<br>
+ constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning {{temporary}}<br>
+ constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning {{temporary}} expected-note {{read of object outside its lifetime}}<br>
};<br>
- constexpr int k1 = S().t; // expected-error {{constant expression}} expected-note {{in call}}<br>
+ constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor<br>
constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}<br>
}<br>
<br>
<br>
Modified: cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp Tue Jul 17 02:23:31 2018<br>
@@ -31,8 +31,8 @@ void test_default_arg2() {<br>
}<br>
<br>
// Check that multiple CXXDefaultInitExprs don't cause an assertion failure.<br>
-struct A { int &&r = 0; }; // expected-warning 2{{not supported}}<br>
+struct A { int &&r = 0; }; // expected-warning {{binding reference member}} // expected-note {{reference member declared here}}<br>
struct B { A x, y; };<br>
-B b = {}; // expected-note 2{{in default member initializer for field 'r' used here}}<br>
+B b = {};<br>
<br>
}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Tue Jul 17 02:23:31 2018<br>
@@ -153,14 +153,13 @@ void dangle() {<br>
}<br>
<br>
struct haslist1 {<br>
- std::initializer_list<int> il // expected-note {{declared here}}<br>
- = {1, 2, 3}; // ok, unused<br>
- std::initializer_list<int> jl{1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}}<br>
+ std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}<br>
+ std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}<br>
haslist1();<br>
};<br>
<br>
-haslist1::haslist1() // expected-note {{used here}}<br>
-: il{1, 2, 3} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}<br>
+haslist1::haslist1()<br>
+: il{1, 2, 3} // expected-warning{{at the end of the constructor}}<br>
{}<br>
<br>
namespace PR12119 {<br>
<br>
Modified: cfe/trunk/test/SemaCXX/eval-crashes.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/eval-crashes.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/eval-crashes.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/eval-crashes.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/eval-crashes.cpp Tue Jul 17 02:23:31 2018<br>
@@ -26,10 +26,10 @@ namespace pr33140_0b {<br>
<br>
namespace pr33140_2 {<br>
// FIXME: The declaration of 'b' below should lifetime-extend two int<br>
- // temporaries.<br>
- struct A { int &&r = 0; }; // expected-warning 2{{not supported}}<br>
+ // temporaries, invalidating this warning to some extent.<br>
+ struct A { int &&r = 0; }; // expected-warning {{binding reference member 'r' to a temporary}} expected-note {{here}}<br>
struct B { A x, y; };<br>
- B b = {}; // expected-note 2{{used here}}<br>
+ B b = {};<br>
}<br>
<br>
namespace pr33140_3 {<br>
<br>
Modified: cfe/trunk/test/SemaCXX/member-init.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-init.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-init.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/member-init.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/member-init.cpp Tue Jul 17 02:23:31 2018<br>
@@ -86,8 +86,9 @@ namespace PR14838 {<br>
};<br>
struct thing {};<br>
struct another {<br>
- another() : r(thing()) {} // expected-error {{binds to a temporary object}}<br>
+ another() : r(thing()) {}<br>
// expected-error@-1 {{temporary of type 'PR14838::function' has private destructor}}<br>
+ // expected-warning@-2 {{binding reference member 'r' to a temporary value}}<br>
const function &r; // expected-note {{reference member declared here}}<br>
} af;<br>
}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/warn-dangling-field.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-dangling-field.cpp?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-dangling-field.cpp?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/warn-dangling-field.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/warn-dangling-field.cpp Tue Jul 17 02:23:31 2018<br>
@@ -20,7 +20,7 @@ struct S {<br>
<br>
struct S2 {<br>
const X &x; // expected-note {{reference member declared here}}<br>
- S2(int i) : x(i) {} // expected-error {{member 'x' binds to a temporary}}<br>
+ S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}}<br>
};<br>
<br>
struct S3 {<br>
@@ -43,9 +43,9 @@ S5 s5 = { 0 }; // ok, lifetime-extended<br>
<br>
struct S6 {<br>
S5 s5; // expected-note {{here}}<br>
- S6() : s5 { 0 } {} // expected-error {{reference subobject of member 's5' binds to a temporary}}<br>
+ S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}}<br>
};<br>
<br>
struct S7 : S5 {<br>
- S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a temporary}}<br>
+ S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}}<br>
};<br>
<br>
Modified: cfe/trunk/www/cxx_dr_status.html<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=337255&r1=337254&r2=337255&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=337255&r1=337254&r2=337255&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/www/cxx_dr_status.html (original)<br>
+++ cfe/trunk/www/cxx_dr_status.html Tue Jul 17 02:23:31 2018<br>
@@ -9991,7 +9991,7 @@ and <I>POD class</I></td><br>
<td><a href="<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1696" rel="noreferrer" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1696</a>">1696</a></td><br>
<td>CD4</td><br>
<td>Temporary lifetime and non-static data member initializers</td><br>
- <td class="svn" align="center">SVN</td><br>
+ <td class="none" align="center">Unknown</td><br>
</tr><br>
<tr class="open" id="1697"><br>
<td><a href="<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1697" rel="noreferrer" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1697</a>">1697</a></td><br>
@@ -10705,7 +10705,7 @@ and <I>POD class</I></td><br>
<td><a href="<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1815" rel="noreferrer" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1815</a>">1815</a></td><br>
<td>CD4</td><br>
<td>Lifetime extension in aggregate initialization</td><br>
- <td class="none" align="center">No</td><br>
+ <td class="none" align="center">Unknown</td><br>
</tr><br>
<tr id="1816"><br>
<td><a href="<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1816" rel="noreferrer" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1816</a>">1816</a></td><br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>