[C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
Hi! In constexpr evaluation of array references for arrays with unknown bounds, we need to diagnose out of bounds accesses, but really don't know the bounds at compile time, right now GCC will see nelts as error_mark_node + 1 and will not consider them a constant expression at all. >From the clang commit message it seems that CWG is leaning towards allowing &array_with_unknown_bound[0] and array_with_unknown_bound, but disallowing any other indexes (i.e. assume the array could have zero elements). The following patch implements that. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-01-24 Jakub Jelinek PR c++/83993 * constexpr.c (diag_array_subscript): Emit different diagnostics if TYPE_DOMAIN (arraytype) is NULL. (cxx_eval_array_reference, cxx_eval_store_expression): For arrays with NULL TYPE_DOMAIN use size_zero_node as nelts. * g++.dg/init/pr83993-1.C: New test. * g++.dg/cpp0x/pr83993.C: New test. --- gcc/cp/constexpr.c.jj 2018-01-19 23:34:04.897278768 +0100 +++ gcc/cp/constexpr.c 2018-01-24 13:38:40.572913190 +0100 @@ -2270,13 +2270,20 @@ diag_array_subscript (const constexpr_ct tree sidx = fold_convert (ssizetype, index); if (DECL_P (array)) { - error ("array subscript value %qE is outside the bounds " -"of array %qD of type %qT", sidx, array, arraytype); + if (TYPE_DOMAIN (arraytype)) + error ("array subscript value %qE is outside the bounds " + "of array %qD of type %qT", sidx, array, arraytype); + else + error ("array subscript value %qE used on array %qD of " + "type %qT with unknown bounds", sidx, array, arraytype); inform (DECL_SOURCE_LOCATION (array), "declared here"); } - else + else if (TYPE_DOMAIN (arraytype)) error ("array subscript value %qE is outside the bounds " "of array type %qT", sidx, arraytype); + else + error ("array subscript value %qE used on array of type %qT " + "with unknown bounds", sidx, arraytype); } } @@ -2361,7 +2368,12 @@ cxx_eval_array_reference (const constexp tree nelts; if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) -nelts = array_type_nelts_top (TREE_TYPE (ary)); +{ + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; +} else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else @@ -3439,7 +3451,12 @@ cxx_eval_store_expression (const constex tree nelts, ary; ary = TREE_OPERAND (probe, 0); if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) - nelts = array_type_nelts_top (TREE_TYPE (ary)); + { + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; + } else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else --- gcc/testsuite/g++.dg/init/pr83993-1.C.jj2018-01-24 13:45:43.430864528 +0100 +++ gcc/testsuite/g++.dg/init/pr83993-1.C 2018-01-24 13:44:59.352869530 +0100 @@ -0,0 +1,11 @@ +// PR c++/83993 +// { dg-do compile } + +extern const int a[]; +const int *const b = &a[0]; + +int +foo () +{ + return b[0]; +} --- gcc/testsuite/g++.dg/cpp0x/pr83993.C.jj 2018-01-24 14:09:01.846716177 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr83993.C2018-01-24 14:08:41.246718212 +0100 @@ -0,0 +1,49 @@ +// PR c++/83993 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +extern const int a[]; +const int b[5] = { 1, 2, 3, 4, 5 }; +extern const int c[4]; +constexpr const int *d = &a[0]; +constexpr const int *d2 = a; +constexpr const int *e = &a[1];// { dg-error "array subscript value '1' used on array 'a' of type 'const int \\\[\\\]' with unknown bounds" } +constexpr const int *f = &b[0]; +constexpr const int *f2 = b; +constexpr const int *g = &b[5]; +constexpr const int *h = &b[6];// { dg-error "array subscript value '6' is outside the bounds of array 'b' of type 'const int \\\[5\\\]'" } +constexpr const int *i = &c[0]; +constexpr const int *i2 = c; +constexpr const int *j = &c[4]; +constexpr const int *k = &c[5];// { dg-error "array subscript value '5' is outside the bounds of array 'c' of type 'const int \\\[4\\\]'" } +extern const int l[]; + +void +foo () +{ + extern const int l[3]; + constexpr const int *m = &l[0]; + constexpr const int *m2 = l; + constexpr const int *n = &l[1]; + static_assert (m == m2, ""); +} + +constexpr const int *m = &l[0]; +constexpr const int *m2 = l; +constexpr const int *n = &l[1];// { dg-error "array subscript value '1' used on array 'l' of type 'const
Re: [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
On 01/24/2018 04:19 PM, Jakub Jelinek wrote: Hi! In constexpr evaluation of array references for arrays with unknown bounds, we need to diagnose out of bounds accesses, but really don't know the bounds at compile time, right now GCC will see nelts as error_mark_node + 1 and will not consider them a constant expression at all. From the clang commit message it seems that CWG is leaning towards allowing &array_with_unknown_bound[0] and array_with_unknown_bound, but disallowing any other indexes (i.e. assume the array could have zero elements). The following patch implements that. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Unless your goal is to have GCC 8 reject just some subset of expressions in the reported test case (and fix the rest in the future) then there still are other potentially invalid expressions that GCC will continue to accept. For example, the initialization of p in f() is rejected with the patch but the use of the same expression in g() is still accepted (Clang silently accepts both). It could be due to the same problem as bug 82877. Other similar issues are being tracked in bug 82876 and 82874. extern const int a[]; constexpr int f () { const int *p = &a[7], *q = &a[0]; return p - q; } constexpr int g () { return &a[7] - &a[0]; } constexpr const int i = f (); constexpr const int j = g (); Regarding the patch, just a couple of minor nits: The consensus we have reached some time back was not to quote integer constants so I would suggest to follow it in new code and take the opportunity to remove the quoting from surrounding code. https://gcc.gnu.org/wiki/DiagnosticsGuidelines#Quoting In addition, I would suggest to phrase the error as "array subscript value %E is used *with* array qD" as opposed to "on array." If we wanted to make it clearer that it's the fact that the index is non-zero is the problem mentioning it in the warning might help ("non-zero array subscript %E...") Alternatively, since the bounds are unknown is evident from the type of the array (e.g., "int[]") just: "array subscript value %E may be outside the bounds of array %qD of type %qT" might be good enough. Martin 2018-01-24 Jakub Jelinek PR c++/83993 * constexpr.c (diag_array_subscript): Emit different diagnostics if TYPE_DOMAIN (arraytype) is NULL. (cxx_eval_array_reference, cxx_eval_store_expression): For arrays with NULL TYPE_DOMAIN use size_zero_node as nelts. * g++.dg/init/pr83993-1.C: New test. * g++.dg/cpp0x/pr83993.C: New test. --- gcc/cp/constexpr.c.jj 2018-01-19 23:34:04.897278768 +0100 +++ gcc/cp/constexpr.c 2018-01-24 13:38:40.572913190 +0100 @@ -2270,13 +2270,20 @@ diag_array_subscript (const constexpr_ct tree sidx = fold_convert (ssizetype, index); if (DECL_P (array)) { - error ("array subscript value %qE is outside the bounds " -"of array %qD of type %qT", sidx, array, arraytype); + if (TYPE_DOMAIN (arraytype)) + error ("array subscript value %qE is outside the bounds " + "of array %qD of type %qT", sidx, array, arraytype); + else + error ("array subscript value %qE used on array %qD of " + "type %qT with unknown bounds", sidx, array, arraytype); inform (DECL_SOURCE_LOCATION (array), "declared here"); } - else + else if (TYPE_DOMAIN (arraytype)) error ("array subscript value %qE is outside the bounds " "of array type %qT", sidx, arraytype); + else + error ("array subscript value %qE used on array of type %qT " + "with unknown bounds", sidx, arraytype); } } @@ -2361,7 +2368,12 @@ cxx_eval_array_reference (const constexp tree nelts; if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) -nelts = array_type_nelts_top (TREE_TYPE (ary)); +{ + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; +} else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else @@ -3439,7 +3451,12 @@ cxx_eval_store_expression (const constex tree nelts, ary; ary = TREE_OPERAND (probe, 0); if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) - nelts = array_type_nelts_top (TREE_TYPE (ary)); + { + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; + } else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else --- gcc/testsuite/g++.dg/init/pr83993-1.C.jj2018-01-24 13:45:43.430864528 +0100 +++ gcc/testsuite/g++.dg/init/pr83993-1.C 2018-01-24 13:44:59.352869530 +0100 @@ -0,0 +1,11 @@ +// PR
Re: [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
On Thu, Jan 25, 2018 at 01:13:56PM -0700, Martin Sebor wrote: > On 01/24/2018 04:19 PM, Jakub Jelinek wrote: > > Hi! > > > > In constexpr evaluation of array references for arrays with unknown bounds, > > we need to diagnose out of bounds accesses, but really don't know the bounds > > at compile time, right now GCC will see nelts as error_mark_node + 1 and > > will not consider them a constant expression at all. > > From the clang commit message it seems that CWG is leaning towards allowing > > &array_with_unknown_bound[0] and array_with_unknown_bound, but disallowing > > any other indexes (i.e. assume the array could have zero elements). > > The following patch implements that. Bootstrapped/regtested on x86_64-linux > > and i686-linux, ok for trunk? > > Unless your goal is to have GCC 8 reject just some subset of > expressions in the reported test case (and fix the rest in > the future) then there still are other potentially invalid > expressions that GCC will continue to accept. For example, > the initialization of p in f() is rejected with the patch but > the use of the same expression in g() is still accepted (Clang > silently accepts both). It could be due to the same problem > as bug 82877. Other similar issues are being tracked in bug > 82876 and 82874. The goal is to fix the PR and improve the handling of unknown bound arrays while at it. There is no time nor good timing for something much more substantial. After all, with the patch we still don't reject e.g. some cases if g++.dg/cpp0x/pr83993.C testcase uses the [a-z]2 pointers instead of corresponding array in the array refs it tests. > extern const int a[]; > > constexpr int f () > { > const int *p = &a[7], *q = &a[0]; > return p - q; > } > > constexpr int g () > { > return &a[7] - &a[0]; > } > > constexpr const int i = f (); > constexpr const int j = g (); I believe the fix for this is to save bodies of constexpr functions/methods before the folding and do the constexpr evaluations on those rather than on something we've folded already, but that is certainly not suitable for GCC8. > Regarding the patch, just a couple of minor nits: > > The consensus we have reached some time back was not to quote > integer constants so I would suggest to follow it in new code > and take the opportunity to remove the quoting from surrounding > code. > > https://gcc.gnu.org/wiki/DiagnosticsGuidelines#Quoting In this case I was just extending existing warning and wanted consistency with that. Both can be changed in a GCC9 follow-up, or if Jason/Nathan want it now, even for GCC8, sure. > In addition, I would suggest to phrase the error as "array > subscript value %E is used *with* array qD" as opposed to > "on array." If we wanted to make it clearer that it's That looks reasonable. > the fact that the index is non-zero is the problem mentioning > it in the warning might help ("non-zero array subscript %E...") Well, even zero subscript is wrong if lval is false, i.e. a[0] + 1 rather than e.g. &a[0]. So we'd need to have another wordings for the case when the index is zero. > Alternatively, since the bounds are unknown is evident from > the type of the array (e.g., "int[]") just: "array subscript > value %E may be outside the bounds of array %qD of type %qT" > might be good enough. Dunno, perhaps. Jakub
Re: [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
On Thu, Jan 25, 2018 at 5:53 PM, Jakub Jelinek wrote: > On Thu, Jan 25, 2018 at 01:13:56PM -0700, Martin Sebor wrote: >> On 01/24/2018 04:19 PM, Jakub Jelinek wrote: >> > Hi! >> > >> > In constexpr evaluation of array references for arrays with unknown bounds, >> > we need to diagnose out of bounds accesses, but really don't know the >> > bounds >> > at compile time, right now GCC will see nelts as error_mark_node + 1 and >> > will not consider them a constant expression at all. >> > From the clang commit message it seems that CWG is leaning towards allowing >> > &array_with_unknown_bound[0] and array_with_unknown_bound, but disallowing >> > any other indexes (i.e. assume the array could have zero elements). >> > The following patch implements that. Bootstrapped/regtested on >> > x86_64-linux >> > and i686-linux, ok for trunk? >> >> Unless your goal is to have GCC 8 reject just some subset of >> expressions in the reported test case (and fix the rest in >> the future) then there still are other potentially invalid >> expressions that GCC will continue to accept. For example, >> the initialization of p in f() is rejected with the patch but >> the use of the same expression in g() is still accepted (Clang >> silently accepts both). It could be due to the same problem >> as bug 82877. Other similar issues are being tracked in bug >> 82876 and 82874. > > The goal is to fix the PR and improve the handling of unknown > bound arrays while at it. > There is no time nor good timing for something much more substantial. > After all, with the patch we still don't reject e.g. > some cases if g++.dg/cpp0x/pr83993.C testcase uses the [a-z]2 pointers > instead of corresponding array in the array refs it tests. > >> extern const int a[]; >> >> constexpr int f () >> { >> const int *p = &a[7], *q = &a[0]; >> return p - q; >> } >> >> constexpr int g () >> { >> return &a[7] - &a[0]; >> } >> >> constexpr const int i = f (); >> constexpr const int j = g (); > > I believe the fix for this is to save bodies of constexpr > functions/methods before the folding and do the constexpr evaluations on > those rather than on something we've folded already, but that is > certainly not suitable for GCC8. > >> Regarding the patch, just a couple of minor nits: >> >> The consensus we have reached some time back was not to quote >> integer constants so I would suggest to follow it in new code >> and take the opportunity to remove the quoting from surrounding >> code. >> >> https://gcc.gnu.org/wiki/DiagnosticsGuidelines#Quoting > > In this case I was just extending existing warning and wanted > consistency with that. Both can be changed in a GCC9 follow-up, > or if Jason/Nathan want it now, even for GCC8, sure. > >> In addition, I would suggest to phrase the error as "array >> subscript value %E is used *with* array qD" as opposed to >> "on array." If we wanted to make it clearer that it's > > That looks reasonable. > >> the fact that the index is non-zero is the problem mentioning >> it in the warning might help ("non-zero array subscript %E...") > > Well, even zero subscript is wrong if lval is false, i.e. a[0] + 1 > rather than e.g. &a[0]. So we'd need to have another wordings > for the case when the index is zero. But if lval is false we want the value of the array, and if we know the value we know the bounds, so that shouldn't be needed. Jason
Re: [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
On Wed, Jan 31, 2018 at 11:02:36AM -0500, Jason Merrill wrote: > > In this case I was just extending existing warning and wanted > > consistency with that. Both can be changed in a GCC9 follow-up, > > or if Jason/Nathan want it now, even for GCC8, sure. So, do you want %qE as in the patch or %E? Note, sidx might actually not be a INTEGER_CST (as we only verify_constant it which allows all kinds of expressions), though usually it will be. E.g. the if (!tree_fits_shwi_p (index) || (i = tree_to_shwi (index)) < 0) { diag_array_subscript (ctx, ary, index); case will call it if index is some reduced_constant_expression_p which is not INTEGER_CST, initializer_constant_valid_p* has lots of cases, sure not all apply to integral types. > > Well, even zero subscript is wrong if lval is false, i.e. a[0] + 1 > > rather than e.g. &a[0]. So we'd need to have another wordings > > for the case when the index is zero. > > But if lval is false we want the value of the array, and if we know > the value we know the bounds, so that shouldn't be needed. You're right, when dereferencing it we'll error already earlier, because the array of unknown bounds can't be constexpr. I think the " with unknown bounds" part still might be useful to users, it can be seen in the type as [], but it might take some time to the users to figure out that is the reason why we disallow it. So like this? 2018-01-31 Jakub Jelinek PR c++/83993 * constexpr.c (diag_array_subscript): Emit different diagnostics if TYPE_DOMAIN (arraytype) is NULL. (cxx_eval_array_reference, cxx_eval_store_expression): For arrays with NULL TYPE_DOMAIN use size_zero_node as nelts. * g++.dg/init/pr83993-1.C: New test. * g++.dg/cpp0x/pr83993.C: New test. --- gcc/cp/constexpr.c.jj 2018-01-19 23:34:04.897278768 +0100 +++ gcc/cp/constexpr.c 2018-01-24 13:38:40.572913190 +0100 @@ -2270,13 +2270,20 @@ diag_array_subscript (const constexpr_ct tree sidx = fold_convert (ssizetype, index); if (DECL_P (array)) { - error ("array subscript value %qE is outside the bounds " -"of array %qD of type %qT", sidx, array, arraytype); + if (TYPE_DOMAIN (arraytype)) + error ("array subscript value %qE is outside the bounds " + "of array %qD of type %qT", sidx, array, arraytype); + else + error ("non-zero array subscript %qE is used with array %qD of " + "type %qT with unknown bounds", sidx, array, arraytype); inform (DECL_SOURCE_LOCATION (array), "declared here"); } - else + else if (TYPE_DOMAIN (arraytype)) error ("array subscript value %qE is outside the bounds " "of array type %qT", sidx, arraytype); + else + error ("non-zero array subscript %qE is used with array of type %qT " + "with unknown bounds", sidx, arraytype); } } @@ -2361,7 +2368,12 @@ cxx_eval_array_reference (const constexp tree nelts; if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) -nelts = array_type_nelts_top (TREE_TYPE (ary)); +{ + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; +} else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else @@ -3439,7 +3451,12 @@ cxx_eval_store_expression (const constex tree nelts, ary; ary = TREE_OPERAND (probe, 0); if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) - nelts = array_type_nelts_top (TREE_TYPE (ary)); + { + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; + } else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else --- gcc/testsuite/g++.dg/init/pr83993-1.C.jj2018-01-24 13:45:43.430864528 +0100 +++ gcc/testsuite/g++.dg/init/pr83993-1.C 2018-01-24 13:44:59.352869530 +0100 @@ -0,0 +1,11 @@ +// PR c++/83993 +// { dg-do compile } + +extern const int a[]; +const int *const b = &a[0]; + +int +foo () +{ + return b[0]; +} --- gcc/testsuite/g++.dg/cpp0x/pr83993.C.jj 2018-01-24 14:09:01.846716177 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr83993.C2018-01-24 14:08:41.246718212 +0100 @@ -0,0 +1,49 @@ +// PR c++/83993 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +extern const int a[]; +const int b[5] = { 1, 2, 3, 4, 5 }; +extern const int c[4]; +constexpr const int *d = &a[0]; +constexpr const int *d2 = a; +constexpr const int *e = &a[1];// { dg-error "non-zero array subscript '1' is used with array 'a' of type 'const int \\\[\\\]' with unknown bounds" } +constexpr const int *f = &b[0]; +constexpr const int *f2 = b;
Re: [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993)
OK. On Wed, Jan 31, 2018 at 12:45 PM, Jakub Jelinek wrote: > On Wed, Jan 31, 2018 at 11:02:36AM -0500, Jason Merrill wrote: >> > In this case I was just extending existing warning and wanted >> > consistency with that. Both can be changed in a GCC9 follow-up, >> > or if Jason/Nathan want it now, even for GCC8, sure. > > So, do you want %qE as in the patch or %E? Note, sidx might > actually not be a INTEGER_CST (as we only verify_constant it which > allows all kinds of expressions), though usually it will be. > E.g. the > if (!tree_fits_shwi_p (index) > || (i = tree_to_shwi (index)) < 0) > { > diag_array_subscript (ctx, ary, index); > case will call it if index is some reduced_constant_expression_p > which is not INTEGER_CST, initializer_constant_valid_p* has lots > of cases, sure not all apply to integral types. > >> > Well, even zero subscript is wrong if lval is false, i.e. a[0] + 1 >> > rather than e.g. &a[0]. So we'd need to have another wordings >> > for the case when the index is zero. >> >> But if lval is false we want the value of the array, and if we know >> the value we know the bounds, so that shouldn't be needed. > > You're right, when dereferencing it we'll error already earlier, > because the array of unknown bounds can't be constexpr. > > I think the " with unknown bounds" part still might be useful to users, > it can be seen in the type as [], but it might take some time to the users > to figure out that is the reason why we disallow it. > > So like this? > > 2018-01-31 Jakub Jelinek > > PR c++/83993 > * constexpr.c (diag_array_subscript): Emit different diagnostics > if TYPE_DOMAIN (arraytype) is NULL. > (cxx_eval_array_reference, cxx_eval_store_expression): For arrays > with NULL TYPE_DOMAIN use size_zero_node as nelts. > > * g++.dg/init/pr83993-1.C: New test. > * g++.dg/cpp0x/pr83993.C: New test. > > --- gcc/cp/constexpr.c.jj 2018-01-19 23:34:04.897278768 +0100 > +++ gcc/cp/constexpr.c 2018-01-24 13:38:40.572913190 +0100 > @@ -2270,13 +2270,20 @@ diag_array_subscript (const constexpr_ct >tree sidx = fold_convert (ssizetype, index); >if (DECL_P (array)) > { > - error ("array subscript value %qE is outside the bounds " > -"of array %qD of type %qT", sidx, array, arraytype); > + if (TYPE_DOMAIN (arraytype)) > + error ("array subscript value %qE is outside the bounds " > + "of array %qD of type %qT", sidx, array, arraytype); > + else > + error ("non-zero array subscript %qE is used with array %qD of " > + "type %qT with unknown bounds", sidx, array, arraytype); > inform (DECL_SOURCE_LOCATION (array), "declared here"); > } > - else > + else if (TYPE_DOMAIN (arraytype)) > error ("array subscript value %qE is outside the bounds " >"of array type %qT", sidx, arraytype); > + else > + error ("non-zero array subscript %qE is used with array of type %qT " > + "with unknown bounds", sidx, arraytype); > } > } > > @@ -2361,7 +2368,12 @@ cxx_eval_array_reference (const constexp > >tree nelts; >if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) > -nelts = array_type_nelts_top (TREE_TYPE (ary)); > +{ > + if (TYPE_DOMAIN (TREE_TYPE (ary))) > + nelts = array_type_nelts_top (TREE_TYPE (ary)); > + else > + nelts = size_zero_node; > +} >else if (VECTOR_TYPE_P (TREE_TYPE (ary))) > nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); >else > @@ -3439,7 +3451,12 @@ cxx_eval_store_expression (const constex > tree nelts, ary; > ary = TREE_OPERAND (probe, 0); > if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) > - nelts = array_type_nelts_top (TREE_TYPE (ary)); > + { > + if (TYPE_DOMAIN (TREE_TYPE (ary))) > + nelts = array_type_nelts_top (TREE_TYPE (ary)); > + else > + nelts = size_zero_node; > + } > else if (VECTOR_TYPE_P (TREE_TYPE (ary))) > nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); > else > --- gcc/testsuite/g++.dg/init/pr83993-1.C.jj2018-01-24 13:45:43.430864528 > +0100 > +++ gcc/testsuite/g++.dg/init/pr83993-1.C 2018-01-24 13:44:59.352869530 > +0100 > @@ -0,0 +1,11 @@ > +// PR c++/83993 > +// { dg-do compile } > + > +extern const int a[]; > +const int *const b = &a[0]; > + > +int > +foo () > +{ > + return b[0]; > +} > --- gcc/testsuite/g++.dg/cpp0x/pr83993.C.jj 2018-01-24 14:09:01.846716177 > +0100 > +++ gcc/testsuite/g++.dg/cpp0x/pr83993.C2018-01-24 14:08:41.246718212 > +0100 > @@ -0,0 +1,49 @@ > +// PR c++/83993 > +// { dg-do compile { target c++11 } } > +// { dg-options "" } > + > +extern const int a[]; > +const int b[5] = { 1, 2, 3, 4, 5 }; > +extern const int c[4]; > +c