summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2015-06-02 02:28:19 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2015-06-02 02:28:19 +0000
commit399fbdbdddd6ea476c7f47d20bd2ceb0be827218 (patch)
tree1587f66f189daa25f9f3d68dc7bba6b4d6e5e5d6
parent7d2a579e44dbc8da7c850ba3a55473a973a3b61f (diff)
downloadgcc-399fbdbdddd6ea476c7f47d20bd2ceb0be827218.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@224007 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/c-family/c-opts.c2
-rw-r--r--gcc/common.opt7
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/mangle.c71
-rw-r--r--gcc/testsuite/g++.dg/abi/macro0.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle-regparm.C29
-rw-r--r--libiberty/ChangeLog5
-rw-r--r--libiberty/cp-demangle.c3
-rw-r--r--libiberty/testsuite/demangle-expected3
9 files changed, 123 insertions, 7 deletions
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 <jason@redhat.com>
+
+ 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 <jason@redhat.com>
* 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 <CV-qualifiers> 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<tree> 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 <typename F, typename T>
+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 <jason@redhat.com>
+
+ * cp-demangle.c (cplus_demangle_type): Handle arguments to vendor
+ extended qualifier.
+
2015-05-22 Yunlian Jiang <yunlian@google.com>
* 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<void ( regparm<3> stdcall*)(int, int), int>(void ( regparm<3> stdcall*)(int, int), int, void ( regparm<3> stdcall*)(int, int))