[Bug c++/104230] Non-type template arguments of reference and pointer type fail when initialized by pointer to member operator

2022-05-22 Thread anton at socialhacker dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104230

--- Comment #3 from anton at socialhacker dot com ---
I've found the relevant discussion about the correct way to mangle subobject
references in template parameters here:

https://github.com/itanium-cxx-abi/cxx-abi/issues/47

It looks like Clang already has this implemented.  but I'm not sure which
version of the compiler has the referenced commits.

[Bug c++/104230] Non-type template arguments of reference and pointer type fail when initialized by pointer to member operator

2022-01-31 Thread anton at socialhacker dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104230

--- Comment #2 from anton at socialhacker dot com ---
Hmm, sorry, still learning the bugzilla UI.  I thought that patch would be
attached to my next comment.  I don't believe that patch is a solution to the
problem.  It was just a way I was able to make progress debugging the issue.  I
followed that patch with one that allowed GCC to mangle the resulting
POINTER_PLUS_EXPR.  But the end result was that the two template instantiations
were not considered the same (as far as __is_same was concerned).

I'm pretty sure that the problem is upstream instead of downstream from the
location where the diagnostic is generated (in invalid_tparm_referent_p).  And
I've been working my way backwards into the parser, but it's much slower going
for me.  I've found where the two different parse trees are generated for the
two different version of the template parameters.  But they happen in such
different portions of the parser I'm not sure at all how to have them generate
the same tree eventually, which is I'm guessing the right answer to the
problem.

That is, instead of generating a COMPONENT_REF for the accepted form, and a
POINTER_PLUS_EXPR for the rejected form, GCC should probably be generating
COMPONENT_REF for both.  But I think it's forgotten the required information to
do that conversion from POINTER_PLUS_EXPR by the time it's needed.

I'm guessing someone who knows the parser side well might have a better chance
at seeing how that should be done.

[Bug c++/104230] Non-type template arguments of reference and pointer type fail when initialized by pointer to member operator

2022-01-31 Thread anton at socialhacker dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104230

--- Comment #1 from anton at socialhacker dot com ---
Created attachment 52321
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52321=edit
Patch to get member references via pointers accepted as template arguments

[Bug c++/104230] New: Non-type template arguments of reference and pointer type fail when initialized by pointer to member operator

2022-01-25 Thread anton at socialhacker dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104230

Bug ID: 104230
   Summary: Non-type template arguments of reference and pointer
type fail when initialized by pointer to member
operator
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: anton at socialhacker dot com
  Target Milestone: ---

I believe that GCC incorrectly rejects non-type template arguments of pointer
and reference type that were generated by using the pointer to member operator. 

My reading of "P1907R1: Inconsistencies with non-type template parameters" [1]
makes me think that these uses should be acceptable.  In particular the change
to "13.4.2 [temp.arg.nontype] paragraph 2" moves the restriction of passing a
reference to a subobject so that it only applies to subobjects of already
disallowed values (temporaries, string literals ...).  And it looks like that's
working when using direct member access operators, but not when using pointer
to member operators.  And nothing there seems to indicate how the reference or
pointer is generated, so presumably any valid constant expression that
generates a valid pointer or reference should be acceptable.

Below is a simple test case that fails on both the trunk [2] and 11.2 [3]
versions on compiler explorer.

struct T { int a; int b; } t;

template  struct U {};

U<> u1;
U<> u2;
U<(&(t.*(::a)))> u3; // Interestingly doesn't fail, good?
U<(&(t.*(::b)))> u4; // Fails, shouldn't fail in C++20 I believe

template  struct V {};

V v1;
V v2;
V<(t.*(::a))> v3; // Fails, shouldn't fail in C++20 I believe
V<(t.*(::b))> v4; // Fails, shouldn't fail in C++20 I believe

Both compiler version produce the same output when run with `--std=c++20
-Wall`:

:8:18: error: '(((int*)(& t)) + 4)' is not a valid template
argument for 'int*' because it is not the address of a variable
8 | U<(&(t.*(::b)))> u4;
  |  ^
:14:15: error: '&(int&)(& t)' is not a valid template argument of
type 'int&' because '(int&)(& t)' is not a variable
   14 | V<(t.*(::a))> v3;
  |   ^
:15:15: error: '&(((int&)(& t)) + 4)' is not a valid template
argument of type 'int&' because '(((int&)(& t)) + 4)' is not a variable
   15 | V<(t.*(::b))> v4;
  |   ^

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1907r1.html

[2] gcc version 12.0.1 20220125 (experimental)
(Compiler-Explorer-Build-gcc-bb99171b9b0f01a46bfca2d3cbd52fc6faf6cbaa-binutils-2.36.1)

[3] gcc version 11.2.0 (Compiler-Explorer-Build-gcc--binutils-2.36.1)