From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1479 invoked by alias); 10 Oct 2014 14:02:05 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 1042 invoked by uid 48); 10 Oct 2014 14:02:00 -0000 From: "steffen.muething at iwr dot uni-heidelberg.de" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/63506] New: GCC deduces wrong return type of operator*() inside template functions Date: Fri, 10 Oct 2014 14:02:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 4.9.1 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: steffen.muething at iwr dot uni-heidelberg.de X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter attachments.created Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2014-10/txt/msg00780.txt.bz2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63506 Bug ID: 63506 Summary: GCC deduces wrong return type of operator*() inside template functions Product: gcc Version: 4.9.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: steffen.muething at iwr dot uni-heidelberg.de Created attachment 33681 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33681&action=edit Minimal working example based on std::vector When trying to convert some iterators in our numerics library DUNE (dune-project.org) to return temporaries instead of const refs, I stumbled over the following bug in GCC 4.8.3 and 4.9.1: Given a class with an operator*() that returns a temporary: struct iterator { ... proxy operator*() const { return ...; } proxy get() const { return ...; } }; the expression 'decltype(*it())' should yield 'proxy', and a variable declared with 'auto&& x = *it;' should be of type 'proxy&&'. The above is true inside normal functions: void bar(iterator it) { typedef decltype(*it()) P; // P == proxy auto&& x = *it; // decltype(x) == proxy&& } But inside a function template, 'decltype(*it())' becomes 'proxy&', and 'auto&& x = *it' fails with a compiler error: template void foo(T t, iterator it) { typedef decltype(*it()) P; // P == proxy& auto&& x = *it; // compiler error, see below } error: invalid initialization of non-const reference of type 'proxy&' from an rvalue of type 'proxy' For some reason, the compiler deduces the wrong type early on and then fails when it later realizes the correct return type... This problem can easily be observed with a std::vector, which returns a proxy from its iterator. I have attached a minimal working example: The contained code (which creates a vector and iterates over its contents with a range-based for loop using auto&&) works in main() and in a normal function bar(), but it fails to compile in foo(), which is a function template. GCC 4.6 and 4.7 compile foo() correctly.