* 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
+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.
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;
}
}
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)
#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))
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);
/* 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;
}
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}
^~~~~~~~~~~~~~~
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);
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;
{
compound_literal
= finish_compound_literal (TREE_TYPE (type), compound_literal,
- complain);
+ complain, fcl_context);
return cp_build_c_cast (type, compound_literal, complain);
}
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;
}
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))
--- /dev/null
+// 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});
+}