diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 28 | ||||
-rw-r--r-- | clang/test/CXX/special/class.copy/p11.0x.copy.cpp | 1 | ||||
-rw-r--r-- | clang/test/CXX/special/class.copy/p11.0x.move.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/special/class.ctor/p5-0x.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.param/p5.cpp | 9 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-dangling-field.cpp | 16 |
8 files changed, 53 insertions, 19 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 302ec8b08cd..ac76e4d400b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5947,10 +5947,12 @@ def warn_init_ptr_member_to_parameter_addr : Warning< "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. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 008bb73dc80..5d6eab0f173 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2479,15 +2479,7 @@ static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, } } - 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()) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index b678f91bf72..a4bccacb2da 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2461,6 +2461,7 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, { 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() const { } 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(), diff --git a/clang/test/CXX/special/class.copy/p11.0x.copy.cpp b/clang/test/CXX/special/class.copy/p11.0x.copy.cpp index fab3b9dd7bf..011c1e9a876 100644 --- a/clang/test/CXX/special/class.copy/p11.0x.copy.cpp +++ b/clang/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -116,6 +116,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy c // -- 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@-1{{binding reference member 'ri' to a temporary}} expected-note@-1 {{here}} }; RValue RVa; RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}} diff --git a/clang/test/CXX/special/class.copy/p11.0x.move.cpp b/clang/test/CXX/special/class.copy/p11.0x.move.cpp index ff9478be8b4..ebcce491c40 100644 --- a/clang/test/CXX/special/class.copy/p11.0x.move.cpp +++ b/clang/test/CXX/special/class.copy/p11.0x.move.cpp @@ -108,7 +108,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy c // 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; diff --git a/clang/test/CXX/special/class.ctor/p5-0x.cpp b/clang/test/CXX/special/class.ctor/p5-0x.cpp index 0f4add8c974..2360345a484 100644 --- a/clang/test/CXX/special/class.ctor/p5-0x.cpp +++ b/clang/test/CXX/special/class.ctor/p5-0x.cpp @@ -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 diff --git a/clang/test/CXX/temp/temp.param/p5.cpp b/clang/test/CXX/temp/temp.param/p5.cpp index 67efc4e4816..c25868267e4 100644 --- a/clang/test/CXX/temp/temp.param/p5.cpp +++ b/clang/test/CXX/temp/temp.param/p5.cpp @@ -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}} diff --git a/clang/test/SemaCXX/warn-dangling-field.cpp b/clang/test/SemaCXX/warn-dangling-field.cpp index 95f8c61ebb7..eb65bd06692 100644 --- a/clang/test/SemaCXX/warn-dangling-field.cpp +++ b/clang/test/SemaCXX/warn-dangling-field.cpp @@ -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}} +}; |