diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 66 | ||||
-rw-r--r-- | gcc/cp/call.c | 31 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 28 | ||||
-rw-r--r-- | gcc/cp/decl.c | 528 | ||||
-rw-r--r-- | gcc/cp/error.c | 4 | ||||
-rw-r--r-- | gcc/cp/init.c | 53 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 7 | ||||
-rw-r--r-- | gcc/cp/parser.c | 304 | ||||
-rw-r--r-- | gcc/cp/pt.c | 152 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 5 | ||||
-rw-r--r-- | gcc/cp/tree.c | 10 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 15 |
13 files changed, 1101 insertions, 110 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 678c44d5d40..65574d3ee4b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,69 @@ +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 + error message. + (print_error_for_call_failure): Likewise. + (build_new_function_call): Pass them in. + * name-lookup.c (supplement_binding_1): Don't complain about a + conflict with an erroneous declaration. + * error.c (dump_decl): Fix printing of alias declaration. + * decl.c (make_typename_type): Call cxx_incomplete_type_error. + * parser.c (cp_parser_diagnose_invalid_type_name): Likewise. + * semantics.c (perform_koenig_lookup): Don't wrap an error in + TEMPLATE_ID_EXPR. + +2016-11-12 Jason Merrill <jason@redhat.com> + + CWG 2233 + * typeck.c (convert_arguments): Handle default arg followed by none. + + * constexpr.c (potential_constant_expression_1): REALPART_EXPR and + IMAGPART_EXPR can be lvalues. + + DR 374 + PR c++/56840 + * pt.c (check_specialization_namespace): Allow any enclosing + namespace. + (check_unqualified_spec_or_inst): New. + (check_explicit_specialization): Call it. + * parser.c (cp_parser_elaborated_type_specifier) + (cp_parser_class_head): Call it. + 2016-11-10 Jason Merrill <jason@redhat.com> PR c++/77337 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0dcf322344c..f6f45905162 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4146,8 +4146,16 @@ static void print_error_for_call_failure (tree fn, vec<tree, va_gc> *args, struct z_candidate *candidates) { + tree targs = NULL_TREE; + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + { + targs = TREE_OPERAND (fn, 1); + fn = TREE_OPERAND (fn, 0); + } tree name = DECL_NAME (OVL_CURRENT (fn)); location_t loc = location_of (name); + if (targs) + name = lookup_template_function (name, targs); if (!any_strictly_viable (candidates)) error_at (loc, "no matching function for call to %<%D(%A)%>", @@ -4215,8 +4223,6 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args, bool koenig_p, return cp_build_function_call_vec (candidates->fn, args, complain); // Otherwise, emit notes for non-viable candidates. - if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) - fn = TREE_OPERAND (fn, 0); print_error_for_call_failure (fn, *args, candidates); } result = error_mark_node; @@ -8649,19 +8655,20 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, TREE_TYPE (instance)); else { - char *pretty_name; - bool free_p; - tree arglist; - - pretty_name = name_as_c_string (name, basetype, &free_p); - arglist = build_tree_list_vec (user_args); + tree arglist = build_tree_list_vec (user_args); + tree errname = name; + if (IDENTIFIER_CTOR_OR_DTOR_P (errname)) + { + tree fn = DECL_ORIGIN (get_first_fn (fns)); + errname = DECL_NAME (fn); + } + if (explicit_targs) + errname = lookup_template_function (errname, explicit_targs); if (skip_first_for_error) arglist = TREE_CHAIN (arglist); - error ("no matching function for call to %<%T::%s(%A)%#V%>", - basetype, pretty_name, arglist, + error ("no matching function for call to %<%T::%E(%A)%#V%>", + basetype, errname, arglist, TREE_TYPE (instance)); - if (free_p) - free (pretty_name); } print_z_candidates (location_of (name), candidates); } diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f75f0b039fa..e8c7702dede 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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) @@ -5105,6 +5107,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, #endif return RECUR (t, any); + case REALPART_EXPR: + case IMAGPART_EXPR: case COMPONENT_REF: case BIT_FIELD_REF: case ARROW_EXPR: @@ -5276,8 +5280,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, return true; /* fall through. */ - case REALPART_EXPR: - case IMAGPART_EXPR: case CONJ_EXPR: case SAVE_EXPR: case FIX_TRUNC_EXPR: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8183775b49e..8c2dbe1fba6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); @@ -6082,6 +6097,7 @@ extern void reset_specialization (void); extern void end_specialization (void); extern void begin_explicit_instantiation (void); extern void end_explicit_instantiation (void); +extern void check_unqualified_spec_or_inst (tree, location_t); extern tree check_explicit_specialization (tree, tree, int, int); extern int num_template_headers_for_class (tree); extern void check_template_variable (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 185c98bebb8..f142c1fb931 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3756,8 +3756,13 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, if (!t) { if (complain & tf_error) - error (want_template ? G_("no class template named %q#T in %q#T") - : G_("no type named %q#T in %q#T"), name, context); + { + if (!COMPLETE_TYPE_P (context)) + cxx_incomplete_type_error (NULL_TREE, context); + else + error (want_template ? G_("no class template named %q#T in %q#T") + : G_("no type named %q#T in %q#T"), name, context); + } return error_mark_node; } @@ -6069,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; } @@ -6249,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) @@ -6765,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) @@ -7132,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; @@ -7868,8 +8263,7 @@ check_class_member_definition_namespace (tree decl) diagnostics. */ if (processing_specialization) return; - /* There are no restrictions on the placement of - explicit instantiations. */ + /* We check this in check_explicit_instantiation_namespace. */ if (processing_explicit_instantiation) return; /* [class.mfct] @@ -9445,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); @@ -9646,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; @@ -9855,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 @@ -10089,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 @@ -10228,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; @@ -10739,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)) { @@ -10750,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. */ @@ -11129,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; @@ -11715,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) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index aa92a7e6a6b..fe1f75110b8 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1049,7 +1049,9 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_whitespace (pp); pp_cxx_ws_string (pp, "="); pp_cxx_whitespace (pp); - dump_type (pp, DECL_ORIGINAL_TYPE (t), flags); + dump_type (pp, (DECL_ORIGINAL_TYPE (t) + ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t)), + flags); break; } if ((flags & TFF_DECL_SPECIFIERS) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5eba4c3e18c..1fad79cb247 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index e574c271194..7ad65b89599 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -565,7 +565,8 @@ supplement_binding_1 (cxx_binding *binding, tree decl) } else { - diagnose_name_conflict (decl, bval); + if (!error_operand_p (bval)) + diagnose_name_conflict (decl, bval); ok = false; } @@ -3558,7 +3559,7 @@ set_decl_namespace (tree decl, tree scope, bool friendp) /* Since decl is a function, old should contain a function decl. */ if (!is_overloaded_fn (old)) goto complain; - /* A template can be explicitly specialized in any namespace. */ + /* We handle these in check_explicit_instantiation_namespace. */ if (processing_explicit_instantiation) return; if (processing_template_decl || processing_specialization) @@ -5392,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) ; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7b95dba72f2..9360ab0cbd6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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] */ @@ -3272,7 +3276,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, parser->scope, id, parser->scope); else if (TYPE_P (parser->scope)) { - if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + if (!COMPLETE_TYPE_P (parser->scope)) + cxx_incomplete_type_error (location_of (id), NULL_TREE, + parser->scope); + else if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) error_at (location_of (id), "%qE in %q#T does not name a template type", id, parser->scope); @@ -6925,6 +6932,29 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, warn_for_memset (input_location, arg0, arg2, literal_mask); } + if (TREE_CODE (postfix_expression) == FUNCTION_DECL + && warn_restrict) + { + unsigned i; + tree arg; + FOR_EACH_VEC_SAFE_ELT (args, i, arg) + TREE_VISITED (arg) = 0; + + unsigned param_pos = 0; + for (tree decl = DECL_ARGUMENTS (postfix_expression); + decl != NULL_TREE; + decl = DECL_CHAIN (decl), param_pos++) + { + tree type = TREE_TYPE (decl); + if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type) + && !TYPE_READONLY (TREE_TYPE (type))) + warn_for_restrict (param_pos, args); + } + + FOR_EACH_VEC_SAFE_ELT (args, i, arg) + TREE_VISITED (arg) = 0; + } + if (TREE_CODE (postfix_expression) == COMPONENT_REF) { tree instance = TREE_OPERAND (postfix_expression, 0); @@ -11445,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)) @@ -11465,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 @@ -11490,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; } @@ -11582,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; @@ -11655,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; } @@ -12528,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 @@ -12613,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; @@ -12765,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)) @@ -12780,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: @@ -17004,24 +17247,28 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, globalscope = cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* Look for the nested-name-specifier. */ + tree nested_name_specifier; if (tag_type == typename_type && !globalscope) { - if (!cp_parser_nested_name_specifier (parser, + nested_name_specifier + = cp_parser_nested_name_specifier (parser, /*typename_keyword_p=*/true, /*check_dependency_p=*/true, /*type_p=*/true, - is_declaration)) + is_declaration); + if (!nested_name_specifier) return error_mark_node; } else /* Even though `typename' is not present, the proposed resolution to Core Issue 180 says that in `class A<T>::B', `B' should be considered a type-name, even if `A<T>' is dependent. */ - cp_parser_nested_name_specifier_opt (parser, - /*typename_keyword_p=*/true, - /*check_dependency_p=*/true, - /*type_p=*/true, - is_declaration); + nested_name_specifier + = cp_parser_nested_name_specifier_opt (parser, + /*typename_keyword_p=*/true, + /*check_dependency_p=*/true, + /*type_p=*/true, + is_declaration); /* For everything but enumeration types, consider a template-id. For an enumeration type, consider only a plain identifier. */ if (tag_type != enum_type) @@ -17069,8 +17316,18 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL) ; else if (TREE_CODE (decl) == TYPE_DECL) - type = check_elaborated_type_specifier (tag_type, decl, - /*allow_template_p=*/true); + { + type = check_elaborated_type_specifier (tag_type, decl, + /*allow_template_p=*/true); + + /* If the next token is a semicolon, this must be a specialization, + instantiation, or friend declaration. Check the scope while we + still know whether or not we had a nested-name-specifier. */ + if (type != error_mark_node + && !nested_name_specifier && !is_friend + && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + check_unqualified_spec_or_inst (type, token->location); + } else if (decl == error_mark_node) type = error_mark_node; } @@ -18588,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; @@ -22336,6 +22594,11 @@ cp_parser_class_head (cp_parser* parser, { type = TREE_TYPE (id); type = maybe_process_partial_specialization (type); + + /* Check the scope while we still know whether or not we had a + nested-name-specifier. */ + if (type != error_mark_node) + check_unqualified_spec_or_inst (type, type_start_token->location); } if (nested_name_specifier) pushed_scope = push_scope (nested_name_specifier); @@ -25457,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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d4855d5bc35..7eeb27ddd1c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -772,28 +772,29 @@ check_specialization_namespace (tree tmpl) /* [tmpl.expl.spec] - An explicit specialization shall be declared in the namespace of - which the template is a member, or, for member templates, in the - namespace of which the enclosing class or enclosing class - template is a member. An explicit specialization of a member - function, member class or static data member of a class template - shall be declared in the namespace of which the class template is - a member. */ + An explicit specialization shall be declared in a namespace enclosing the + specialized template. An explicit specialization whose declarator-id is + not qualified shall be declared in the nearest enclosing namespace of the + template, or, if the namespace is inline (7.3.1), any namespace from its + enclosing namespace set. */ if (current_scope() != DECL_CONTEXT (tmpl) && !at_namespace_scope_p ()) { error ("specialization of %qD must appear at namespace scope", tmpl); return false; } - if (is_associated_namespace (current_namespace, tpl_ns)) - /* Same or super-using namespace. */ + + if (cxx_dialect < cxx11 + ? is_associated_namespace (current_namespace, tpl_ns) + : is_ancestor (current_namespace, tpl_ns)) + /* Same or enclosing namespace. */ return true; else { permerror (input_location, "specialization of %qD in different namespace", tmpl); - permerror (DECL_SOURCE_LOCATION (tmpl), - " from definition of %q#D", tmpl); + inform (DECL_SOURCE_LOCATION (tmpl), + " from definition of %q#D", tmpl); return false; } } @@ -2586,6 +2587,36 @@ check_template_variable (tree decl) } } +/* An explicit specialization whose declarator-id or class-head-name is not + qualified shall be declared in the nearest enclosing namespace of the + template, or, if the namespace is inline (7.3.1), any namespace from its + enclosing namespace set. + + If the name declared in the explicit instantiation is an unqualified name, + the explicit instantiation shall appear in the namespace where its template + is declared or, if that namespace is inline (7.3.1), any namespace from its + enclosing namespace set. */ + +void +check_unqualified_spec_or_inst (tree t, location_t loc) +{ + tree tmpl = most_general_template (t); + if (DECL_NAMESPACE_SCOPE_P (tmpl) + && !is_associated_namespace (current_namespace, + CP_DECL_CONTEXT (tmpl))) + { + if (processing_specialization) + permerror (loc, "explicit specialization of %qD outside its " + "namespace must use a nested-name-specifier", tmpl); + else if (processing_explicit_instantiation + && cxx_dialect >= cxx11) + /* This was allowed in C++98, so only pedwarn. */ + pedwarn (loc, OPT_Wpedantic, "explicit instantiation of %qD " + "outside its namespace must use a nested-name-" + "specifier", tmpl); + } +} + /* Check to see if the function just declared, as indicated in DECLARATOR, and in DECL, is a specialization of a function template. We may also discover that the declaration is an explicit @@ -2949,15 +2980,8 @@ check_explicit_specialization (tree declarator, return error_mark_node; else { - if (!ctype && !was_template_id - && (specialization || member_specialization - || explicit_instantiation) - && !is_associated_namespace (CP_DECL_CONTEXT (decl), - CP_DECL_CONTEXT (tmpl))) - error ("%qD is not declared in %qD", - tmpl, current_namespace); - else if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_HIDDEN_FRIEND_P (tmpl)) + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_HIDDEN_FRIEND_P (tmpl)) { if (pedwarn (DECL_SOURCE_LOCATION (decl), 0, "friend declaration %qD is not visible to " @@ -2965,6 +2989,9 @@ check_explicit_specialization (tree declarator, inform (DECL_SOURCE_LOCATION (tmpl), "friend declaration here"); } + else if (!ctype && !is_friend + && CP_DECL_CONTEXT (decl) == current_namespace) + check_unqualified_spec_or_inst (tmpl, DECL_SOURCE_LOCATION (decl)); tree gen_tmpl = most_general_template (tmpl); @@ -15284,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. */ @@ -15427,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); + } } } } @@ -15454,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); } @@ -24773,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 @@ -24858,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; @@ -24866,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; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1a7c478d4ec..0164f2e5c74 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2259,7 +2259,7 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args, } } - if (fn && template_id) + if (fn && template_id && fn != error_mark_node) fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args); return fn; @@ -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. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7872dd29cf8..c59543768a8 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 211696cf029..2d8b7b10440 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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))) @@ -3835,6 +3841,10 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl, { for (; typetail != void_list_node; ++i) { + /* After DR777, with explicit template args we can end up with a + default argument followed by no default argument. */ + if (!TREE_PURPOSE (typetail)) + break; tree parmval = convert_default_arg (TREE_VALUE (typetail), TREE_PURPOSE (typetail), @@ -3850,9 +3860,10 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl, break; } } - else + + if (typetail && typetail != void_list_node) { - if (complain & tf_error) + if (complain & tf_error) error_args_num (input_location, fndecl, /*too_many_p=*/false); return -1; } |