Bug 80471 - (gcc extension) Forwarding-reference `auto` function parameters do not follow the same rules as template functions or generic lambdas
Summary: (gcc extension) Forwarding-reference `auto` function parameters do not follow...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.0.1
: P3 normal
Target Milestone: 10.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-04-20 09:35 UTC by Vittorio Romeo
Modified: 2020-02-18 17:14 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vittorio Romeo 2017-04-20 09:35:14 UTC
Consider the following code:

    #include <type_traits>

    template<class T>
    decltype(auto) f(T&& a){return a;}

    decltype(auto) g(auto&& a){return a;}

    auto z = [](auto&& a) -> decltype(auto) { return a; };

    int main()
    {
        int i;
        static_assert(std::is_same< decltype(f(i)), int& >::value);
        static_assert(std::is_same< decltype(g(i)), int  >::value); // !!
        static_assert(std::is_same< decltype(z(i)), int& >::value);
    }

On wandbox:
https://wandbox.org/permlink/Js8HmI0XtqFmvkRz

---

The function `g` should intuitively behave like `f` or `z`. Its return type is however deduced as `int` instead of `int&` when an lvalue is passed to it.

Additional context/information:
http://stackoverflow.com/questions/43515229/
Comment 1 paolo@gcc.gnu.org 2017-10-04 21:25:51 UTC
Author: paolo
Date: Wed Oct  4 21:25:20 2017
New Revision: 253432

URL: https://gcc.gnu.org/viewcvs?rev=253432&root=gcc&view=rev
Log:
2017-10-04  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/80471
	* g++.dg/cpp1y/pr80471.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/pr80471.C
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 2 Paolo Carlini 2017-10-04 21:26:37 UTC
Works fine with the released 7.1.0.
Comment 3 GCC Commits 2020-02-11 01:46:39 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:a6ee556c7659877bb59b719f11ca2153e86ded59

commit r10-6571-ga6ee556c7659877bb59b719f11ca2153e86ded59
Author: Patrick Palka <ppalka@redhat.com>
Date:   Sun Feb 9 22:23:25 2020 -0500

    c++: Fix return type deduction with an abbreviated function template
    
    This patch fixes two issues with return type deduction in the presence of an
    abbreviated function template.
    
    The first issue (PR 69448) is that if a placeholder auto return type contains
    any modifiers such as & or *, then the abbreviated function template
    compensation in splice_late_return_type does not get performed for the
    underlying auto node, leading to incorrect return type deduction.  This happens
    because splice_late_return_type does not consider that a placeholder auto return
    type might have modifiers.  To fix this it seems we need to look through
    modifiers in the return type to obtain the location of the underlying auto node
    in order to replace it with the adjusted auto node.  To that end this patch
    refactors the utility function find_type_usage to return a pointer to the
    matched tree, and uses it to find and replace the underlying auto node.
    
    The second issue (PR 80471) is that the AUTO_IS_DECLTYPE flag is not being
    preserved in splice_late_return_type when compensating for an abbreviated
    function template, leading to us treating a decltype(auto) return type as if it
    was an auto return type.  Fixed by making make_auto_1 set the AUTO_IS_DECLTYPE
    flag whenever we're building a decltype(auto) node and adjusting callers
    appropriately.  The test for PR 80471 is adjusted to expect the correct
    behavior.
    
    gcc/cp/ChangeLog:
    
    	PR c++/69448
    	PR c++/80471
    	* type-utils.h (find_type_usage): Refactor to take a tree * and to
    	return a tree *, and update documentation accordingly.
    	* pt.c (make_auto_1): Set AUTO_IS_DECLTYPE when building a
    	decltype(auto) node.
    	(make_constrained_decltype_auto): No need to explicitly set
    	AUTO_IS_DECLTYPE anymore.
    	(splice_late_return_type): Use find_type_usage to find and
    	replace a possibly nested auto node instead of using is_auto.
    	Check test for is_auto into an assert when deciding whether
    	to late_return_type.
    	(type_uses_auto): Adjust the call to find_type_usage.
    	* parser.c (cp_parser_decltype): No need to explicitly set
    	AUTO_IS_DECLTYPE anymore.
    
    libcc1/ChangeLog:
    
    	PR c++/69448
    	PR c++/80471
    	* libcp1plugin.cc (plugin_get_expr_type): No need to explicitly set
    	AUTO_IS_DECLTYPE anymore.
    
    gcc/testsuite/ChangeLog:
    
    	PR c++/69448
    	PR c++/80471
    	* g++.dg/concepts/abbrev3.C: New test.
    	* g++.dg/cpp2a/concepts-pr80471.C: Adjust a static_assert to expect the
    	correct behavior.
    	* g++.dg/cpp0x/auto9.C: Adjust a dg-error directive.
Comment 4 Patrick Palka 2020-02-18 17:14:36 UTC
Target milestone changed to GCC 10