Bug 31584 - [DR502] nested enum not considered dependent
Summary: [DR502] nested enum not considered dependent
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.2
: P3 normal
Target Milestone: 4.3.0
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2007-04-15 21:14 UTC by Markus Werle
Modified: 2023-06-05 08:53 UTC (History)
6 users (show)

See Also:
Host: i586-suse-linux
Target:
Build:
Known to work:
Known to fail: 4.4.3, 4.5.2, 4.6.0
Last reconfirmed: 2010-05-03 13:01:44


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Werle 2007-04-15 21:14:58 UTC
Hi!

The following code snippet leads to an ICE, but I am not sure
whether the stuff I am trying to do is valid.
Any pointer to info about that also appreciated.

Target: i586-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --libexecdir=/usr/lib --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.1.2 --enable-ssp --disable-libssp --disable-libgcj --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit --enable-libstdcxx-allocator=new --program-suffix=-4.1 --enable-version-specific-runtime-libs --without-system-libunwind --with-cpu=generic --host=i586-suse-linux
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)



enum Outer { a, b };

template <class T>
class C
{
public:
  enum Inner { c, d };
  template<Inner I, int dummy> struct Dispatcher;

  template<int dummy> struct Dispatcher<c, dummy> 
  {
    static const Outer Show = a;
  };

  template<int dummy> struct Dispatcher<d, dummy> 
  {
    static const Outer Show = b;
  };

public:
  template <Inner I> void DoSomething(int j)
  {
    typedef Dispatcher<I, 1> dispatcher_t;
    static const Outer o = dispatcher_t::Show;
  }
};


int main()
{
  C<double> Test;
  Test.DoSomething<C<double>::c>(1);
}
Comment 1 Andrew Pinski 2007-04-16 07:43:22 UTC
The trunk gives:
t.cc: In member function 'void C<T>::DoSomething(int) [with C<T>::Inner I = c, T = double]':
t.cc:32:   instantiated from here
t.cc:24: error: incomplete type 'C<double>::Dispatcher<c, 1>' used in nested name specifier


Which seems likes the correct error message.
Comment 2 Markus Werle 2007-04-16 10:31:11 UTC
The compiler at 
http://www.comeaucomputing.com/tryitout/
has absolutely no problems with the code.

M$-VC8 says:
error C2754: 'C<T>::Dispatcher<c,dummy>' : a partial specialization cannot have a dependent non-type template parameter
which somehow is an error message that clearly states what might be wrong.
The "incomplete type" statement is somehow misleading - IMHO

Could you change the error message in this case?

Of course I disagree with gcc and VC8 here.
Any pointer to a TR on this subject?

Best Regards,

Markus
Comment 3 Markus Werle 2007-04-18 07:51:27 UTC
I started a discussion about this code on
comp.lang.c++.moderated, subject  
"enum in template memfun in class template - valid C++?" 
see
<http://groups.google.com/groups/profile?enc_user=IUBmLhUAAACyipKMT4DNptGfylSI-1gK9h3i3SmjGmAJbX05nZ-8fQ>

Your turn.

Markus  
Comment 5 Jonathan Wakely 2010-04-28 18:47:05 UTC
compiles without error using 4.4.3 or 4.6.0
Comment 6 Markus Werle 2010-05-03 12:53:32 UTC
Hi!

Though I love the fact that this code now compiles, I am still unsure whether this is the right thing to have.
From http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#502 I see that 
the proposed resolution (February, 2010) stands against what David Vandevoorde said in http://groups.google.de/group/comp.lang.c++.moderated/browse_thread/thread/8c3b8a84ed78b003/4d9603171894a75d?hl=de#4d9603171894a75d
and the enum now is dependent and so IMHO the code should not compile.
Maybe I missed something. Could you please shed some more light on this?

Markus Werle
Comment 7 Jonathan Wakely 2010-05-03 13:01:44 UTC
I didn't realise there was a DR about this, confirm ...
Comment 8 Jonathan Wakely 2010-05-03 13:02:05 UTC
... and suspend until the issue is ready
Comment 9 Markus Werle 2010-09-15 09:03:51 UTC
Hi!

Looks like http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#502
now has a resolution, namely that a type is dependent if it is
a nested class or enumeration that is a member of the current instantiation.
So though the voting might not be through, the compilers could already adopt the proposed behavior and give some informational error message.

-> Change Status back to new?

Markus

Comment 10 Jonathan Wakely 2011-05-05 00:47:58 UTC
unsuspending, DR 502 is part of the FDIS
Comment 11 Jonathan Wakely 2011-05-05 17:32:15 UTC
Summary changed, as there's no ICE now. This is 'accepts-invalid' because DR502 means C<T>::Inner is dependent, and [temp.class.spec]/8 says specialized non-type arguments shall not have dependent types.


Reduced:

template <class T>
struct C
{
  enum Inner { c };

  template<Inner I, int dummy> struct Dispatcher;

  template<int dummy> struct Dispatcher<c, dummy> 
  { };

};

int main()
{
  C<double> Test;
}

expected error would be something like:

error: type 'C<T>::Inner' of template argument 'c' depends on a template parameter
Comment 12 Andrew Pinski 2021-08-04 21:41:38 UTC
GCC, ICC, clang and MSVC all accept the testcase in comment #11.
Comment 13 Richard Smith 2023-06-04 23:25:05 UTC
(In reply to Andrew Pinski from comment #12)
> GCC, ICC, clang and MSVC all accept the testcase in comment #11.

I believe the testcase is valid. The instantiation of `C<double>` looks like this:

struct C<double>
{
  enum Inner { c };

  template<Inner I, int dummy> struct Dispatcher;

  template<int dummy> struct Dispatcher<c, dummy> 
  { };

};

... and the template argument `c` here refers to the non-dependent enumeration constant `C<double>::c`.

The rule governing whether the original template `C` is valid is [temp.res.general]/6 (https://eel.is/c++draft/temp.res.general#6), and in particular:

> no diagnostic shall be issued for a template for which a valid specialization can be generated

Because `C` has valid specializations, it's valid.
Comment 14 Jonathan Wakely 2023-06-05 08:53:37 UTC
So there's no bug now then. The error in comment 1 was probably fixed by:

commit g:dc28490d05f5ef25c5ff24ef946f48f402a20be8
Author: Jason Merrill
Date:   Tue Sep 4 13:27:21 2007

    re PR c++/14032 (Specialization of inner template using outer template argument doesn't work)
    
            PR c++/14032
            * pt.c (most_specialized_class): Substitute outer template
            arguments into the arguments of a member template partial
            specialization.
            (strip_innermost_template_args): New fn.
    
    From-SVN: r128076

And so this was fixed for GCC 4.3.0