aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.cc')
-rw-r--r--gcc/cp/decl.cc535
1 files changed, 498 insertions, 37 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 8122fca..4b1a335 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -572,9 +572,9 @@ poplevel_named_label_1 (named_label_entry **slot, cp_binding_level *bl)
ent->in_stmt_expr = true;
break;
case sk_block:
- if (level_for_constexpr_if (bl->level_chain))
+ if (level_for_constexpr_if (obl))
ent->in_constexpr_if = true;
- else if (level_for_consteval_if (bl->level_chain))
+ else if (level_for_consteval_if (obl))
ent->in_consteval_if = true;
break;
default:
@@ -4336,7 +4336,19 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
tree label;
/* For templates, just add the case label; we'll do semantic
- analysis at instantiation-time. */
+ analysis at instantiation-time. But diagnose case labels
+ in expansion statements with switch outside of it here. */
+ if (in_expansion_stmt)
+ for (cp_binding_level *b = current_binding_level;
+ b != switch_stack->level; b = b->level_chain)
+ if (b->kind == sk_template_for && b->this_entity)
+ {
+ auto_diagnostic_group d;
+ error ("jump to case label");
+ inform (EXPR_LOCATION (b->this_entity),
+ " enters %<template for%> statement");
+ return error_mark_node;
+ }
label = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
return add_stmt (build_case_label (low_value, high_value, label));
}
@@ -8595,6 +8607,13 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
variant = cp_get_callee_fndecl_nofold (STRIP_REFERENCE_REF (variant));
input_location = save_loc;
+ if (variant == decl)
+ {
+ error_at (varid_loc, "variant %qD is the same as base function",
+ variant);
+ return true;
+ }
+
if (variant)
{
bool fail;
@@ -9633,13 +9652,17 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
error has been diagnosed. */
static tree
-find_decomp_class_base (location_t loc, tree type, tree ret)
+find_decomp_class_base (location_t loc, tree type, tree ret,
+ tsubst_flags_t complain)
{
if (LAMBDA_TYPE_P (type))
{
- auto_diagnostic_group d;
- error_at (loc, "cannot decompose lambda closure type %qT", type);
- inform (location_of (type), "lambda declared here");
+ if (complain & tf_error)
+ {
+ auto_diagnostic_group d;
+ error_at (loc, "cannot decompose lambda closure type %qT", type);
+ inform (location_of (type), "lambda declared here");
+ }
return error_mark_node;
}
@@ -9653,6 +9676,8 @@ find_decomp_class_base (location_t loc, tree type, tree ret)
return type;
else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
+ if ((complain & tf_error) == 0)
+ return error_mark_node;
auto_diagnostic_group d;
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
error_at (loc, "cannot decompose class type %qT because it has an "
@@ -9665,6 +9690,8 @@ find_decomp_class_base (location_t loc, tree type, tree ret)
}
else if (!accessible_p (type, field, true))
{
+ if ((complain & tf_error) == 0)
+ return error_mark_node;
auto_diagnostic_group d;
error_at (loc, "cannot decompose inaccessible member %qD of %qT",
field, type);
@@ -9686,28 +9713,32 @@ find_decomp_class_base (location_t loc, tree type, tree ret)
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
auto_diagnostic_group d;
- tree t = find_decomp_class_base (loc, TREE_TYPE (base_binfo), ret);
+ tree t = find_decomp_class_base (loc, TREE_TYPE (base_binfo), ret,
+ complain);
if (t == error_mark_node)
{
- inform (location_of (type), "in base class of %qT", type);
+ if (complain & tf_error)
+ inform (location_of (type), "in base class of %qT", type);
return error_mark_node;
}
if (t != NULL_TREE && t != ret)
{
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);
+ if (complain & tf_error)
+ 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 != NULL_TREE)
{
- error_at (loc, "cannot decompose class type %qT: its base "
- "classes %qT and %qT have non-static data "
- "members", type, ret, t);
+ if (complain & tf_error)
+ 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
@@ -9738,7 +9769,7 @@ get_tuple_size (tree type)
if (val == error_mark_node)
return NULL_TREE;
if (VAR_P (val) || TREE_CODE (val) == CONST_DECL)
- val = maybe_constant_value (val);
+ val = maybe_constant_value (val, NULL_TREE, mce_true);
if (TREE_CODE (val) == INTEGER_CST)
return val;
else
@@ -9748,7 +9779,7 @@ get_tuple_size (tree type)
/* Return std::tuple_element<I,TYPE>::type. */
static tree
-get_tuple_element_type (tree type, unsigned i)
+get_tuple_element_type (tree type, unsigned HOST_WIDE_INT i)
{
tree args = make_tree_vec (2);
TREE_VEC_ELT (args, 0) = build_int_cst (integer_type_node, i);
@@ -9764,7 +9795,7 @@ get_tuple_element_type (tree type, unsigned i)
/* Return e.get<i>() or get<i>(e). */
static tree
-get_tuple_decomp_init (tree decl, unsigned i)
+get_tuple_decomp_init (tree decl, unsigned HOST_WIDE_INT i)
{
tree targs = make_tree_vec (1);
TREE_VEC_ELT (targs, 0) = build_int_cst (integer_type_node, i);
@@ -9870,6 +9901,134 @@ cp_maybe_mangle_decomp (tree decl, cp_decomp *decomp)
}
}
+/* Append #i to DECL_NAME (decl) or for name independent decls
+ clear DECL_NAME (decl). */
+
+static void
+set_sb_pack_name (tree decl, unsigned HOST_WIDE_INT i)
+{
+ if (name_independent_decl_p (decl))
+ /* Only "_" names are treated as name independent, "_#0" etc. is not and
+ because we pushdecl the individual decl elements of structured binding
+ pack, we could get redeclaration errors if there are 2 or more name
+ independent structured binding packs in the same scope. */
+ DECL_NAME (decl) = NULL_TREE;
+ else
+ {
+ tree name = DECL_NAME (decl);
+ size_t len = IDENTIFIER_LENGTH (name) + 22;
+ char *n = XALLOCAVEC (char, len);
+ snprintf (n, len, "%s#" HOST_WIDE_INT_PRINT_UNSIGNED,
+ IDENTIFIER_POINTER (name), i);
+ DECL_NAME (decl) = get_identifier (n);
+ }
+}
+
+/* Return structured binding size of TYPE or -1 if erroneous. */
+
+HOST_WIDE_INT
+cp_decomp_size (location_t loc, tree type, tsubst_flags_t complain)
+{
+ if (TYPE_REF_P (type))
+ {
+ type = complete_type (TREE_TYPE (type));
+ if (type == error_mark_node)
+ return -1;
+ if (!COMPLETE_TYPE_P (type))
+ {
+ if (complain & tf_error)
+ error_at (loc, "structured binding refers to incomplete type %qT",
+ type);
+ return -1;
+ }
+ }
+
+ unsigned HOST_WIDE_INT eltscnt = 0;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (TYPE_DOMAIN (type) == NULL_TREE)
+ {
+ if (complain & tf_error)
+ error_at (loc, "cannot decompose array of unknown bound %qT",
+ type);
+ return -1;
+ }
+ tree nelts = array_type_nelts_top (type);
+ if (nelts == error_mark_node)
+ return -1;
+ if (!tree_fits_shwi_p (nelts))
+ {
+ if (complain & tf_error)
+ error_at (loc, "cannot decompose variable length array %qT", type);
+ return -1;
+ }
+ return tree_to_shwi (nelts);
+ }
+ /* 2 GNU extensions. */
+ else if (TREE_CODE (type) == COMPLEX_TYPE)
+ return 2;
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&eltscnt))
+ {
+ if (complain & tf_error)
+ error_at (loc, "cannot decompose variable length vector %qT", type);
+ return -1;
+ }
+ return eltscnt;
+ }
+ else if (tree tsize = get_tuple_size (type))
+ {
+ if (tsize == error_mark_node
+ || !tree_fits_shwi_p (tsize)
+ || tree_int_cst_sgn (tsize) < 0)
+ {
+ if (complain & tf_error)
+ error_at (loc, "%<std::tuple_size<%T>::value%> is not an integral "
+ "constant expression", type);
+ return -1;
+ }
+ return tree_to_shwi (tsize);
+ }
+ else if (TREE_CODE (type) == UNION_TYPE)
+ {
+ if (complain & tf_error)
+ error_at (loc, "cannot decompose union type %qT", type);
+ return -1;
+ }
+ else if (!CLASS_TYPE_P (type))
+ {
+ if (complain & tf_error)
+ error_at (loc, "cannot decompose non-array non-class type %qT", type);
+ return -1;
+ }
+ else if (processing_template_decl && complete_type (type) == error_mark_node)
+ return -1;
+ else if (!COMPLETE_TYPE_P (type))
+ {
+ if (complain & tf_error)
+ error_at (loc, "structured binding refers to incomplete class type "
+ "%qT", type);
+ return -1;
+ }
+ else
+ {
+ tree btype = find_decomp_class_base (loc, type, NULL_TREE, complain);
+ if (btype == error_mark_node)
+ return -1;
+ else if (btype == NULL_TREE)
+ return 0;
+ for (tree field = TYPE_FIELDS (btype); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) != FIELD_DECL
+ || DECL_ARTIFICIAL (field)
+ || DECL_UNNAMED_BIT_FIELD (field))
+ continue;
+ else
+ eltscnt++;
+ return eltscnt;
+ }
+}
+
/* 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
@@ -9926,10 +10085,13 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
auto_vec<tree, 16> v;
v.safe_grow (count, true);
tree d = first;
+ int pack = -1;
for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
{
v[count - i - 1] = d;
fit_decomposition_lang_decl (d, decl);
+ if (DECL_PACK_P (d))
+ pack = count - i - 1;
}
tree type = TREE_TYPE (decl);
@@ -9951,6 +10113,14 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
tree eltype = NULL_TREE;
unsigned HOST_WIDE_INT eltscnt = 0;
+ /* Structured binding packs when initializer is non-dependent should
+ have their DECL_VALUE_EXPR set to a TREE_VEC. First two elements
+ of that TREE_VEC are the base and index, what is normally represented
+ as DECL_VALUE_EXPR ARRAY_REF <base, index> where index is the index
+ of the pack first element. The remaining elements of the TREE_VEC
+ are VAR_DECLs for the pack elements. */
+ tree packv = NULL_TREE;
+
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree nelts;
@@ -9969,7 +10139,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
goto error_out;
}
eltscnt = tree_to_uhwi (nelts);
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
{
cnt_mismatch:
auto_diagnostic_group d;
@@ -9990,12 +10160,37 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
eltype = TREE_TYPE (type);
for (unsigned int i = 0; i < count; i++)
{
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ tree a = unshare_expr (dexp);
+ a = build4 (ARRAY_REF, eltype, a, size_int (j + pack),
+ NULL_TREE, NULL_TREE);
+ SET_DECL_VALUE_EXPR (t, a);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ }
+ continue;
+ }
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (processing_template_decl)
continue;
tree t = unshare_expr (dexp);
- t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE);
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
+ t = build4 (ARRAY_REF, eltype, t, size_int (j), NULL_TREE, NULL_TREE);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
@@ -10004,17 +10199,41 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
else if (TREE_CODE (type) == COMPLEX_TYPE)
{
eltscnt = 2;
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
for (unsigned int i = 0; i < count; i++)
{
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ tree a = build1 (pack + j ? IMAGPART_EXPR : REALPART_EXPR, eltype,
+ unshare_expr (dexp));
+ SET_DECL_VALUE_EXPR (t, a);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ }
+ continue;
+ }
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (processing_template_decl)
continue;
tree t = unshare_expr (dexp);
- t = build1 (i ? IMAGPART_EXPR : REALPART_EXPR, eltype, t);
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
+ t = build1 (j ? IMAGPART_EXPR : REALPART_EXPR, eltype, t);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
@@ -10026,19 +10245,47 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
error_at (loc, "cannot decompose variable length vector %qT", type);
goto error_out;
}
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
for (unsigned int i = 0; i < count; i++)
{
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ tree a = unshare_expr (dexp);
+ location_t loc = DECL_SOURCE_LOCATION (t);
+ tree s = size_int (j + pack);
+ convert_vector_to_array_for_subscript (loc, &a, s);
+ a = build4 (ARRAY_REF, eltype, a, s,
+ NULL_TREE, NULL_TREE);
+ SET_DECL_VALUE_EXPR (t, a);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ }
+ continue;
+ }
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (processing_template_decl)
continue;
tree t = unshare_expr (dexp);
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]),
- &t, size_int (i));
- t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE);
+ &t, size_int (j));
+ t = build4 (ARRAY_REF, eltype, t, size_int (j), NULL_TREE, NULL_TREE);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
@@ -10062,11 +10309,11 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
goto error_out;
}
eltscnt = tree_to_uhwi (tsize);
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
- if (test_p)
+ if (test_p && eltscnt)
return true;
- if (!processing_template_decl && DECL_DECOMP_BASE (decl))
+ if (!processing_template_decl && DECL_DECOMP_BASE (decl) && eltscnt)
{
/* For structured bindings used in conditions we need to evaluate
the conversion of decl (aka e in the standard) to bool or
@@ -10096,16 +10343,70 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
location_t sloc = input_location;
location_t dloc = DECL_SOURCE_LOCATION (v[i]);
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ input_location = dloc;
+ tree init = get_tuple_decomp_init (decl, j + pack);
+ tree eltype = (init == error_mark_node ? error_mark_node
+ : get_tuple_element_type (type, j + pack));
+ input_location = sloc;
+
+ if (VOID_TYPE_P (eltype))
+ {
+ error ("%<std::tuple_element<%wu, %T>::type%> is "
+ "%<void%>", j + pack, type);
+ eltype = error_mark_node;
+ }
+ if (init == error_mark_node || eltype == error_mark_node)
+ {
+ inform (dloc, "in initialization of structured binding "
+ "pack %qD", v[pack]);
+ goto error_out;
+ }
+ maybe_push_decl (t);
+ /* Save the decltype away before reference collapse. */
+ hash_map_safe_put<hm_ggc> (decomp_type_table, t, eltype);
+ eltype = cp_build_reference_type (eltype, !lvalue_p (init));
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ DECL_HAS_VALUE_EXPR_P (t) = 0;
+ if (!processing_template_decl)
+ {
+ copy_linkage (t, decl);
+ tree name = DECL_NAME (t);
+ if (TREE_STATIC (decl))
+ DECL_NAME (t) = DECL_NAME (v[pack]);
+ cp_finish_decl (t, init, /*constexpr*/false,
+ /*asm*/NULL_TREE, LOOKUP_NORMAL);
+ if (TREE_STATIC (decl))
+ {
+ DECL_ASSEMBLER_NAME (t);
+ DECL_NAME (t) = name;
+ }
+ }
+ }
+ continue;
+ }
+
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
input_location = dloc;
- tree init = get_tuple_decomp_init (decl, i);
+ tree init = get_tuple_decomp_init (decl, j);
tree eltype = (init == error_mark_node ? error_mark_node
- : get_tuple_element_type (type, i));
+ : get_tuple_element_type (type, j));
input_location = sloc;
if (VOID_TYPE_P (eltype))
{
- error ("%<std::tuple_element<%u, %T>::type%> is %<void%>",
- i, type);
+ error ("%<std::tuple_element<%wu, %T>::type%> is %<void%>",
+ j, type);
eltype = error_mark_node;
}
if (init == error_mark_node || eltype == error_mark_node)
@@ -10154,11 +10455,18 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
type);
else
{
- tree btype = find_decomp_class_base (loc, type, NULL_TREE);
+ tree btype = find_decomp_class_base (loc, type, NULL_TREE,
+ tf_warning_or_error);
if (btype == error_mark_node)
goto error_out;
else if (btype == NULL_TREE)
{
+ if (pack == 0 && count == 1)
+ {
+ eltscnt = 0;
+ packv = make_tree_vec (2);
+ goto done;
+ }
error_at (loc, "cannot decompose class type %qT without non-static "
"data members", type);
goto error_out;
@@ -10170,7 +10478,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
continue;
else
eltscnt++;
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
tree t = dexp;
if (type != btype)
@@ -10179,6 +10487,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
/*nonnull*/false, tf_warning_or_error);
type = btype;
}
+ unsigned HOST_WIDE_INT j = 0;
unsigned int i = 0;
for (tree field = TYPE_FIELDS (btype); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) != FIELD_DECL
@@ -10191,6 +10500,32 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
NULL_TREE);
if (REFERENCE_REF_P (tt))
tt = TREE_OPERAND (tt, 0);
+ if (pack != -1 && j >= (unsigned) pack)
+ {
+ if (j == (unsigned) pack)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ i++;
+ }
+ if (j < (unsigned) pack + eltscnt - (count - 1))
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 3 - i) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j + 1 - i);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = TREE_TYPE (tt);
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ SET_DECL_VALUE_EXPR (t, tt);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ else
+ DECL_HAS_VALUE_EXPR_P (t) = 0;
+ j++;
+ continue;
+ }
+ }
TREE_TYPE (v[i]) = TREE_TYPE (tt);
layout_decl (v[i], 0);
if (!processing_template_decl)
@@ -10199,7 +10534,26 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
i++;
+ j++;
}
+ if (pack != -1 && j == (unsigned) pack)
+ {
+ gcc_checking_assert (eltscnt == count - 1);
+ packv = make_tree_vec (2);
+ }
+ }
+ done:
+ if (packv)
+ {
+ gcc_checking_assert (pack != -1);
+ TREE_VEC_ELT (packv, 0) = decl;
+ TREE_VEC_ELT (packv, 1) = size_int (pack);
+ SET_DECL_VALUE_EXPR (v[pack], packv);
+ DECL_HAS_VALUE_EXPR_P (v[pack]) = 1;
+ DECL_IGNORED_P (v[pack]) = 1;
+ if (!processing_template_decl)
+ for (unsigned int i = 0; i < TREE_VEC_LENGTH (packv) - 2U; ++i)
+ pushdecl (TREE_VEC_ELT (packv, 2 + i));
}
if (processing_template_decl)
{
@@ -12670,6 +13024,88 @@ mark_inline_variable (tree decl, location_t loc)
}
+/* Diagnose -Wnon-c-typedef-for-linkage pedwarn. TYPE is the unnamed class
+ with a typedef name for linkage purposes with freshly updated TYPE_NAME,
+ ORIG is the anonymous TYPE_NAME before that change. */
+
+static bool
+diagnose_non_c_class_typedef_for_linkage (tree type, tree orig)
+{
+ gcc_rich_location richloc (DECL_SOURCE_LOCATION (orig));
+ tree name = DECL_NAME (TYPE_NAME (type));
+ richloc.add_fixit_insert_before (IDENTIFIER_POINTER (name));
+ return pedwarn (&richloc, OPT_Wnon_c_typedef_for_linkage,
+ "anonymous non-C-compatible type given name for linkage "
+ "purposes by %<typedef%> declaration");
+}
+
+/* Diagnose -Wnon-c-typedef-for-linkage violations on T. TYPE and ORIG
+ like for diagnose_non_c_class_typedef_for_linkage, T is initially equal
+ to TYPE but during recursion can be set to nested classes. */
+
+static bool
+maybe_diagnose_non_c_class_typedef_for_linkage (tree type, tree orig, tree t)
+{
+ if (!BINFO_BASE_BINFOS (TYPE_BINFO (t))->is_empty ())
+ {
+ auto_diagnostic_group d;
+ if (diagnose_non_c_class_typedef_for_linkage (type, orig))
+ inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)),
+ "type is not C-compatible because it has a base class");
+ return true;
+ }
+ for (tree field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ switch (TREE_CODE (field))
+ {
+ case VAR_DECL:
+ /* static data members have been diagnosed already. */
+ continue;
+ case FIELD_DECL:
+ if (DECL_INITIAL (field))
+ {
+ auto_diagnostic_group d;
+ if (diagnose_non_c_class_typedef_for_linkage (type, orig))
+ inform (DECL_SOURCE_LOCATION (field),
+ "type is not C-compatible because %qD has default "
+ "member initializer", field);
+ return true;
+ }
+ continue;
+ case CONST_DECL:
+ continue;
+ case TYPE_DECL:
+ if (DECL_SELF_REFERENCE_P (field))
+ continue;
+ if (DECL_IMPLICIT_TYPEDEF_P (field))
+ {
+ if (TREE_CODE (TREE_TYPE (field)) == ENUMERAL_TYPE)
+ continue;
+ if (CLASS_TYPE_P (TREE_TYPE (field)))
+ {
+ tree tf = TREE_TYPE (field);
+ if (maybe_diagnose_non_c_class_typedef_for_linkage (type, orig,
+ tf))
+ return true;
+ continue;
+ }
+ }
+ /* FALLTHRU */
+ case FUNCTION_DECL:
+ case TEMPLATE_DECL:
+ {
+ auto_diagnostic_group d;
+ if (diagnose_non_c_class_typedef_for_linkage (type, orig))
+ inform (DECL_SOURCE_LOCATION (field),
+ "type is not C-compatible because it contains %qD "
+ "declaration", field);
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
/* Assign a typedef-given name to a class or enumeration type declared
as anonymous at first. This was split out of grokdeclarator
because it is also used in libcc1. */
@@ -12677,7 +13113,8 @@ mark_inline_variable (tree decl, location_t loc)
void
name_unnamed_type (tree type, tree decl)
{
- gcc_assert (TYPE_UNNAMED_P (type));
+ gcc_assert (TYPE_UNNAMED_P (type)
+ || enum_with_enumerator_for_linkage_p (type));
/* Replace the anonymous decl with the real decl. Be careful not to
rename other typedefs (such as the self-reference) of type. */
@@ -12695,12 +13132,16 @@ name_unnamed_type (tree type, tree decl)
/* Adjust linkage now that we aren't unnamed anymore. */
reset_type_linkage (type);
+ if (CLASS_TYPE_P (type) && warn_non_c_typedef_for_linkage)
+ maybe_diagnose_non_c_class_typedef_for_linkage (type, orig, type);
+
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
/* Check that our job is done, and that it would fail if we
attempted to do it again. */
- gcc_assert (!TYPE_UNNAMED_P (type));
+ gcc_assert (!TYPE_UNNAMED_P (type)
+ && !enum_with_enumerator_for_linkage_p (type));
}
/* Check that decltype(auto) was well-formed: only plain decltype(auto)
@@ -14950,7 +15391,10 @@ grokdeclarator (const cp_declarator *declarator,
&& unqualified_id
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && TYPE_UNNAMED_P (type)
+ && (TYPE_UNNAMED_P (type)
+ /* An enum may have previously used an enumerator for linkage
+ purposes, but we want the typedef name to take priority. */
+ || enum_with_enumerator_for_linkage_p (type))
&& declspecs->type_definition_p
&& attributes_naming_typedef_ok (*attrlist)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
@@ -17793,6 +18237,18 @@ start_enum (tree name, tree enumtype, tree underlying_type,
return enumtype;
}
+/* Returns true if TYPE is an enum that uses an enumerator name for
+ linkage purposes. */
+
+bool
+enum_with_enumerator_for_linkage_p (tree type)
+{
+ return (cxx_dialect >= cxx20
+ && UNSCOPED_ENUM_P (type)
+ && TYPE_ANON_P (type)
+ && TYPE_VALUES (type));
+}
+
/* After processing and defining all the values of an enumeration type,
install their decls in the enumeration type.
ENUMTYPE is the type object. */
@@ -18023,6 +18479,11 @@ finish_enum_value_list (tree enumtype)
fixup_type_variants (current_class_type);
}
+ /* P2115: An unnamed enum uses the name of its first enumerator for
+ linkage purposes; reset the type linkage if that is the case. */
+ if (enum_with_enumerator_for_linkage_p (enumtype))
+ reset_type_linkage (enumtype);
+
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, namespace_bindings_p ());