Bug 40595 - [C++0x] ICE trying to use sfinae with variadic template pack expansion
Summary: [C++0x] ICE trying to use sfinae with variadic template pack expansion
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: 4.4.1
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: 35569
  Show dependency treegraph
 
Reported: 2009-06-29 18:44 UTC by Jonathan Wakely
Modified: 2009-07-01 10:53 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 Jonathan Wakely 2009-06-29 18:44:24 UTC
template<int N>
struct S
{
    typedef int type;
};

template<typename T>
struct Get
{
    static T get();
};

#ifdef BUG
# define ELLIPSIS ...
#else
# define ELLIPSIS
#endif

template<typename F>
struct B
{
    template<typename ELLIPSIS Args>
        typename S<sizeof( Get<F>::get() (Get<Args>::get() ELLIPSIS) )>::type
        f(Args&& ELLIPSIS a);
};

struct X
{
    bool operator()(int) const;
};

int main()
{
    B<X> b;
    b.f(1);
} 

jwakely@gcc16:~/src/tests$ g++ -std=c++0x  -c pr.cc 
jwakely@gcc16:~/src/tests$ g++ -std=c++0x  -c pr.cc  -DBUG
pr.cc: In instantiation of ‘B<X>’:
pr.cc:35:10:   instantiated from here
pr.cc:25:9: internal compiler error: in tsubst, at cp/pt.c:9733
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

The code compiles fine with a single template parameter, but not with a parameter pack of size one.

I'm trying to use SFINAE to disable overloads when a function call expression is invalid, which is needed to implement std::bind for C++0x
Comment 1 Jonathan Wakely 2009-06-30 09:53:28 UTC
(In reply to comment #0)
> I'm trying to use SFINAE to disable overloads when a function call expression
> is invalid, which is needed to implement std::bind for C++0x
 
N.B. the use of an invalid expression in a sizeof context is not valid in C++03, but the SFINAE rules were extended to cover general expressions by n2634 so I believe the code is valid in C++0x (see 14.9.2 [temp.deduct] p8 in WP n2914) and should result in a type deduction failure not a hard error.




Comment 2 Paolo Carlini 2009-06-30 10:11:33 UTC
Jon, are there any hopes for a temporary workaround for std::bind?
Comment 3 Jonathan Wakely 2009-06-30 10:52:46 UTC
The basic problem is I've made std::result_of too good ;-)

My new result_of uses decltype to determine the exact result type of an arbitrary function call, including resolving overloads based on whether the callable object and arguments are lvalues or rvalues.

If you look at struct _Bind in include/tr1_impl/functional you will see it has multiple overloads of operator() and __call() with different cv-qualifiers. Those overloads are used to ensure the cv qualifiers of the functor _M_f are the same as the cv qualifiers of the _Bind object, as required by [func.bind.bind].  The return type of those overloads uses result_of, but that involves forming invalid expressions e.g. when there is no const volatile operator() on the functor type.

I can solve that by using sfinae to remove the overloads when the expression is invalid, but this bug prevents it.

A temporary solution would be to remove the const and volatile overloads for now.  That will work for 99% of cases, and will pass most of the testsuite, because users don't usually invoke const or volatile binders.

This would fail under that workaround:

void f(int);
auto const b = std::bind(f, 1);
b();

Another options would be to support the example above, but to fudge the result_of so that it does not use the correct cv qualifiers.  That would fail for this case:

struct F {
  char* operator() const;
  int operator();
};

i.e. when the cv qualifiers of the function object are significant and affect the result type of the function call operator. For that type, using result_of with the wrong cv qualifiers would cause _Bind to fail, because it infers a result tyep that is not convertible to the actual result of the call.
Comment 4 Jason Merrill 2009-06-30 19:36:51 UTC
Subject: Bug 40595

Author: jason
Date: Tue Jun 30 19:36:36 2009
New Revision: 149117

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=149117
Log:
	PR c++/40595
	* pt.c (tsubst_pack_expansion): Handle unexpanded packs in an
	EXPR_PACK_EXPANSION.

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

Comment 5 Jason Merrill 2009-06-30 19:45:40 UTC
Subject: Bug 40595

Author: jason
Date: Tue Jun 30 19:45:21 2009
New Revision: 149118

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=149118
Log:
	PR c++/40595
	* pt.c (tsubst_pack_expansion): Handle unexpanded packs in an
	EXPR_PACK_EXPANSION.


Added:
    branches/gcc-4_4-branch/gcc/testsuite/g++.dg/cpp0x/variadic94.C
      - copied unchanged from r149117, trunk/gcc/testsuite/g++.dg/cpp0x/variadic94.C
Modified:
    branches/gcc-4_4-branch/gcc/cp/ChangeLog
    branches/gcc-4_4-branch/gcc/cp/pt.c
    branches/gcc-4_4-branch/gcc/testsuite/ChangeLog

Comment 6 Jason Merrill 2009-06-30 19:49:19 UTC
Fixed for 4.4.1.
Comment 7 Mikael Pettersson 2009-07-01 10:53:55 UTC
(In reply to comment #6)
> Fixed for 4.4.1.

This test case causes the same ICE in tsubst also with gcc-4.3.4.

After packporting the ICE fix, 4.3.4 instead fails with:

variadic94.C: In function 'int main()':
variadic94.C:32: sorry, unimplemented: call_expr cannot be mangled due to a defect in the C++ ABI

Is this an inherent limitation in 4.3 or just another unfixed bug?

Comment 8 Jason Merrill 2009-07-01 20:01:58 UTC
Subject: Re:  [C++0x] ICE trying to use sfinae with variadic
 template pack expansion

On 07/01/2009 06:53 AM, mikpe at it dot uu dot se wrote:
> Is this an inherent limitation in 4.3 or just another unfixed bug?

I'm not planning to fix C++0x bugs in 4.3.

Jason