Commit 3885527d by Paolo Carlini Committed by Paolo Carlini

re PR c++/83921 (GCC rejects constexpr initialization of empty aggregate.)

/cp
2018-01-23  Paolo Carlini  <paolo.carlini@oracle.com>

	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  <paolo.carlini@oracle.com>

	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
parent 7a007e44
2018-01-23 Paolo Carlini <paolo.carlini@oracle.com>
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 <jason@redhat.com> 2018-01-23 Jason Merrill <jason@redhat.com>
PR c++/83947 - ICE with auto declarations. PR c++/83947 - ICE with auto declarations.
......
...@@ -5707,14 +5707,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, ...@@ -5707,14 +5707,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
"%<thread_local%> in %<constexpr%> context", tmp); "%<thread_local%> in %<constexpr%> context", tmp);
return false; return false;
} }
else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp)) else if (!check_for_uninitialized_const_var
{ (tmp, /*constexpr_context_p=*/true, flags))
if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized "
"variable %qD in %<constexpr%> context", tmp);
return false; return false;
} }
}
return RECUR (tmp, want_rval); return RECUR (tmp, want_rval);
case TRY_FINALLY_EXPR: case TRY_FINALLY_EXPR:
......
...@@ -6221,6 +6221,7 @@ extern tree finish_case_label (location_t, tree, tree); ...@@ -6221,6 +6221,7 @@ extern tree finish_case_label (location_t, tree, tree);
extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t); extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t);
extern bool check_array_designated_initializer (constructor_elt *, extern bool check_array_designated_initializer (constructor_elt *,
unsigned HOST_WIDE_INT); unsigned HOST_WIDE_INT);
extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
/* in decl2.c */ /* in decl2.c */
extern void record_mangling (tree, bool); extern void record_mangling (tree, bool);
......
...@@ -72,7 +72,6 @@ static int check_static_variable_definition (tree, tree); ...@@ -72,7 +72,6 @@ static int check_static_variable_definition (tree, tree);
static void record_unknown_type (tree, const char *); static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (tree, tree, bool); static tree builtin_function_1 (tree, tree, bool);
static int member_function_or_else (tree, tree, enum overload_flags); 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 tree local_variable_p_walkfn (tree *, int *, void *);
static const char *tag_name (enum tag_types); static const char *tag_name (enum tag_types);
static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool); static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
...@@ -5545,10 +5544,14 @@ maybe_commonize_var (tree decl) ...@@ -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 bool
check_for_uninitialized_const_var (tree decl) check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
tsubst_flags_t complain)
{ {
tree type = strip_array_types (TREE_TYPE (decl)); tree type = strip_array_types (TREE_TYPE (decl));
...@@ -5557,26 +5560,38 @@ check_for_uninitialized_const_var (tree decl) ...@@ -5557,26 +5560,38 @@ check_for_uninitialized_const_var (tree decl)
7.1.6 */ 7.1.6 */
if (VAR_P (decl) if (VAR_P (decl)
&& TREE_CODE (type) != REFERENCE_TYPE && TREE_CODE (type) != REFERENCE_TYPE
&& (CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl)) && (constexpr_context_p
&& !DECL_INITIAL (decl)) || CP_TYPE_CONST_P (type) || var_in_constexpr_fn (decl))
&& !DECL_NONTRIVIALLY_INITIALIZED_P (decl))
{ {
tree field = default_init_uninitialized_part (type); tree field = default_init_uninitialized_part (type);
if (!field) if (!field)
return; return true;
if (!constexpr_context_p)
{
if (CP_TYPE_CONST_P (type)) if (CP_TYPE_CONST_P (type))
{
if (complain & tf_error)
permerror (DECL_SOURCE_LOCATION (decl), permerror (DECL_SOURCE_LOCATION (decl),
"uninitialized const %qD", decl); "uninitialized const %qD", decl);
}
else else
{ {
if (!is_instantiation_of_constexpr (current_function_decl)) if (!is_instantiation_of_constexpr (current_function_decl)
&& (complain & tf_error))
error_at (DECL_SOURCE_LOCATION (decl), error_at (DECL_SOURCE_LOCATION (decl),
"uninitialized variable %qD in %<constexpr%> function", "uninitialized variable %qD in %<constexpr%> "
decl); "function", decl);
cp_function_chain->invalid_constexpr = true; 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; tree defaulted_ctor;
...@@ -5591,7 +5606,11 @@ check_for_uninitialized_const_var (tree decl) ...@@ -5591,7 +5606,11 @@ check_for_uninitialized_const_var (tree decl)
"and the implicitly-defined constructor does not " "and the implicitly-defined constructor does not "
"initialize %q#D", field); "initialize %q#D", field);
} }
return false;
} }
return true;
} }
/* Structure holding the current initializer being processed by reshape_init. /* Structure holding the current initializer being processed by reshape_init.
...@@ -6252,7 +6271,8 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) ...@@ -6252,7 +6271,8 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
flags |= LOOKUP_ALREADY_DIGESTED; flags |= LOOKUP_ALREADY_DIGESTED;
} }
else if (!init) 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 /* Do not reshape constructors of vectors (they don't need to be
reshaped. */ reshaped. */
else if (BRACE_ENCLOSED_INITIALIZER_P (init)) else if (BRACE_ENCLOSED_INITIALIZER_P (init))
...@@ -6379,7 +6399,8 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) ...@@ -6379,7 +6399,8 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false, diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false,
/*complain=*/true); /*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) if (init && init != error_mark_node)
......
2018-01-23 Paolo Carlini <paolo.carlini@oracle.com>
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 <dmalcolm@redhat.com> 2018-01-23 David Malcolm <dmalcolm@redhat.com>
PR c++/83974 PR c++/83974
......
// PR c++/83921
// { dg-do compile { target c++14 } }
struct Foo { };
constexpr void test() { Foo f; }
// PR c++/83921
// { dg-do compile { target c++14 } }
struct Foo { Foo() = default; };
constexpr void test() { Foo f; }
// PR c++/83921
// { dg-do compile { target c++14 } }
struct Foo { int m; };
constexpr void test() { Foo f; } // { dg-error "uninitialized" }
// 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;
}
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment