From 3885527ddf9ea47d0eab8d2c3a503a8e8e01d97d Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Wed, 24 Jan 2018 00:57:18 +0000 Subject: [PATCH] re PR c++/83921 (GCC rejects constexpr initialization of empty aggregate.) /cp 2018-01-23 Paolo Carlini PR c++/83921 * decl.c (check_for_uninitialized_const_var): Not static; add bool and tsubst_flags_t parameters; adjust to be used both in constexpr context and not. * constexpr.c (potential_constant_expression_1): Use the above. * cp-tree.h (check_for_uninitialized_const_var): Declare. /testsuite 2018-01-23 Paolo Carlini PR c++/83921 * g++.dg/cpp1y/constexpr-83921-1.C: New. * g++.dg/cpp1y/constexpr-83921-2.C: Likewise. * g++.dg/cpp1y/constexpr-83921-3.C: Likewise. * g++.dg/ext/stmtexpr20.C: Likewise. * g++.dg/ext/stmtexpr21.C: Likewise. From-SVN: r257009 --- gcc/cp/ChangeLog | 9 +++ gcc/cp/constexpr.c | 10 +--- gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 59 +++++++++++++------ gcc/testsuite/ChangeLog | 9 +++ .../g++.dg/cpp1y/constexpr-83921-1.C | 5 ++ .../g++.dg/cpp1y/constexpr-83921-2.C | 5 ++ .../g++.dg/cpp1y/constexpr-83921-3.C | 5 ++ gcc/testsuite/g++.dg/ext/stmtexpr20.C | 13 ++++ gcc/testsuite/g++.dg/ext/stmtexpr21.C | 13 ++++ 10 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-83921-1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-83921-2.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-83921-3.C create mode 100644 gcc/testsuite/g++.dg/ext/stmtexpr20.C create mode 100644 gcc/testsuite/g++.dg/ext/stmtexpr21.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9c2cba99121..bc89041a7da 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2018-01-23 Paolo Carlini + + PR c++/83921 + * decl.c (check_for_uninitialized_const_var): Not static; add + bool and tsubst_flags_t parameters; adjust to be used both in + constexpr context and not. + * constexpr.c (potential_constant_expression_1): Use the above. + * cp-tree.h (check_for_uninitialized_const_var): Declare. + 2018-01-23 Jason Merrill PR c++/83947 - ICE with auto declarations. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index ca7f369f7e9..4d2ee4a28fc 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5707,13 +5707,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, "% in % 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 % context", tmp); - return false; - } + else if (!check_for_uninitialized_const_var + (tmp, /*constexpr_context_p=*/true, flags)) + return false; } return RECUR (tmp, want_rval); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 46882dcd47b..8983674881d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6221,6 +6221,7 @@ extern tree finish_case_label (location_t, tree, 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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1970865f367..408a1b77830 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -72,7 +72,6 @@ static int check_static_variable_definition (tree, 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); @@ -5545,10 +5544,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)); @@ -5557,26 +5560,38 @@ check_for_uninitialized_const_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)) - && !DECL_INITIAL (decl)) + && (constexpr_context_p + || CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl)) + && !DECL_NONTRIVIALLY_INITIALIZED_P (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 % 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 % " + "function", decl); + cp_function_chain->invalid_constexpr = true; + } } + else if (complain & tf_error) + error_at (DECL_SOURCE_LOCATION (decl), + "uninitialized variable %qD in % context", + decl); - if (CLASS_TYPE_P (type)) + if (CLASS_TYPE_P (type) && (complain & tf_error)) { tree defaulted_ctor; @@ -5591,7 +5606,11 @@ check_for_uninitialized_const_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. @@ -6252,7 +6271,8 @@ check_initializer (tree decl, tree init, int flags, vec **cleanups) 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)) @@ -6379,7 +6399,8 @@ check_initializer (tree decl, tree init, int flags, vec **cleanups) 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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fb7e4571757..23fdb9fd30c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2018-01-23 Paolo Carlini + + PR c++/83921 + * g++.dg/cpp1y/constexpr-83921-1.C: New. + * g++.dg/cpp1y/constexpr-83921-2.C: Likewise. + * g++.dg/cpp1y/constexpr-83921-3.C: Likewise. + * g++.dg/ext/stmtexpr20.C: Likewise. + * g++.dg/ext/stmtexpr21.C: Likewise. + 2018-01-23 David Malcolm PR c++/83974 diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-1.C new file mode 100644 index 00000000000..e4b8d1fc420 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-1.C @@ -0,0 +1,5 @@ +// PR c++/83921 +// { dg-do compile { target c++14 } } + +struct Foo { }; +constexpr void test() { Foo f; } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-2.C new file mode 100644 index 00000000000..80393fc6ce7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-2.C @@ -0,0 +1,5 @@ +// PR c++/83921 +// { dg-do compile { target c++14 } } + +struct Foo { Foo() = default; }; +constexpr void test() { Foo f; } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-3.C new file mode 100644 index 00000000000..4b1ed5c3a87 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-83921-3.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr20.C b/gcc/testsuite/g++.dg/ext/stmtexpr20.C new file mode 100644 index 00000000000..33355e3b990 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/stmtexpr20.C @@ -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; +} diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr21.C b/gcc/testsuite/g++.dg/ext/stmtexpr21.C new file mode 100644 index 00000000000..259cb2f1913 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/stmtexpr21.C @@ -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; +} -- 2.30.2