Bug 91353 - Implement P1331R2: Permitting trivial default initialization in constexpr contexts
Summary: Implement P1331R2: Permitting trivial default initialization in constexpr con...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 88323
  Show dependency treegraph
 
Reported: 2019-08-05 09:11 UTC by Jakub Jelinek
Modified: 2019-08-12 19:50 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-08-05 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2019-08-05 09:11:23 UTC
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.
Comment 1 Jakub Jelinek 2019-08-05 15:00:26 UTC
Note, I won't have time soon to work on this further, so if anyone wants to take it over, reusing or not reusing the above patch, feel free.