r183869 - Move detection of reference members binding to temporaries from building of
Richard Smith
richard-llvm at metafoo.co.uk
Wed Jun 12 14:51:51 PDT 2013
Author: rsmith
Date: Wed Jun 12 16:51:50 2013
New Revision: 183869
URL: http://llvm.org/viewvc/llvm-project?rev=183869&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp
cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
cfe/trunk/test/CXX/temp/temp.param/p5.cpp
cfe/trunk/test/SemaCXX/warn-dangling-field.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jun 12 16:51:50 2013
@@ -5947,10 +5947,12 @@ def warn_init_ptr_member_to_parameter_ad
"initializing pointer member %0 with the stack address of parameter %1">,
InGroup<DanglingField>;
def warn_bind_ref_member_to_temporary : Warning<
- "binding reference member %0 to a temporary value">,
+ "binding reference %select{|subobject of }1member %0 to a temporary value">,
InGroup<DanglingField>;
def note_ref_or_ptr_member_declared_here : Note<
"%select{reference|pointer}0 member declared here">;
+def note_ref_subobject_of_member_declared_here : Note<
+ "member with reference subobject declared here">;
// For non-floating point, expressions of the form x == x or x != x
// should result in a warning, since these always evaluate to a constant.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jun 12 16:51:50 2013
@@ -2479,15 +2479,7 @@ static void CheckForDanglingReferenceOrP
}
}
- if (isa<MaterializeTemporaryExpr>(Init->IgnoreParens())) {
- // Taking the address of a temporary will be diagnosed as a hard error.
- if (IsPointer)
- return;
-
- S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary)
- << Member << Init->getSourceRange();
- } else if (const DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
// We only warn when referring to a non-reference parameter declaration.
const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
if (!Parameter || Parameter->getType()->isReferenceType())
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jun 12 16:51:50 2013
@@ -2461,6 +2461,7 @@ InitializedEntity InitializedEntity::Ini
{
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 @@ bool InitializedEntity::allowsNRVO() con
}
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 @@ InitializationSequence::Perform(Sema &S,
// 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(),
Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp Wed Jun 12 16:51:50 2013
@@ -116,6 +116,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // e
// -- a non-static data member of rvalue reference type
struct RValue {
int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
+ // expected-warning at -1{{binding reference member 'ri' to a temporary}} expected-note at -1 {{here}}
};
RValue RVa;
RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}
Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp Wed Jun 12 16:51:50 2013
@@ -108,7 +108,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // e
// The restriction on rvalue reference members applies to only the copy
// constructor.
struct RValue {
- int &&ri = 1;
+ int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}
RValue(RValue&&);
};
RValue::RValue(RValue&&) = default;
Modified: cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Wed Jun 12 16:51:50 2013
@@ -43,7 +43,7 @@ class NotDeleted2a { int &a = n; };
NotDeleted2a nd2a;
class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
NotDeleted2b nd2b;
-class NotDeleted2c { int &&a = 0; };
+class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding reference member 'a' to a temporary}} expected-note {{here}}
NotDeleted2c nd2c;
// - any non-variant non-static data member of const qualified type (or array
Modified: cfe/trunk/test/CXX/temp/temp.param/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p5.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.param/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.param/p5.cpp Wed Jun 12 16:51:50 2013
@@ -1,14 +1,13 @@
// RUN: %clang_cc1 -verify %s -std=c++11
-// expected-no-diagnostics
template<const int I> struct S {
decltype(I) n;
- int &&r = I;
+ int &&r = I; // expected-warning 2{{binding reference member 'r' to a temporary value}} expected-note 2{{declared here}}
};
-S<5> s;
+S<5> s; // expected-note {{instantiation}}
template<typename T, T v> struct U {
decltype(v) n;
- int &&r = v;
+ int &&r = v; // expected-warning {{binding reference member 'r' to a temporary value}} expected-note {{declared here}}
};
-U<const int, 6> u;
+U<const int, 6> u; // expected-note {{instantiation}}
Modified: cfe/trunk/test/SemaCXX/warn-dangling-field.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-dangling-field.cpp?rev=183869&r1=183868&r2=183869&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-dangling-field.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-dangling-field.cpp Wed Jun 12 16:51:50 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wdangling-field -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wdangling-field -verify -std=c++11 %s
struct X {
X(int);
@@ -35,3 +35,17 @@ template <typename T> struct S4 {
template struct S4<int>; // no warning from this instantiation
template struct S4<int&>; // expected-note {{in instantiation}}
+
+struct S5 {
+ const X &x; // expected-note {{here}}
+};
+S5 s5 = { 0 }; // ok, lifetime-extended
+
+struct S6 {
+ S5 s5; // expected-note {{here}}
+ S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}}
+};
+
+struct S7 : S5 {
+ S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}}
+};
More information about the cfe-commits
mailing list