| Summary: | [10 Regression] uninitialized variable accepted as a constant expression in C++ 20 | ||
|---|---|---|---|
| Product: | gcc | Reporter: | 康桓瑋 <hewillk> |
| Component: | c++ | Assignee: | Patrick Palka <ppalka> |
| Status: | RESOLVED FIXED | ||
| Severity: | normal | CC: | mpolacek, msebor, ppalka, webrown.cpp |
| Priority: | P3 | Keywords: | accepts-invalid |
| Version: | 11.0 | ||
| Target Milestone: | 11.0 | ||
| See Also: | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97128 | ||
| Host: | Target: | ||
| Build: | Known to work: | ||
| Known to fail: | 10.2.0, 11.0 | Last reconfirmed: | 2021-04-15 00:00:00 |
| Bug Depends on: | |||
| Bug Blocks: | 55004 | ||
|
Description
康桓瑋
2021-03-21 18:22:40 UTC
Confirmed with -std=c++20. In earlier modes GCC rejects the test case as expected. $ (set -x && gcc -O2 -S -Wall -std=c++20 pr99700.C && gcc -O2 -S -Wall -std=c++17 pr99700.C) + gcc -O2 -S -Wall -std=c++20 pr99700.C + gcc -O2 -S -Wall -std=c++17 pr99700.C pr99700.C: In constructor ‘constexpr A::A()’: pr99700.C:2:29: error: member ‘A::c’ must be initialized by mem-initializer in ‘constexpr’ constructor 2 | constexpr A() { c[0] = 0; } | ^ pr99700.C:3:8: note: declared here 3 | char c[2]; | ^ pr99700.C: At global scope: pr99700.C:6:13: error: ‘constexpr A::A()’ called in a constant expression 6 | constexpr A a; | ^ pr99700.C:2:13: note: ‘constexpr A::A()’ declared here 2 | constexpr A() { c[0] = 0; } | ^ When reporting bugs please include all the information we ask for here: https://gcc.gnu.org/bugs/#need. Links to other sites are not a substitute. Bisection points to r279019 AKA the fix for PR c++/91353 as the first revision when the code started to be accepted. It seems reduced_constant_expression_p needs to check that a CONSTRUCTOR_NO_CLEARING array ctor initializes all elements.
I'm testing:
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c8d9dae36fb..6e530f9c88d 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -46,6 +46,7 @@ do { \
static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex,
bool insert = false);
+static int array_index_cmp (tree key, tree index);
/* Returns true iff FUN is an instantiation of a constexpr function
template or a defaulted constexpr function. */
@@ -2912,7 +2913,25 @@ reduced_constant_expression_p (tree t)
else if (cxx_dialect >= cxx20
/* An ARRAY_TYPE doesn't have any TYPE_FIELDS. */
&& TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
- field = NULL_TREE;
+ {
+ tree min = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (t)));
+ tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t)));
+ if (find_array_ctor_elt (t, min) == -1
+ || find_array_ctor_elt (t, max) == -1)
+ return false;
+ tree cursor = size_zero_node;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, idx, val)
+ {
+ if (!reduced_constant_expression_p (val))
+ return false;
+ if (array_index_cmp (cursor, idx) != 0)
+ return false;
+ if (TREE_CODE (idx) == RANGE_EXPR)
+ cursor = TREE_OPERAND (idx, 1);
+ cursor = int_const_binop (PLUS_EXPR, cursor, size_one_node);
+ }
+ return true;
+ }
else if (cxx_dialect >= cxx20
&& TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
{
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:baf05d54dc919c968d12de9d049e36e5bac10dec commit r11-8216-gbaf05d54dc919c968d12de9d049e36e5bac10dec Author: Patrick Palka <ppalka@redhat.com> Date: Fri Apr 16 09:24:46 2021 -0400 c++: partially initialized constexpr array [PR99700] Here, reduced_constant_expression_p is incorrectly returning true for a partially initialized array CONSTRUCTOR (in C++20 mode) because when the CONSTRUCTOR_NO_CLEARING flag is set, the predicate doesn't check that the CONSTRUCTOR spans the entire array like it does for class CONSTRUCTORS. This patch adds a dedicated loop for the array case that simultaneously verifies the CONSTRUCTOR spans the entire array and is made up of valid constant expressions. gcc/cp/ChangeLog: PR c++/99700 * constexpr.c (reduced_constant_expression_p): For array CONSTRUCTORs, use a dedicated loop that additionally verifies the CONSTRUCTOR spans the entire array. gcc/testsuite/ChangeLog: PR c++/99700 * g++.dg/cpp2a/constexpr-init21.C: New test. Fixed for GCC 11 so far. The patch doesn't apply cleanly to the 10 branch, and since this is only a C++20 regression, it doesn't seem worth backporting. |