[Bug c++/91353] New: Implement P1331R2: Permitting trivial default initialization in constexprcontexts

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon Aug 5 09:11:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91353

            Bug ID: 91353
           Summary: Implement P1331R2: Permitting trivial default
                    initialization in constexprcontexts
           Product: gcc
           Version: 9.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

Out of curiousity, I've played with this a little bit.
Given
constexpr int
foo (int x)
{
  int a;
  a = 5;
  return x + a;
}

static_assert (foo (2) == 7);

constexpr int
bar (int x)
{
  const int a; // { dg-error "" }
  constexpr int b; // { dg-error "" }
  return x;
}

constexpr int
baz (int x)
{
  int a;
  return x + a; // { dg-error "" }
}

constexpr int a = baz (5);

constexpr int
qux ()
{
  struct S { int a = -5; int b; } s;
  return s.a;
}

static_assert (qux () == -5);

constexpr int
quux ()
{
  struct S { int a = 9; int b; } s;
  return s.b; // { dg-error "" }
}

constexpr int b = quux ();

the following patch doesn't diagnose the quux bug of using uninitialized s.b.
For some reason CONSTRUCTOR_NO_CLEARING is not set and thus we value-initialize
instead of diagnosing.

--- gcc/cp/decl.c.jj    2019-08-05 09:58:07.713491022 +0200
+++ gcc/cp/decl.c       2019-08-05 10:22:28.534127984 +0200
@@ -5742,8 +5742,10 @@ check_for_uninitialized_const_var (tree
      7.1.6 */
   if (VAR_P (decl)
       && !TYPE_REF_P (type)
-      && (constexpr_context_p
-         || CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl))
+      && (CP_TYPE_CONST_P (type)
+          || (cxx_dialect < cxx2a
+             && (constexpr_context_p
+                 || var_in_constexpr_fn (decl))))
       && !DECL_NONTRIVIALLY_INITIALIZED_P (decl))
     {
       tree field = default_init_uninitialized_part (type);
@@ -5752,7 +5754,7 @@ check_for_uninitialized_const_var (tree

       bool show_notes = true;

-      if (!constexpr_context_p)
+      if (!constexpr_context_p || cxx_dialect >= cxx2a)
        {
          if (CP_TYPE_CONST_P (type))
            {
--- gcc/cp/constexpr.c.jj       2019-08-05 09:57:55.147683227 +0200
+++ gcc/cp/constexpr.c  2019-08-05 10:51:56.954215860 +0200
@@ -814,13 +814,15 @@ cx_check_missing_mem_inits (tree ctype,
            continue;
          if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
            {
-             /* Recurse to check the anonummous aggregate member.  */
+             /* Recurse to check the anonymous aggregate member.  */
              bad |= cx_check_missing_mem_inits
                (TREE_TYPE (field), NULL_TREE, complain);
              if (bad && !complain)
                return true;
              continue;
            }
+         if (cxx_dialect >= cxx2a)
+           continue;
          ftype = strip_array_types (TREE_TYPE (field));
          if (type_has_constexpr_default_constructor (ftype))
            {
@@ -6617,8 +6619,9 @@ potential_constant_expression_1 (tree t,
                          "%<thread_local%> in %<constexpr%> context", tmp);
              return false;
            }
-         else if (!check_for_uninitialized_const_var
-                  (tmp, /*constexpr_context_p=*/true, flags))
+         else if (cxx_dialect < cxx2a
+                  && !check_for_uninitialized_const_var
+                        (tmp, /*constexpr_context_p=*/true, flags))
            return false;
        }
       return RECUR (tmp, want_rval);
--- gcc/cp/method.c.jj  2019-05-20 23:33:13.818084173 +0200
+++ gcc/cp/method.c     2019-08-05 10:46:07.057545848 +0200
@@ -1410,7 +1410,9 @@ walk_field_subobs (tree fields, special_
          /* For an implicitly-defined default constructor to be constexpr,
             every member must have a user-provided default constructor or
             an explicit initializer.  */
-         if (constexpr_p && !CLASS_TYPE_P (mem_type)
+         if (constexpr_p
+             && cxx_dialect < cxx2a
+             && !CLASS_TYPE_P (mem_type)
              && TREE_CODE (DECL_CONTEXT (field)) != UNION_TYPE)
            {
              *constexpr_p = false;

Not really sure with the removal of diagnostics for constexpr ctors not
initializing all non-static data members  for -std=c++2a, shall we diagnose
somewhere else if a const or constexpr variable is initialized with such a
constructor?  And part of this change shall be bumping for cxx_dialect >= cxx2a
of __cpp_constexpr value.


More information about the Gcc-bugs mailing list