X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Fdecl.c;h=5e510c91aa30c0c35afe49669a60895203f0719c;hb=606358faa6dbcebb271c1eb9b269a93374fba784;hp=e0d67328121e9c57a0171461c156f80289dde230;hpb=62dca3d53ee985e5fd69eb5e2611a8d157ea7bdc;p=gcc.git diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e0d67328121..5e510c91aa3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -920,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. @@ -999,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. */ @@ -1013,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 { @@ -1057,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; } @@ -1336,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. @@ -1644,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); @@ -1656,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; @@ -2916,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))) @@ -4146,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} }; @@ -4928,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 @@ -7006,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, @@ -7430,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; } @@ -7704,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) @@ -7946,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); @@ -8319,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 @@ -8436,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); @@ -8969,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); } @@ -9614,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); } @@ -9665,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; @@ -10523,7 +10606,6 @@ grokdeclarator (const cp_declarator *declarator, 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); @@ -10948,14 +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; } /* 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 (input_location, OPT_Wpedantic, + 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); } @@ -11330,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 @@ -11489,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) @@ -11508,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; @@ -12519,12 +12608,18 @@ 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_at (typespec_loc, - "% 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_at (typespec_loc, "parameter declared %"); type = error_mark_node; @@ -12696,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) { @@ -12729,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; @@ -12738,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 @@ -13712,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; } @@ -15055,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. */ @@ -15068,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) { @@ -16340,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); } @@ -16746,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 @@ -16759,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) @@ -16928,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; }