Bug 38958 - 'unused variable' warning emitted when extending the lifetime of a returned RAII type by holding a reference to const despite delayed destructor side-effects. [dtor]
Summary: 'unused variable' warning emitted when extending the lifetime of a returned R...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.2.1
: P3 normal
Target Milestone: 4.9.0
Assignee: Paolo Carlini
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2009-01-24 13:32 UTC by fs.open.work
Modified: 2015-01-07 15:18 UTC (History)
2 users (show)

See Also:
Host: i686-pc-linux-gnu, mingw
Target: i686-pc-linux-gnu, mingw, arm-xscale-linux-gnu
Build: i686-pc-linux-gnu, mingw
Known to work:
Known to fail:
Last reconfirmed: 2009-01-30 15:23:42


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description fs.open.work 2009-01-24 13:32:18 UTC
Given a class C with destructor side-effects (as is common with RAII classes) and a function fn which returns a rvalue of type C

   C fn()

the lifetime of the rvalue returned by fn() can be extended by holding a reference to const C with

   C const& r = fn()

Although r is not explicitly referenced subsequently in the calling scope, upon leaving scope the rvalue's dtor will be invoked.  So r is implicitly 'used'.

The assignment
   C c = fn()
has the same effect because of return value optimization.  Though copy-semantics must be checked, the copy is elided.

G++ generates an 'unused variable' warning for 'r' but not for 'c'.

The following program demonstrates the warning.  The 'volatile int g' and forced-inline noise is to compare the generated assembly to that generated when the const& is removed.  The output in both cases is equivalent (identical at -O2; the only difference in lower optimizations is an additional indirection with the const& present).

----------------------------------
volatile int g; // for obvious side-effect visibility in generated assembly

struct Lock
{
   __attribute__((always_inline)) // for obvious side-effect visibility in generated assembly

   ~Lock() { g = 0; }
};

Lock AcquireLock() { return Lock(); }

int main()
{
   Lock const& lock = AcquireLock();
   g = 1;
   g = 2;
   g = 3;
}
----------------------------------
In both cases, const& present and not present, the sequence of values moved into g are 1,2,3,0 as desired.

This might be related to Bug 10416 but does not appear to duplicate it since removing the const& removes the warning in this case.

This warning can be avoided by relying on return-value optimization and using the assignment without the const& to generate equivalent code but I don't think it should be emitted at all if it is not for the RVO version.  I would expect it emitted for both or not emitted for either.
Comment 1 Wolfgang Bangerth 2009-01-30 15:23:42 UTC
Confirmed.
Comment 2 Paolo Carlini 2013-06-12 13:57:55 UTC
Mine.
Comment 3 Paolo Carlini 2013-06-12 21:38:15 UTC
Fixed for 4.9.0.
Comment 4 Jonathan Wakely 2014-07-28 14:38:00 UTC
*** Bug 61935 has been marked as a duplicate of this bug. ***
Comment 5 Paolo Carlini 2014-11-02 08:50:15 UTC
*** Bug 63657 has been marked as a duplicate of this bug. ***
Comment 6 Jason Merrill 2014-11-22 02:22:10 UTC
Author: jason
Date: Sat Nov 22 02:21:35 2014
New Revision: 217957

URL: https://gcc.gnu.org/viewcvs?rev=217957&root=gcc&view=rev
Log:
	PR c++/63657
	PR c++/38958
	* call.c (set_up_extended_ref_temp): Set TREE_USED on the reference
	if the temporary has a non-trivial destructor.
	* decl.c (poplevel): Don't look through references.

Added:
    trunk/gcc/testsuite/g++.dg/warn/Wunused-var-22.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/decl.c
Comment 7 Jason Merrill 2015-01-07 15:18:37 UTC
Author: jason
Date: Wed Jan  7 15:18:05 2015
New Revision: 219306

URL: https://gcc.gnu.org/viewcvs?rev=219306&root=gcc&view=rev
Log:
	PR c++/63657
	PR c++/38958
	* call.c (set_up_extended_ref_temp): Set TREE_USED on the reference
	if the temporary has a non-trivial destructor.
	* decl.c (poplevel): Don't look through references.

Added:
    branches/gcc-4_9-branch/gcc/testsuite/g++.dg/warn/Wunused-var-22.C
Modified:
    branches/gcc-4_9-branch/gcc/cp/ChangeLog
    branches/gcc-4_9-branch/gcc/cp/call.c
    branches/gcc-4_9-branch/gcc/cp/decl.c