Bug 84463

Summary: [6/7 Regression] Supposedly-incompliant "error: '* key0' is not a constant expression"
Product: gcc Reporter: sergey.ignatchenko
Component: c++Assignee: Jakub Jelinek <jakub>
Status: RESOLVED FIXED    
Severity: normal CC: daniel.kruegler, webrown.cpp
Priority: P2 Keywords: rejects-valid
Version: 7.2.0   
Target Milestone: 6.5   
Host: Target:
Build: Known to work: 5.5.0
Known to fail: 6.4.0, 7.3.0, 8.0.1 Last reconfirmed: 2018-04-16 00:00:00
Attachments: gcc8-pr84463.patch

Description sergey.ignatchenko 2018-02-19 13:25:52 UTC
== COMPILER ==========

root@ubuntu-gcc7:~/ithare/kscope/test/nix# g++ --version
g++ (Ubuntu 7.2.0-8ubuntu3) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

== CODE ============

#include <stdint.h>
#include <cstddef>

struct chacha_tv {
	const char *desc;
	const uint8_t key[32];
	const uint8_t iv[8];
	const size_t len;
	const unsigned char out[512];
};

static constexpr chacha_tv chacha_test_vectors[] = {
	{
		"TC1: All zero key and IV",
		{
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		},
		{
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		},
		64,
		{
			0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
			0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
			0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
			0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
			0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
			0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
			0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
			0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
		},
	},
};

constexpr int
KSCOPE_CT_Chacha_set_key_iv2(const uint8_t* key0, int keybits /*128 or 256*/, const uint8_t iv0[8], const uint8_t counter0[8]) {
        uint8_t c = key0[0];
	return 0;
}

constexpr static const chacha_tv* tv = &chacha_test_vectors[0];
constexpr static const int k = tv->key[0];
constexpr static uint8_t kk[3] = {0,1,2};
constexpr static int x0 = KSCOPE_CT_Chacha_set_key_iv2(chacha_test_vectors[0].key,256,tv->iv,nullptr);//OK
constexpr static int x1 = KSCOPE_CT_Chacha_set_key_iv2(kk,256,tv->iv,nullptr);//OK
constexpr static int x2 = KSCOPE_CT_Chacha_set_key_iv2(tv->key,256,tv->iv,nullptr);

== PROBLEM ============

When trying to compile the code above with GCC 7.2, the following error is generated:
../chachatest.cpp:50:55:   in constexpr expansion of 'KSCOPE_CT_Chacha_set_key_i
v2(((const uint8_t*)(((const uint8_t (*)[32])tv) + 8)), 256, ((const uint8_t*)((
(const uint8_t (*)[8])tv) + 40)), 0)'
../chachatest.cpp:41:27: error: '* key0' is not a constant expression
         uint8_t c = key0[0];

Expected behaviour is to acknowledge that key0 is an 'address constant expression' in a sense of 5.19 (at least my humble reading of the standard says that it is), and to allow the code to be compiled. Notes:
- note that both x0 and x1 compile ok
- both Clang and MSVC seem to agree it is an 'address constant expression' and don't complain.
Comment 1 sergey.ignatchenko 2018-02-19 19:34:51 UTC
oops, forgot to mention command line:
g++  -std=c++1z -lstdc++ -Werror ../chachatest.cpp

where chachatest.cpp is provided in "CODE" section above
Comment 2 Jonathan Wakely 2018-04-16 13:30:35 UTC
Started to fail with r230365 ("Merge C++ delayed folding branch.")
Comment 3 Jakub Jelinek 2018-04-16 15:06:12 UTC
Created attachment 43948 [details]
gcc8-pr84463.patch

Untested fix.
Comment 4 Jakub Jelinek 2018-04-18 06:58:17 UTC
Author: jakub
Date: Wed Apr 18 06:57:45 2018
New Revision: 259458

URL: https://gcc.gnu.org/viewcvs?rev=259458&root=gcc&view=rev
Log:
	PR c++/84463
	* typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like
	tricks from here to ...
	* cp-gimplify.c (cp_fold) <case ADDR_EXPR>: ... here.  Only use it
	if INDIRECT_REF's operand is INTEGER_CST cast to pointer type.

	* g++.dg/cpp0x/constexpr-nullptr-1.C: Add -O1 to dg-options.
	* g++.dg/cpp0x/constexpr-nullptr-2.C: Expect different diagnostics
	in two cases.  Uncomment two other tests and add expected dg-error for
	them.
	* g++.dg/init/struct2.C: Cast to int rather than long to avoid
	-Wnarrowing diagnostics on some targets for c++11.
	* g++.dg/parse/array-size2.C: Remove xfail.
	* g++.dg/cpp0x/constexpr-84463.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-gimplify.c
    trunk/gcc/cp/typeck.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C
    trunk/gcc/testsuite/g++.dg/init/struct2.C
    trunk/gcc/testsuite/g++.dg/parse/array-size2.C
Comment 5 Jakub Jelinek 2018-04-18 07:03:28 UTC
Fixed for 8+.  Not really sure if this patch should be backported.
Comment 6 Jakub Jelinek 2018-06-22 08:23:43 UTC
.
Comment 7 Jakub Jelinek 2018-06-22 21:13:04 UTC
Author: jakub
Date: Fri Jun 22 21:12:32 2018
New Revision: 261956

URL: https://gcc.gnu.org/viewcvs?rev=261956&root=gcc&view=rev
Log:
	Backported from mainline
	2018-04-18  Jakub Jelinek  <jakub@redhat.com>

	PR c++/84463
	* typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like
	tricks from here to ...
	* cp-gimplify.c (cp_fold) <case ADDR_EXPR>: ... here.  Only use it
	if INDIRECT_REF's operand is INTEGER_CST cast to pointer type.

	* g++.dg/cpp0x/constexpr-nullptr-1.C: Add -O1 to dg-options.
	* g++.dg/cpp0x/constexpr-nullptr-2.C: Expect different diagnostics
	in two cases.  Uncomment two other tests and add expected dg-error for
	them.
	* g++.dg/init/struct2.C: Cast to int rather than long to avoid
	-Wnarrowing diagnostics on some targets for c++11.
	* g++.dg/parse/array-size2.C: Remove xfail.
	* g++.dg/cpp0x/constexpr-84463.C: New test.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/cp-gimplify.c
    branches/gcc-7-branch/gcc/cp/typeck.c
    branches/gcc-7-branch/gcc/testsuite/ChangeLog
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C
    branches/gcc-7-branch/gcc/testsuite/g++.dg/init/struct2.C
    branches/gcc-7-branch/gcc/testsuite/g++.dg/parse/array-size2.C