From 5dab8b11c41fe72ea606c38884f7730bd2aeafdc Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 5 Nov 2018 02:46:57 -0500 Subject: [PATCH] Fix various latent issues revealed by P0732 work. The initialized_type hunk fixes handling of void AGGR_INIT_EXPRs that call a non-constructor; an AGGR_INIT_EXPR can have void type if its initialization semantics are more complicated than just expanding the call. The cxx_eval_vec_init_1 hunk corrects AGGR_INIT_EXPRs that were nonsensically built to initialize an object of void type. And the build_aggr_init_expr hunk makes sure we don't do that again. The ocp_convert and cxx_eval_outermost_constant_expr hunks deal with making sure that a constant CONSTRUCTOR has the right type. * cvt.c (ocp_convert): Don't wrap a CONSTRUCTOR in a NOP_EXPR. * constexpr.c (initialized_type): Fix AGGR_INIT_EXPR handling. (cxx_eval_vec_init_1): Correct type of AGGR_INIT_EXPR. (cxx_eval_outermost_constant_expr): Make sure a CONSTRUCTOR has the right type. Don't wrap a CONSTRUCTOR if one was passed in. * tree.c (build_aggr_init_expr): Check for void. From-SVN: r265788 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/constexpr.c | 22 +++++++++++++--------- gcc/cp/cvt.c | 10 +++++++++- gcc/cp/tree.c | 2 ++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7e9c0e2642a..4f40627a226 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2018-11-04 Jason Merrill + * cvt.c (ocp_convert): Don't wrap a CONSTRUCTOR in a NOP_EXPR. + * constexpr.c (initialized_type): Fix AGGR_INIT_EXPR handling. + (cxx_eval_vec_init_1): Correct type of AGGR_INIT_EXPR. + (cxx_eval_outermost_constant_expr): Make sure a CONSTRUCTOR has the + right type. Don't wrap a CONSTRUCTOR if one was passed in. + * tree.c (build_aggr_init_expr): Check for void. + PR c++/60503 - wrong lambda attribute syntax. * parser.c (cp_parser_lambda_declarator_opt): Fix attribute handling. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 7692b1727da..4fb1ba527e3 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2778,8 +2778,10 @@ initialized_type (tree t) { if (TYPE_P (t)) return t; - tree type = cv_unqualified (TREE_TYPE (t)); - if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR) + tree type = TREE_TYPE (t); + if (!VOID_TYPE_P (type)) + /* No need to look deeper. */; + else if (TREE_CODE (t) == CALL_EXPR) { /* A constructor call has void type, so we need to look deeper. */ tree fn = get_function_named_in_call (t); @@ -2787,7 +2789,9 @@ initialized_type (tree t) && DECL_CXX_CONSTRUCTOR_P (fn)) type = DECL_CONTEXT (fn); } - return type; + else if (TREE_CODE (t) == AGGR_INIT_EXPR) + type = TREE_TYPE (AGGR_INIT_EXPR_SLOT (t)); + return cv_unqualified (type); } /* We're about to initialize element INDEX of an array or class from VALUE. @@ -3000,7 +3004,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, &argvec, elttype, LOOKUP_NORMAL, complain); release_tree_vector (argvec); - init = build_aggr_init_expr (TREE_TYPE (init), init); + init = build_aggr_init_expr (elttype, init); pre_init = true; } @@ -5089,7 +5093,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, r = build_nop (TREE_TYPE (r), r); TREE_CONSTANT (r) = false; } - else if (non_constant_p || r == t) + else if (non_constant_p) return t; if (should_unshare) @@ -5097,18 +5101,18 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (TREE_CODE (r) == CONSTRUCTOR && CLASS_TYPE_P (TREE_TYPE (r))) { + r = adjust_temp_type (type, r); if (TREE_CODE (t) == TARGET_EXPR && TARGET_EXPR_INITIAL (t) == r) return t; - else + else if (TREE_CODE (t) != CONSTRUCTOR) { r = get_target_expr (r); TREE_CONSTANT (r) = true; - return r; } } - else - return r; + + return r; } /* Returns true if T is a valid subexpression of a constant expression, diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 315b0d6a65a..b04e9a70652 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -725,7 +725,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags, /* We need a new temporary; don't take this shortcut. */; else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e))) { - if (same_type_p (type, TREE_TYPE (e))) + tree etype = TREE_TYPE (e); + if (same_type_p (type, etype)) /* The call to fold will not always remove the NOP_EXPR as might be expected, since if one of the types is a typedef; the comparison in fold is just equality of pointers, not a @@ -743,9 +744,16 @@ ocp_convert (tree type, tree expr, int convtype, int flags, { /* Don't build a NOP_EXPR of class type. Instead, change the type of the temporary. */ + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype)); TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type; return e; } + else if (TREE_CODE (e) == CONSTRUCTOR) + { + gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype)); + TREE_TYPE (e) = type; + return e; + } else { /* We shouldn't be treating objects of ADDRESSABLE type as diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 74018e97bb7..51af9f2015e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -576,6 +576,8 @@ build_aggr_init_expr (tree type, tree init) tree rval; int is_ctor; + gcc_assert (!VOID_TYPE_P (type)); + /* Don't build AGGR_INIT_EXPR in a template. */ if (processing_template_decl) return init;