X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=gcc%2Fcp%2Fmangle.c;h=11eb8962d2848765e482fe5054e1f0e7c97bd243;hb=99dee82307f1e163e150c9c810452979994047ce;hp=59a3111fba249d8b84962c285b512fb444dea060;hpb=e4a148963e82ff2f34c794de0ad7ad3fa2e7b123;p=thirdparty%2Fgcc.git diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 59a3111fba24..11eb8962d284 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1,5 +1,5 @@ /* Name mangling for the 3.0 -*- C++ -*- ABI. - Copyright (C) 2000-2018 Free Software Foundation, Inc. + Copyright (C) 2000-2021 Free Software Foundation, Inc. Written by Alex Samuel This file is part of GCC. @@ -117,6 +117,9 @@ struct GTY(()) globals { /* True if the mangling will be different in C++17 mode. */ bool need_cxx17_warning; + + /* True if we mangled a module name. */ + bool mod; }; static GTY (()) globals G; @@ -170,7 +173,7 @@ integer_type_codes[itk_none] = '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; -static int decl_is_template_id (const tree, tree* const); +static tree maybe_template_info (const tree); /* Functions for handling substitutions. */ @@ -233,7 +236,6 @@ static void write_discriminator (const int); static void write_local_name (tree, const tree, const tree); static void dump_substitution_candidates (void); static tree mangle_decl_string (const tree); -static int local_class_index (tree); static void maybe_check_abi_tags (tree, tree = NULL_TREE, int = 10); static bool equal_abi_tags (tree, tree); @@ -273,11 +275,10 @@ static tree mangle_special_for_type (const tree, const char *); write_number ((NUMBER), /*unsigned_p=*/1, 10) /* If DECL is a template instance (including the uninstantiated template - itself), return nonzero and, if TEMPLATE_INFO is non-NULL, set - *TEMPLATE_INFO to its template info. Otherwise return zero. */ + itself), return its TEMPLATE_INFO. Otherwise return NULL. */ -static int -decl_is_template_id (const tree decl, tree* const template_info) +static tree +maybe_template_info (const tree decl) { if (TREE_CODE (decl) == TYPE_DECL) { @@ -286,33 +287,20 @@ decl_is_template_id (const tree decl, tree* const template_info) const tree type = TREE_TYPE (decl); if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type)) - { - if (template_info != NULL) - /* For a templated TYPE_DECL, the template info is hanging - off the type. */ - *template_info = TYPE_TEMPLATE_INFO (type); - return 1; - } + return TYPE_TEMPLATE_INFO (type); } else { - /* Check if this is a primary template. */ + /* Check if the template is a primary template. */ if (DECL_LANG_SPECIFIC (decl) != NULL && VAR_OR_FUNCTION_DECL_P (decl) && DECL_TEMPLATE_INFO (decl) - && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)) - && TREE_CODE (decl) != TEMPLATE_DECL) - { - if (template_info != NULL) - /* For most templated decls, the template info is hanging - off the decl. */ - *template_info = DECL_TEMPLATE_INFO (decl); - return 1; - } + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) + return DECL_TEMPLATE_INFO (decl); } /* It's not a template id. */ - return 0; + return NULL_TREE; } /* Produce debugging output of current substitution candidates. */ @@ -415,8 +403,7 @@ canonicalize_for_substitution (tree node) else node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node), cp_type_quals (node)); - if (TREE_CODE (node) == FUNCTION_TYPE - || TREE_CODE (node) == METHOD_TYPE) + if (FUNC_OR_METHOD_TYPE_P (node)) { node = build_ref_qualified_type (node, type_memfn_rqual (orig)); tree r = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (orig)); @@ -630,7 +617,7 @@ find_substitution (tree node) { tree args = CLASSTYPE_TI_ARGS (type); if (TREE_VEC_LENGTH (args) == 3 - && same_type_p (TREE_VEC_ELT (args, 0), char_type_node) + && template_args_equal (TREE_VEC_ELT (args, 0), char_type_node) && is_std_substitution_char (TREE_VEC_ELT (args, 1), SUBID_CHAR_TRAITS) && is_std_substitution_char (TREE_VEC_ELT (args, 2), @@ -654,8 +641,7 @@ find_substitution (tree node) args > . */ tree args = CLASSTYPE_TI_ARGS (type); if (TREE_VEC_LENGTH (args) == 2 - && TYPE_P (TREE_VEC_ELT (args, 0)) - && same_type_p (TREE_VEC_ELT (args, 0), char_type_node) + && template_args_equal (TREE_VEC_ELT (args, 0), char_type_node) && is_std_substitution_char (TREE_VEC_ELT (args, 1), SUBID_CHAR_TRAITS)) { @@ -800,7 +786,7 @@ mangle_return_type_p (tree decl) return (!DECL_CONSTRUCTOR_P (decl) && !DECL_DESTRUCTOR_P (decl) && !DECL_CONV_FN_P (decl) - && decl_is_template_id (decl, NULL)); + && maybe_template_info (decl)); } /* ::= @@ -827,9 +813,8 @@ write_encoding (const tree decl) { tree fn_type; tree d; - bool tmpl = decl_is_template_id (decl, NULL); - if (tmpl) + if (maybe_template_info (decl)) { fn_type = get_mostly_instantiated_function_type (decl); /* FN_TYPE will not have parameter types for in-charge or @@ -850,6 +835,62 @@ write_encoding (const tree decl) } } +/* Interface to substitution and identifer mangling, used by the + module name mangler. */ + +void +mangle_module_substitution (int v) +{ + if (v < 10) + { + write_char ('_'); + write_char ('0' + v); + } + else + { + write_char ('W'); + write_unsigned_number (v - 10); + write_char ('_'); + } +} + +void +mangle_identifier (char c, tree id) +{ + if (c) + write_char (c); + write_source_name (id); +} + +/* If the outermost non-namespace context (including DECL itself) is + a module-linkage decl, mangle the module information. For module + global initializers we need to include the partition part. + + ::= W + E + :: + || _ ;; short backref + || W _ ;; long backref + || P ;; partition introducer +*/ + +static void +write_module (int m, bool include_partition) +{ + G.mod = true; + + write_char ('W'); + mangle_module (m, include_partition); + write_char ('E'); +} + +static void +maybe_write_module (tree decl) +{ + int m = get_originating_module (decl, true); + if (m >= 0) + write_module (m, false); +} + /* Lambdas can have a bit more context for mangling, specifically VAR_DECL or PARM_DECL context, which doesn't belong in DECL_CONTEXT. */ @@ -875,7 +916,16 @@ decl_mangling_context (tree decl) else if (template_type_parameter_p (decl)) /* template type parms have no mangling context. */ return NULL_TREE; - return CP_DECL_CONTEXT (decl); + + tcontext = CP_DECL_CONTEXT (decl); + + /* Ignore the artificial declare reduction functions. */ + if (tcontext + && TREE_CODE (tcontext) == FUNCTION_DECL + && DECL_OMP_DECLARE_REDUCTION_P (tcontext)) + return decl_mangling_context (tcontext); + + return tcontext; } /* ::= @@ -903,6 +953,9 @@ write_name (tree decl, const int ignore_local_scope) decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); } + if (modules_p ()) + maybe_write_module (decl); + context = decl_mangling_context (decl); gcc_assert (context != NULL_TREE); @@ -924,13 +977,12 @@ write_name (tree decl, const int ignore_local_scope) || (abi_version_at_least (7) && TREE_CODE (context) == PARM_DECL)))) { - tree template_info; /* Is this a template instance? */ - if (decl_is_template_id (decl, &template_info)) + if (tree info = maybe_template_info (decl)) { /* Yes: use . */ - write_unscoped_template_name (TI_TEMPLATE (template_info)); - write_template_args (TI_ARGS (template_info)); + write_unscoped_template_name (TI_TEMPLATE (info)); + write_template_args (TI_ARGS (info)); } else /* Everything else gets an . */ @@ -1032,8 +1084,6 @@ write_unscoped_template_name (const tree decl) static void write_nested_name (const tree decl) { - tree template_info; - MANGLE_TRACE_TREE ("nested-name", decl); write_char ('N'); @@ -1056,11 +1106,11 @@ write_nested_name (const tree decl) } /* Is this a template instance? */ - if (decl_is_template_id (decl, &template_info)) + if (tree info = maybe_template_info (decl)) { /* Yes, use . */ write_template_prefix (decl); - write_template_args (TI_ARGS (template_info)); + write_template_args (TI_ARGS (info)); } else if ((!abi_version_at_least (10) || TREE_CODE (decl) == TYPE_DECL) && TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE) @@ -1097,8 +1147,6 @@ static void write_prefix (const tree node) { tree decl; - /* Non-NULL if NODE represents a template-id. */ - tree template_info = NULL; if (node == NULL || node == global_namespace) @@ -1115,6 +1163,7 @@ write_prefix (const tree node) if (find_substitution (node)) return; + tree template_info = NULL_TREE; if (DECL_P (node)) { /* If this is a function or parm decl, that means we've hit function @@ -1127,19 +1176,20 @@ write_prefix (const tree node) return; decl = node; - decl_is_template_id (decl, &template_info); + template_info = maybe_template_info (decl); } else { /* Node is a type. */ decl = TYPE_NAME (node); + /* The DECL might not point at the node. */ if (CLASSTYPE_TEMPLATE_ID_P (node)) template_info = TYPE_TEMPLATE_INFO (node); } if (TREE_CODE (node) == TEMPLATE_TYPE_PARM) write_template_param (node); - else if (template_info != NULL) + else if (template_info) /* Templated. */ { write_template_prefix (decl); @@ -1186,15 +1236,14 @@ write_template_prefix (const tree node) tree decl = DECL_P (node) ? node : TYPE_NAME (node); tree type = DECL_P (node) ? TREE_TYPE (node) : node; tree context = decl_mangling_context (decl); - tree template_info; tree templ; tree substitution; MANGLE_TRACE_TREE ("template-prefix", node); /* Find the template decl. */ - if (decl_is_template_id (decl, &template_info)) - templ = TI_TEMPLATE (template_info); + if (tree info = maybe_template_info (decl)) + templ = TI_TEMPLATE (info); else if (TREE_CODE (type) == TYPENAME_TYPE) /* For a typename type, all we have is the name. */ templ = DECL_NAME (decl); @@ -1360,15 +1409,14 @@ write_unqualified_name (tree decl) /* Conversion operator. Handle it right here. ::= cv */ tree type; - if (decl_is_template_id (decl, NULL)) + if (maybe_template_info (decl)) { tree fn_type; fn_type = get_mostly_instantiated_function_type (decl); type = TREE_TYPE (fn_type); } else if (FNDECL_USED_AUTO (decl)) - type = (DECL_STRUCT_FUNCTION (decl)->language - ->x_auto_return_pattern); + type = DECL_SAVED_AUTO_RETURN_TYPE (decl); else type = DECL_CONV_FN_TYPE (decl); write_conversion_operator_name (type); @@ -1405,8 +1453,7 @@ write_unqualified_name (tree decl) if (TREE_CODE (decl) == TYPE_DECL && TYPE_UNNAMED_P (type)) write_unnamed_type_name (type); - else if (TREE_CODE (decl) == TYPE_DECL - && LAMBDA_TYPE_P (type)) + else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (type)) write_closure_type_name (type); else write_source_name (DECL_NAME (decl)); @@ -1546,30 +1593,6 @@ write_abi_tags (tree tags) release_tree_vector (vec); } -/* Simplified unique_ptr clone to release a tree vec on exit. */ - -struct releasing_vec -{ - typedef vec vec_t; - - releasing_vec (vec_t *v): v(v) { } - releasing_vec (): v(make_tree_vector ()) { } - - /* Copy constructor is deliberately declared but not defined, - copies must always be elided. */ - releasing_vec (const releasing_vec &); - - vec_t &operator* () const { return *v; } - vec_t *operator-> () const { return v; } - vec_t *get () const { return v; } - operator vec_t *() const { return v; } - tree& operator[] (unsigned i) const { return (*v)[i]; } - - ~releasing_vec() { release_tree_vector (v); } -private: - vec_t *v; -}; - /* True iff the TREE_LISTS T1 and T2 of ABI tags are equivalent. */ static bool @@ -1642,7 +1665,7 @@ write_unnamed_type_name (const tree type) MANGLE_TRACE_TREE ("unnamed-type-name", type); if (TYPE_FUNCTION_SCOPE_P (type)) - discriminator = local_class_index (type); + discriminator = discriminator_for_local_entity (TYPE_NAME (type)); else if (TYPE_CLASS_SCOPE_P (type)) discriminator = nested_anon_class_index (type); else @@ -1913,58 +1936,25 @@ write_special_name_destructor (const tree dtor) } } -/* Scan the vector of local classes and return how many others with the - same name (or same no name) and context precede ENTITY. */ - -static int -local_class_index (tree entity) -{ - int ix, discriminator = 0; - tree name = (TYPE_UNNAMED_P (entity) ? NULL_TREE - : TYPE_IDENTIFIER (entity)); - tree ctx = TYPE_CONTEXT (entity); - for (ix = 0; ; ix++) - { - tree type = (*local_classes)[ix]; - if (type == entity) - return discriminator; - if (TYPE_CONTEXT (type) == ctx - && (name ? TYPE_IDENTIFIER (type) == name - : TYPE_UNNAMED_P (type))) - ++discriminator; - } - gcc_unreachable (); -} - /* Return the discriminator for ENTITY appearing inside - FUNCTION. The discriminator is the lexical ordinal of VAR among - entities with the same name in the same FUNCTION. */ + FUNCTION. The discriminator is the lexical ordinal of VAR or TYPE among + entities with the same name and kind in the same FUNCTION. */ static int discriminator_for_local_entity (tree entity) { - if (DECL_DISCRIMINATOR_P (entity)) + if (!DECL_LANG_SPECIFIC (entity)) { - if (DECL_DISCRIMINATOR_SET_P (entity)) - return DECL_DISCRIMINATOR (entity); - else - /* The first entity with a particular name doesn't get - DECL_DISCRIMINATOR set up. */ - return 0; - } - else if (TREE_CODE (entity) == TYPE_DECL) - { - /* Scan the list of local classes. */ - entity = TREE_TYPE (entity); - - /* Lambdas and unnamed types have their own discriminators. */ - if (LAMBDA_TYPE_P (entity) || TYPE_UNNAMED_P (entity)) - return 0; - - return local_class_index (entity); + /* Some decls, like __FUNCTION__, don't need a discriminator. */ + gcc_checking_assert (DECL_ARTIFICIAL (entity)); + return 0; } + else if (tree disc = DECL_DISCRIMINATOR (entity)) + return TREE_INT_CST_LOW (disc); else - gcc_unreachable (); + /* The first entity with a particular name doesn't get + DECL_DISCRIMINATOR set up. */ + return 0; } /* Return the discriminator for STRING, a string literal used inside @@ -2062,7 +2052,10 @@ write_local_name (tree function, const tree local_entity, from , so it doesn't try to process the enclosing function scope again. */ write_name (entity, /*ignore_local_scope=*/1); - write_discriminator (discriminator_for_local_entity (local_entity)); + if (DECL_DISCRIMINATOR_P (local_entity) + && !(TREE_CODE (local_entity) == TYPE_DECL + && TYPE_ANON_P (TREE_TYPE (local_entity)))) + write_discriminator (discriminator_for_local_entity (local_entity)); } } @@ -2125,8 +2118,7 @@ write_type (tree type) t = cp_build_type_attribute_variant (t, attrs); } gcc_assert (t != type); - if (TREE_CODE (t) == FUNCTION_TYPE - || TREE_CODE (t) == METHOD_TYPE) + if (FUNC_OR_METHOD_TYPE_P (t)) { t = build_ref_qualified_type (t, type_memfn_rqual (type)); if (flag_noexcept_type) @@ -2157,8 +2149,7 @@ write_type (tree type) /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); - if (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE) + if (FUNC_OR_METHOD_TYPE_P (type)) type = cxx_copy_lang_qualifiers (type, type_orig); /* According to the C++ ABI, some library classes are passed the @@ -2363,11 +2354,11 @@ write_type (tree type) break; case TYPEOF_TYPE: - sorry ("mangling typeof, use decltype instead"); + sorry ("mangling %, use % instead"); break; case UNDERLYING_TYPE: - sorry ("mangling __underlying_type"); + sorry ("mangling %<__underlying_type%>"); break; case LANG_TYPE: @@ -2398,6 +2389,34 @@ attr_strcmp (const void *p1, const void *p2) return strcmp (as1->name, as2->name); } +/* Return true if we should mangle a type attribute with name NAME. */ + +static bool +mangle_type_attribute_p (tree name) +{ + const attribute_spec *as = lookup_attribute_spec (name); + if (!as || !as->affects_type_identity) + return false; + + /* Skip internal-only attributes, which are distinguished from others + by having a space. At present, all internal-only attributes that + affect type identity are target-specific and are handled by + targetm.mangle_type instead. + + Another reason to do this is that a space isn't a valid identifier + character for most file formats. */ + if (strchr (IDENTIFIER_POINTER (name), ' ')) + return false; + + /* The following attributes are mangled specially. */ + if (is_attribute_p ("transaction_safe", name)) + return false; + if (is_attribute_p ("abi_tag", name)) + return false; + + return true; +} + /* Non-terminal for type nodes. Returns the number of CV-qualifiers written for TYPE. @@ -2423,14 +2442,8 @@ write_CV_qualifiers_for_type (const tree type) { auto_vec vec; for (tree a = TYPE_ATTRIBUTES (type); a; a = TREE_CHAIN (a)) - { - tree name = get_attribute_name (a); - const attribute_spec *as = lookup_attribute_spec (name); - if (as && as->affects_type_identity - && !is_attribute_p ("transaction_safe", name) - && !is_attribute_p ("abi_tag", name)) - vec.safe_push (a); - } + if (mangle_type_attribute_p (get_attribute_name (a))) + vec.safe_push (a); if (abi_warn_or_compat_version_crosses (10) && !vec.is_empty ()) G.need_abi_warning = true; if (abi_version_at_least (10)) @@ -2527,10 +2540,12 @@ write_builtin_type (tree type) break; case INTEGER_TYPE: - /* TYPE may still be wchar_t, char16_t, or char32_t, since that + /* TYPE may still be wchar_t, char8_t, char16_t, or char32_t, since that isn't in integer_type_nodes. */ if (type == wchar_type_node) write_char ('w'); + else if (type == char8_type_node) + write_string ("Du"); else if (type == char16_type_node) write_string ("Ds"); else if (type == char32_type_node) @@ -2595,11 +2610,11 @@ write_builtin_type (tree type) write_char ('d'); else if (type == long_double_type_node) write_char ('e'); - else if (type == dfloat32_type_node) + else if (type == dfloat32_type_node || type == fallback_dfloat32_type) write_string ("Df"); - else if (type == dfloat64_type_node) + else if (type == dfloat64_type_node || type == fallback_dfloat64_type) write_string ("Dd"); - else if (type == dfloat128_type_node) + else if (type == dfloat128_type_node || type == fallback_dfloat128_type) write_string ("De"); else gcc_unreachable (); @@ -2862,7 +2877,10 @@ write_member_name (tree member) write_unqualified_id (member); } else if (DECL_P (member)) - write_unqualified_name (member); + { + gcc_assert (!DECL_OVERLOADED_OPERATOR_P (member)); + write_unqualified_name (member); + } else if (TREE_CODE (member) == TEMPLATE_ID_EXPR) { tree name = TREE_OPERAND (member, 0); @@ -2874,6 +2892,60 @@ write_member_name (tree member) write_expression (member); } +/* EXPR is a base COMPONENT_REF; write the minimized base conversion path for + converting to BASE, or just the conversion of EXPR if BASE is null. + + "Given a fully explicit base path P := C_n -> ... -> C_0, the minimized base + path Min(P) is defined as follows: let C_i be the last element for which the + conversion to C_0 is unambiguous; if that element is C_n, the minimized path + is C_n -> C_0; otherwise, the minimized path is Min(C_n -> ... -> C_i) -> + C_0." + + We mangle the conversion to C_i if it's different from C_n. */ + +static bool +write_base_ref (tree expr, tree base = NULL_TREE) +{ + if (TREE_CODE (expr) != COMPONENT_REF) + return false; + + tree field = TREE_OPERAND (expr, 1); + + if (TREE_CODE (field) != FIELD_DECL || !DECL_FIELD_IS_BASE (field)) + return false; + + tree object = TREE_OPERAND (expr, 0); + + tree binfo = NULL_TREE; + if (base) + { + tree cur = TREE_TYPE (object); + binfo = lookup_base (cur, base, ba_unique, NULL, tf_none); + } + else + /* We're at the end of the base conversion chain, so it can't be + ambiguous. */ + base = TREE_TYPE (field); + + if (binfo == error_mark_node) + { + /* cur->base is ambiguous, so make the conversion to + last explicit, expressed as a cast (last&)object. */ + tree last = TREE_TYPE (expr); + write_string (OVL_OP_INFO (false, CAST_EXPR)->mangled_name); + write_type (build_reference_type (last)); + write_expression (object); + } + else if (write_base_ref (object, base)) + /* cur->base is unambiguous, but we had another base conversion + underneath and wrote it out. */; + else + /* No more base conversions, just write out the object. */ + write_expression (object); + + return true; +} + /* ::= ::= ::= @@ -2890,13 +2962,22 @@ write_expression (tree expr) { enum tree_code code = TREE_CODE (expr); + if (TREE_CODE (expr) == TARGET_EXPR) + { + expr = TARGET_EXPR_INITIAL (expr); + code = TREE_CODE (expr); + } + /* Skip NOP_EXPR and CONVERT_EXPR. They can occur when (say) a pointer argument is converted (via qualification conversions) to another type. */ while (CONVERT_EXPR_CODE_P (code) + || code == IMPLICIT_CONV_EXPR || location_wrapper_p (expr) /* Parentheses aren't mangled. */ || code == PAREN_EXPR - || code == NON_LVALUE_EXPR) + || code == NON_LVALUE_EXPR + || (code == VIEW_CONVERT_EXPR + && TREE_CODE (TREE_OPERAND (expr, 0)) == TEMPLATE_PARM_INDEX)) { expr = TREE_OPERAND (expr, 0); code = TREE_CODE (expr); @@ -3033,11 +3114,30 @@ write_expression (tree expr) else goto normal_expr; } - else if (TREE_CODE (expr) == ALIGNOF_EXPR - && TYPE_P (TREE_OPERAND (expr, 0))) + else if (TREE_CODE (expr) == ALIGNOF_EXPR) { - write_string ("at"); - write_type (TREE_OPERAND (expr, 0)); + if (!ALIGNOF_EXPR_STD_P (expr)) + { + if (abi_warn_or_compat_version_crosses (15)) + G.need_abi_warning = true; + if (abi_version_at_least (15)) + { + /* We used to mangle __alignof__ like alignof. */ + write_string ("v111__alignof__"); + if (TYPE_P (TREE_OPERAND (expr, 0))) + write_type (TREE_OPERAND (expr, 0)); + else + write_expression (TREE_OPERAND (expr, 0)); + return; + } + } + if (TYPE_P (TREE_OPERAND (expr, 0))) + { + write_string ("at"); + write_type (TREE_OPERAND (expr, 0)); + } + else + goto normal_expr; } else if (code == SCOPE_REF || code == BASELINK) @@ -3047,7 +3147,8 @@ write_expression (tree expr) { scope = TREE_OPERAND (expr, 0); member = TREE_OPERAND (expr, 1); - gcc_assert (!BASELINK_P (member)); + if (BASELINK_P (member)) + member = BASELINK_FUNCTIONS (member); } else { @@ -3064,6 +3165,7 @@ write_expression (tree expr) write_expression (member); else { + gcc_assert (code != BASELINK || BASELINK_QUALIFIED_P (expr)); write_string ("sr"); write_type (scope); write_member_name (member); @@ -3179,23 +3281,76 @@ write_expression (tree expr) } else if (code == CONSTRUCTOR) { - vec *elts = CONSTRUCTOR_ELTS (expr); - unsigned i; tree val; + bool braced_init = BRACE_ENCLOSED_INITIALIZER_P (expr); + tree etype = TREE_TYPE (expr); - if (BRACE_ENCLOSED_INITIALIZER_P (expr)) + if (braced_init) write_string ("il"); else { write_string ("tl"); - write_type (TREE_TYPE (expr)); + write_type (etype); + } + + bool nontriv = !trivial_type_p (etype); + if (nontriv || !zero_init_expr_p (expr)) + { + /* Convert braced initializer lists to STRING_CSTs so that + A<"Foo"> mangles the same as A<{'F', 'o', 'o', 0}> while + still using the latter mangling for strings that + originated as braced initializer lists. */ + expr = braced_lists_to_strings (etype, expr); + + if (TREE_CODE (expr) == CONSTRUCTOR) + { + vec *elts = CONSTRUCTOR_ELTS (expr); + unsigned last_nonzero = UINT_MAX, i; + constructor_elt *ce; + tree val; + + if (!nontriv) + FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) + if (!zero_init_expr_p (val)) + last_nonzero = i; + + if (nontriv || last_nonzero != UINT_MAX) + for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i) + { + if (i > last_nonzero) + break; + /* FIXME handle RANGE_EXPR */ + if (TREE_CODE (etype) == UNION_TYPE) + { + /* Express the active member as a designator. */ + write_string ("di"); + write_unqualified_name (ce->index); + } + write_expression (ce->value); + } + } + else + { + gcc_assert (TREE_CODE (expr) == STRING_CST); + write_expression (expr); + } } - FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) - write_expression (val); + write_char ('E'); + } + else if (code == LAMBDA_EXPR) + { + /* [temp.over.link] Two lambda-expressions are never considered + equivalent. + + So just use the closure type mangling. */ + write_string ("tl"); + write_type (LAMBDA_EXPR_CLOSURE (expr)); write_char ('E'); } else if (dependent_name (expr)) { - write_unqualified_id (dependent_name (expr)); + tree name = dependent_name (expr); + gcc_assert (!IDENTIFIER_ANY_OP_P (name)); + write_unqualified_id (name); } else { @@ -3231,6 +3386,8 @@ write_expression (tree expr) ob = TREE_OPERAND (ob, 0); write_expression (ob); } + else if (write_base_ref (expr)) + return; else if (!is_dummy_object (ob)) { write_string ("dt"); @@ -3285,8 +3442,7 @@ write_expression (tree expr) /* Mangle a dependent name as the name, not whatever happens to be the first function in the overload set. */ - if ((TREE_CODE (fn) == FUNCTION_DECL - || TREE_CODE (fn) == OVERLOAD) + if (OVL_P (fn) && type_dependent_expression_p_push (expr)) fn = OVL_NAME (fn); @@ -3386,8 +3542,14 @@ write_expression (tree expr) static void write_template_arg_literal (const tree value) { - write_char ('L'); - write_type (TREE_TYPE (value)); + if (TREE_CODE (value) == STRING_CST) + /* Temporarily mangle strings as braced initializer lists. */ + write_string ("tl"); + else + write_char ('L'); + + tree valtype = TREE_TYPE (value); + write_type (valtype); /* Write a null member pointer value as (type)0, regardless of its real representation. */ @@ -3403,7 +3565,9 @@ write_template_arg_literal (const tree value) case INTEGER_CST: gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node) || integer_zerop (value) || integer_onep (value)); - write_integer_cst (value); + if (!(abi_version_at_least (14) + && NULLPTR_TYPE_P (TREE_TYPE (value)))) + write_integer_cst (value); break; case REAL_CST: @@ -3430,8 +3594,31 @@ write_template_arg_literal (const tree value) break; case STRING_CST: - sorry ("string literal in function template signature"); - break; + { + /* Mangle strings the same as braced initializer lists. */ + unsigned n = TREE_STRING_LENGTH (value); + const char *str = TREE_STRING_POINTER (value); + + /* Count the number of trailing nuls and subtract them from + STRSIZE because they don't need to be mangled. */ + for (const char *p = str + n - 1; ; --p) + { + if (*p || p == str) + { + n -= str + n - !!*p - p; + break; + } + } + tree eltype = TREE_TYPE (valtype); + for (const char *p = str; n--; ++p) + { + write_char ('L'); + write_type (eltype); + write_unsigned_number (*(const unsigned char*)p); + write_string ("E"); + } + break; + } default: gcc_unreachable (); @@ -3467,6 +3654,10 @@ write_template_arg (tree node) } } + if (template_parm_object_p (node)) + /* We want to mangle the argument, not the var we stored it in. */ + node = tparm_object_argument (node); + /* Strip a conversion added by convert_nontype_argument. */ if (TREE_CODE (node) == IMPLICIT_CONV_EXPR) node = TREE_OPERAND (node, 0); @@ -3702,14 +3893,13 @@ start_mangling (const tree entity) G.entity = entity; G.need_abi_warning = false; G.need_cxx17_warning = false; + G.mod = false; obstack_free (&name_obstack, name_base); mangle_obstack = &name_obstack; name_base = obstack_alloc (&name_obstack, 0); } -/* Done with mangling. If WARN is true, and the name of G.entity will - be mangled differently in a future version of the ABI, issue a - warning. */ +/* Done with mangling. Release the data. */ static void finish_mangling_internal (void) @@ -3717,6 +3907,9 @@ finish_mangling_internal (void) /* Clear all the substitutions. */ vec_safe_truncate (G.substitutions, 0); + if (G.mod) + mangle_module_fini (); + /* Null-terminate the string. */ write_char ('\0'); } @@ -3761,13 +3954,26 @@ init_mangle (void) subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream"); } +/* Generate a mangling for MODULE's global initializer fn. */ + +tree +mangle_module_global_init (int module) +{ + start_mangling (NULL_TREE); + + write_string ("_ZGI"); + write_module (module, true); + write_char ('v'); + + return finish_mangling_get_identifier (); +} + /* Generate the mangled name of DECL. */ static tree mangle_decl_string (const tree decl) { tree result; - location_t saved_loc = input_location; tree saved_fn = NULL_TREE; bool template_p = false; @@ -3785,7 +3991,7 @@ mangle_decl_string (const tree decl) current_function_decl = NULL_TREE; } } - input_location = DECL_SOURCE_LOCATION (decl); + iloc_sentinel ils (DECL_SOURCE_LOCATION (decl)); start_mangling (decl); @@ -3804,7 +4010,6 @@ mangle_decl_string (const tree decl) pop_tinst_level (); current_function_decl = saved_fn; } - input_location = saved_loc; return result; } @@ -4184,18 +4389,18 @@ maybe_check_abi_tags (tree t, tree for_decl, int ver) if (for_decl && DECL_THUNK_P (for_decl)) warning_at (DECL_SOURCE_LOCATION (t), OPT_Wabi, "the mangled name of a thunk for %qD changes between " - "-fabi-version=%d and -fabi-version=%d", + "%<-fabi-version=%d%> and %<-fabi-version=%d%>", t, flag_abi_version, warn_abi_version); else if (for_decl) warning_at (DECL_SOURCE_LOCATION (for_decl), OPT_Wabi, "the mangled name of %qD changes between " - "-fabi-version=%d and -fabi-version=%d", + "%<-fabi-version=%d%> and %<-fabi-version=%d%>", for_decl, flag_abi_version, warn_abi_version); else warning_at (DECL_SOURCE_LOCATION (t), OPT_Wabi, "the mangled name of the initialization guard variable " - "for %qD changes between -fabi-version=%d and " - "-fabi-version=%d", + "for %qD changes between %<-fabi-version=%d%> and " + "%<-fabi-version=%d%>", t, flag_abi_version, warn_abi_version); } } @@ -4270,10 +4475,7 @@ decl_tls_wrapper_p (const tree fn) } /* Return an identifier for the name of a temporary variable used to - initialize a static reference. This isn't part of the ABI, but we might - as well call them something readable. */ - -static GTY(()) int temp_count; + initialize a static reference. This is now part of the ABI. */ tree mangle_ref_init_variable (const tree variable) @@ -4284,7 +4486,20 @@ mangle_ref_init_variable (const tree variable) write_name (variable, /*ignore_local_scope=*/0); /* Avoid name clashes with aggregate initialization of multiple references at once. */ - write_unsigned_number (temp_count++); + write_compact_number (current_ref_temp_count++); + return finish_mangling_get_identifier (); +} + +/* Return an identifier for the mangled name of a C++20 template parameter + object for template argument EXPR. */ + +tree +mangle_template_parm_object (tree expr) +{ + start_mangling (expr); + write_string ("_ZTAX"); + write_expression (expr); + write_char ('E'); return finish_mangling_get_identifier (); }