From 603eaec49a32f4b409ca8c22e71e6f683c799758 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 1 Jun 2015 22:28:19 -0400 Subject: [PATCH] re PR c++/44282 (fastcall is not mangled at all) PR c++/44282 gcc/cp/ * mangle.c (attr_strcmp): New. (write_CV_qualifiers_for_type): Also write out attributes that affect type identity. (write_type): Strip all attributes after writing qualifiers. libiberty/ * cp-demangle.c (cplus_demangle_type): Handle arguments to vendor extended qualifier. From-SVN: r224007 --- gcc/c-family/c-opts.c | 2 +- gcc/common.opt | 7 ++- gcc/cp/ChangeLog | 8 +++ gcc/cp/mangle.c | 71 ++++++++++++++++++++++- gcc/testsuite/g++.dg/abi/macro0.C | 2 +- gcc/testsuite/g++.dg/abi/mangle-regparm.C | 29 +++++++++ libiberty/ChangeLog | 5 ++ libiberty/cp-demangle.c | 3 + libiberty/testsuite/demangle-expected | 3 + 9 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/mangle-regparm.C diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index fe5fce78597..8996fe3a9e6 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -894,7 +894,7 @@ c_common_post_options (const char **pfilename) /* Change flag_abi_version to be the actual current ABI level for the benefit of c_cpp_builtins. */ if (flag_abi_version == 0) - flag_abi_version = 8; + flag_abi_version = 9; /* Set C++ standard to C++98 if not specified on the command line. */ if (c_dialect_cxx () && cxx_dialect == cxx_unset) diff --git a/gcc/common.opt b/gcc/common.opt index 6e15af2e189..32b416a324f 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -836,8 +836,11 @@ Driver Undocumented ; ; 8: The version of the ABI that corrects the substitution behavior of ; function types with function-cv-qualifiers. -; First selectable in G++ 4.9 and default in G++ 5 -; (set in c_common_post_options). +; First selectable in G++ 4.9 and default in G++ 5. +; +; 9: The version of the ABI that mangles attributes that affect type +; identity, such as ia32 calling convention attributes (stdcall, etc.) +; Default in G++ 6 (set in c_common_post_options). ; ; Additional positive integers will be assigned as new versions of ; the ABI become the default version of the ABI. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 467449c5fbd..78d779133a6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2015-06-01 Jason Merrill + + PR c++/44282 + * mangle.c (attr_strcmp): New. + (write_CV_qualifiers_for_type): Also write out attributes that + affect type identity. + (write_type): Strip all attributes after writing qualifiers. + 2015-05-31 Jason Merrill * constexpr.c (cxx_eval_indirect_ref): Try folding first. diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index aa466cdd0fe..8fd06e3c2cd 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -75,6 +75,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-ref.h" #include "cgraph.h" #include "wide-int.h" +#include "attribs.h" /* Debugging support. */ @@ -1916,11 +1917,15 @@ write_type (tree type) candidates. */ { tree t = TYPE_MAIN_VARIANT (type); + if (TYPE_ATTRIBUTES (t) && !OVERLOAD_TYPE_P (t)) + t = cp_build_type_attribute_variant (t, NULL_TREE); + gcc_assert (t != type); if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE) { t = build_ref_qualified_type (t, type_memfn_rqual (type)); - if (abi_version_at_least (8)) + if (abi_version_at_least (8) + || type == TYPE_MAIN_VARIANT (type)) /* Avoid adding the unqualified function type as a substitution. */ write_function_type (t); else @@ -2168,6 +2173,20 @@ write_type (tree type) add_substitution (type); } +/* qsort callback for sorting a vector of attribute entries. */ + +static int +attr_strcmp (const void *p1, const void *p2) +{ + tree a1 = *(const tree*)p1; + tree a2 = *(const tree*)p2; + + const attribute_spec *as1 = lookup_attribute_spec (get_attribute_name (a1)); + const attribute_spec *as2 = lookup_attribute_spec (get_attribute_name (a2)); + + return strcmp (as1->name, as2->name); +} + /* Non-terminal for type nodes. Returns the number of CV-qualifiers written for TYPE. @@ -2182,9 +2201,55 @@ write_CV_qualifiers_for_type (const tree type) "In cases where multiple order-insensitive qualifiers are present, they should be ordered 'K' (closest to the base type), - 'V', 'r', and 'U' (farthest from the base type) ..." + 'V', 'r', and 'U' (farthest from the base type) ..." */ + + /* Mangle attributes that affect type identity as extended qualifiers. + + We mangle them onto the obstack, then copy the result into a string + vector and back up the obstack. Once we've handled all of them we + sort them and write them out in order. + + We don't do this with classes and enums because their attributes + are part of their definitions, not something added on. */ + + if (abi_version_at_least (9) && !OVERLOAD_TYPE_P (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 ("abi_tag", name)) + vec.safe_push (a); + } + vec.qsort (attr_strcmp); + while (!vec.is_empty()) + { + tree a = vec.pop(); + const attribute_spec *as + = lookup_attribute_spec (get_attribute_name (a)); + + write_char ('U'); + write_unsigned_number (strlen (as->name)); + write_string (as->name); + if (TREE_VALUE (a)) + { + write_char ('I'); + for (tree args = TREE_VALUE (a); args; + args = TREE_CHAIN (args)) + { + tree arg = TREE_VALUE (args); + write_template_arg (arg); + } + write_char ('E'); + } + + ++num_qualifiers; + } + } - Note that we do not use cp_type_quals below; given "const + /* Note that we do not use cp_type_quals below; given "const int[3]", the "const" is emitted with the "int", not with the array. */ cp_cv_quals quals = TYPE_QUALS (type); diff --git a/gcc/testsuite/g++.dg/abi/macro0.C b/gcc/testsuite/g++.dg/abi/macro0.C index fbcbb2cdc96..35b8769c3d3 100644 --- a/gcc/testsuite/g++.dg/abi/macro0.C +++ b/gcc/testsuite/g++.dg/abi/macro0.C @@ -1,6 +1,6 @@ // This testcase will need to be kept in sync with c_common_post_options. // { dg-options "-fabi-version=0" } -#if __GXX_ABI_VERSION != 1008 +#if __GXX_ABI_VERSION != 1009 #error "Incorrect value of __GXX_ABI_VERSION" #endif diff --git a/gcc/testsuite/g++.dg/abi/mangle-regparm.C b/gcc/testsuite/g++.dg/abi/mangle-regparm.C new file mode 100644 index 00000000000..7d4121b5f73 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle-regparm.C @@ -0,0 +1,29 @@ +// { dg-do run { target i?86-*-* } } +// { dg-final { scan-assembler "_Z18IndirectExternCallIPU7stdcallU7regparmILi3EEFviiEiEvT_T0_S3_" } } + +typedef __SIZE_TYPE__ size_t; + +template +void IndirectExternCall(F f, T t1, T t2) { + typedef F (*WrapF)(F); + f (t1, t2); +} + +__attribute__((regparm(3), stdcall)) +void regparm_func (int i, int j) +{ + if (i != 24 || j != 42) + __builtin_abort(); +} + +void normal_func (int i, int j) +{ + if (i != 24 || j != 42) + __builtin_abort(); +} + +int main() +{ + IndirectExternCall (regparm_func, 24, 42); + IndirectExternCall (normal_func, 24, 42); +} diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index e9bc2c7df68..f2b014841aa 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,8 @@ +2015-06-01 Jason Merrill + + * cp-demangle.c (cplus_demangle_type): Handle arguments to vendor + extended qualifier. + 2015-05-22 Yunlian Jiang * configure.ac: Add AC_GNU_SOURCE. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 77c2cee9d17..2988b6bcb01 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -2470,6 +2470,9 @@ cplus_demangle_type (struct d_info *di) case 'U': d_advance (di, 1); ret = d_source_name (di); + if (d_peek_char (di) == 'I') + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + d_template_args (di)); ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, cplus_demangle_type (di), ret); break; diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index a030685de08..6ea64aef859 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4356,3 +4356,6 @@ _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z --format=gnu-v3 _Z1fSsB3fooS_ f(std::string[abi:foo], std::string[abi:foo]) +--format=gnu-v3 +_Z18IndirectExternCallIPU7stdcallU7regparmILi3EEFviiEiEvT_T0_S3_ +void IndirectExternCall stdcall*)(int, int), int>(void ( regparm<3> stdcall*)(int, int), int, void ( regparm<3> stdcall*)(int, int)) -- 2.30.2