Move detection of reference members binding to temporaries from building of
CXXCtorInitializers to the point where we perform the questionable lifetime
extension. This exposed a selection of false negatives in the warning.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183869 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index b678f91..a4bccac 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2461,6 +2461,7 @@
{
InitializedEntity Result;
Result.Kind = EK_Base;
+ Result.Parent = 0;
Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
@@ -2553,6 +2554,7 @@
}
unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
+ assert(getParent() != this);
unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0;
for (unsigned I = 0; I != Depth; ++I)
OS << "`-";
@@ -5566,9 +5568,33 @@
// entity's lifetime.
const ValueDecl *ExtendingDecl =
getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl)
+ if (ExtendingDecl) {
performLifetimeExtension(CurInit.get(), ExtendingDecl);
+ // Warn if a field lifetime-extends a temporary.
+ if (isa<FieldDecl>(ExtendingDecl)) {
+ bool IsSubobjectMember = false;
+ for (const InitializedEntity *Ent = Entity.getParent(); Ent;
+ Ent = Ent->getParent()) {
+ if (Ent->getKind() != InitializedEntity::EK_Base) {
+ IsSubobjectMember = true;
+ break;
+ }
+ }
+ S.Diag(CurInit.get()->getExprLoc(),
+ diag::warn_bind_ref_member_to_temporary)
+ << ExtendingDecl << CurInit.get()->getSourceRange()
+ << IsSubobjectMember;
+ if (IsSubobjectMember)
+ S.Diag(ExtendingDecl->getLocation(),
+ diag::note_ref_subobject_of_member_declared_here);
+ else
+ S.Diag(ExtendingDecl->getLocation(),
+ diag::note_ref_or_ptr_member_declared_here)
+ << /*IsPointer*/false;
+ }
+ }
+
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
Entity.getType().getNonReferenceType(), CurInit.get(),