All recent versions of G++ fail to compile the following well-formed program with the error below. Clang compiles it fine, as does EDG eccp 4.11 (though eccp issues a bogus "subscript out of range" warning). $ cat zzz.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc -B /home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -fpermissive -fdump-tree-gimple=/dev/stdout -xc++ zzz.c typedef const char A4 [10]; constexpr A4 a [] = { "123", "123456", "123456789" }; constexpr int len (const char *s) { return *s ? 1 + len (s + 1) : 0; } constexpr const char *s = a [0]; constexpr const char *t = (a + 2)[-2]; constexpr int n0 = len (s); constexpr int n1 = len (t); constexpr int n2 = len (a [0]); constexpr int n3 = len ((a + 2)[-2]); #define A(e) static_assert ((e), #e) A (n0 == 3); A (n0 == n1); A (n0 == n2); A (n0 == n3); zzz.c:14:24: in constexpr expansion of ‘len(((const char*)(& a)))’ zzz.c:14:26: error: accessing value of ‘a’ through a ‘const char’ glvalue in a constant expression constexpr int n1 = len (t); ^ zzz.c:17:24: in constexpr expansion of ‘len(((const char*)((const char (*)[10])(& a))))’ zzz.c:17:36: error: accessing value of ‘a’ through a ‘const char’ glvalue in a constant expression constexpr int n3 = len ((a + 2)[-2]); ^
Confirmed.
Hi! I'm working on a library that does a lot of work inside constexpr functions. In simple cases like the example above it's relatively easy to avoid this bug. In real life, however, it's almost impossible. Although this bug is not considered important, it it important for me. Currently, it is the only reason my library doesn't work with GCC. I'd really appreciate it if this bug was assigned to someone. If there are no volunteers, I'd be happy to help myself. Unfortunately, I'm not familiar with GCC's code base at all. So some pointers to where I can get started would be very helpful. Tom
(In reply to Tom Westerhout from comment #2) Start by stepping through the GCC code that handles the test case and figuring out what triggers the error and what makes GCC accept the successful case. Compile GCC for debugging (https://gcc.gnu.org/wiki/DebuggingGCC), load xgcc into GDB, set a breakpoint in function error(), and run it. A relatively easy way to figure things out is to start two debugging sessions side by side, one with the successful test case and one with the failing one, step through them side by side, and make note of the differences. To see the tree operand that's being processed call the GCC function debug_tree() on it.
A motivating example for this error to be given higher priority. An array_ref wrapper for multidimensional C-arrays T[M][N]... providing constexpr access via an index operator[] -> returns array_ref<T> when T is an array type or -> returns T& otherwise for non-array T https://wandbox.org/permlink/vcAokwqzk5tOF1ok #include <type_traits> template <typename T> struct array_ref; template <typename T> using ref_t = std::conditional_t< std::is_array_v<T>, array_ref<T>, T&>; template <typename T, unsigned N> struct array_ref<T[N]> { T* a; // T (&a)[N]; using const_reference = const ref_t<T>; constexpr const_reference operator[](unsigned I) const { return {a[I]}; } }; template <typename A> array_ref(A&) -> array_ref<A>; constexpr int a2[2] = {1,2}; static_assert( array_ref{a2}[0] == 1 ); constexpr int a22[2][2] = {{1,2},{3,4}}; static_assert( array_ref{a22}[0][0] == 1 ); > error: non-constant condition for static assertion static_assert( array_ref{a22}[0][0] == 1 ); > error: accessing value of 'a22' through a 'const int' glvalue in a constant expression Clang accepts. (MSVC untested.) A workaround is to replace the pointer member with a reference member (a reference member is less flexible and generally discouraged). So GCC with this bug forces the less flexible implementation afaict - I couldn't find a workaround that uses a pointer member. Like std::array, array_ref is intended to provide array copy. This is why >1D index operations return wrapped array_ref<T> (the wandbox link includes some static_asserts to illustrate). Constexpr is a requirement for my application; a reasonable requirement for a wrapped C-array. Other multi-dimensional array implementations must've hit this
Oops - I left the wandbox link on Clang... Here's the GCC Head link: https://wandbox.org/permlink/rfvn9VSwZgU6nerN
A simpler example exhibiting this bogus error; an innocent, idiomatic, pedantic, platonic pair of nested range-for loops iterating a 2D array: g++ prog.cc -Wall -Wextra -std=c++14 -pedantic-errors #include <type_traits> template <typename A> constexpr auto sum(A const& a) { int tot = 0; for (auto& row : a) for (auto elem : row) tot += elem; return tot; } constexpr int const a22[2][2] = {{1,2},{3,4}}; static_assert( sum(a22) == 10, "badsum"); prog.cc:17:18: in 'constexpr' expansion of 'sum<int [2][2]>(a22)' prog.cc:17:24: error: accessing value of 'a22' through a 'const int' glvalue in a constant expression
*** Bug 89239 has been marked as a duplicate of this bug. ***
Created attachment 46968 [details] partial fix This fixes handling of references to the first object, but not later ones, so several of the testcases in this PR still fail. Putting this aside for now.
Author: jakub Date: Fri Oct 4 06:56:02 2019 New Revision: 276563 URL: https://gcc.gnu.org/viewcvs?rev=276563&root=gcc&view=rev Log: PR c++/71504 * constexpr.c (cxx_fold_indirect_ref_1): New function. (cxx_fold_indirect_ref): Use it. * g++.dg/cpp0x/constexpr-array21.C: New test. * g++.dg/cpp1y/constexpr-array7.C: New test. * g++.dg/cpp1z/constexpr-array1.C: New test. 2019-10-04 Jason Merrill <jason@redhat.com> PR c++/71504 * g++.dg/cpp0x/constexpr-array20.C: New test. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-array20.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-array21.C trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-array7.C trunk/gcc/testsuite/g++.dg/cpp1z/constexpr-array1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c trunk/gcc/testsuite/ChangeLog
Fixed for GCC 10.
GCC 10.1 has been released.
GCC 10.2 is released, adjusting target milestone.
GCC 10.3 is being released, retargeting bugs to GCC 10.4.
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
.