Bug 10118 - Bad diagnostic with cast in template argument expression
Summary: Bad diagnostic with cast in template argument expression
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.0.4
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: pmf, ptmf
  Show dependency treegraph
 
Reported: 2003-03-17 03:36 UTC by philippeb
Modified: 2021-07-23 19:49 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 3.4.0, 4.5.3, 4.8.3, 4.9.3, 5.3.0, 6.3.0, 7.0
Last reconfirmed: 2021-07-23 00:00:00


Attachments
ptmctc.cpp (138 bytes, text/plain)
2003-05-21 15:17 UTC, philippeb
Details

Note You need to log in before you can comment on or make changes to this bug.
Description philippeb 2003-03-17 03:36:00 UTC
The cast of a non-virtual member function pointer to a derived class is not working at compile time.

Release:
3.0.4

Environment:
Debian GNU / Linux
Comment 1 philippeb 2003-03-17 03:36:00 UTC
Fix:
?
Comment 2 Wolfgang Bangerth 2003-03-18 00:26:06 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Confirmed:
    -------------------------
    struct A { void foo(); };
    struct B : A {};
    typedef void (B::*B_ptr) ();
    
    template <class T, void (T::* U)()>  struct CT {};
    
    CT<B, (B_ptr) &A::foo>  c;
    --------------------------
    
    g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc
    x.cc:8: error: `{A::foo(), 0}' is not a valid template argument
    x.cc:8: error: it must be a pointer-to-member of the form `&X::Y'
    x.cc:8: error: expected constructor, destructor, or type conversion
    
    This never compiled from 2.95 to present mainline.
    
    W.
Comment 3 Andrew Pinski 2003-07-17 00:06:10 UTC
2.91.66 accepted this so this is a regression.
Comment 4 Mark Mitchell 2003-09-05 18:44:20 UTC
This code is invalid; the cast may not appear as part of a template argument.

Clearly, the error message (with the brace notation) is sub-optimal.

I've removed the target milestone because I don't know if the error message has
regressed; the audit trail says that most versions of G++ have correctly
rejected this code.
Comment 5 Wolfgang Bangerth 2003-09-05 18:49:41 UTC
Since this is invalid code, it's no longer a regression.

Also, the error message is not a regression. 2.95 gives
g/x> c++ -c x.cc
x.cc:7: `(&A::foo)' is not a valid template argument
x.cc:7: it must be a pointer-to-member of the form `&X::Y'
x.cc:7: ANSI C++ forbids declaration `c' with no type

That's about as bad as what we now get. The message is clearly
suboptimal nevertheless, so let's keep this PR open.

W.
Comment 6 Andrew Pinski 2003-12-05 02:44:15 UTC
this is semi-fixed on the mainline (get rid of the "()" and it would be considered fixed, unless 
someone says otherwise. )
pr1011.cc:7: error: `A::foo()' cannot appear in a constant-expression
pr1011.cc:7: error: a casts to a type other than an integral or enumeration type cannot appear in a 
constant-expression
pr1011.cc:7: error: template argument 2 is invalid
pr1011.cc:7: error: expected constructor, destructor, or type conversion
Comment 7 Wolfgang Bangerth 2003-12-05 03:31:09 UTC
I see two open issues here: first, the error message has wrong 
grammar ("a cast_s_"). 
 
The second thing is that what is being attempted here doesn't seem 
to be possible: neither of these work: 
 
CT<B, &A::foo>  c1; 
CT<B, &B::foo>  c2; 
CT<B, (B_ptr)&B::foo>  c3; 
 
The second one is particularly confusing, since &B::foo immediately decays 
to A::*, but this has recently been discussed in another PR and seems to 
be standards conforming. The last one should cast this back, but this 
isn't allowed. The first one should of course be wrong. So we are left 
with a situation where something just can't be done. Someone should 
file a DR for this, this is clearly a less than satisfactory situation... 
 
W. 
Comment 8 Andrew Pinski 2004-08-20 06:52:49 UTC
Slightly error message change:
pr10118.cc:8: error: `A::foo()' cannot appear in a constant-expression
pr10118.cc:8: error: `&' cannot appear in a constant-expression
pr10118.cc:8: error: a cast to a type other than an integral or enumeration type cannot appear in a 
constant-expression
pr10118.cc:8: error: template argument 2 is invalid
pr10118.cc:8: error: invalid type in declaration before ';' token
Comment 9 Gabriel Dos Reis 2004-08-20 07:12:22 UTC
Subject: Re:  Bad diagnostic with cast in template argument expression

"pinskia at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| Slightly error message change:
| pr10118.cc:8: error: `A::foo()' cannot appear in a constant-expression

This is wrong and I know why.  The code cp/error.c is too contrived to
fix it properly.  It is better to rely on the code in
cp/cxx-pretty-print.c to fix it.

| pr10118.cc:8: error: `&' cannot appear in a constant-expression

This does nto make any sense.

-- Gaby
Comment 10 Martin Sebor 2017-02-28 01:15:44 UTC
For the test case in comment #2 GCC 7.0 print the following errors.  The English text of the errors looks fine but the types are still pretty wacky:

$ cat t.C && /ssd/build/gcc-git-svn/gcc/xgcc -B /ssd/build/gcc-git-svn/gcc -S -Wall -Wextra t.C
    struct A { void foo(); };
    struct B : A {};
    typedef void (B::*B_ptr) ();
    
    template <class T, void (T::* U)()>  struct CT {};
    
    CT<B, (B_ptr) &A::foo>  c;
t.C:7:26: error: ‘void (B::*)(){((void (B::*)())A::foo), (0 + 0)}’ is not a valid template argument for type ‘void (B::*)()’
     CT<B, (B_ptr) &A::foo>  c;
                          ^
t.C:7:26: error: it must be a pointer-to-member of the form ‘&X::Y’
t.C:7:26: error: could not convert template argument ‘void (B::*)(){((void (B::*)())A::foo), (0 + 0)}’ from ‘void (B::*)()’ to ‘void (B::*)()’


Clang 5.0 prints a much clearer error message:

t.C:7:11: error: non-type template argument is not a pointer to member constant
    CT<B, (B_ptr) &A::foo>  c;
          ^~~~~~~~~~~~~~~
Comment 11 Andrew Pinski 2021-07-23 19:49:11 UTC
We get now:
<source>:7:26: error: 'void (B::*)(){((void (B::*)())A::foo), 0}' is not a valid template argument for type 'void (B::*)()'
    7 |     CT<B, (B_ptr) &A::foo>  c;
      |                          ^
<source>:7:26: note: it must be a pointer-to-member of the form '&X::Y'
ASM generation compiler returned: 1
<source>:7:26: error: 'void (B::*)(){((void (B::*)())A::foo), 0}' is not a valid template argument for type 'void (B::*)()'
    7 |     CT<B, (B_ptr) &A::foo>  c;
      |                          ^
<source>:7:26: note: it must be a pointer-to-member of the form '&X::Y'
Execution build compiler returned: 1

While clang produces:
<source>:7:11: error: non-type template argument is not a pointer to member constant
    CT<B, (B_ptr) &A::foo>  c;
          ^~~~~~~~~~~~~~~
1 error generated.
ASM generation compiler returned: 1
<source>:7:11: error: non-type template argument is not a pointer to member constant
    CT<B, (B_ptr) &A::foo>  c;
          ^~~~~~~~~~~~~~~

Both are not obvious but gcc is still worse as it has the "{((void (B::*)())A::foo), 0}" part there still.