From: Jason Merrill Date: Tue, 9 May 2017 13:48:58 +0000 (-0400) Subject: PR c++/70167 - array prvalue treated as lvalue X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6064858051d6e07bb89f3384c0d828f07c576c7a;p=gcc.git PR c++/70167 - array prvalue treated as lvalue * cp-tree.h (CONSTRUCTOR_C99_COMPOUND_LITERAL): New. (enum fcl_t): New. * semantics.c (finish_compound_literal): Add fcl_context parameter. Only make a static variable for C99 syntax. * parser.c (cp_parser_postfix_expression): Pass it. * pt.c (tsubst_copy_and_build): Likewise. * call.c (extend_ref_init_temps): Set DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. From-SVN: r247793 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c4b850f5186..a5990e2a6c2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2017-05-09 Jason Merrill + + PR c++/70167 - array prvalue treated as lvalue + * cp-tree.h (CONSTRUCTOR_C99_COMPOUND_LITERAL): New. + (enum fcl_t): New. + * semantics.c (finish_compound_literal): Add fcl_context parameter. + Only make a static variable for C99 syntax. + * parser.c (cp_parser_postfix_expression): Pass it. + * pt.c (tsubst_copy_and_build): Likewise. + * call.c (extend_ref_init_temps): Set + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. + 2017-05-09 Nathan Sidwell * cp-lang.c (get_global_decls, cxx_pushdecl): New. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d9accd16401..dee236e703d 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -10516,6 +10516,9 @@ extend_ref_init_temps (tree decl, tree init, vec **cleanups) FOR_EACH_VEC_SAFE_ELT (elts, i, p) p->value = extend_ref_init_temps (decl, p->value, cleanups); } + recompute_constructor_flags (ctor); + if (decl_maybe_constant_var_p (decl) && TREE_CONSTANT (ctor)) + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; } } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b64fa6dafbc..100f85c1265 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -369,6 +369,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL) CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE) + CONSTUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR) 4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) @@ -3898,6 +3899,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define CONSTRUCTOR_MUTABLE_POISON(NODE) \ (TREE_LANG_FLAG_2 (CONSTRUCTOR_CHECK (NODE))) +/* True if this typed CONSTRUCTOR represents C99 compound-literal syntax rather + than C++11 functional cast syntax. */ +#define CONSTRUCTOR_C99_COMPOUND_LITERAL(NODE) \ + (TREE_LANG_FLAG_3 (CONSTRUCTOR_CHECK (NODE))) + #define DIRECT_LIST_INIT_P(NODE) \ (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE)) @@ -6483,7 +6489,10 @@ extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); extern cp_expr finish_unary_op_expr (location_t, enum tree_code, cp_expr, tsubst_flags_t); -extern tree finish_compound_literal (tree, tree, tsubst_flags_t); +/* Whether this call to finish_compound_literal represents a C++11 functional + cast or a C99 compound literal. */ +enum fcl_t { fcl_functional, fcl_c99 }; +extern tree finish_compound_literal (tree, tree, tsubst_flags_t, fcl_t = fcl_functional); extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ab56f120083..19514525d2f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6770,7 +6770,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Form the representation of the compound-literal. */ postfix_expression = finish_compound_literal (type, initializer, - tf_warning_or_error); + tf_warning_or_error, fcl_c99); postfix_expression.set_location (initializer.get_location ()); break; } @@ -26834,7 +26834,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type) type = TREE_TYPE (type); cast = finish_compound_literal (type, expression_list, - tf_warning_or_error); + tf_warning_or_error, fcl_functional); /* Create a location of the form: type_name{i, f} ^~~~~~~~~~~~~~~ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b42b1fc10fb..a4a0d83503a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17709,7 +17709,12 @@ tsubst_copy_and_build (tree t, CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t); if (TREE_HAS_CONSTRUCTOR (t)) - RETURN (finish_compound_literal (type, r, complain)); + { + fcl_t cl = fcl_functional; + if (CONSTRUCTOR_C99_COMPOUND_LITERAL (t)) + cl = fcl_c99; + RETURN (finish_compound_literal (type, r, complain, cl)); + } TREE_TYPE (r) = type; RETURN (r); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b15763d08c2..238dfff4743 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2647,12 +2647,14 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr, return result; } -/* Finish a compound-literal expression. TYPE is the type to which - the CONSTRUCTOR in COMPOUND_LITERAL is being cast. */ +/* Finish a compound-literal expression or C++11 functional cast with aggregate + initializer. TYPE is the type to which the CONSTRUCTOR in COMPOUND_LITERAL + is being cast. */ tree finish_compound_literal (tree type, tree compound_literal, - tsubst_flags_t complain) + tsubst_flags_t complain, + fcl_t fcl_context) { if (type == error_mark_node) return error_mark_node; @@ -2661,7 +2663,7 @@ finish_compound_literal (tree type, tree compound_literal, { compound_literal = finish_compound_literal (TREE_TYPE (type), compound_literal, - complain); + complain, fcl_context); return cp_build_c_cast (type, compound_literal, complain); } @@ -2682,6 +2684,8 @@ finish_compound_literal (tree type, tree compound_literal, TREE_TYPE (compound_literal) = type; /* Mark the expression as a compound literal. */ TREE_HAS_CONSTRUCTOR (compound_literal) = 1; + if (fcl_context == fcl_c99) + CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1; return compound_literal; } @@ -2717,10 +2721,17 @@ finish_compound_literal (tree type, tree compound_literal, compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL, complain); if (TREE_CODE (compound_literal) == CONSTRUCTOR) - TREE_HAS_CONSTRUCTOR (compound_literal) = true; + { + TREE_HAS_CONSTRUCTOR (compound_literal) = true; + if (fcl_context == fcl_c99) + CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1; + } /* Put static/constant array temporaries in static variables. */ + /* FIXME all C99 compound literals should be variables rather than C++ + temporaries, unless they are used as an aggregate initializer. */ if ((!at_function_scope_p () || CP_TYPE_CONST_P (type)) + && fcl_context == fcl_c99 && TREE_CODE (type) == ARRAY_TYPE && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) && initializer_constant_valid_p (compound_literal, type)) diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array6.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array6.C new file mode 100644 index 00000000000..fdfde0a3c60 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array6.C @@ -0,0 +1,11 @@ +// PR c++/70167 +// { dg-do compile { target c++11 } } + +template void f(T(&&)[S]) { } + +using arr = const int[2]; + +int main() +{ + f(arr{1, 2}); +}