Bug 43382 - [C++0x] ICE with auto return type and variadic templates
Summary: [C++0x] ICE with auto return type and variadic templates
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: 4.5.1
Assignee: Jason Merrill
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-03-15 20:13 UTC by Chris Jefferson
Modified: 2020-04-20 22:56 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-05-26 04:59:29


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Jefferson 2010-03-15 20:13:54 UTC
The following code causes an assert on a recent svn g++, with -std=c++0x. On g++ 4.4 it produces an error. I believe the code to be valid, but am not 100% positive.

#include <vector>

struct Range
{
	int lb;
	int ub;
	Range(int i, int j) : lb(i), ub(j) {}
	Range(const Range& r) = default;
	Range() = default;
};

template<class T>
T deref(const T& t)
{ return t; }

template <class T, template <typename T, typename...> class Cont,
	  class... Args>
auto
deref(const Cont<T>& u, int i, Args... args)
-> decltype(deref(u[i], args...))
{ deref(u[i], args...); }

template <class T, template <typename T, typename...> class Cont,
	  class... Args>
auto
deref(const Cont<T>& u, Range r, Args... args)
-> Cont<decltype(deref(u[0], args...))>
{
	typedef decltype(deref(u[0], args...)) member;
	Cont<member> retval;
	for(int i = r.lb; i <= r.ub; ++i)
	{
		retval.push_back(deref(u[i], args...));
	} 
	return retval;
}



int main(void)
{
	std::vector<std::vector<std::vector<int>>> v;
	int i = deref(v, 1,2,3);
	std::vector<int> j = deref(v, 1, Range(1,2), 3);
}
Comment 1 Paolo Carlini 2010-03-15 23:56:30 UTC
If you could reduce it somewhat, it would be appreciated.

Let's add Jason in CC.
Comment 2 Chris Jefferson 2010-03-16 08:38:59 UTC
Reduced testcase:

template<class T>
struct Container
{ T f() const; };

template<class T>
T deref(const T& t)
{ return t; }


template <class T, class... Args>
auto
deref(const T& u, int r, Args... args)
-> decltype(deref(u.f(), args...))
{ return deref(u.f(), args...); }

int main(void)
{
    Container<Container<int>> v;
    deref(v,1,2);
}
Comment 3 Paolo Carlini 2010-03-16 10:27:59 UTC
Thanks Chris.
Comment 4 Richard Biener 2010-03-16 11:51:44 UTC
4.4 ICEs for me:

> g++-4.4 -S t.C -std=c++0x
t.C: In function ‘int main()’:
t.C:12: internal compiler error: in tsubst_copy, at cp/pt.c:10077
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugs.opensuse.org/> for instructions.
Comment 5 Jason Merrill 2010-05-26 15:00:19 UTC
Subject: Bug 43382

Author: jason
Date: Wed May 26 15:00:02 2010
New Revision: 159873

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159873
Log:
	PR c++/43382
	* pt.c (fn_type_unification): Don't get confused by recursive
	unification.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/variadic101.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c
    trunk/gcc/testsuite/ChangeLog

Comment 6 Jason Merrill 2010-05-26 15:19:00 UTC
Subject: Bug 43382

Author: jason
Date: Wed May 26 15:18:46 2010
New Revision: 159875

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159875
Log:
	PR c++/43382
	* pt.c (fn_type_unification): Don't get confused by recursive
	unification.

Added:
    branches/gcc-4_5-branch/gcc/testsuite/g++.dg/cpp0x/variadic101.C
Modified:
    branches/gcc-4_5-branch/gcc/cp/ChangeLog
    branches/gcc-4_5-branch/gcc/cp/pt.c
    branches/gcc-4_5-branch/gcc/testsuite/ChangeLog

Comment 7 Jason Merrill 2010-05-26 17:15:14 UTC
Fixed for 4.5.1.
Comment 8 GCC Commits 2020-04-20 22:56:13 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

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

commit r10-7835-ga3a4f6be0c7ac1536c4d1def14217840b04dd488
Author: Patrick Palka <ppalka@redhat.com>
Date:   Mon Apr 20 18:34:00 2020 -0400

    c++: Recursive unification with packs and explicit targs [PR94628]
    
    This PR seems to be similar to PR c++/43382, except that the recursive call to
    the variadic function with trailing return type in this testcase is additionally
    given some explicit template arguments.
    
    In the first testcase below, when resolving the recursive call to 'select',
    fn_type_unification first substitutes in the call's explicit template arguments
    before doing unification, and so during this substitution the template argument
    pack for Args is incomplete.
    
    Since the pack is incomplete, the substitution of 'args...' in the trailing
    return type decltype(f(args...)) is handled by the unsubstituted_packs case of
    tsubst_pack_expansion.  But the handling of this case happens _before_ we reset
    local_specializations, and so the substitution ends up reusing the old binding
    for 'args' from local_specializations rather than building a new one.
    
    This patch fixes this issue by setting up local_specializations sooner in
    tsubst_pack_expansion, before the handling of the unsubstituted_packs case.
    It also adds a new policy to local_specialization_stack so that we could use the
    class here to conditionally replace local_specializations.
    
    gcc/cp/ChangeLog:
    
            PR c++/94628
            * cp-tree.h (lss_policy::lss_nop): New enumerator.
            * pt.c (local_specialization_stack::local_specialization_stack): Handle
            an lss_nop policy.
            (local_specialization_stack::~local_specialization_stack): Likewise.
            (tsubst_pack_expansion): Use a local_specialization_stack instead of
            manually saving and restoring local_specializations.  Conditionally
            replace local_specializations sooner, before the handling of the
            unsubstituted_packs case.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/94628
            * g++.dg/cpp0x/variadic179.C: New test.
            * g++.dg/cpp0x/variadic180.C: New test.