X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Fdecl.c;h=5e510c91aa30c0c35afe49669a60895203f0719c;hb=606358faa6dbcebb271c1eb9b269a93374fba784;hp=66dc4c4a2ce358bb6c41ce006754076780aaa1a8;hpb=4593483f15ca2a82049500b9434e736996bb0891;p=gcc.git diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 66dc4c4a2ce..5e510c91aa3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -100,6 +100,7 @@ static tree build_cp_library_fn (tree, enum tree_code, tree, int); static void store_parm_decls (tree); static void initialize_local_var (tree, tree); static void expand_static_init (tree, tree); +static location_t smallest_type_location (const cp_decl_specifier_seq*); /* The following symbols are subsumed in the cp_global_trees array, and listed here individually for documentation purposes. @@ -919,6 +920,31 @@ determine_local_discriminator (tree decl) } + +/* Returns true if functions FN1 and FN2 have equivalent trailing + requires clauses. */ + +static bool +function_requirements_equivalent_p (tree newfn, tree oldfn) +{ + /* In the concepts TS, the combined constraints are compared. */ + if (cxx_dialect < cxx2a) + { + tree ci1 = get_constraints (oldfn); + tree ci2 = get_constraints (newfn); + tree req1 = ci1 ? CI_ASSOCIATED_CONSTRAINTS (ci1) : NULL_TREE; + tree req2 = ci2 ? CI_ASSOCIATED_CONSTRAINTS (ci2) : NULL_TREE; + return cp_tree_equal (req1, req2); + } + + /* Compare only trailing requirements. */ + tree reqs1 = get_trailing_function_requirements (newfn); + tree reqs2 = get_trailing_function_requirements (oldfn); + if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE)) + return false; + return cp_tree_equal (reqs1, reqs2); +} + /* Subroutine of duplicate_decls: return truthvalue of whether or not types of these decls match. @@ -998,6 +1024,12 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */) else types_match = 0; + /* Two function declarations match if either has a requires-clause + then both have a requires-clause and their constraints-expressions + are equivalent. */ + if (types_match && flag_concepts) + types_match = function_requirements_equivalent_p (newdecl, olddecl); + /* The decls dont match if they correspond to two different versions of the same function. Disallow extern "C" functions to be versions for now. */ @@ -1012,23 +1044,21 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */) } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) { + if (!template_heads_equivalent_p (newdecl, olddecl)) + return 0; + tree oldres = DECL_TEMPLATE_RESULT (olddecl); tree newres = DECL_TEMPLATE_RESULT (newdecl); if (TREE_CODE (newres) != TREE_CODE (oldres)) return 0; - if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), - DECL_TEMPLATE_PARMS (olddecl))) - return 0; - - if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) - types_match = (same_type_p (TREE_TYPE (oldres), TREE_TYPE (newres)) - && equivalently_constrained (olddecl, newdecl)); + /* Two template types match if they are the same. Otherwise, compare + the underlying declarations. */ + if (TREE_CODE (newres) == TYPE_DECL) + types_match = same_type_p (TREE_TYPE (newres), TREE_TYPE (oldres)); else - // We don't need to check equivalently_constrained for variable and - // function templates because we check it on the results. - types_match = decls_match (oldres, newres); + types_match = decls_match (newres, oldres); } else { @@ -1056,11 +1086,6 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */) COMPARE_REDECLARATION); } - // Normal functions can be constrained, as can variable partial - // specializations. - if (types_match && VAR_OR_FUNCTION_DECL_P (newdecl)) - types_match = equivalently_constrained (newdecl, olddecl); - return types_match; } @@ -1335,6 +1360,46 @@ merge_attribute_bits (tree newdecl, tree olddecl) && lookup_attribute ("gnu_inline", \ DECL_ATTRIBUTES (fn))) +/* A subroutine of duplicate_decls. Emits a diagnostic when newdecl + ambiguates olddecl. Returns true if an error occurs. */ + +static bool +duplicate_function_template_decls (tree newdecl, tree olddecl) +{ + + tree newres = DECL_TEMPLATE_RESULT (newdecl); + tree oldres = DECL_TEMPLATE_RESULT (olddecl); + /* Function template declarations can be differentiated by parameter + and return type. */ + if (compparms (TYPE_ARG_TYPES (TREE_TYPE (oldres)), + TYPE_ARG_TYPES (TREE_TYPE (newres))) + && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)), + TREE_TYPE (TREE_TYPE (olddecl)))) + { + /* ... and also by their template-heads and requires-clauses. */ + if (template_heads_equivalent_p (newdecl, olddecl) + && function_requirements_equivalent_p (newres, oldres)) + { + error ("ambiguating new declaration %q+#D", newdecl); + inform (DECL_SOURCE_LOCATION (olddecl), + "old declaration %q#D", olddecl); + return true; + } + + /* FIXME: The types are the same but the are differences + in either the template heads or function requirements. + We should be able to diagnose a set of common errors + stemming from these declarations. For example: + + template requires C void f(...); + template void f(...) requires C; + + These are functionally equivalent but not equivalent. */ + } + + return false; +} + /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations. If the redeclaration is invalid, a diagnostic is issued, and the error_mark_node is returned. Otherwise, OLDDECL is returned. @@ -1643,11 +1708,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) if (TREE_CODE (newdecl) == TEMPLATE_DECL) { + tree oldres = DECL_TEMPLATE_RESULT (olddecl); + tree newres = DECL_TEMPLATE_RESULT (newdecl); + /* The name of a class template may not be declared to refer to any other template, class, function, object, namespace, value, or type in the same scope. */ - if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL - || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) + if (TREE_CODE (oldres) == TYPE_DECL + || TREE_CODE (newres) == TYPE_DECL) { error_at (newdecl_loc, "conflicting declaration of template %q#D", newdecl); @@ -1655,24 +1723,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) "previous declaration %q#D", olddecl); return error_mark_node; } - else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL - && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL - && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))), - TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)))) - && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), - DECL_TEMPLATE_PARMS (olddecl)) - /* Template functions can be disambiguated by - return type. */ - && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)), - TREE_TYPE (TREE_TYPE (olddecl))) - /* Template functions can also be disambiguated by - constraints. */ - && equivalently_constrained (olddecl, newdecl)) + + else if (TREE_CODE (oldres) == FUNCTION_DECL + && TREE_CODE (newres) == FUNCTION_DECL) { - error_at (newdecl_loc, "ambiguating new declaration %q#D", - newdecl); - inform (olddecl_loc, - "old declaration %q#D", olddecl); + if (duplicate_function_template_decls (newdecl, olddecl)) + return error_mark_node; + return NULL_TREE; } else if (check_concept_refinement (olddecl, newdecl)) return error_mark_node; @@ -1922,10 +1979,29 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) if (TREE_CODE (newdecl) == FUNCTION_DECL) { - if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl)) - inform (olddecl_loc, DECL_INITIAL (olddecl) - ? G_("previous definition of %qD here") - : G_("previous declaration of %qD here"), olddecl); + if (merge_attr) + { + if (diagnose_mismatched_attributes (olddecl, newdecl)) + inform (olddecl_loc, DECL_INITIAL (olddecl) + ? G_("previous definition of %qD here") + : G_("previous declaration of %qD here"), olddecl); + + /* [dcl.attr.noreturn]: The first declaration of a function shall + specify the noreturn attribute if any declaration of that function + specifies the noreturn attribute. */ + tree a; + if (TREE_THIS_VOLATILE (newdecl) + && !TREE_THIS_VOLATILE (olddecl) + /* This applies to [[noreturn]] only, not its GNU variants. */ + && (a = lookup_attribute ("noreturn", DECL_ATTRIBUTES (newdecl))) + && cxx11_attribute_p (a) + && get_attribute_namespace (a) == NULL_TREE) + { + error_at (newdecl_loc, "function %qD declared %<[[noreturn]]%> " + "but its first declaration was not", newdecl); + inform (olddecl_loc, "previous declaration of %qD", olddecl); + } + } /* Now that functions must hold information normally held by field decls, there is extra work to do so that @@ -2025,9 +2101,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) tree old_result = DECL_TEMPLATE_RESULT (olddecl); tree new_result = DECL_TEMPLATE_RESULT (newdecl); TREE_TYPE (olddecl) = TREE_TYPE (old_result); - DECL_TEMPLATE_SPECIALIZATIONS (olddecl) - = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl), - DECL_TEMPLATE_SPECIALIZATIONS (newdecl)); + + /* The new decl should not already have gathered any + specializations. */ + gcc_assert (!DECL_TEMPLATE_SPECIALIZATIONS (newdecl)); DECL_ATTRIBUTES (old_result) = (*targetm.merge_decl_attributes) (old_result, new_result); @@ -2183,9 +2260,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) SET_DECL_DEPENDENT_INIT_P (newdecl, true); DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl) |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl); - if (DECL_CLASS_SCOPE_P (olddecl)) - DECL_DECLARED_CONSTEXPR_P (newdecl) - |= DECL_DECLARED_CONSTEXPR_P (olddecl); + DECL_DECLARED_CONSTEXPR_P (newdecl) + |= DECL_DECLARED_CONSTEXPR_P (olddecl); /* Merge the threadprivate attribute from OLDDECL into NEWDECL. */ if (DECL_LANG_SPECIFIC (olddecl) @@ -2272,7 +2348,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); - DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl); + if (DECL_IS_OPERATOR_NEW_P (olddecl)) + DECL_SET_IS_OPERATOR_NEW (newdecl, true); DECL_LOOPING_CONST_OR_PURE_P (newdecl) |= DECL_LOOPING_CONST_OR_PURE_P (olddecl); @@ -2367,7 +2444,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) /* Don't really know how much of the language-specific values we should copy from old to new. */ DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); - DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl); DECL_INITIALIZED_IN_CLASS_P (newdecl) |= DECL_INITIALIZED_IN_CLASS_P (olddecl); @@ -2522,8 +2598,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) if (fndecl_built_in_p (olddecl) && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match)) { - DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + copy_decl_built_in_function (newdecl, olddecl); /* If we're keeping the built-in definition, keep the rtl, regardless of declaration matches. */ COPY_DECL_RTL (olddecl, newdecl); @@ -2544,9 +2619,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) set_builtin_decl_declared_p (fncode, true); break; } - } - copy_attributes_to_builtin (newdecl); + copy_attributes_to_builtin (newdecl); + } } if (new_defines_function) /* If defining a function declared with other language @@ -2897,6 +2972,9 @@ redeclaration_error_message (tree newdecl, tree olddecl) return NULL; } + if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == CONCEPT_DECL) + return G_("redefinition of %q#D"); + if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL || (DECL_TEMPLATE_RESULT (newdecl) == DECL_TEMPLATE_RESULT (olddecl))) @@ -3228,32 +3306,32 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names, { case sk_try: if (!saw_eh) - inf = N_("enters try block"); + inf = G_(" enters % block"); saw_eh = true; break; case sk_catch: if (!saw_eh) - inf = N_("enters catch block"); + inf = G_(" enters % block"); saw_eh = true; break; case sk_omp: if (!saw_omp) - inf = N_("enters OpenMP structured block"); + inf = G_(" enters OpenMP structured block"); saw_omp = true; break; case sk_transaction: if (!saw_tm) - inf = N_("enters synchronized or atomic statement"); + inf = G_(" enters synchronized or atomic statement"); saw_tm = true; break; case sk_block: if (!saw_cxif && level_for_constexpr_if (b->level_chain)) { - inf = N_("enters constexpr if statement"); + inf = G_(" enters % statement"); loc = EXPR_LOCATION (b->level_chain->this_entity); saw_cxif = true; } @@ -3269,7 +3347,7 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names, complained = identify_goto (decl, input_location, locus, DK_ERROR); identified = 2; if (complained) - inform (loc, " %s", inf); + inform (loc, inf); } } @@ -3364,7 +3442,7 @@ check_goto (tree decl) identified = 2; } if (complained) - inform (DECL_SOURCE_LOCATION (bad), " enters catch block"); + inform (DECL_SOURCE_LOCATION (bad), " enters % block"); saw_catch = true; } else if (complained) @@ -3382,13 +3460,13 @@ check_goto (tree decl) if (complained) { if (ent->in_try_scope) - inform (input_location, " enters try block"); + inform (input_location, " enters % block"); else if (ent->in_catch_scope && !saw_catch) - inform (input_location, " enters catch block"); + inform (input_location, " enters % block"); else if (ent->in_transaction_scope) inform (input_location, " enters synchronized or atomic statement"); else if (ent->in_constexpr_if) - inform (input_location, " enters % if statement"); + inform (input_location, " enters % statement"); } if (ent->in_omp_scope) @@ -3538,7 +3616,7 @@ pop_switch (void) location_t switch_location; /* Emit warnings as needed. */ - switch_location = cp_expr_loc_or_loc (cs->switch_stmt, input_location); + switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt); const bool bool_cond_p = (SWITCH_STMT_TYPE (cs->switch_stmt) && TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE); @@ -3609,16 +3687,23 @@ case_conversion (tree type, tree value) value = mark_rvalue_use (value); + if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) + type = type_promotes_to (type); + + tree ovalue = value; + /* The constant-expression VALUE shall be a converted constant expression + of the adjusted type of the switch condition, which doesn't allow + narrowing conversions. */ + value = build_converted_constant_expr (type, value, tf_warning_or_error); + if (cxx_dialect >= cxx11 && (SCOPED_ENUM_P (type) - || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)))) - { - if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) - type = type_promotes_to (type); - value = (perform_implicit_conversion_flags - (type, value, tf_warning_or_error, - LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL)); - } + || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (ovalue)))) + /* Use the converted value. */; + else + /* The already integral case. */ + value = ovalue; + return cxx_constant_value (value); } @@ -4120,6 +4205,9 @@ initialize_predefined_identifiers (void) {"value", &value_identifier, cik_normal}, {"_FUN", &fun_identifier, cik_normal}, {"__closure", &closure_identifier, cik_normal}, + {"heap uninit", &heap_uninit_identifier, cik_normal}, + {"heap ", &heap_identifier, cik_normal}, + {"heap deleted", &heap_deleted_identifier, cik_normal}, {NULL, NULL, cik_normal} }; @@ -4337,12 +4425,14 @@ cxx_init_decl_processing (void) deltype = build_exception_variant (deltype, empty_except_spec); tree opnew = push_cp_library_fn (NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; - DECL_IS_OPERATOR_NEW (opnew) = 1; + DECL_SET_IS_OPERATOR_NEW (opnew, true); opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; - DECL_IS_OPERATOR_NEW (opnew) = 1; - push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); - push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_NEW (opnew, true); + tree opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); if (flag_sized_deallocation) { /* Also push the sized deallocation variants: @@ -4354,8 +4444,10 @@ cxx_init_decl_processing (void) deltype = cp_build_type_attribute_variant (void_ftype_ptr_size, extvisattr); deltype = build_exception_variant (deltype, empty_except_spec); - push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); - push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); } if (aligned_new_threshold) @@ -4373,18 +4465,20 @@ cxx_init_decl_processing (void) newtype = build_exception_variant (newtype, new_eh_spec); opnew = push_cp_library_fn (NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; - DECL_IS_OPERATOR_NEW (opnew) = 1; + DECL_SET_IS_OPERATOR_NEW (opnew, true); opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; - DECL_IS_OPERATOR_NEW (opnew) = 1; + DECL_SET_IS_OPERATOR_NEW (opnew, true); /* operator delete (void *, align_val_t); */ deltype = build_function_type_list (void_type_node, ptr_type_node, align_type_node, NULL_TREE); deltype = cp_build_type_attribute_variant (deltype, extvisattr); deltype = build_exception_variant (deltype, empty_except_spec); - push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); - push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); if (flag_sized_deallocation) { @@ -4394,8 +4488,10 @@ cxx_init_decl_processing (void) NULL_TREE); deltype = cp_build_type_attribute_variant (deltype, extvisattr); deltype = build_exception_variant (deltype, empty_except_spec); - push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); - push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_SET_IS_OPERATOR_DELETE (opdel, true); } } @@ -4476,13 +4572,27 @@ cp_fname_init (const char* name, tree *type_p) static tree cp_make_fname_decl (location_t loc, tree id, int type_dep) { - const char *const name = (type_dep && in_template_function () - ? NULL : fname_as_string (type_dep)); + const char * name = NULL; + bool release_name = false; + if (!(type_dep && in_template_function ())) + { + if (current_function_decl == NULL_TREE) + name = "top level"; + else if (type_dep == 1) /* __PRETTY_FUNCTION__ */ + name = cxx_printable_name (current_function_decl, 2); + else if (type_dep == 0) /* __FUNCTION__ */ + { + name = fname_as_string (type_dep); + release_name = true; + } + else + gcc_unreachable (); + } tree type; tree init = cp_fname_init (name, &type); tree decl = build_decl (loc, VAR_DECL, id, type); - if (name) + if (release_name) free (CONST_CAST (char *, name)); /* As we're using pushdecl_with_scope, we must set the context. */ @@ -4782,6 +4892,24 @@ warn_misplaced_attr_for_class_type (location_t location, class_type, class_key_or_enum_as_string (class_type)); } +/* Returns the cv-qualifiers that apply to the type specified + by the DECLSPECS. */ + +static int +get_type_quals (const cp_decl_specifier_seq *declspecs) +{ + int type_quals = TYPE_UNQUALIFIED; + + if (decl_spec_seq_has_spec_p (declspecs, ds_const)) + type_quals |= TYPE_QUAL_CONST; + if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) + type_quals |= TYPE_QUAL_VOLATILE; + if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) + type_quals |= TYPE_QUAL_RESTRICT; + + return type_quals; +} + /* Make sure that a declaration with no declarator is well-formed, i.e. just declares a tagged type or anonymous union. @@ -4801,7 +4929,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, bool error_p = false; if (declspecs->multiple_types_p) - error ("multiple types in one declaration"); + error_at (smallest_type_location (declspecs), + "multiple types in one declaration"); else if (declspecs->redefined_builtin_type) { if (!in_system_header_at (input_location)) @@ -4861,9 +4990,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, /* Anonymous unions are objects, so they can have specifiers. */; SET_ANON_AGGR_TYPE_P (declared_type); - if (TREE_CODE (declared_type) != UNION_TYPE - && !in_system_header_at (input_location)) - pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous structs"); + if (TREE_CODE (declared_type) != UNION_TYPE) + pedwarn (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (declared_type)), + OPT_Wpedantic, "ISO C++ prohibits anonymous structs"); } else @@ -4908,6 +5037,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, else if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr)) error_at (declspecs->locations[ds_constexpr], "% cannot be used for type declarations"); + else if (decl_spec_seq_has_spec_p (declspecs, ds_constinit)) + error_at (declspecs->locations[ds_constinit], + "% cannot be used for type declarations"); } if (declspecs->attributes && warn_attributes && declared_type) @@ -5078,7 +5210,8 @@ start_decl (const cp_declarator *declarator, && TREE_CODE (decl) == TYPE_DECL) { error_at (DECL_SOURCE_LOCATION (decl), - "typedef %qD is initialized (use decltype instead)", decl); + "typedef %qD is initialized (use %qs instead)", + decl, "decltype"); return error_mark_node; } @@ -5129,7 +5262,7 @@ start_decl (const cp_declarator *declarator, && DECL_UNINLINABLE (decl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl))) warning_at (DECL_SOURCE_LOCATION (decl), 0, - "inline function %qD given attribute noinline", decl); + "inline function %qD given attribute %qs", decl, "noinline"); if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context))) { @@ -5236,7 +5369,14 @@ start_decl (const cp_declarator *declarator, decl = maybe_push_decl (decl); if (processing_template_decl) - decl = push_template_decl (decl); + { + /* Make sure that for a `constinit' decl push_template_decl creates + a DECL_TEMPLATE_INFO info for us, so that cp_finish_decl can then set + TINFO_VAR_DECLARED_CONSTINIT. */ + if (decl_spec_seq_has_spec_p (declspecs, ds_constinit)) + retrofit_lang_decl (decl); + decl = push_template_decl (decl); + } if (decl == error_mark_node) return error_mark_node; @@ -5463,8 +5603,9 @@ check_array_designated_initializer (constructor_elt *ce, sorry ("non-trivial designated initializers not supported"); } else - error ("C99 designator %qE is not an integral constant-expression", - ce->index); + error_at (cp_expr_loc_or_input_loc (ce->index), + "C99 designator %qE is not an integral constant-expression", + ce->index); return false; } @@ -5701,7 +5842,7 @@ check_for_uninitialized_const_var (tree decl, bool constexpr_context_p, { if (complain & tf_error) show_notes = permerror (DECL_SOURCE_LOCATION (decl), - "uninitialized const %qD", decl); + "uninitialized %", decl); } else { @@ -5842,8 +5983,9 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, /* Pointers initialized to strings must be treated as non-zero even if the string is empty. */ tree init_type = TREE_TYPE (elt_init); - if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)) - || !initializer_zerop (elt_init)) + if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type))) + last_nonzero = index; + else if (!type_initializer_zero_p (elt_type, elt_init)) last_nonzero = index; /* This can happen with an invalid initializer (c++/54501). */ @@ -6034,8 +6176,9 @@ has_designator_problem (reshape_iter *d, tsubst_flags_t complain) if (d->cur->index) { if (complain & tf_error) - error ("C99 designator %qE outside aggregate initializer", - d->cur->index); + error_at (cp_expr_loc_or_input_loc (d->cur->index), + "C99 designator %qE outside aggregate initializer", + d->cur->index); else return true; } @@ -6380,7 +6523,7 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags) static tree check_initializer (tree decl, tree init, int flags, vec **cleanups) { - tree type = TREE_TYPE (decl); + tree type; tree init_code = NULL; tree core_type; @@ -6538,11 +6681,12 @@ check_initializer (tree decl, tree init, int flags, vec **cleanups) about aggregate initialization of non-aggregate classes. */ flags |= LOOKUP_ALREADY_DIGESTED; } - else if (DECL_DECLARED_CONSTEXPR_P (decl)) + else if (DECL_DECLARED_CONSTEXPR_P (decl) + || (flags & LOOKUP_CONSTINIT)) { - /* Declared constexpr, but no suitable initializer; massage - init appropriately so we can pass it into store_init_value - for the error. */ + /* Declared constexpr or constinit, but no suitable initializer; + massage init appropriately so we can pass it into + store_init_value for the error. */ if (CLASS_TYPE_P (type) && (!init || TREE_CODE (init) == TREE_LIST)) { @@ -6924,6 +7068,19 @@ notice_forced_label_r (tree *tp, int *walk_subtrees, void *) return NULL_TREE; } +/* Return true if DECL has either a trivial destructor, or for C++2A + is constexpr and has a constexpr destructor. */ + +static bool +decl_maybe_constant_destruction (tree decl, tree type) +{ + return (TYPE_HAS_TRIVIAL_DESTRUCTOR (type) + || (cxx_dialect >= cxx2a + && VAR_P (decl) + && DECL_DECLARED_CONSTEXPR_P (decl) + && type_has_constexpr_destructor (strip_array_types (type)))); +} + /* Finish processing of a declaration; install its line number and initial value. If the length of an array type is not known before, @@ -7020,8 +7177,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, return; if (TREE_CODE (type) == FUNCTION_TYPE) { - error ("initializer for % has function type " - "(did you forget the %<()%> ?)", decl); + error ("initializer for % has function type; " + "did you forget the %<()%>?", decl); TREE_TYPE (decl) = error_mark_node; return; } @@ -7105,6 +7262,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, DECL_INITIAL (decl) = NULL_TREE; } + /* Handle `constinit' on variable templates. */ + if (flags & LOOKUP_CONSTINIT) + TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (decl)) = true; + /* Generally, initializers in templates are expanded when the template is instantiated. But, if DECL is a variable constant then it can be used in future constant expressions, so its value @@ -7196,6 +7357,19 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (VAR_P (decl)) { + duration_kind dk = decl_storage_duration (decl); + /* [dcl.constinit]/1 "The constinit specifier shall be applied + only to a declaration of a variable with static or thread storage + duration." */ + if ((flags & LOOKUP_CONSTINIT) + && !(dk == dk_thread || dk == dk_static)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "% can only be applied to a variable with " + "static or thread storage duration"); + return; + } + /* If this is a local variable that will need a mangled name, register it now. We must do this before processing the initializer for the variable, since the initialization might @@ -7331,7 +7505,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, TREE_READONLY (decl) = 1; /* Likewise if it needs destruction. */ - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + if (!decl_maybe_constant_destruction (decl, type)) TREE_READONLY (decl) = 0; } @@ -7412,8 +7586,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, DECL_ATTRIBUTES (decl)); complete_type (TREE_TYPE (decl)); if (!cp_omp_mappable_type (TREE_TYPE (decl))) - error ("%q+D in declare target directive does not have mappable type", - decl); + { + error ("%q+D in declare target directive does not have mappable" + " type", decl); + cp_omp_emit_unmappable_type_notes (TREE_TYPE (decl)); + } else if (!lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)) && !lookup_attribute ("omp declare target link", @@ -7602,13 +7779,6 @@ get_tuple_decomp_init (tree decl, unsigned i) based on the actual type of the variable, so store it in a hash table. */ static GTY((cache)) tree_cache_map *decomp_type_table; -static void -store_decomp_type (tree v, tree t) -{ - if (!decomp_type_table) - decomp_type_table = tree_cache_map::create_ggc (13); - decomp_type_table->put (v, t); -} tree lookup_decomp_type (tree v) @@ -7624,7 +7794,7 @@ cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count) { if (!processing_template_decl && !error_operand_p (decl) - && DECL_NAMESPACE_SCOPE_P (decl)) + && TREE_STATIC (decl)) { auto_vec v; v.safe_grow (count); @@ -7844,7 +8014,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) goto error_out; } /* Save the decltype away before reference collapse. */ - store_decomp_type (v[i], eltype); + hash_map_safe_put (decomp_type_table, v[i], eltype); eltype = cp_build_reference_type (eltype, !lvalue_p (init)); TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); @@ -7855,8 +8025,27 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) DECL_HAS_VALUE_EXPR_P (v[i]) = 0; } if (!processing_template_decl) - cp_finish_decl (v[i], init, /*constexpr*/false, - /*asm*/NULL_TREE, LOOKUP_NORMAL); + { + TREE_PUBLIC (v[i]) = TREE_PUBLIC (decl); + TREE_STATIC (v[i]) = TREE_STATIC (decl); + DECL_COMMON (v[i]) = DECL_COMMON (decl); + DECL_COMDAT (v[i]) = DECL_COMDAT (decl); + if (TREE_STATIC (v[i])) + { + CP_DECL_THREAD_LOCAL_P (v[i]) + = CP_DECL_THREAD_LOCAL_P (decl); + set_decl_tls_model (v[i], DECL_TLS_MODEL (decl)); + if (DECL_ONE_ONLY (decl)) + make_decl_one_only (v[i], cxx_comdat_group (v[i])); + if (TREE_PUBLIC (decl)) + DECL_WEAK (v[i]) = DECL_WEAK (decl); + DECL_VISIBILITY (v[i]) = DECL_VISIBILITY (decl); + DECL_VISIBILITY_SPECIFIED (v[i]) + = DECL_VISIBILITY_SPECIFIED (decl); + } + cp_finish_decl (v[i], init, /*constexpr*/false, + /*asm*/NULL_TREE, LOOKUP_NORMAL); + } } /* Ignore reads from the underlying decl performed during initialization of the individual variables. If those will be read, we'll mark @@ -8198,6 +8387,13 @@ register_dtor_fn (tree decl) if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) return void_node; + if (decl_maybe_constant_destruction (decl, type) + && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + { + cxx_maybe_build_cleanup (decl, tf_warning_or_error); + return void_node; + } + /* If we're using "__cxa_atexit" (or "__cxa_thread_atexit" or "__aeabi_atexit"), and DECL is a class object, we can just pass the destructor to "__cxa_atexit"; we don't have to build a temporary @@ -8315,7 +8511,7 @@ expand_static_init (tree decl, tree init) gcc_assert (TREE_STATIC (decl)); /* Some variables require no dynamic initialization. */ - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) + if (decl_maybe_constant_destruction (decl, TREE_TYPE (decl))) { /* Make sure the destructor is callable. */ cxx_maybe_build_cleanup (decl, tf_warning_or_error); @@ -8828,10 +9024,10 @@ grokfndecl (tree ctype, if (location == UNKNOWN_LOCATION) location = input_location; - // Was the concept specifier present? + /* Was the concept specifier present? */ bool concept_p = inlinep & 4; - // Concept declarations must have a corresponding definition. + /* Concept declarations must have a corresponding definition. */ if (concept_p && !funcdef_flag) { error_at (location, "concept %qD has no definition", declarator); @@ -8848,12 +9044,12 @@ grokfndecl (tree ctype, tree tmpl_reqs = NULL_TREE; if (processing_template_decl > template_class_depth (ctype)) tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); - - /* Adjust the required expression into a constraint. */ - if (decl_reqs) - decl_reqs = normalize_expression (decl_reqs); - tree ci = build_constraints (tmpl_reqs, decl_reqs); + if (concept_p && ci) + { + error_at (location, "a function concept cannot be constrained"); + ci = NULL_TREE; + } set_constraints (decl, ci); } @@ -8918,16 +9114,14 @@ grokfndecl (tree ctype, the information in the TEMPLATE_ID_EXPR. */ SET_DECL_IMPLICIT_INSTANTIATION (decl); - gcc_assert (identifier_p (fns) - || TREE_CODE (fns) == OVERLOAD - || TREE_CODE (fns) == FUNCTION_DECL); + gcc_assert (identifier_p (fns) || OVL_P (fns)); DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args); for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t)) if (TREE_PURPOSE (t) - && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG) + && TREE_CODE (TREE_PURPOSE (t)) == DEFERRED_PARSE) { - error_at (defarg_location (TREE_PURPOSE (t)), + error_at (defparse_location (TREE_PURPOSE (t)), "default arguments are not allowed in declaration " "of friend template specialization %qD", decl); @@ -9129,7 +9323,7 @@ grokfndecl (tree ctype, else if (long_double_p) { if (cpp_interpret_float_suffix (parse_in, suffix, strlen (suffix))) - warning_at (location, 0, "floating point suffix %qs" + warning_at (location, 0, "floating-point suffix %qs" " shadowed by implementation", suffix); } /* 17.6.3.3.5 */ @@ -9495,12 +9689,18 @@ grokvardecl (tree type, if (!same_type_ignoring_top_level_qualifiers_p (type, boolean_type_node)) error_at (declspecs->locations[ds_type_spec], "concept must have type %"); + if (TEMPLATE_PARMS_CONSTRAINTS (current_template_parms)) + { + error_at (location, "a variable concept cannot be constrained"); + TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = NULL_TREE; + } } else if (flag_concepts && processing_template_decl > template_class_depth (scope)) { tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); tree ci = build_constraints (reqs, NULL_TREE); + set_constraints (decl, ci); } @@ -9546,10 +9746,12 @@ build_ptrmemfunc_type (tree type) TYPE_PTRMEMFUNC_FLAG (t) = 1; field = build_decl (input_location, FIELD_DECL, pfn_identifier, type); + DECL_NONADDRESSABLE_P (field) = 1; fields = field; field = build_decl (input_location, FIELD_DECL, delta_identifier, delta_type_node); + DECL_NONADDRESSABLE_P (field) = 1; DECL_CHAIN (field) = fields; fields = field; @@ -10092,6 +10294,22 @@ smallest_type_quals_location (int type_quals, const location_t* locations) return loc; } +/* Returns the smallest among the latter and locations[ds_type_spec]. */ + +static location_t +smallest_type_location (int type_quals, const location_t* locations) +{ + location_t loc = smallest_type_quals_location (type_quals, locations); + return min_location (loc, locations[ds_type_spec]); +} + +static location_t +smallest_type_location (const cp_decl_specifier_seq *declspecs) +{ + int type_quals = get_type_quals (declspecs); + return smallest_type_location (type_quals, declspecs->locations); +} + /* Check that it's OK to declare a function with the indicated TYPE and TYPE_QUALS. SFK indicates the kind of special function (if any) that this function is. OPTYPE is the type given in a conversion @@ -10110,7 +10328,8 @@ check_special_function_return_type (special_function_kind sfk, { case sfk_constructor: if (type) - error ("return type specification for constructor invalid"); + error_at (smallest_type_location (type_quals, locations), + "return type specification for constructor invalid"); else if (type_quals != TYPE_UNQUALIFIED) error_at (smallest_type_quals_location (type_quals, locations), "qualifiers are not allowed on constructor declaration"); @@ -10123,7 +10342,8 @@ check_special_function_return_type (special_function_kind sfk, case sfk_destructor: if (type) - error ("return type specification for destructor invalid"); + error_at (smallest_type_location (type_quals, locations), + "return type specification for destructor invalid"); else if (type_quals != TYPE_UNQUALIFIED) error_at (smallest_type_quals_location (type_quals, locations), "qualifiers are not allowed on destructor declaration"); @@ -10138,7 +10358,8 @@ check_special_function_return_type (special_function_kind sfk, case sfk_conversion: if (type) - error ("return type specified for %", optype); + error_at (smallest_type_location (type_quals, locations), + "return type specified for %", optype); else if (type_quals != TYPE_UNQUALIFIED) error_at (smallest_type_quals_location (type_quals, locations), "qualifiers are not allowed on declaration of " @@ -10149,7 +10370,8 @@ check_special_function_return_type (special_function_kind sfk, case sfk_deduction_guide: if (type) - error ("return type specified for deduction guide"); + error_at (smallest_type_location (type_quals, locations), + "return type specified for deduction guide"); else if (type_quals != TYPE_UNQUALIFIED) error_at (smallest_type_quals_location (type_quals, locations), "qualifiers are not allowed on declaration of " @@ -10165,7 +10387,7 @@ check_special_function_return_type (special_function_kind sfk, for (int i = 0; i < ds_last; ++i) if (i != ds_explicit && locations[i]) error_at (locations[i], - "decl-specifier in declaration of deduction guide"); + "% in declaration of deduction guide"); break; default: @@ -10181,19 +10403,20 @@ check_special_function_return_type (special_function_kind sfk, error-recovery purposes. */ tree -check_var_type (tree identifier, tree type) +check_var_type (tree identifier, tree type, location_t loc) { if (VOID_TYPE_P (type)) { if (!identifier) - error ("unnamed variable or field declared void"); + error_at (loc, "unnamed variable or field declared void"); else if (identifier_p (identifier)) { gcc_assert (!IDENTIFIER_ANY_OP_P (identifier)); - error ("variable or field %qE declared void", identifier); + error_at (loc, "variable or field %qE declared void", + identifier); } else - error ("variable or field declared void"); + error_at (loc, "variable or field declared void"); type = error_mark_node; } @@ -10234,15 +10457,12 @@ name_unnamed_type (tree type, tree decl) /* Replace the anonymous name with the real name everywhere. */ for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) - { - if (anon_aggrname_p (TYPE_IDENTIFIER (t))) - /* We do not rename the debug info representing the - unnamed tagged type because the standard says in - [dcl.typedef] that the naming applies only for - linkage purposes. */ - /*debug_hooks->set_name (t, decl);*/ - TYPE_NAME (t) = decl; - } + if (IDENTIFIER_ANON_P (TYPE_IDENTIFIER (t))) + /* We do not rename the debug info representing the unnamed + tagged type because the standard says in [dcl.typedef] that + the naming applies only for linkage purposes. */ + /*debug_hooks->set_name (t, decl);*/ + TYPE_NAME (t) = decl; if (TYPE_LANG_SPECIFIC (type)) TYPE_WAS_UNNAMED (type) = 1; @@ -10320,6 +10540,7 @@ grokdeclarator (const cp_declarator *declarator, tree type = NULL_TREE; int longlong = 0; int explicit_intN = 0; + int int_n_alt = 0; int virtualp, explicitp, friendp, inlinep, staticp; int explicit_int = 0; int explicit_char = 0; @@ -10355,7 +10576,7 @@ grokdeclarator (const cp_declarator *declarator, a member function. */ cp_ref_qualifier rqual = REF_QUAL_NONE; /* cv-qualifiers that apply to the type specified by the DECLSPECS. */ - int type_quals = TYPE_UNQUALIFIED; + int type_quals = get_type_quals (declspecs); tree raises = NULL_TREE; int template_count = 0; tree returned_attrs = NULL_TREE; @@ -10382,9 +10603,9 @@ grokdeclarator (const cp_declarator *declarator, bool template_parm_flag = false; bool typedef_p = decl_spec_seq_has_spec_p (declspecs, ds_typedef); bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr); + bool constinit_p = decl_spec_seq_has_spec_p (declspecs, ds_constinit); bool late_return_type_p = false; bool array_parameter_p = false; - location_t saved_loc = input_location; tree reqs = NULL_TREE; signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed); @@ -10393,6 +10614,7 @@ grokdeclarator (const cp_declarator *declarator, long_p = decl_spec_seq_has_spec_p (declspecs, ds_long); longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long); explicit_intN = declspecs->explicit_intN_p; + int_n_alt = declspecs->int_n_alt; thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread); // Was concept_p specified? Note that ds_concept @@ -10401,13 +10623,6 @@ grokdeclarator (const cp_declarator *declarator, if (concept_p) constexpr_p = true; - if (decl_spec_seq_has_spec_p (declspecs, ds_const)) - type_quals |= TYPE_QUAL_CONST; - if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) - type_quals |= TYPE_QUAL_VOLATILE; - if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) - type_quals |= TYPE_QUAL_RESTRICT; - if (decl_context == FUNCDEF) funcdef_flag = true, decl_context = NORMAL; else if (decl_context == MEMFUNCDEF) @@ -10422,13 +10637,15 @@ grokdeclarator (const cp_declarator *declarator, if (initialized > 1) funcdef_flag = true; - location_t typespec_loc = smallest_type_quals_location (type_quals, - declspecs->locations); - typespec_loc = min_location (typespec_loc, - declspecs->locations[ds_type_spec]); + location_t typespec_loc = smallest_type_location (type_quals, + declspecs->locations); if (typespec_loc == UNKNOWN_LOCATION) typespec_loc = input_location; + location_t id_loc = declarator ? declarator->id_loc : input_location; + if (id_loc == UNKNOWN_LOCATION) + id_loc = input_location; + /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ for (id_declarator = declarator; @@ -10486,7 +10703,8 @@ grokdeclarator (const cp_declarator *declarator, ctype = qualifying_scope; if (!MAYBE_CLASS_TYPE_P (ctype)) { - error ("%q#T is not a class or a namespace", ctype); + error_at (id_declarator->id_loc, + "%q#T is not a class or namespace", ctype); ctype = NULL_TREE; } else if (innermost_code != cdk_function @@ -10494,8 +10712,9 @@ grokdeclarator (const cp_declarator *declarator, && !uniquely_derived_from_p (ctype, current_class_type)) { - error ("invalid use of qualified-name %<%T::%D%>", - qualifying_scope, decl); + error_at (id_declarator->id_loc, + "invalid use of qualified-name %<%T::%D%>", + qualifying_scope, decl); return error_mark_node; } } @@ -10508,13 +10727,15 @@ grokdeclarator (const cp_declarator *declarator, { if (innermost_code != cdk_function) { - error ("declaration of %qD as non-function", decl); + error_at (EXPR_LOCATION (decl), + "declaration of %qE as non-function", decl); return error_mark_node; } else if (!qualifying_scope && !(current_class_type && at_class_scope_p ())) { - error ("declaration of %qD as non-member", decl); + error_at (EXPR_LOCATION (decl), + "declaration of %qE as non-member", decl); return error_mark_node; } @@ -10593,7 +10814,7 @@ grokdeclarator (const cp_declarator *declarator, D1 ( parameter-declaration-clause) ... */ if (funcdef_flag && innermost_code != cdk_function) { - error ("function definition does not declare parameters"); + error_at (id_loc, "function definition does not declare parameters"); return error_mark_node; } @@ -10601,7 +10822,7 @@ grokdeclarator (const cp_declarator *declarator, && innermost_code != cdk_function && ! (ctype && !declspecs->any_specifiers_p)) { - error ("declaration of %qD as non-function", dname); + error_at (id_loc, "declaration of %qD as non-function", dname); return error_mark_node; } @@ -10610,7 +10831,7 @@ grokdeclarator (const cp_declarator *declarator, if (UDLIT_OPER_P (dname) && innermost_code != cdk_function) { - error ("declaration of %qD as non-function", dname); + error_at (id_loc, "declaration of %qD as non-function", dname); return error_mark_node; } @@ -10618,12 +10839,12 @@ grokdeclarator (const cp_declarator *declarator, { if (typedef_p) { - error ("declaration of %qD as %", dname); + error_at (id_loc, "declaration of %qD as %", dname); return error_mark_node; } else if (decl_context == PARM || decl_context == CATCHPARM) { - error ("declaration of %qD as parameter", dname); + error_at (id_loc, "declaration of %qD as parameter", dname); return error_mark_node; } } @@ -10669,17 +10890,39 @@ grokdeclarator (const cp_declarator *declarator, return error_mark_node; } + if (constinit_p && typedef_p) + { + error_at (declspecs->locations[ds_constinit], + "% cannot appear in a typedef declaration"); + return error_mark_node; + } + + /* [dcl.spec]/2 "At most one of the constexpr, consteval, and constinit + keywords shall appear in a decl-specifier-seq." */ + if (constinit_p && constexpr_p) + { + gcc_rich_location richloc (declspecs->locations[ds_constinit]); + richloc.add_range (declspecs->locations[ds_constexpr]); + error_at (&richloc, + "can use at most one of the % and % " + "specifiers"); + return error_mark_node; + } + /* If there were multiple types specified in the decl-specifier-seq, issue an error message. */ if (declspecs->multiple_types_p) { - error ("two or more data types in declaration of %qs", name); + error_at (typespec_loc, + "two or more data types in declaration of %qs", name); return error_mark_node; } if (declspecs->conflicting_specifiers_p) { - error ("conflicting specifiers in declaration of %qs", name); + error_at (min_location (declspecs->locations[ds_typedef], + declspecs->locations[ds_storage_class]), + "conflicting specifiers in declaration of %qs", name); return error_mark_node; } @@ -10693,6 +10936,7 @@ grokdeclarator (const cp_declarator *declarator, cp_warn_deprecated_use (type); if (type && TREE_CODE (type) == TYPE_DECL) { + cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (type)); typedef_decl = type; type = TREE_TYPE (typedef_decl); if (DECL_ARTIFICIAL (typedef_decl)) @@ -10763,13 +11007,14 @@ grokdeclarator (const cp_declarator *declarator, else if (in_system_header_at (input_location) || flag_ms_extensions) /* Allow it, sigh. */; else if (! is_main) - permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name); + permerror (id_loc, "ISO C++ forbids declaration of %qs with no type", + name); else if (pedantic) - pedwarn (input_location, OPT_Wpedantic, + pedwarn (id_loc, OPT_Wpedantic, "ISO C++ forbids declaration of %qs with no type", name); else - warning (OPT_Wreturn_type, - "ISO C++ forbids declaration of %qs with no type", name); + warning_at (id_loc, OPT_Wreturn_type, + "ISO C++ forbids declaration of %qs with no type", name); if (type_was_error_mark_node && template_parm_flag) /* FIXME we should be able to propagate the error_mark_node as is @@ -10785,12 +11030,15 @@ grokdeclarator (const cp_declarator *declarator, { 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); + error_at (declspecs->locations[ds_type_spec], + "%<__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, + /* Don't pedwarn if the alternate "__intN__" form has been used instead + of "__intN". */ + else if (!int_n_alt && pedantic && ! in_system_header_at (input_location)) + pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic, "ISO C++ does not support %<__int%d%> for %qs", int_n_data[declspecs->int_n_idx].bitsize, name); } @@ -10938,7 +11186,8 @@ grokdeclarator (const cp_declarator *declarator, if (decl_spec_seq_has_spec_p (declspecs, ds_complex)) { if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) - error ("complex invalid for %qs", name); + error_at (declspecs->locations[ds_complex], + "complex invalid for %qs", name); /* If a modifier is specified, the resulting complex is the complex form of TYPE. E.g, "complex short" is "complex short int". */ else if (type == integer_type_node) @@ -11053,6 +11302,12 @@ grokdeclarator (const cp_declarator *declarator, "a parameter cannot be declared %"); constexpr_p = 0; } + else if (constinit_p) + { + error_at (declspecs->locations[ds_constinit], + "a parameter cannot be declared %"); + constexpr_p = 0; + } } /* Give error if `virtual' is used outside of class declaration. */ @@ -11070,40 +11325,47 @@ grokdeclarator (const cp_declarator *declarator, ? declarator->declarator->id_loc : declarator->id_loc); if (inlinep) error_at (declspecs->locations[ds_inline], - "structured binding declaration cannot be %"); + "structured binding declaration cannot be %qs", "inline"); if (typedef_p) error_at (declspecs->locations[ds_typedef], - "structured binding declaration cannot be %"); + "structured binding declaration cannot be %qs", "typedef"); if (constexpr_p) error_at (declspecs->locations[ds_constexpr], "structured " - "binding declaration cannot be %"); - if (thread_p) - error_at (declspecs->locations[ds_thread], - "structured binding declaration cannot be %qs", - declspecs->gnu_thread_keyword_p - ? "__thread" : "thread_local"); + "binding declaration cannot be %qs", "constexpr"); + if (thread_p && cxx_dialect < cxx2a) + pedwarn (declspecs->locations[ds_thread], 0, + "structured binding declaration can be %qs only in " + "%<-std=c++2a%> or %<-std=gnu++2a%>", + declspecs->gnu_thread_keyword_p + ? "__thread" : "thread_local"); if (concept_p) error_at (declspecs->locations[ds_concept], - "structured binding declaration cannot be %"); + "structured binding declaration cannot be %qs", "concept"); + /* [dcl.struct.bind] "A cv that includes volatile is deprecated." */ + if (type_quals & TYPE_QUAL_VOLATILE) + warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile, + "%-qualified structured binding is deprecated"); switch (storage_class) { case sc_none: break; case sc_register: - error_at (loc, "structured binding declaration cannot be " - "%"); + error_at (loc, "structured binding declaration cannot be %qs", + "register"); break; case sc_static: - error_at (loc, "structured binding declaration cannot be " - "%"); + if (cxx_dialect < cxx2a) + pedwarn (loc, 0, + "structured binding declaration can be %qs only in " + "%<-std=c++2a%> or %<-std=gnu++2a%>", "static"); break; case sc_extern: - error_at (loc, "structured binding declaration cannot be " - "%"); + error_at (loc, "structured binding declaration cannot be %qs", + "extern"); break; case sc_mutable: - error_at (loc, "structured binding declaration cannot be " - "%"); + error_at (loc, "structured binding declaration cannot be %qs", + "mutable"); break; case sc_auto: error_at (loc, "structured binding declaration cannot be " @@ -11129,12 +11391,12 @@ grokdeclarator (const cp_declarator *declarator, 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; + if (storage_class != sc_static) + { + storage_class = sc_none; + declspecs->storage_class = sc_none; + } } /* Static anonymous unions are dealt with here. */ @@ -11151,7 +11413,10 @@ grokdeclarator (const cp_declarator *declarator, && storage_class != sc_static) || typedef_p)) { - error ("multiple storage classes in declaration of %qs", name); + location_t loc + = min_location (declspecs->locations[ds_thread], + declspecs->locations[ds_storage_class]); + error_at (loc, "multiple storage classes in declaration of %qs", name); thread_p = false; } if (decl_context != NORMAL @@ -11195,7 +11460,8 @@ grokdeclarator (const cp_declarator *declarator, else if (toplevel_bindings_p ()) { if (storage_class == sc_auto) - error ("top-level declaration of %qs specifies %", name); + error_at (declspecs->locations[ds_storage_class], + "top-level declaration of %qs specifies %", name); } else if (thread_p && storage_class != sc_extern @@ -11309,7 +11575,9 @@ grokdeclarator (const cp_declarator *declarator, type = create_array_type_for_decl (dname, type, declarator->u.array.bounds, declarator->id_loc); - if (!valid_array_size_p (input_location, type, dname)) + if (!valid_array_size_p (dname + ? declarator->id_loc : input_location, + type, dname)) type = error_mark_node; if (declarator->std_attributes) @@ -11328,9 +11596,10 @@ grokdeclarator (const cp_declarator *declarator, /* Declaring a function type. */ - input_location = declspecs->locations[ds_type_spec]; - abstract_virtuals_error (ACU_RETURN, type); - input_location = saved_loc; + { + iloc_sentinel ils (declspecs->locations[ds_type_spec]); + abstract_virtuals_error (ACU_RETURN, type); + } /* Pick up type qualifiers which should be applied to `this'. */ memfn_quals = declarator->u.function.qualifiers; @@ -11442,6 +11711,8 @@ grokdeclarator (const cp_declarator *declarator, else if (late_return_type && sfk != sfk_conversion) { + if (late_return_type == error_mark_node) + return error_mark_node; if (cxx_dialect < cxx11) /* Not using maybe_warn_cpp0x because this should always be an error. */ @@ -11470,6 +11741,13 @@ grokdeclarator (const cp_declarator *declarator, if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type)) warning_at (typespec_loc, OPT_Wignored_qualifiers, "type " "qualifiers ignored on function return type"); + /* [dcl.fct] "A volatile-qualified return type is + deprecated." */ + if (type_quals & TYPE_QUAL_VOLATILE) + warning_at (typespec_loc, OPT_Wvolatile, + "%-qualified return type is " + "deprecated"); + /* We now know that the TYPE_QUALS don't apply to the decl, but to its return type. */ type_quals = TYPE_UNQUALIFIED; @@ -11489,6 +11767,23 @@ grokdeclarator (const cp_declarator *declarator, "an array", name); return error_mark_node; } + if (constinit_p) + { + error_at (declspecs->locations[ds_constinit], + "% on function return type is not " + "allowed"); + return error_mark_node; + } + /* Only plain decltype(auto) is allowed. */ + if (tree a = type_uses_auto (type)) + { + if (AUTO_IS_DECLTYPE (a) && a != type) + { + error_at (typespec_loc, "%qT as type rather than " + "plain %", type); + return error_mark_node; + } + } if (ctype == NULL_TREE && decl_context == FIELD @@ -11513,9 +11808,12 @@ grokdeclarator (const cp_declarator *declarator, virtual. A constructor may not be static. A constructor may not be declared with ref-qualifier. */ if (staticp == 2) - error ((flags == DTOR_FLAG) - ? G_("destructor cannot be static member function") - : G_("constructor cannot be static member function")); + error_at (declspecs->locations[ds_storage_class], + (flags == DTOR_FLAG) + ? G_("destructor cannot be static member " + "function") + : G_("constructor cannot be static member " + "function")); if (memfn_quals) { error ((flags == DTOR_FLAG) @@ -11568,13 +11866,29 @@ grokdeclarator (const cp_declarator *declarator, friendp = 0; } if (decl_context == NORMAL) - error ("friend declaration not in class definition"); + error_at (declarator->id_loc, + "friend declaration not in class definition"); if (current_function_decl && funcdef_flag) { - error ("can%'t define friend function %qs in a local " - "class definition", name); + error_at (declarator->id_loc, + "cannot define friend function %qs in a local " + "class definition", name); friendp = 0; } + /* [class.friend]/6: A function can be defined in a friend + declaration if the function name is unqualified. */ + if (funcdef_flag && in_namespace) + { + if (in_namespace == global_namespace) + error_at (declarator->id_loc, + "friend function definition %qs cannot have " + "a name qualified with %<::%>", name); + else + error_at (declarator->id_loc, + "friend function definition %qs cannot have " + "a name qualified with %<%D::%>", name, + in_namespace); + } } else if (ctype && sfk == sfk_conversion) { @@ -11610,7 +11924,8 @@ grokdeclarator (const cp_declarator *declarator, && inner_declarator->u.id.sfk == sfk_destructor && arg_types != void_list_node) { - error ("destructors may not have parameters"); + error_at (declarator->id_loc, + "destructors may not have parameters"); arg_types = void_list_node; parms = NULL_TREE; } @@ -11826,6 +12141,8 @@ grokdeclarator (const cp_declarator *declarator, } } + id_loc = declarator ? declarator->id_loc : input_location; + /* A `constexpr' specifier used in an object declaration declares the object as `const'. */ if (constexpr_p && innermost_code != cdk_function) @@ -11869,13 +12186,13 @@ grokdeclarator (const cp_declarator *declarator, { if (friendp) { - permerror (input_location, "member functions are implicitly " - "friends of their class"); + permerror (declspecs->locations[ds_friend], + "member functions are implicitly " + "friends of their class"); friendp = 0; } else - permerror (declarator->id_loc, - "extra qualification %<%T::%> on member %qs", + permerror (id_loc, "extra qualification %<%T::%> on member %qs", ctype, name); } else if (/* If the qualifying type is already complete, then we @@ -11904,19 +12221,19 @@ grokdeclarator (const cp_declarator *declarator, if (current_class_type && (!friendp || funcdef_flag || initialized)) { - error (funcdef_flag || initialized - ? G_("cannot define member function %<%T::%s%> " - "within %qT") - : G_("cannot declare member function %<%T::%s%> " - "within %qT"), - ctype, name, current_class_type); + error_at (id_loc, funcdef_flag || initialized + ? G_("cannot define member function %<%T::%s%> " + "within %qT") + : G_("cannot declare member function %<%T::%s%> " + "within %qT"), + ctype, name, current_class_type); return error_mark_node; } } else if (typedef_p && current_class_type) { - error ("cannot declare member %<%T::%s%> within %qT", - ctype, name, current_class_type); + error_at (id_loc, "cannot declare member %<%T::%s%> within %qT", + ctype, name, current_class_type); return error_mark_node; } } @@ -11963,9 +12280,11 @@ grokdeclarator (const cp_declarator *declarator, && variably_modified_type_p (type, NULL_TREE)) { if (decl_context == FIELD) - error ("data member may not have variably modified type %qT", type); + error_at (id_loc, + "data member may not have variably modified type %qT", type); else - error ("parameter may not have variably modified type %qT", type); + error_at (id_loc, + "parameter may not have variably modified type %qT", type); type = error_mark_node; } @@ -12029,14 +12348,23 @@ grokdeclarator (const cp_declarator *declarator, } } - location_t loc = declarator ? declarator->id_loc : input_location; - /* If this is declaring a typedef name, return a TYPE_DECL. */ if (typedef_p && decl_context != TYPENAME) { bool alias_p = decl_spec_seq_has_spec_p (declspecs, ds_alias); tree decl; + if (funcdef_flag) + { + if (decl_context == NORMAL) + error_at (id_loc, + "typedef may not be a function definition"); + else + error_at (id_loc, + "typedef may not be a member function definition"); + return error_mark_node; + } + /* This declaration: typedef void f(int) const; @@ -12071,14 +12399,14 @@ grokdeclarator (const cp_declarator *declarator, if (id_declarator && declarator->u.id.qualifying_scope) { - error ("typedef name may not be a nested-name-specifier"); + error_at (id_loc, "typedef name may not be a nested-name-specifier"); type = error_mark_node; } if (decl_context == FIELD) - decl = build_lang_decl_loc (loc, TYPE_DECL, unqualified_id, type); + decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type); else - decl = build_decl (loc, TYPE_DECL, unqualified_id, type); + decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type); if (decl_context != FIELD) { @@ -12095,7 +12423,7 @@ grokdeclarator (const cp_declarator *declarator, } else if (current_class_type && constructor_name_p (unqualified_id, current_class_type)) - permerror (input_location, "ISO C++ forbids nested type %qD with same name " + permerror (id_loc, "ISO C++ forbids nested type %qD with same name " "as enclosing class", unqualified_id); @@ -12253,7 +12581,7 @@ grokdeclarator (const cp_declarator *declarator, /* Only functions may be declared using an operator-function-id. */ if (dname && IDENTIFIER_ANY_OP_P (dname)) { - error ("declaration of %qD as non-function", dname); + error_at (id_loc, "declaration of %qD as non-function", dname); return error_mark_node; } @@ -12267,7 +12595,7 @@ grokdeclarator (const cp_declarator *declarator, error message later. */ if (decl_context != PARM) { - type = check_var_type (unqualified_id, type); + type = check_var_type (unqualified_id, type, id_loc); if (type == error_mark_node) return error_mark_node; } @@ -12280,13 +12608,20 @@ grokdeclarator (const cp_declarator *declarator, if (ctype || in_namespace) error ("cannot use %<::%> in parameter declaration"); - if (type_uses_auto (type) - && !(cxx_dialect >= cxx17 && template_parm_flag)) + tree auto_node = type_uses_auto (type); + if (auto_node && !(cxx_dialect >= cxx17 && template_parm_flag)) { if (cxx_dialect >= cxx14) - error ("% parameter not permitted in this context"); + { + if (decl_context == PARM && AUTO_IS_DECLTYPE (auto_node)) + error_at (typespec_loc, + "cannot declare a parameter with %"); + else + error_at (typespec_loc, + "% parameter not permitted in this context"); + } else - error ("parameter declared %"); + error_at (typespec_loc, "parameter declared %"); type = error_mark_node; } @@ -12354,7 +12689,7 @@ grokdeclarator (const cp_declarator *declarator, && (TREE_CODE (ctype) == UNION_TYPE || TREE_CODE (ctype) == QUAL_UNION_TYPE)) { - error ("flexible array member in union"); + error_at (id_loc, "flexible array member in union"); type = error_mark_node; } else @@ -12363,8 +12698,8 @@ grokdeclarator (const cp_declarator *declarator, if (in_system_header_at (input_location)) /* Do not warn on flexible array members in system headers because glibc uses them. */; - else if (name && declarator) - pedwarn (declarator->id_loc, OPT_Wpedantic, + else if (name) + pedwarn (id_loc, OPT_Wpedantic, "ISO C++ forbids flexible array member %qs", name); else pedwarn (input_location, OPT_Wpedantic, @@ -12384,7 +12719,7 @@ grokdeclarator (const cp_declarator *declarator, else if (in_namespace && !friendp) { /* Something like struct S { int N::j; }; */ - error ("invalid use of %<::%>"); + error_at (id_loc, "invalid use of %<::%>"); return error_mark_node; } else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id) @@ -12439,15 +12774,15 @@ grokdeclarator (const cp_declarator *declarator, if (!ctype) { gcc_assert (friendp); - error ("expected qualified name in friend declaration " - "for destructor %qD", uqname); + error_at (id_loc, "expected qualified name in friend " + "declaration for destructor %qD", uqname); return error_mark_node; } if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0))) { - error ("declaration of %qD as member of %qT", - uqname, ctype); + error_at (id_loc, "declaration of %qD as member of %qT", + uqname, ctype); return error_mark_node; } if (concept_p) @@ -12456,12 +12791,13 @@ grokdeclarator (const cp_declarator *declarator, "a destructor cannot be %"); return error_mark_node; } - if (constexpr_p) - { - error_at (declspecs->locations[ds_constexpr], - "a destructor cannot be %"); - return error_mark_node; - } + if (constexpr_p && cxx_dialect < cxx2a) + { + error_at (declspecs->locations[ds_constexpr], + "% destructors only available" + " with %<-std=c++2a%> or %<-std=gnu++2a%>"); + return error_mark_node; + } } else if (sfk == sfk_constructor && friendp && !ctype) { @@ -12489,8 +12825,8 @@ grokdeclarator (const cp_declarator *declarator, tree tmpl = TREE_OPERAND (unqualified_id, 0); if (variable_template_p (tmpl)) { - error ("specialization of variable template %qD " - "declared as function", tmpl); + error_at (id_loc, "specialization of variable template " + "%qD declared as function", tmpl); inform (DECL_SOURCE_LOCATION (tmpl), "variable template declared here"); return error_mark_node; @@ -12498,10 +12834,11 @@ grokdeclarator (const cp_declarator *declarator, } /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ - function_context = (ctype != NULL_TREE) ? - decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE; - publicp = (! friendp || ! staticp) - && function_context == NULL_TREE; + function_context + = (ctype != NULL_TREE + ? decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE); + publicp = ((! friendp || ! staticp) + && function_context == NULL_TREE); decl = grokfndecl (ctype, type, TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR @@ -12516,7 +12853,7 @@ grokdeclarator (const cp_declarator *declarator, initialized == SD_DELETED, sfk, funcdef_flag, late_return_type_p, template_count, in_namespace, - attrlist, declarator->id_loc); + attrlist, id_loc); decl = set_virt_specifiers (decl, virt_specifiers); if (decl == NULL_TREE) return error_mark_node; @@ -12549,8 +12886,7 @@ grokdeclarator (const cp_declarator *declarator, { if (unqualified_id) { - error_at (declarator->id_loc, - "field %qD has incomplete type %qT", + error_at (id_loc, "field %qD has incomplete type %qT", unqualified_id, type); cxx_incomplete_type_inform (strip_array_types (type)); } @@ -12565,8 +12901,8 @@ grokdeclarator (const cp_declarator *declarator, { if (friendp) { - if (unqualified_id && declarator) - error_at (declarator->id_loc, + if (unqualified_id) + error_at (id_loc, "%qE is neither function nor member function; " "cannot be declared friend", unqualified_id); else @@ -12610,7 +12946,7 @@ grokdeclarator (const cp_declarator *declarator, { /* C++ allows static class members. All other work for this is done by grokfield. */ - decl = build_lang_decl_loc (loc, VAR_DECL, + decl = build_lang_decl_loc (id_loc, VAR_DECL, unqualified_id, type); set_linkage_for_static_data_member (decl); if (concept_p) @@ -12654,11 +12990,18 @@ grokdeclarator (const cp_declarator *declarator, else if (constexpr_p) { error_at (declspecs->locations[ds_constexpr], - "non-static data member %qE declared %", - unqualified_id); + "non-static data member %qE declared " + "%", unqualified_id); constexpr_p = false; } - decl = build_decl (loc, FIELD_DECL, unqualified_id, type); + else if (constinit_p) + { + error_at (declspecs->locations[ds_constinit], + "non-static data member %qE declared " + "%", unqualified_id); + constinit_p = false; + } + decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; if (bitfield && !unqualified_id) { @@ -12708,9 +13051,12 @@ grokdeclarator (const cp_declarator *declarator, // FIXME:gcc_assert (original_name == dname); if (storage_class == sc_auto) - error ("storage class % invalid for function %qs", name); + error_at (declspecs->locations[ds_storage_class], + "storage class % invalid for function %qs", name); else if (storage_class == sc_register) - error ("storage class % invalid for function %qs", name); + error_at (declspecs->locations[ds_storage_class], + "storage class % invalid for function %qs", + name); else if (thread_p) { if (declspecs->gnu_thread_keyword_p) @@ -12776,7 +13122,7 @@ grokdeclarator (const cp_declarator *declarator, funcdef_flag, late_return_type_p, template_count, in_namespace, attrlist, - declarator->id_loc); + id_loc); if (decl == NULL_TREE) return error_mark_node; @@ -12823,7 +13169,7 @@ grokdeclarator (const cp_declarator *declarator, concept_p, template_count, ctype ? ctype : in_namespace, - loc); + id_loc); if (decl == NULL_TREE) return error_mark_node; @@ -12869,7 +13215,7 @@ grokdeclarator (const cp_declarator *declarator, if (innermost_code == cdk_decomp) { gcc_assert (declarator && declarator->kind == cdk_decomp); - DECL_SOURCE_LOCATION (decl) = declarator->id_loc; + DECL_SOURCE_LOCATION (decl) = id_loc; DECL_ARTIFICIAL (decl) = 1; fit_decomposition_lang_decl (decl, NULL_TREE); } @@ -13010,8 +13356,8 @@ check_default_argument (tree decl, tree arg, tsubst_flags_t complain) tree var; tree decl_type; - if (TREE_CODE (arg) == DEFAULT_ARG) - /* We get a DEFAULT_ARG when looking at an in-class declaration + if (TREE_CODE (arg) == DEFERRED_PARSE) + /* We get a DEFERRED_PARSE when looking at an in-class declaration with a default argument. Ignore the argument for now; we'll deal with it after the class is complete. */ return arg; @@ -13046,7 +13392,9 @@ check_default_argument (tree decl, tree arg, tsubst_flags_t complain) /* Avoid redundant -Wzero-as-null-pointer-constant warnings at the call sites. */ if (TYPE_PTR_OR_PTRMEM_P (decl_type) - && null_ptr_cst_p (arg)) + && null_ptr_cst_p (arg) + /* Don't lose side-effects as in PR90473. */ + && !TREE_SIDE_EFFECTS (arg)) return nullptr_node; /* [dcl.fct.default] @@ -13087,7 +13435,10 @@ type_is_deprecated (tree type) if (TREE_DEPRECATED (TYPE_NAME (type))) return type; else - return NULL_TREE; + { + cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (TYPE_NAME (type))); + return NULL_TREE; + } } /* Do warn about using typedefs to a deprecated class. */ @@ -13171,6 +13522,13 @@ grokparms (tree parmlist, tree *parms) cp_warn_deprecated_use (deptype); } + /* [dcl.fct] "A parameter with volatile-qualified type is + deprecated." */ + if (CP_TYPE_VOLATILE_P (type)) + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wvolatile, + "%-qualified parameter is " + "deprecated"); + /* Top-level qualifiers on the parameters are ignored for function types. */ type = cp_build_qualified_type (type, 0); @@ -13391,15 +13749,11 @@ grok_special_member_properties (tree decl) are no other parameters or else all other parameters have default arguments. */ TYPE_HAS_COPY_CTOR (class_type) = 1; - if (user_provided_p (decl)) - TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 1; if (ctor > 1) TYPE_HAS_CONST_COPY_CTOR (class_type) = 1; } else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl))) TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1; - else if (move_fn_p (decl) && user_provided_p (decl)) - TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1; else if (is_list_ctor (decl)) TYPE_HAS_LIST_CTOR (class_type) = 1; @@ -13420,13 +13774,9 @@ grok_special_member_properties (tree decl) if (assop) { TYPE_HAS_COPY_ASSIGN (class_type) = 1; - if (user_provided_p (decl)) - TYPE_HAS_COMPLEX_COPY_ASSIGN (class_type) = 1; if (assop != 1) TYPE_HAS_CONST_COPY_ASSIGN (class_type) = 1; } - else if (move_fn_p (decl) && user_provided_p (decl)) - TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1; } else if (IDENTIFIER_CONV_OP_P (DECL_NAME (decl))) TYPE_HAS_CONVERSION (class_type) = true; @@ -13459,7 +13809,8 @@ grok_ctor_properties (const_tree ctype, const_tree decl) or implicitly defined), there's no need to worry about their existence. Theoretically, they should never even be instantiated, but that's hard to forestall. */ - error ("invalid constructor; you probably meant %<%T (const %T&)%>", + error_at (DECL_SOURCE_LOCATION (decl), + "invalid constructor; you probably meant %<%T (const %T&)%>", ctype, ctype); return false; } @@ -13551,10 +13902,13 @@ grok_op_properties (tree decl, bool complain) } if (op_flags & OVL_OP_FLAG_DELETE) - coerce_delete_type (decl, loc); + { + DECL_SET_IS_OPERATOR_DELETE (decl, true); + coerce_delete_type (decl, loc); + } else { - DECL_IS_OPERATOR_NEW (decl) = 1; + DECL_SET_IS_OPERATOR_NEW (decl, true); TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl), loc); } @@ -13614,7 +13968,7 @@ grok_op_properties (tree decl, bool complain) if (operator_code == COND_EXPR) { /* 13.4.0.3 */ - error_at (loc, "ISO C++ prohibits overloading operator ?:"); + error_at (loc, "ISO C++ prohibits overloading %"); return false; } @@ -14062,7 +14416,7 @@ xref_tag_1 (enum tag_types tag_code, tree name, /* In case of anonymous name, xref_tag is only called to make type node and push name. Name lookup is not required. */ tree t = NULL_TREE; - if (scope != ts_lambda && !anon_aggrname_p (name)) + if (scope != ts_lambda && !IDENTIFIER_ANON_P (name)) t = lookup_and_check_tag (tag_code, name, scope, template_header_p); if (t == error_mark_node) @@ -14724,7 +15078,7 @@ finish_enum_value_list (tree enumtype) if (TYPE_PRECISION (enumtype)) { if (precision > TYPE_PRECISION (enumtype)) - error ("specified mode too small for enumeral values"); + error ("specified mode too small for enumerated values"); else { use_short_enum = true; @@ -14799,11 +15153,8 @@ finish_enum_value_list (tree enumtype) type of the enumeration. */ for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values)) { - location_t saved_location; - decl = TREE_VALUE (values); - saved_location = input_location; - input_location = DECL_SOURCE_LOCATION (decl); + iloc_sentinel ils (DECL_SOURCE_LOCATION (decl)); if (fixed_underlying_type_p) /* If the enumeration type has a fixed underlying type, we already checked all of the enumerator values. */ @@ -14812,8 +15163,6 @@ finish_enum_value_list (tree enumtype) value = perform_implicit_conversion (underlying_type, DECL_INITIAL (decl), tf_warning_or_error); - input_location = saved_location; - /* Do not clobber shared ints. */ if (value != error_mark_node) { @@ -14920,8 +15269,9 @@ build_enumerator (tree name, tree value, tree enumtype, tree attributes, if (! INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))) { - error ("enumerator value for %qD must have integral or " - "unscoped enumeration type", name); + error_at (cp_expr_loc_or_input_loc (value), + "enumerator value for %qD must have integral or " + "unscoped enumeration type", name); value = NULL_TREE; } else @@ -15253,7 +15603,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) if (DECL_DECLARED_INLINE_P (decl1) && lookup_attribute ("noinline", attrs)) warning_at (DECL_SOURCE_LOCATION (decl1), 0, - "inline function %qD given attribute noinline", decl1); + "inline function %qD given attribute %qs", decl1, "noinline"); /* Handle gnu_inline attribute. */ if (GNU_INLINE_P (decl1)) @@ -15641,13 +15991,6 @@ start_function (cp_decl_specifier_seq *declspecs, invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1); if (decl1 == error_mark_node) return false; - /* If the declarator is not suitable for a function definition, - cause a syntax error. */ - if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) - { - error ("invalid function declaration"); - return false; - } if (DECL_MAIN_P (decl1)) /* main must return int. grokfndecl should have corrected it @@ -15682,6 +16025,39 @@ use_eh_spec_block (tree fn) && !DECL_DEFAULTED_FN (fn)); } +/* Helper function to push ARGS into the current lexical scope. DECL + is the function declaration. NONPARMS is used to handle enum + constants. */ + +void +do_push_parm_decls (tree decl, tree args, tree *nonparms) +{ + /* If we're doing semantic analysis, then we'll call pushdecl + for each of these. We must do them in reverse order so that + they end in the correct forward order. */ + args = nreverse (args); + + tree next; + for (tree parm = args; parm; parm = next) + { + next = DECL_CHAIN (parm); + if (TREE_CODE (parm) == PARM_DECL) + pushdecl (parm); + else if (nonparms) + { + /* If we find an enum constant or a type tag, put it aside for + the moment. */ + TREE_CHAIN (parm) = NULL_TREE; + *nonparms = chainon (*nonparms, parm); + } + } + + /* Get the decls in their original chain order and record in the + function. This is all and only the PARM_DECLs that were + pushed into scope by the loop above. */ + DECL_ARGUMENTS (decl) = get_local_decls (); +} + /* Store the parameter declarations into the current function declaration. This is called after parsing the parameter declarations, before digesting the body of the function. @@ -15692,7 +16068,6 @@ static void store_parm_decls (tree current_function_parms) { tree fndecl = current_function_decl; - tree parm; /* This is a chain of any other decls that came in among the parm declarations. If a parm is declared with enum {foo, bar} x; @@ -15707,35 +16082,12 @@ store_parm_decls (tree current_function_parms) and complain if any redundant old-style parm decls were written. */ tree specparms = current_function_parms; - tree next; /* Must clear this because it might contain TYPE_DECLs declared at class level. */ current_binding_level->names = NULL; - /* If we're doing semantic analysis, then we'll call pushdecl - for each of these. We must do them in reverse order so that - they end in the correct forward order. */ - specparms = nreverse (specparms); - - for (parm = specparms; parm; parm = next) - { - next = DECL_CHAIN (parm); - if (TREE_CODE (parm) == PARM_DECL) - pushdecl (parm); - else - { - /* If we find an enum constant or a type tag, - put it aside for the moment. */ - TREE_CHAIN (parm) = NULL_TREE; - nonparms = chainon (nonparms, parm); - } - } - - /* Get the decls in their original chain order and record in the - function. This is all and only the PARM_DECLs that were - pushed into scope by the loop above. */ - DECL_ARGUMENTS (fndecl) = get_local_decls (); + do_push_parm_decls (fndecl, specparms, &nonparms); } else DECL_ARGUMENTS (fndecl) = NULL_TREE; @@ -16081,8 +16433,17 @@ finish_function (bool inline_p) if (!processing_template_decl && FNDECL_USED_AUTO (fndecl) && TREE_TYPE (fntype) == DECL_SAVED_AUTO_RETURN_TYPE (fndecl)) { - if (is_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl))) + if (is_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl)) + && !current_function_returns_value + && !current_function_returns_null) { + /* We haven't applied return type deduction because we haven't + seen any return statements. Do that now. */ + tree node = type_uses_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl)); + do_auto_deduction (DECL_SAVED_AUTO_RETURN_TYPE (fndecl), + void_node, node, tf_warning_or_error, + adc_return_type); + apply_deduced_return_type (fndecl, void_type_node); fntype = TREE_TYPE (fndecl); } @@ -16182,6 +16543,7 @@ finish_function (bool inline_p) && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)) && global_dc->option_enabled (OPT_Wreturn_type, + global_dc->lang_mask, global_dc->option_state)) add_return_star_this_fixit (&richloc, fndecl); } @@ -16292,12 +16654,6 @@ grokmethod (cp_decl_specifier_seq *declspecs, if (fndecl == error_mark_node) return error_mark_node; - if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL) - { - error ("invalid member function declaration"); - return error_mark_node; - } - if (attrlist) cplus_decl_attributes (&fndecl, attrlist, 0); @@ -16492,6 +16848,9 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain) cleanup = error_mark_node; else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) /* Discard the call. */; + else if (decl_maybe_constant_destruction (decl, type) + && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + cxx_constant_dtor (call, decl); else if (cleanup) cleanup = cp_build_compound_expr (cleanup, call, complain); else @@ -16505,6 +16864,8 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain) the end of the block. So let's unset the location of the destructor call instead. */ protected_set_expr_location (cleanup, UNKNOWN_LOCATION); + if (cleanup && CONVERT_EXPR_P (cleanup)) + protected_set_expr_location (TREE_OPERAND (cleanup, 0), UNKNOWN_LOCATION); if (cleanup && DECL_P (decl) @@ -16573,20 +16934,20 @@ cp_tree_node_structure (union lang_tree_node * t) { switch (TREE_CODE (&t->generic)) { - case DEFAULT_ARG: return TS_CP_DEFAULT_ARG; + case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT; + case BASELINK: return TS_CP_BASELINK; + case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO; case DEFERRED_NOEXCEPT: return TS_CP_DEFERRED_NOEXCEPT; + case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE; case IDENTIFIER_NODE: return TS_CP_IDENTIFIER; + case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR; case OVERLOAD: return TS_CP_OVERLOAD; - case TEMPLATE_PARM_INDEX: return TS_CP_TPI; case PTRMEM_CST: return TS_CP_PTRMEM; - case BASELINK: return TS_CP_BASELINK; - case TEMPLATE_DECL: return TS_CP_TEMPLATE_DECL; case STATIC_ASSERT: return TS_CP_STATIC_ASSERT; - case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT; - case TRAIT_EXPR: return TS_CP_TRAIT_EXPR; - case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR; + case TEMPLATE_DECL: return TS_CP_TEMPLATE_DECL; case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO; - case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO; + case TEMPLATE_PARM_INDEX: return TS_CP_TPI; + case TRAIT_EXPR: return TS_CP_TRAIT_EXPR; case USERDEF_LITERAL: return TS_CP_USERDEF_LITERAL; default: return TS_CP_GENERIC; } @@ -16674,7 +17035,9 @@ require_deduced_type (tree decl, tsubst_flags_t complain) { if (undeduced_auto_decl (decl)) { - if (complain & tf_error) + if (TREE_NO_WARNING (decl) && seen_error ()) + /* We probably already complained about deduction failure. */; + else if (complain & tf_error) error ("use of %qD before deduction of %", decl); return false; }