Bug 85437 - [8 Regression] member pointer static upcast rejected in a constexpr context
Summary: [8 Regression] member pointer static upcast rejected in a constexpr context
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.0
: P1 normal
Target Milestone: 8.0
Assignee: Nathan Sidwell
URL:
Keywords: rejects-valid
: 85438 (view as bug list)
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2018-04-17 14:54 UTC by Martin Sebor
Modified: 2024-01-13 16:56 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work: 7.3.1
Known to fail:
Last reconfirmed: 2018-04-17 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2018-04-17 14:54:08 UTC
The following valid test case (extracted from bug 70248) is accepted by GCC 7 (and Clang and ICC) but rejected by GCC 8:

$ cat pr70248.C && gcc -S -Wall pr70248.C
struct A {};
struct B : A { int x; };
constexpr int A::*bx = static_cast<int(A::*)>(&B::x);

pr70248.C:4:24: error: a reinterpret_cast is not a constant expression
 constexpr int A::*bx = static_cast<int(A::*)>(&B::x);
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 1 Martin Sebor 2018-04-17 14:56:32 UTC
The first revision to reject the test case is r249088:

Overhaul pointer-to-member conversion and template argument handling.

	* call.c (standard_conversion): Avoid creating ck_pmem when the
	class type is the same.
	* cvt.c (can_convert_qual): Split from
	perform_qualification_conversions.
	* constexpr.c (cxx_eval_constant_expression): Check it.
	* typeck.c (convert_ptrmem): Only cplus_expand_constant if
	adjustment is necessary.
	* pt.c (check_valid_ptrmem_cst_expr): Compare class types.
	(convert_nontype_argument): Avoid redundant error.
Comment 2 Marek Polacek 2018-04-17 14:58:38 UTC
Confirmed.
Comment 3 Jakub Jelinek 2018-04-17 15:01:42 UTC
*** Bug 85438 has been marked as a duplicate of this bug. ***
Comment 4 Jakub Jelinek 2018-04-17 15:07:47 UTC
convert_ptrmem here creates a NOP_EXPR around the PTRMEM_CST, even when it is for a static cast rather than reinterpret_cast.  The OFFSET_TYPEs are different, but they have the same TREE_TYPE etc.
Then constexpr.c doesn't consider that cast to be usable in constant expressions and because it is called with allow_non_constant, it wraps the new PTRMEM_CST with another NOP_EXPR and that is where following constexpr.c call errors on.
Comment 5 Jakub Jelinek 2018-04-17 15:10:45 UTC
(gdb) p debug_tree (type)
 <offset_type 0x7fffefd9d150
    type <integer_type 0x7fffefc625e8 int public type_6 SI
        size <integer_cst 0x7fffefc650c0 constant 32>
        unit-size <integer_cst 0x7fffefc650d8 constant 4>
        align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefc625e8 precision:32 min <integer_cst 0x7fffefc65078 -2147483648> max <integer_cst 0x7fffefc65090 2147483647>
        pointer_to_this <pointer_type 0x7fffefc6aa80>>
    DI
    size <integer_cst 0x7fffefc45e70 type <integer_type 0x7fffefc620a8 bitsizetype> constant 64>
    unit-size <integer_cst 0x7fffefc45e88 type <integer_type 0x7fffefc62000 sizetype> constant 8>
    align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefd9d150 basetype <record_type 0x7fffefd88150 A>>
$4 = void
(gdb) p debug_tree (op->typed.type)
 <offset_type 0x7fffefd9d3f0
    type <integer_type 0x7fffefc625e8 int public type_6 SI
        size <integer_cst 0x7fffefc650c0 constant 32>
        unit-size <integer_cst 0x7fffefc650d8 constant 4>
        align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefc625e8 precision:32 min <integer_cst 0x7fffefc65078 -2147483648> max <integer_cst 0x7fffefc65090 2147483647>
        pointer_to_this <pointer_type 0x7fffefc6aa80>>
    DI
    size <integer_cst 0x7fffefc45e70 type <integer_type 0x7fffefc620a8 bitsizetype> constant 64>
    unit-size <integer_cst 0x7fffefc45e88 type <integer_type 0x7fffefc62000 sizetype> constant 8>
    align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefd9d3f0 basetype <record_type 0x7fffefd889d8 B>>

Ah, one has basetype A, the other B, and both:
4600		    if (same_type_ignoring_top_level_qualifiers_p (type,
4601								   TREE_TYPE (op))
4602			|| can_convert_qual (type, op))
tests fail in this case.
Comment 6 Alexandre Oliva 2018-04-18 03:47:30 UTC
FTR, there's a patch with various caveats at https://gcc.gnu.org/ml/gcc-patches/2018-04/msg00852.html
Comment 7 Jakub Jelinek 2018-04-25 07:10:49 UTC
Author: jakub
Date: Wed Apr 25 07:10:16 2018
New Revision: 259629

URL: https://gcc.gnu.org/viewcvs?rev=259629&root=gcc&view=rev
Log:
	PR c++/85437
	PR c++/49171
	* cp-tree.h (REINTERPRET_CAST_P): New.
	* constexpr.c (cxx_eval_constant_expression) <case NOP_EXPR>:
	Reject REINTERPET_CAST_P conversions.  Use cplus_expand_constant
	for non-trivial PTRMEM_CST cases.
	* typeck.c (build_nop_reinterpret): New.
	(build_reinterpret_cast_1): Use it.  Set REINTERPRET_CAST_P on
	NOP_EXPRs returned by cp_convert.

	* g++.dg/cpp0x/addressof1.C: Make reinterpret cases runtime checks.
	* g++.dg/cpp0x/constexpr-cast.C: Remove xfails
	* g++.dg/cpp0x/constexpr-nullptr-2.C: Likewise.
	* g++.dg/cpp0x/constexpr-pmf1.C: Check when optimized.
	* g++.dg/cpp0x/pr85437-1.C: New.
	* g++.dg/cpp0x/pr85437-2.C: New.
	* g++.dg/cpp0x/pr85437-3.C: New.
	* g++.dg/cpp0x/pr85437-4.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-1.C
    trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-2.C
    trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-3.C
    trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/typeck.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/cpp0x/addressof1.C
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-pmf1.C
Comment 8 Jakub Jelinek 2018-04-25 07:11:23 UTC
Fixed by Nathan.