Bug 18950

Summary: specialization of template class with inner template members
Product: gcc Reporter: Boris Dorès <boris>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: jwakely.gcc
Priority: P2 Keywords: rejects-valid
Version: 3.4.3   
Target Milestone: ---   
Host: i686-pc-linux-gnu Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu Known to work: 4.10.0, 4.8.0, 4.9.0
Known to fail: 2.95.3, 3.0.4, 3.2.3, 3.3.2, 3.4.3, 4.0.0 Last reconfirmed: 2004-12-13 15:27:08

Description Boris Dorès 2004-12-13 09:42:33 UTC
The following code used to compile fine with gcc 3.3 (linux x86), but
doesn't anymore with gcc 3.4 (just as a hint, it seems to compile fine
with Comeau) :

template<class T1,int N1>
class Class
{
public:
   template<class T2,int N2> T2 function( T2 param );
};

template<>
template<class T2,int N2>
T2 Class<int,1>::function( T2 param )
{ // line 11
        return param * N2;
}

int main()
{
        Class<int,1> instance;
        return instance.function<char,4>( 12 );
}

  This produces the following output:

test-gcc34.cpp:11: error: template-id `function<>' for `T2 Class<int,
   1>::function(T2)' does not match any template declaration
test-gcc34.cpp:11: error: erreur de syntaxe before `{' token

  It works if we add the specialized declaration of the class "Class":

template<>
class Class<int,1>
{
public:
   template<class T2,int N2> T2 function( T2 param );
};

  but this can be painful if "Class" contains a lot more members.

  It also works if "function" is only templated by one argument :

template<>
template<class T2>
T2 Class<int,1>::function( T2 param )
{ // line 11
        return param * 2;
}

  Thanks.
Comment 1 Kriang Lerdsuwanakij 2004-12-13 15:27:08 UTC
Should be allowed according to 14.7.3/16.  All my GCC versions
fail to compile the testcase (maybe some 3.3.x does) so I can't 
verify that it's a regression.

The problem is some incorrect logic in 'determine_specialization':
it tries to deduce N2 from

  template<> template<class T2,int N2>
    T2 Class<int,1>::function( T2 param )

to match against

  template<class T1,int N1> template<class T2,int N2>
    T2 Class<T1,N1>::function( T2 param );
Comment 2 Andrew Pinski 2004-12-13 15:54:56 UTC
3.3.2 also rejects this code also:
pr18950.cc:11: error: template-id `function<>' for `T2 Class<int, 
   1>::function(T2)' does not match any template declaration
pr18950.cc:11: error: syntax error before `{' token
Comment 3 Boris Dorès 2004-12-13 17:36:01 UTC
(In reply to comment #2)
> 3.3.2 also rejects this code also:

  I'm really sorry, it seems I oversimplified our real test case
(the previous problem might be related, but indeed it's not a regression).
  
  The following code is a closer version of what we have, and this time
it compiles fine with g++ 3.3.1, but not with g++ 3.4.0 :

template<class T1,int N1>
class Class
{
public:
    template <class T2,int N2> void function( const Class<T2,N2>& );
};

template<>
template<class T2,int N2>
void Class<int,1>::function( const Class<T2,N2>& param ) 
{
    param;// line 12
}

int main()
{
    Class<int,1> instance;
    Class<char,2> param;
    instance.function( param );
}

  The output is :

test-gcc34.cpp: In member function `void Class<T1, N1>::function(const Class<T2,
N2>&) [with T2 = T2, int N2 = N2, T1 = int, int N1 = 1]':
test-gcc34.cpp:12: error: `param' undeclared (first use this function)
test-gcc34.cpp:12: error: (Each undeclared identifier is reported only once for
each function it appears in.)


  Sorry about the misinformation in the first place.
Comment 4 Andrew Pinski 2004-12-13 18:09:28 UTC
(In reply to comment #3)
> (In reply to comment #2)
> 
>   Sorry about the misinformation in the first place.

I split this off to PR 18962, yes that testcase is a regression, but I think the problem which causes to 
reject the first testcase and the second one, is different which is why I split it off to a new bug report.
Comment 5 Paolo Carlini 2014-07-07 08:58:53 UTC
Fixed looong time ago.