aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-05-09 09:48:58 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-05-09 09:48:58 -0400
commit6064858051d6e07bb89f3384c0d828f07c576c7a (patch)
tree815f68ce3b1ebd2059c5d426b0319427a127795a /gcc
parent6c38fbc648dc7bfa73ef703d1584196f64dcc151 (diff)
downloadgcc-6064858051d6e07bb89f3384c0d828f07c576c7a.zip
gcc-6064858051d6e07bb89f3384c0d828f07c576c7a.tar.gz
gcc-6064858051d6e07bb89f3384c0d828f07c576c7a.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c3
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/parser.c4
-rw-r--r--gcc/cp/pt.c7
-rw-r--r--gcc/cp/semantics.c21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-array6.C11
7 files changed, 60 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c4b850f..a5990e2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2017-05-09 Jason Merrill <jason@redhat.com>
+
+ 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 <nathan@acm.org>
* cp-lang.c (get_global_decls, cxx_pushdecl): New.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d9accd1..dee236e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -10516,6 +10516,9 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **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 b64fa6d..100f85c 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 ab56f12..1951452 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 b42b1fc..a4a0d83 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 b15763d..238dfff 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 0000000..fdfde0a
--- /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<class T, unsigned S> void f(T(&&)[S]) { }
+
+using arr = const int[2];
+
+int main()
+{
+ f(arr{1, 2});
+}