diff options
Diffstat (limited to 'gcc/cp/decl.cc')
-rw-r--r-- | gcc/cp/decl.cc | 538 |
1 files changed, 501 insertions, 37 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index cb3ebff..f088d09 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "langhooks-def.h" /* For lhd_simulate_record_decl */ #include "coroutines.h" +#include "contracts.h" #include "gcc-urlifier.h" #include "diagnostic-highlight-colors.h" #include "pretty-print-markup.h" @@ -572,9 +573,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 +4337,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 +8608,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 +9653,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 +9677,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 +9691,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 +9714,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 +9770,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 +9780,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 +9796,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 +9902,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 +10086,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 +10114,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 +10140,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 +10161,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 +10200,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 +10246,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 +10310,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 +10344,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 +10456,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 +10479,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 +10488,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 +10501,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 +10535,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 +13025,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 +13114,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 +13133,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 +15392,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 +18238,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 +18480,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 ()); @@ -18440,6 +18902,8 @@ build_clobber_this (clobber_kind kind) } tree exprstmt = build2 (MODIFY_EXPR, void_type_node, thisref, clobber); + if (kind == CLOBBER_OBJECT_BEGIN) + TREE_SET_CODE (exprstmt, INIT_EXPR); if (vbases) exprstmt = build_if_in_charge (exprstmt); |