Implement P0217R3 - C++17 structured bindings

gcc/
	* match.pd: Don't try to compare addresses of variables with
	DECL_VALUE_EXPR.
gcc/cp/
	* cp-tree.h (struct lang_decl_base): Add decomposition_p.
	(DECL_DECOMPOSITION_P): New
	(enum auto_deduction_context): Add adc_decomp_type.
	(enum cp_declarator_kind): Add cdk_decomp.
	* constexpr.c (cxx_eval_constant_expression): Look through
	DECL_VALUE_EXPR.
	(potential_constant_expression_1): Likewise.
	* decl.c (reshape_init): Preserve CONSTRUCTOR_IS_DIRECT_INIT.
	(check_initializer): Use build_aggr_init for DECL_DECOMPOSITION_P.
	(cp_finish_decl): Pass adc_decomp_type for decomposition.
	(find_decomp_class_base, get_tuple_size, get_tuple_element_type)
	(get_tuple_decomp_init, cp_finish_decomp): New.
	(grokdeclarator): Handle decomposition.
	* init.c (build_aggr_init): Handle decomposition array.
	(build_vec_init): Handle initialization from { array }.
	* name-lookup.c (add_function): Always wrap TEMPLATE_DECL in
	OVERLOAD.
	* parser.c (declarator_can_be_parameter_pack): Handle cdk_decomp.
	(function_declarator_p, strip_declarator_types)
	(cp_parser_check_declarator_template_parameters): Likewise.
	(cp_parser_range_for, cp_convert_range_for): Handle decomposition.
	(cp_parser_simple_declaration): Parse decomposition.
	(cp_parser_decomposition_declaration): New.
	* pt.c (tsubst_decomp_names): New.
	(subst_expr) [DECL_EXPR, RANGE_FOR_STMT]: Handle decomposition.
	(do_auto_deduction): Handle adc_decomp_type.
	* semantics.c (finish_decltype_type): Look through DECL_VALUE_EXPR.
	* typeck.c (is_bitfield_expr_with_lowered_type): Likewise.
	* tree.c (lvalue_kind): Likewise.
	(cp_build_reference_type): Handle reference collapsing.

Co-Authored-By: Jason Merrill <jason@redhat.com>

From-SVN: r242377
This commit is contained in:
Jakub Jelinek 2016-11-14 06:02:58 +01:00 committed by Jason Merrill
parent e7555e42d0
commit 70f40fea6a
14 changed files with 939 additions and 59 deletions

View File

@ -1,3 +1,8 @@
2016-11-13 Jakub Jelinek <jakub@redhat.com>
* match.pd: Don't try to compare addresses of variables with
DECL_VALUE_EXPR.
2016-11-13 Kugan Vivekanandarajah <kuganv@linaro.org>
* ipa-cp.c (ipa_get_jf_pass_through_result): Skip unary expressions.

View File

@ -1,3 +1,38 @@
2016-11-13 Jakub Jelinek <jakub@redhat.com>
Jason Merrill <jason@redhat.com>
Implement P0217R3 - C++17 structured bindings
* cp-tree.h (struct lang_decl_base): Add decomposition_p.
(DECL_DECOMPOSITION_P): New
(enum auto_deduction_context): Add adc_decomp_type.
(enum cp_declarator_kind): Add cdk_decomp.
* constexpr.c (cxx_eval_constant_expression): Look through
DECL_VALUE_EXPR.
(potential_constant_expression_1): Likewise.
* decl.c (reshape_init): Preserve CONSTRUCTOR_IS_DIRECT_INIT.
(check_initializer): Use build_aggr_init for DECL_DECOMPOSITION_P.
(cp_finish_decl): Pass adc_decomp_type for decomposition.
(find_decomp_class_base, get_tuple_size, get_tuple_element_type)
(get_tuple_decomp_init, cp_finish_decomp): New.
(grokdeclarator): Handle decomposition.
* init.c (build_aggr_init): Handle decomposition array.
(build_vec_init): Handle initialization from { array }.
* name-lookup.c (add_function): Always wrap TEMPLATE_DECL in
OVERLOAD.
* parser.c (declarator_can_be_parameter_pack): Handle cdk_decomp.
(function_declarator_p, strip_declarator_types)
(cp_parser_check_declarator_template_parameters): Likewise.
(cp_parser_range_for, cp_convert_range_for): Handle decomposition.
(cp_parser_simple_declaration): Parse decomposition.
(cp_parser_decomposition_declaration): New.
* pt.c (tsubst_decomp_names): New.
(subst_expr) [DECL_EXPR, RANGE_FOR_STMT]: Handle decomposition.
(do_auto_deduction): Handle adc_decomp_type.
* semantics.c (finish_decltype_type): Look through DECL_VALUE_EXPR.
* typeck.c (is_bitfield_expr_with_lowered_type): Likewise.
* tree.c (lvalue_kind): Likewise.
(cp_build_reference_type): Handle reference collapsing.
2016-11-13 Jason Merrill <jason@redhat.com>
* call.c (build_new_method_call_1): Include template arguments in

View File

@ -3770,7 +3770,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return (*ctx->values->get (t));
case VAR_DECL:
if (is_capture_proxy (t))
if (DECL_HAS_VALUE_EXPR_P (t))
return cxx_eval_constant_expression (ctx, DECL_VALUE_EXPR (t),
lval, non_constant_p, overflow_p);
/* fall through */
@ -5037,6 +5037,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
return RECUR (TREE_OPERAND (t, 0), rval);
case VAR_DECL:
if (DECL_HAS_VALUE_EXPR_P (t))
return RECUR (DECL_VALUE_EXPR (t), rval);
if (want_rval
&& !var_in_maybe_constexpr_fn (t)
&& !type_dependent_expression_p (t)

View File

@ -2228,7 +2228,8 @@ struct GTY(()) lang_decl_base {
unsigned u2sel : 1;
unsigned concept_p : 1; /* applies to vars and functions */
unsigned var_declared_inline_p : 1; /* var */
/* 2 spare bits */
unsigned decomposition_p : 1; /* var */
/* 1 spare bit */
};
/* True for DECL codes which have template info and access. */
@ -3626,6 +3627,16 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \
= true)
/* Nonzero if NODE is the artificial VAR_DECL for decomposition
declaration. */
#define DECL_DECOMPOSITION_P(NODE) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
? DECL_LANG_SPECIFIC (NODE)->u.base.decomposition_p \
: false)
#define SET_DECL_DECOMPOSITION_P(NODE) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.decomposition_p \
= true)
/* Nonzero if NODE is an inline VAR_DECL. In C++17, static data members
declared with constexpr specifier are implicitly inline variables. */
#define DECL_INLINE_VAR_P(NODE) \
@ -5165,7 +5176,8 @@ enum auto_deduction_context
adc_variable_type, /* Variable initializer deduction */
adc_return_type, /* Return type deduction */
adc_unify, /* Template argument deduction */
adc_requirement /* Argument dedution constraint */
adc_requirement, /* Argument deduction constraint */
adc_decomp_type /* Decomposition declaration initializer deduction */
};
/* True iff this TEMPLATE_TYPE_PARM represents decltype(auto). */
@ -5382,6 +5394,7 @@ enum cp_declarator_kind {
cdk_pointer,
cdk_reference,
cdk_ptrmem,
cdk_decomp,
cdk_error
};
@ -5412,7 +5425,8 @@ struct cp_declarator {
/* Whether we parsed an ellipsis (`...') just before the declarator,
to indicate this is a parameter pack. */
BOOL_BITFIELD parameter_pack_p : 1;
location_t id_loc; /* Currently only set for cdk_id and cdk_function. */
location_t id_loc; /* Currently only set for cdk_id, cdk_decomp and
cdk_function. */
/* GNU Attributes that apply to this declarator. If the declarator
is a pointer or a reference, these attribute apply to the type
pointed to. */
@ -5421,8 +5435,8 @@ struct cp_declarator {
declarator is a pointer or a reference, these attributes apply
to the pointer, rather than to the type pointed to. */
tree std_attributes;
/* For all but cdk_id and cdk_error, the contained declarator. For
cdk_id and cdk_error, guaranteed to be NULL. */
/* For all but cdk_id, cdk_decomp and cdk_error, the contained declarator.
For cdk_id, cdk_decomp and cdk_error, guaranteed to be NULL. */
cp_declarator *declarator;
union {
/* For identifiers. */
@ -5794,6 +5808,7 @@ extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int,
extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
extern void cp_finish_decl (tree, tree, bool, tree, int);
extern void cp_finish_decomp (tree, tree, unsigned int);
extern int cp_complete_array_type (tree *, tree, bool);
extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t);
extern tree build_ptrmemfunc_type (tree);
@ -6066,7 +6081,7 @@ extern tree implicitly_declare_fn (special_function_kind, tree,
extern bool maybe_clone_body (tree);
/* In parser.c */
extern tree cp_convert_range_for (tree, tree, tree, bool);
extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool);
extern bool parsing_nsdmi (void);
extern void inject_this_parameter (tree, cp_cv_quals);

View File

@ -6074,6 +6074,10 @@ reshape_init (tree type, tree init, tsubst_flags_t complain)
return error_mark_node;
}
if (CONSTRUCTOR_IS_DIRECT_INIT (init)
&& BRACE_ENCLOSED_INITIALIZER_P (new_init))
CONSTRUCTOR_IS_DIRECT_INIT (new_init) = true;
return new_init;
}
@ -6254,7 +6258,8 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
if (type == error_mark_node)
return NULL_TREE;
if ((type_build_ctor_call (type) || CLASS_TYPE_P (type))
if ((type_build_ctor_call (type) || CLASS_TYPE_P (type)
|| (DECL_DECOMPOSITION_P (decl) && TREE_CODE (type) == ARRAY_TYPE))
&& !(flags & LOOKUP_ALREADY_DIGESTED)
&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type)
@ -6770,10 +6775,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
d_init = build_x_compound_expr_from_list (d_init, ELK_INIT,
tf_warning_or_error);
d_init = resolve_nondeduced_context (d_init, tf_warning_or_error);
type = TREE_TYPE (decl) = do_auto_deduction (type, d_init,
auto_node,
tf_warning_or_error,
adc_variable_type);
enum auto_deduction_context adc = adc_variable_type;
if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
adc = adc_decomp_type;
type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, auto_node,
tf_warning_or_error, adc);
if (type == error_mark_node)
return;
if (TREE_CODE (type) == FUNCTION_TYPE)
@ -7137,6 +7143,390 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
}
/* For class TYPE return itself or some its bases that contain
any direct non-static data members. Return error_mark_node if an
error has been diagnosed. */
static tree
find_decomp_class_base (location_t loc, tree type, tree ret)
{
bool member_seen = false;
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
else if (ret)
return type;
else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
error_at (loc, "cannot decompose class type %qT because it has an "
"anonymous struct member", type);
else
error_at (loc, "cannot decompose class type %qT because it has an "
"anonymous union member", type);
inform (DECL_SOURCE_LOCATION (field), "declared here");
return error_mark_node;
}
else if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
error_at (loc, "cannot decompose non-public member %qD of %qT",
field, type);
inform (DECL_SOURCE_LOCATION (field),
TREE_PRIVATE (field) ? "declared private here"
: "declared protected here");
return error_mark_node;
}
else
member_seen = true;
tree base_binfo, binfo;
tree orig_ret = ret;
int i;
if (member_seen)
ret = type;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
tree t = find_decomp_class_base (loc, TREE_TYPE (base_binfo), ret);
if (t == error_mark_node)
return error_mark_node;
if (t != NULL_TREE)
{
if (ret == type)
{
error_at (loc, "cannot decompose class type %qT: both it and "
"its base class %qT have non-static data members",
type, t);
return error_mark_node;
}
else if (orig_ret != NULL_TREE)
return t;
else if (ret == t)
/* OK, found the same base along another path. We'll complain
in convert_to_base if it's ambiguous. */;
else if (ret != NULL_TREE)
{
error_at (loc, "cannot decompose class type %qT: its base "
"classes %qT and %qT have non-static data "
"members", type, ret, t);
return error_mark_node;
}
else
ret = t;
}
}
return ret;
}
/* Return std::tuple_size<TYPE>::value. */
tree
get_tuple_size (tree type)
{
tree args = make_tree_vec (1);
TREE_VEC_ELT (args, 0) = type;
tree inst = lookup_template_class (get_identifier ("tuple_size"), args,
/*in_decl*/NULL_TREE,
/*context*/std_node,
/*entering_scope*/false, tf_none);
tree val = lookup_qualified_name (inst, get_identifier ("value"),
/*type*/false, /*complain*/false);
if (TREE_CODE (val) == VAR_DECL || TREE_CODE (val) == CONST_DECL)
val = maybe_constant_value (val);
if (TREE_CODE (val) == INTEGER_CST)
return val;
else
return NULL_TREE;
}
/* Return std::tuple_element<I,TYPE>::type. */
tree
get_tuple_element_type (tree type, unsigned i)
{
tree args = make_tree_vec (2);
TREE_VEC_ELT (args, 0) = build_int_cst (integer_type_node, i);
TREE_VEC_ELT (args, 1) = type;
tree inst = lookup_template_class (get_identifier ("tuple_element"), args,
/*in_decl*/NULL_TREE,
/*context*/std_node,
/*entering_scope*/false,
tf_warning_or_error);
return make_typename_type (inst, get_identifier ("type"),
none_type, tf_warning_or_error);
}
/* Return e.get<i>() or get<i>(e). */
tree
get_tuple_decomp_init (tree decl, unsigned i)
{
tree get_id = get_identifier ("get");
tree targs = make_tree_vec (1);
TREE_VEC_ELT (targs, 0) = build_int_cst (integer_type_node, i);
tree etype = TREE_TYPE (decl);
tree e = convert_from_reference (decl);
/* [The id-expression] e is an lvalue if the type of the entity e is an
lvalue reference and an xvalue otherwise. */
if (TREE_CODE (etype) != REFERENCE_TYPE
|| TYPE_REF_IS_RVALUE (etype))
e = move (e);
tree fns = lookup_qualified_name (TREE_TYPE (e), get_id,
/*type*/false, /*complain*/false);
if (fns != error_mark_node)
{
fns = lookup_template_function (fns, targs);
return build_new_method_call (e, fns, /*args*/NULL,
/*path*/NULL_TREE, LOOKUP_NORMAL,
/*fn_p*/NULL, tf_warning_or_error);
}
else
{
vec<tree,va_gc> *args = make_tree_vector_single (e);
fns = lookup_template_function (get_id, targs);
fns = perform_koenig_lookup (fns, args, tf_warning_or_error);
return finish_call_expr (fns, &args, /*novirt*/false,
/*koenig*/true, tf_warning_or_error);
}
}
/* Finish a decomposition declaration. DECL is the underlying declaration
"e", FIRST is the head of a chain of decls for the individual identifiers
chained through DECL_CHAIN in reverse order and COUNT is the number of
those decls. */
void
cp_finish_decomp (tree decl, tree first, unsigned int count)
{
location_t loc = DECL_SOURCE_LOCATION (decl);
if (error_operand_p (decl))
{
error_out:
while (count--)
{
TREE_TYPE (first) = error_mark_node;
if (DECL_HAS_VALUE_EXPR_P (first))
{
SET_DECL_VALUE_EXPR (first, NULL_TREE);
DECL_HAS_VALUE_EXPR_P (first) = 0;
}
first = DECL_CHAIN (first);
}
return;
}
if (type_dependent_expression_p (decl)
/* This happens for range for when not in templates.
Still add the DECL_VALUE_EXPRs for later processing. */
|| (!processing_template_decl
&& type_uses_auto (TREE_TYPE (decl))))
{
for (unsigned int i = 0; i < count; i++)
{
if (!DECL_HAS_VALUE_EXPR_P (first))
{
tree v = build_nt (ARRAY_REF, decl,
size_int (count - i - 1),
NULL_TREE, NULL_TREE);
SET_DECL_VALUE_EXPR (first, v);
DECL_HAS_VALUE_EXPR_P (first) = 1;
}
if (processing_template_decl)
{
retrofit_lang_decl (first);
SET_DECL_DECOMPOSITION_P (first);
}
first = DECL_CHAIN (first);
}
return;
}
auto_vec<tree, 16> v;
v.safe_grow (count);
tree d = first;
for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
{
v[count - i - 1] = d;
if (processing_template_decl)
{
retrofit_lang_decl (d);
SET_DECL_DECOMPOSITION_P (d);
}
}
tree type = TREE_TYPE (decl);
tree eltype = NULL_TREE;
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
unsigned HOST_WIDE_INT eltscnt = 0;
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree nelts;
nelts = array_type_nelts_top (type);
if (nelts == error_mark_node)
goto error_out;
if (!tree_fits_uhwi_p (nelts))
{
error_at (loc, "cannot decompose variable length array %qT", type);
goto error_out;
}
eltscnt = tree_to_uhwi (nelts);
if (count != eltscnt)
{
cnt_mismatch:
if (count > eltscnt)
error_at (loc, "%u names provided while %qT decomposes into "
"%wu elements", count, type, eltscnt);
else
error_at (loc, "only %u names provided while %qT decomposes into "
"%wu elements", count, type, eltscnt);
goto error_out;
}
eltype = TREE_TYPE (type);
for (unsigned int i = 0; i < count; i++)
{
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
tree t = convert_from_reference (decl);
t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF,
eltype, t, size_int (i), NULL_TREE,
NULL_TREE);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
}
/* 2 GNU extensions. */
else if (TREE_CODE (type) == COMPLEX_TYPE)
{
eltscnt = 2;
if (count != eltscnt)
goto cnt_mismatch;
eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
for (unsigned int i = 0; i < count; i++)
{
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
tree t = convert_from_reference (decl);
t = build1_loc (DECL_SOURCE_LOCATION (v[i]),
i ? IMAGPART_EXPR : REALPART_EXPR, eltype,
t);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
}
else if (TREE_CODE (type) == VECTOR_TYPE)
{
eltscnt = TYPE_VECTOR_SUBPARTS (type);
if (count != eltscnt)
goto cnt_mismatch;
eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
for (unsigned int i = 0; i < count; i++)
{
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
tree t = convert_from_reference (decl);
convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]),
&t, size_int (i));
t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF,
eltype, t, size_int (i), NULL_TREE,
NULL_TREE);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
}
else if (tree tsize = get_tuple_size (type))
{
eltscnt = tree_to_uhwi (tsize);
if (count != eltscnt)
goto cnt_mismatch;
for (unsigned i = 0; i < count; ++i)
{
location_t sloc = input_location;
location_t dloc = DECL_SOURCE_LOCATION (v[i]);
input_location = dloc;
tree init = get_tuple_decomp_init (decl, i);
tree eltype = (init == error_mark_node ? error_mark_node
: get_tuple_element_type (type, i));
input_location = sloc;
if (init == error_mark_node || eltype == error_mark_node)
{
inform (dloc, "in initialization of decomposition variable %qD",
v[i]);
goto error_out;
}
eltype = cp_build_reference_type (eltype, !lvalue_p (init));
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (DECL_HAS_VALUE_EXPR_P (v[i]))
{
/* In this case the names are variables, not just proxies. */
SET_DECL_VALUE_EXPR (v[i], NULL_TREE);
DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
}
cp_finish_decl (v[i], init, /*constexpr*/false,
/*asm*/NULL_TREE, LOOKUP_NORMAL);
}
}
else if (TREE_CODE (type) == UNION_TYPE)
{
error_at (loc, "cannot decompose union type %qT", type);
goto error_out;
}
else if (!CLASS_TYPE_P (type))
{
error_at (loc, "cannot decompose non-array non-class type %qT", type);
goto error_out;
}
else
{
tree btype = find_decomp_class_base (loc, type, NULL_TREE);
if (btype == error_mark_node)
goto error_out;
else if (btype == NULL_TREE)
{
error_at (loc, "cannot decompose class type %qT without non-static "
"data members", type);
goto error_out;
}
for (tree field = TYPE_FIELDS (btype); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
else
eltscnt++;
if (count != eltscnt)
goto cnt_mismatch;
tree t = convert_from_reference (decl);
if (type != btype)
{
t = convert_to_base (t, btype, /*check_access*/true,
/*nonnull*/false, tf_warning_or_error);
type = btype;
}
unsigned int i = 0;
for (tree field = TYPE_FIELDS (btype); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
else
{
tree tt = finish_non_static_data_member (field, t, NULL_TREE);
tree probe = tt;
if (REFERENCE_REF_P (probe))
probe = TREE_OPERAND (probe, 0);
TREE_TYPE (v[i]) = TREE_TYPE (probe);
layout_decl (v[i], 0);
SET_DECL_VALUE_EXPR (v[i], tt);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
i++;
}
}
}
/* Returns a declaration for a VAR_DECL as if:
extern "C" TYPE NAME;
@ -9449,7 +9839,7 @@ grokdeclarator (const cp_declarator *declarator,
cp_storage_class storage_class;
bool unsigned_p, signed_p, short_p, long_p, thread_p;
bool type_was_error_mark_node = false;
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool parameter_pack_p = declarator ? declarator->parameter_pack_p : false;
bool template_type_arg = false;
bool template_parm_flag = false;
bool typedef_p = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
@ -9650,6 +10040,10 @@ grokdeclarator (const cp_declarator *declarator,
case cdk_ptrmem:
break;
case cdk_decomp:
name = "decomposition";
break;
case cdk_error:
return error_mark_node;
@ -9859,15 +10253,15 @@ grokdeclarator (const cp_declarator *declarator,
if (explicit_intN)
{
if (! int_n_enabled_p[declspecs->int_n_idx])
{
error ("%<__int%d%> is not supported by this target",
int_n_data[declspecs->int_n_idx].bitsize);
explicit_intN = false;
}
{
error ("%<__int%d%> is not supported by this target",
int_n_data[declspecs->int_n_idx].bitsize);
explicit_intN = false;
}
else if (pedantic && ! in_system_header_at (input_location))
pedwarn (input_location, OPT_Wpedantic,
"ISO C++ does not support %<__int%d%> for %qs",
int_n_data[declspecs->int_n_idx].bitsize, name);
pedwarn (input_location, OPT_Wpedantic,
"ISO C++ does not support %<__int%d%> for %qs",
int_n_data[declspecs->int_n_idx].bitsize, name);
}
/* Now process the modifiers that were specified
@ -10093,6 +10487,79 @@ grokdeclarator (const cp_declarator *declarator,
virtualp = 0;
}
if (innermost_code == cdk_decomp)
{
location_t loc = (declarator->kind == cdk_reference
? declarator->declarator->id_loc : declarator->id_loc);
if (inlinep)
error_at (declspecs->locations[ds_inline],
"decomposition declaration cannot be declared %<inline%>");
if (typedef_p)
error_at (declspecs->locations[ds_typedef],
"decomposition declaration cannot be declared %<typedef%>");
if (constexpr_p)
error_at (declspecs->locations[ds_constexpr], "decomposition "
"declaration cannot be declared %<constexpr%>");
if (thread_p)
error_at (declspecs->locations[ds_thread],
"decomposition declaration cannot be declared %qs",
declspecs->gnu_thread_keyword_p
? "__thread" : "thread_local");
if (concept_p)
error_at (declspecs->locations[ds_concept],
"decomposition declaration cannot be declared %<concept%>");
switch (storage_class)
{
case sc_none:
break;
case sc_register:
error_at (loc, "decomposition declaration cannot be declared "
"%<register%>");
break;
case sc_static:
error_at (loc, "decomposition declaration cannot be declared "
"%<static%>");
break;
case sc_extern:
error_at (loc, "decomposition declaration cannot be declared "
"%<extern%>");
break;
case sc_mutable:
error_at (loc, "decomposition declaration cannot be declared "
"%<mutable%>");
break;
case sc_auto:
error_at (loc, "decomposition declaration cannot be declared "
"C++98 %<auto%>");
break;
default:
gcc_unreachable ();
}
if (TREE_CODE (type) != TEMPLATE_TYPE_PARM
|| TYPE_IDENTIFIER (type) != get_identifier ("auto"))
{
if (type != error_mark_node)
{
error_at (loc, "decomposition declaration cannot be declared "
"with type %qT", type);
inform (loc,
"type must be cv-qualified %<auto%> or reference to "
"cv-qualified %<auto%>");
}
type = build_qualified_type (make_auto (), type_quals);
declspecs->type = type;
}
inlinep = 0;
typedef_p = 0;
constexpr_p = 0;
thread_p = 0;
concept_p = 0;
storage_class = sc_none;
staticp = 0;
declspecs->storage_class = sc_none;
declspecs->locations[ds_thread] = UNKNOWN_LOCATION;
}
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
&& declspecs->type
@ -10232,7 +10699,7 @@ grokdeclarator (const cp_declarator *declarator,
attr_flags);
}
if (declarator->kind == cdk_id)
if (declarator->kind == cdk_id || declarator->kind == cdk_decomp)
break;
inner_declarator = declarator->declarator;
@ -10743,6 +11210,7 @@ grokdeclarator (const cp_declarator *declarator,
is non-NULL, we know it is a cdk_id declarator; otherwise, we
would not have exited the loop above. */
if (declarator
&& declarator->kind == cdk_id
&& declarator->u.id.qualifying_scope
&& MAYBE_CLASS_TYPE_P (declarator->u.id.qualifying_scope))
{
@ -10754,13 +11222,14 @@ grokdeclarator (const cp_declarator *declarator,
{
if (friendp)
{
permerror (input_location, "member functions are implicitly friends of their class");
permerror (input_location, "member functions are implicitly "
"friends of their class");
friendp = 0;
}
else
permerror (declarator->id_loc,
"extra qualification %<%T::%> on member %qs",
ctype, name);
"extra qualification %<%T::%> on member %qs",
ctype, name);
}
else if (/* If the qualifying type is already complete, then we
can skip the following checks. */
@ -11133,7 +11602,8 @@ grokdeclarator (const cp_declarator *declarator,
else if (unqualified_id == NULL_TREE && decl_context != PARM
&& decl_context != CATCHPARM
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
&& ! bitfield
&& innermost_code != cdk_decomp)
{
error ("abstract declarator %qT used as declaration", type);
return error_mark_node;
@ -11719,6 +12189,14 @@ grokdeclarator (const cp_declarator *declarator,
if (inlinep)
mark_inline_variable (decl);
if (innermost_code == cdk_decomp)
{
gcc_assert (declarator && declarator->kind == cdk_decomp);
DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
retrofit_lang_decl (decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_DECOMPOSITION_P (decl);
}
}
if (VAR_P (decl) && !initialized)

View File

@ -1575,27 +1575,34 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree itype;
tree itype = init ? TREE_TYPE (init) : NULL_TREE;
int from_array = 0;
/* An array may not be initialized use the parenthesized
initialization form -- unless the initializer is "()". */
if (init && TREE_CODE (init) == TREE_LIST)
if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp))
from_array = 1;
else
{
if (complain & tf_error)
error ("bad array initializer");
return error_mark_node;
/* An array may not be initialized use the parenthesized
initialization form -- unless the initializer is "()". */
if (init && TREE_CODE (init) == TREE_LIST)
{
if (complain & tf_error)
error ("bad array initializer");
return error_mark_node;
}
/* Must arrange to initialize each element of EXP
from elements of INIT. */
if (cv_qualified_p (type))
TREE_TYPE (exp) = cv_unqualified (type);
if (itype && cv_qualified_p (itype))
TREE_TYPE (init) = cv_unqualified (itype);
from_array = (itype && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)));
}
/* Must arrange to initialize each element of EXP
from elements of INIT. */
itype = init ? TREE_TYPE (init) : NULL_TREE;
if (cv_qualified_p (type))
TREE_TYPE (exp) = cv_unqualified (type);
if (itype && cv_qualified_p (itype))
TREE_TYPE (init) = cv_unqualified (itype);
stmt_expr = build_vec_init (exp, NULL_TREE, init,
/*explicit_value_init_p=*/false,
itype && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)),
from_array,
complain);
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
@ -3891,6 +3898,18 @@ build_vec_init (tree base, tree maxindex, tree init,
base = get_temp_regvar (ptype, rval);
iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
bool direct_init = false;
if (from_array && init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CONSTRUCTOR_NELTS (init) == 1)
{
tree elt = CONSTRUCTOR_ELT (init, 0)->value;
if (TREE_CODE (TREE_TYPE (elt)) == ARRAY_TYPE)
{
direct_init = DIRECT_LIST_INIT_P (init);
init = elt;
}
}
/* If initializing one array from another, initialize element by
element. We rely upon the below calls to do the argument
checking. Evaluate the initializer before entering the try block. */
@ -4115,6 +4134,8 @@ build_vec_init (tree base, tree maxindex, tree init,
from = build1 (INDIRECT_REF, itype, base2);
if (xvalue)
from = move (from);
if (direct_init)
from = build_tree_list (NULL_TREE, from);
}
else
from = NULL_TREE;

View File

@ -5393,7 +5393,7 @@ add_function (struct arg_lookup *k, tree fn)
function templates are ignored. */;
else if (k->fn_set && k->fn_set->add (fn))
/* It's already in the list. */;
else if (!k->functions)
else if (!k->functions && TREE_CODE (fn) != TEMPLATE_DECL)
k->functions = fn;
else if (fn == k->functions)
;

View File

@ -1668,6 +1668,7 @@ declarator_can_be_parameter_pack (cp_declarator *declarator)
{
case cdk_id:
case cdk_array:
case cdk_decomp:
found = true;
break;
@ -1721,6 +1722,7 @@ function_declarator_p (const cp_declarator *declarator)
&& declarator->declarator->kind == cdk_id)
return true;
if (declarator->kind == cdk_id
|| declarator->kind == cdk_decomp
|| declarator->kind == cdk_error)
return false;
declarator = declarator->declarator;
@ -2200,6 +2202,8 @@ static void cp_parser_static_assert
(cp_parser *, bool);
static tree cp_parser_decltype
(cp_parser *);
static tree cp_parser_decomposition_declaration
(cp_parser *, cp_decl_specifier_seq *, tree *, location_t *);
/* Declarators [gram.dcl.decl] */
@ -11471,16 +11475,45 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
bool ivdep)
{
tree stmt, range_expr;
cxx_binding *binding = NULL;
tree name = NULL_TREE;
auto_vec <cxx_binding *, 16> bindings;
auto_vec <tree, 16> names;
tree decomp_first_name = NULL_TREE;
unsigned int decomp_cnt = 0;
/* Get the range declaration momentarily out of the way so that
the range expression doesn't clash with it. */
if (range_decl != error_mark_node)
{
name = DECL_NAME (range_decl);
binding = IDENTIFIER_BINDING (name);
IDENTIFIER_BINDING (name) = binding->previous;
if (DECL_HAS_VALUE_EXPR_P (range_decl))
{
tree v = DECL_VALUE_EXPR (range_decl);
/* For decomposition declaration get all of the corresponding
declarations out of the way. */
if (TREE_CODE (v) == ARRAY_REF
&& VAR_P (TREE_OPERAND (v, 0))
&& DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
{
tree d = range_decl;
range_decl = TREE_OPERAND (v, 0);
decomp_cnt = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
decomp_first_name = d;
for (unsigned int i = 0; i < decomp_cnt; i++, d = DECL_CHAIN (d))
{
tree name = DECL_NAME (d);
names.quick_push (name);
bindings.quick_push (IDENTIFIER_BINDING (name));
IDENTIFIER_BINDING (name)
= IDENTIFIER_BINDING (name)->previous;
}
}
}
if (names.is_empty ())
{
tree name = DECL_NAME (range_decl);
names.quick_push (name);
bindings.quick_push (IDENTIFIER_BINDING (name));
IDENTIFIER_BINDING (name) = IDENTIFIER_BINDING (name)->previous;
}
}
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
@ -11491,11 +11524,12 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
else
range_expr = cp_parser_expression (parser);
/* Put the range declaration back into scope. */
if (range_decl != error_mark_node)
/* Put the range declaration(s) back into scope. */
for (unsigned int i = 0; i < names.length (); i++)
{
binding->previous = IDENTIFIER_BINDING (name);
IDENTIFIER_BINDING (name) = binding;
cxx_binding *binding = bindings[i];
binding->previous = IDENTIFIER_BINDING (names[i]);
IDENTIFIER_BINDING (names[i]) = binding;
}
/* If in template, STMT is converted to a normal for-statement
@ -11516,7 +11550,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
else
{
stmt = begin_for_stmt (scope, init);
stmt = cp_convert_range_for (stmt, range_decl, range_expr, ivdep);
stmt = cp_convert_range_for (stmt, range_decl, range_expr,
decomp_first_name, decomp_cnt, ivdep);
}
return stmt;
}
@ -11608,6 +11643,7 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
tree
cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
tree decomp_first_name, unsigned int decomp_cnt,
bool ivdep)
{
tree begin, end;
@ -11681,6 +11717,8 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
tf_warning_or_error),
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
cp_finish_decomp (range_decl, decomp_first_name, decomp_cnt);
return statement;
}
@ -12554,6 +12592,8 @@ cp_parser_block_declaration (cp_parser *parser,
simple-declaration:
decl-specifier-seq [opt] init-declarator-list [opt] ;
decl-specifier-seq ref-qualifier [opt] [ identifier-list ]
brace-or-equal-initializer ;
init-declarator-list:
init-declarator
@ -12639,6 +12679,45 @@ cp_parser_simple_declaration (cp_parser* parser,
&& !cp_parser_error_occurred (parser))
cp_parser_commit_to_tentative_parse (parser);
/* Look for C++17 decomposition declaration. */
for (size_t n = 1; ; n++)
if (cp_lexer_nth_token_is (parser->lexer, n, CPP_AND)
|| cp_lexer_nth_token_is (parser->lexer, n, CPP_AND_AND))
continue;
else if (cp_lexer_nth_token_is (parser->lexer, n, CPP_OPEN_SQUARE)
&& !cp_lexer_nth_token_is (parser->lexer, n + 1, CPP_OPEN_SQUARE)
&& decl_specifiers.any_specifiers_p)
{
tree decl
= cp_parser_decomposition_declaration (parser, &decl_specifiers,
maybe_range_for_decl,
&init_loc);
/* The next token should be either a `,' or a `;'. */
cp_token *token = cp_lexer_peek_token (parser->lexer);
/* If it's a `;', we are done. */
if (token->type == CPP_SEMICOLON || maybe_range_for_decl)
goto finish;
/* Anything else is an error. */
else
{
/* If we have already issued an error message we don't need
to issue another one. */
if ((decl != error_mark_node
&& DECL_INITIAL (decl) != error_mark_node)
|| cp_parser_uncommitted_to_tentative_parse_p (parser))
cp_parser_error (parser, "expected %<,%> or %<;%>");
/* Skip tokens until we reach the end of the statement. */
cp_parser_skip_to_end_of_statement (parser);
/* If the next token is now a `;', consume it. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
cp_lexer_consume_token (parser->lexer);
goto done;
}
}
else
break;
tree last_type;
last_type = NULL_TREE;
@ -12791,6 +12870,7 @@ cp_parser_simple_declaration (cp_parser* parser,
}
/* Consume the `;'. */
finish:
if (!maybe_range_for_decl)
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
else if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
@ -12806,6 +12886,143 @@ cp_parser_simple_declaration (cp_parser* parser,
pop_deferring_access_checks ();
}
/* Helper of cp_parser_simple_declaration, parse a decomposition declaration.
decl-specifier-seq ref-qualifier [opt] [ identifier-list ]
brace-or-equal-initializer ; */
static tree
cp_parser_decomposition_declaration (cp_parser *parser,
cp_decl_specifier_seq *decl_specifiers,
tree *maybe_range_for_decl,
location_t *init_loc)
{
cp_ref_qualifier ref_qual = cp_parser_ref_qualifier_opt (parser);
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
/* Parse the identifier-list. */
auto_vec<cp_expr, 10> v;
if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
while (true)
{
cp_expr e = cp_parser_identifier (parser);
if (e.get_value () == error_mark_node)
break;
v.safe_push (e);
if (!cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
break;
cp_lexer_consume_token (parser->lexer);
}
location_t end_loc = cp_lexer_peek_token (parser->lexer)->location;
if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
{
end_loc = UNKNOWN_LOCATION;
cp_parser_skip_to_closing_parenthesis_1 (parser, true, CPP_CLOSE_SQUARE,
false);
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
cp_lexer_consume_token (parser->lexer);
else
{
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
}
if (cxx_dialect < cxx1z)
pedwarn (loc, 0, "decomposition declaration only available with "
"-std=c++1z or -std=gnu++1z");
tree pushed_scope;
cp_declarator *declarator = make_declarator (cdk_decomp);
loc = end_loc == UNKNOWN_LOCATION ? loc : make_location (loc, loc, end_loc);
declarator->id_loc = loc;
if (ref_qual != REF_QUAL_NONE)
declarator = make_reference_declarator (TYPE_UNQUALIFIED, declarator,
ref_qual == REF_QUAL_RVALUE,
NULL_TREE);
tree decl = start_decl (declarator, decl_specifiers, SD_INITIALIZED,
NULL_TREE, decl_specifiers->attributes,
&pushed_scope);
unsigned int i;
cp_expr e;
cp_decl_specifier_seq decl_specs;
clear_decl_specs (&decl_specs);
decl_specs.type = make_auto ();
tree prev = decl;
FOR_EACH_VEC_ELT (v, i, e)
{
if (i == 0)
declarator = make_id_declarator (NULL_TREE, e.get_value (), sfk_none);
else
declarator->u.id.unqualified_name = e.get_value ();
declarator->id_loc = e.get_location ();
tree elt_pushed_scope;
tree decl2 = start_decl (declarator, &decl_specs, SD_INITIALIZED,
NULL_TREE, NULL_TREE, &elt_pushed_scope);
if (decl2 == error_mark_node)
decl = error_mark_node;
else if (decl != error_mark_node && DECL_CHAIN (decl2) != prev)
{
/* Ensure we've diagnosed redeclaration if we aren't creating
a new VAR_DECL. */
gcc_assert (errorcount);
decl = error_mark_node;
}
else
prev = decl2;
if (elt_pushed_scope)
pop_scope (elt_pushed_scope);
}
if (v.is_empty ())
{
error_at (loc, "empty decomposition declaration");
decl = error_mark_node;
}
if (maybe_range_for_decl == NULL
|| cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
{
bool non_constant_p = false, is_direct_init = false;
tree initializer;
*init_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the initializer. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
initializer = cp_parser_braced_list (parser, &non_constant_p);
CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1;
is_direct_init = true;
}
else
{
/* Consume the `='. */
cp_parser_require (parser, CPP_EQ, RT_EQ);
initializer = cp_parser_initializer_clause (parser, &non_constant_p);
}
if (decl != error_mark_node)
{
cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT);
cp_finish_decomp (decl, prev, v.length ());
}
}
else if (decl != error_mark_node)
{
*maybe_range_for_decl = prev;
/* Ensure DECL_VALUE_EXPR is created for all the decls but
the underlying DECL. */
cp_finish_decomp (decl, prev, v.length ());
}
if (pushed_scope)
pop_scope (pushed_scope);
return decl;
}
/* Parse a decl-specifier-seq.
decl-specifier-seq:
@ -18628,6 +18845,7 @@ strip_declarator_types (tree type, cp_declarator *declarator)
switch (d->kind)
{
case cdk_id:
case cdk_decomp:
case cdk_error:
d = NULL;
break;
@ -25502,6 +25720,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
return (cp_parser_check_declarator_template_parameters
(parser, declarator->declarator, declarator_location));
case cdk_decomp:
case cdk_error:
return true;

View File

@ -15311,6 +15311,55 @@ tsubst_find_omp_teams (tree *tp, int *walk_subtrees, void *)
return NULL_TREE;
}
/* Helper function for tsubst_expr. For decomposition declaration
artificial base DECL, which is tsubsted PATTERN_DECL, tsubst
also the corresponding decls representing the identifiers
of the decomposition declaration. Return DECL if successful
or error_mark_node otherwise, set *FIRST to the first decl
in the list chained through DECL_CHAIN and *CNT to the number
of such decls. */
static tree
tsubst_decomp_names (tree decl, tree pattern_decl, tree args,
tsubst_flags_t complain, tree in_decl, tree *first,
unsigned int *cnt)
{
tree decl2, decl3, prev = decl;
*cnt = 0;
gcc_assert (DECL_NAME (decl) == NULL_TREE);
for (decl2 = DECL_CHAIN (pattern_decl);
decl2
&& VAR_P (decl2)
&& DECL_DECOMPOSITION_P (decl2)
&& DECL_NAME (decl2);
decl2 = DECL_CHAIN (decl2))
{
(*cnt)++;
gcc_assert (DECL_HAS_VALUE_EXPR_P (decl2));
tree v = DECL_VALUE_EXPR (decl2);
DECL_HAS_VALUE_EXPR_P (decl2) = 0;
SET_DECL_VALUE_EXPR (decl2, NULL_TREE);
decl3 = tsubst (decl2, args, complain, in_decl);
SET_DECL_VALUE_EXPR (decl2, v);
DECL_HAS_VALUE_EXPR_P (decl2) = 1;
if (VAR_P (decl3))
DECL_TEMPLATE_INSTANTIATED (decl3) = 1;
maybe_push_decl (decl3);
if (error_operand_p (decl3))
decl = error_mark_node;
else if (decl != error_mark_node
&& DECL_CHAIN (decl3) != prev)
{
gcc_assert (errorcount);
decl = error_mark_node;
}
else
prev = decl3;
}
*first = prev;
return decl;
}
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
@ -15454,6 +15503,16 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
(pattern_decl));
cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
{
unsigned int cnt;
tree first;
decl = tsubst_decomp_names (decl, pattern_decl, args,
complain, in_decl, &first,
&cnt);
if (decl != error_mark_node)
cp_finish_decomp (decl, first, cnt);
}
}
}
}
@ -15481,7 +15540,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
decl = tsubst (decl, args, complain, in_decl);
maybe_push_decl (decl);
expr = RECUR (RANGE_FOR_EXPR (t));
stmt = cp_convert_range_for (stmt, decl, expr, RANGE_FOR_IVDEP (t));
if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
{
unsigned int cnt;
tree first;
decl = tsubst_decomp_names (decl, RANGE_FOR_DECL (t), args,
complain, in_decl, &first, &cnt);
stmt = cp_convert_range_for (stmt, decl, expr, first, cnt,
RANGE_FOR_IVDEP (t));
}
else
stmt = cp_convert_range_for (stmt, decl, expr, NULL_TREE, 0,
RANGE_FOR_IVDEP (t));
RECUR (RANGE_FOR_BODY (t));
finish_for_stmt (stmt);
}
@ -24800,7 +24870,15 @@ do_auto_deduction (tree type, tree init, tree auto_node,
init = resolve_nondeduced_context (init, complain);
if (AUTO_IS_DECLTYPE (auto_node))
if (context == adc_decomp_type
&& auto_node == type
&& init != error_mark_node
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
/* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers
and initializer has array type, deduce cv-qualified array type. */
return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type),
complain);
else if (AUTO_IS_DECLTYPE (auto_node))
{
bool id = (DECL_P (init)
|| ((TREE_CODE (init) == COMPONENT_REF
@ -24885,6 +24963,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
error("placeholder constraints not satisfied");
break;
case adc_variable_type:
case adc_decomp_type:
error ("deduced initializer does not satisfy "
"placeholder constraints");
break;
@ -24893,7 +24972,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
"placeholder constraints");
break;
case adc_requirement:
error ("deduced expression type does not saatisy "
error ("deduced expression type does not satisfy "
"placeholder constraints");
break;
}

View File

@ -8873,6 +8873,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
if (identifier_p (expr))
expr = lookup_name (expr);
if (VAR_P (expr) && DECL_HAS_VALUE_EXPR_P (expr))
expr = DECL_VALUE_EXPR (expr);
if (INDIRECT_REF_P (expr))
/* This can happen when the expression is, e.g., "a.b". Just
look at the underlying operand. */

View File

@ -142,6 +142,9 @@ lvalue_kind (const_tree ref)
return clk_none;
/* FALLTHRU */
case VAR_DECL:
if (DECL_HAS_VALUE_EXPR_P (ref))
return lvalue_kind (DECL_VALUE_EXPR (CONST_CAST_TREE (ref)));
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
@ -1012,6 +1015,13 @@ tree
cp_build_reference_type (tree to_type, bool rval)
{
tree lvalue_ref, t;
if (TREE_CODE (to_type) == REFERENCE_TYPE)
{
rval = rval && TYPE_REF_IS_RVALUE (to_type);
to_type = TREE_TYPE (to_type);
}
lvalue_ref = build_reference_type (to_type);
if (!rval)
return lvalue_ref;

View File

@ -1885,6 +1885,12 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
return DECL_BIT_FIELD_TYPE (field);
}
case VAR_DECL:
if (DECL_HAS_VALUE_EXPR_P (exp))
return is_bitfield_expr_with_lowered_type (DECL_VALUE_EXPR
(CONST_CAST_TREE (exp)));
return NULL_TREE;
CASE_CONVERT:
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0)))
== TYPE_MAIN_VARIANT (TREE_TYPE (exp)))

View File

@ -2547,8 +2547,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(with
{
int equal = 2;
if (decl_in_symtab_p (base0)
&& decl_in_symtab_p (base1))
/* Punt in GENERIC on variables with value expressions;
the value expressions might point to fields/elements
of other vars etc. */
if (GENERIC
&& ((VAR_P (base0) && DECL_HAS_VALUE_EXPR_P (base0))
|| (VAR_P (base1) && DECL_HAS_VALUE_EXPR_P (base1))))
;
else if (decl_in_symtab_p (base0)
&& decl_in_symtab_p (base1))
equal = symtab_node::get_create (base0)
->equal_address_to (symtab_node::get_create (base1));
else if ((DECL_P (base0)

View File

@ -15,7 +15,7 @@
CHECK (xor_eq); // { dg-error "before .xor_eq. token" }
#undef CHECK
#define CHECK(x) int x
CHECK (<:); // { dg-error "before .<:. token" }
CHECK (<:); // { dg-error "" }
CHECK (:>); // { dg-error "before .:>. token" }
#undef CHECK
#define CHECK(x) x