Hi again,

On 22/01/2018 22:50, Paolo Carlini wrote:
Ok. The below passes the C++ testsuite and I'm finishing testing it. Therefore, as you already hinted to, we can now say that what was *really* missing from potential_constant_expression_1 was the use of default_init_uninitialized_part, which does all the non-trivial work besides the later !DECL_NONTRIVIALLY_INITIALIZED_P check. check_for_uninitialized_const_var also provides the informs, which were completely missing.
Grrr. Testing the library revealed immediately the failure of 18_support/byte/ops.cc, because in constexpr_context_p == true, thus from potential_constant_expression_1, the case CP_TYPE_CONST_P triggers. I guess we really want to keep the existing constexpr_context_p == false cases separate. I'm therefore restarting testing with the below.

Paolo.

///////////////


Index: cp/constexpr.c
===================================================================
--- cp/constexpr.c      (revision 256961)
+++ cp/constexpr.c      (working copy)
@@ -5707,13 +5707,9 @@ potential_constant_expression_1 (tree t, bool want
                          "%<thread_local%> in %<constexpr%> context", tmp);
              return false;
            }
-         else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp))
-           {
-             if (flags & tf_error)
-               error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized "
-                         "variable %qD in %<constexpr%> context", tmp);
-             return false;
-           }
+         else if (!check_for_uninitialized_const_var
+                  (tmp, /*constexpr_context_p=*/true, flags))
+           return false;
        }
       return RECUR (tmp, want_rval);
 
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 256961)
+++ cp/cp-tree.h        (working copy)
@@ -6221,6 +6221,7 @@ extern tree finish_case_label                     
(location_t, tree,
 extern tree cxx_maybe_build_cleanup            (tree, tsubst_flags_t);
 extern bool check_array_designated_initializer  (constructor_elt *,
                                                 unsigned HOST_WIDE_INT);
+extern bool check_for_uninitialized_const_var   (tree, bool, tsubst_flags_t);
 
 /* in decl2.c */
 extern void record_mangling                    (tree, bool);
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 256961)
+++ cp/decl.c   (working copy)
@@ -72,7 +72,6 @@ static int check_static_variable_definition (tree,
 static void record_unknown_type (tree, const char *);
 static tree builtin_function_1 (tree, tree, bool);
 static int member_function_or_else (tree, tree, enum overload_flags);
-static void check_for_uninitialized_const_var (tree);
 static tree local_variable_p_walkfn (tree *, int *, void *);
 static const char *tag_name (enum tag_types);
 static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
@@ -5543,10 +5542,14 @@ maybe_commonize_var (tree decl)
     }
 }
 
-/* Issue an error message if DECL is an uninitialized const variable.  */
+/* Issue an error message if DECL is an uninitialized const variable.
+   CONSTEXPR_CONTEXT_P is true when the function is called in a constexpr
+   context from potential_constant_expression.  Returns true if all is well,
+   false otherwise.  */
 
-static void
-check_for_uninitialized_const_var (tree decl)
+bool
+check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
+                                  tsubst_flags_t complain)
 {
   tree type = strip_array_types (TREE_TYPE (decl));
 
@@ -5555,26 +5558,39 @@ maybe_commonize_var (tree decl)
      7.1.6 */
   if (VAR_P (decl)
       && TREE_CODE (type) != REFERENCE_TYPE
-      && (CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl))
+      && ((!constexpr_context_p
+          && (CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl)))
+         || (constexpr_context_p && !DECL_NONTRIVIALLY_INITIALIZED_P (decl)))
       && !DECL_INITIAL (decl))
     {
       tree field = default_init_uninitialized_part (type);
       if (!field)
-       return;
+       return true;
 
-      if (CP_TYPE_CONST_P (type))
-       permerror (DECL_SOURCE_LOCATION (decl),
-                  "uninitialized const %qD", decl);
-      else
+      if (!constexpr_context_p)
        {
-         if (!is_instantiation_of_constexpr (current_function_decl))
-           error_at (DECL_SOURCE_LOCATION (decl),
-                     "uninitialized variable %qD in %<constexpr%> function",
-                     decl);
-         cp_function_chain->invalid_constexpr = true;
+         if (CP_TYPE_CONST_P (type))
+           {
+             if (complain & tf_error)
+               permerror (DECL_SOURCE_LOCATION (decl),
+                          "uninitialized const %qD", decl);
+           }
+         else
+           {
+             if (!is_instantiation_of_constexpr (current_function_decl)
+                 && (complain & tf_error))
+               error_at (DECL_SOURCE_LOCATION (decl),
+                         "uninitialized variable %qD in %<constexpr%> 
function",
+                         decl);
+             cp_function_chain->invalid_constexpr = true;
+           }
        }
+      else if (complain & tf_error)
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "uninitialized variable %qD in %<constexpr%> context",
+                 decl);
 
-      if (CLASS_TYPE_P (type))
+      if (CLASS_TYPE_P (type) && (complain & tf_error))
        {
          tree defaulted_ctor;
 
@@ -5589,7 +5605,11 @@ maybe_commonize_var (tree decl)
                  "and the implicitly-defined constructor does not "
                  "initialize %q#D", field);
        }
+
+      return false;
     }
+
+  return true;
 }
 
 /* Structure holding the current initializer being processed by reshape_init.
@@ -6250,7 +6270,8 @@ check_initializer (tree decl, tree init, int flags
          flags |= LOOKUP_ALREADY_DIGESTED;
        }
       else if (!init)
-       check_for_uninitialized_const_var (decl);
+       check_for_uninitialized_const_var (decl, /*constexpr_context_p =*/false,
+                                          tf_warning_or_error);
       /* Do not reshape constructors of vectors (they don't need to be
         reshaped.  */
       else if (BRACE_ENCLOSED_INITIALIZER_P (init))
@@ -6377,7 +6398,8 @@ check_initializer (tree decl, tree init, int flags
        diagnose_uninitialized_cst_or_ref_member (core_type, 
/*using_new=*/false,
                                                  /*complain=*/true);
 
-      check_for_uninitialized_const_var (decl);
+      check_for_uninitialized_const_var (decl, /*constexpr_context_p=*/false,
+                                        tf_warning_or_error);
     }
 
   if (init && init != error_mark_node)
Index: testsuite/g++.dg/cpp1y/constexpr-83921-1.C
===================================================================
--- testsuite/g++.dg/cpp1y/constexpr-83921-1.C  (nonexistent)
+++ testsuite/g++.dg/cpp1y/constexpr-83921-1.C  (working copy)
@@ -0,0 +1,5 @@
+// PR c++/83921
+// { dg-do compile { target c++14 } }
+
+struct Foo { };
+constexpr void test() { Foo f; }
Index: testsuite/g++.dg/cpp1y/constexpr-83921-2.C
===================================================================
--- testsuite/g++.dg/cpp1y/constexpr-83921-2.C  (nonexistent)
+++ testsuite/g++.dg/cpp1y/constexpr-83921-2.C  (working copy)
@@ -0,0 +1,5 @@
+// PR c++/83921
+// { dg-do compile { target c++14 } }
+
+struct Foo { Foo() = default; };
+constexpr void test() { Foo f; }
Index: testsuite/g++.dg/cpp1y/constexpr-83921-3.C
===================================================================
--- testsuite/g++.dg/cpp1y/constexpr-83921-3.C  (nonexistent)
+++ testsuite/g++.dg/cpp1y/constexpr-83921-3.C  (working copy)
@@ -0,0 +1,5 @@
+// PR c++/83921
+// { dg-do compile { target c++14 } }
+
+struct Foo { int m; };
+constexpr void test() { Foo f; }  // { dg-error "uninitialized" }
Index: testsuite/g++.dg/ext/stmtexpr20.C
===================================================================
--- testsuite/g++.dg/ext/stmtexpr20.C   (nonexistent)
+++ testsuite/g++.dg/ext/stmtexpr20.C   (working copy)
@@ -0,0 +1,13 @@
+// PR c++/83921
+// { dg-options "" }
+// { dg-do compile { target c++11 } }
+
+struct test { const int *addr; };
+
+const test* setup()
+{
+  static constexpr test atest =
+    { ({ int inner = 1; (const int*)(0); }) };
+
+  return &atest;
+}
Index: testsuite/g++.dg/ext/stmtexpr21.C
===================================================================
--- testsuite/g++.dg/ext/stmtexpr21.C   (nonexistent)
+++ testsuite/g++.dg/ext/stmtexpr21.C   (working copy)
@@ -0,0 +1,13 @@
+// PR c++/83921
+// { dg-options "" }
+// { dg-do compile { target c++11 } }
+
+struct test { const int *addr; };
+
+const test* setup()
+{
+  static constexpr test atest =
+    { ({ int inner; (const int*)(0); }) };  // { dg-error "uninitialized" }
+
+  return &atest;
+}

Reply via email to