Build variant type copies for sysv_va_list_node and ms_va_list_type_node
2016-09-10 Tom de Vries <tom@codesourcery.com>
PR c++/77427
* config/i386/i386.c (ix86_build_builtin_va_list): Build variant type
copies for sysv_va_list_node and ms_va_list_type_node.
* g++.dg/pr77427.C: New test.
---
gcc/config/i386/i386.c | 12 ++++++++++++
gcc/testsuite/g++.dg/pr77427.C | 17 +++++++++++++++++
2 files changed, 29 insertions(+)
@@ -10591,6 +10591,18 @@ ix86_build_builtin_va_list (void)
TYPE_ATTRIBUTES (char_ptr_type));
ms_va_list_type_node = build_type_attribute_variant (char_ptr_type, attr);
+ /* We'll return these type nodes via enum_va_list, and the caller
+ c_common_nodes_and_builtins will modify it by setting the TYPE_NAME.
+ This modification causes the type to move from one equivalence class
+ defined by type_cache_hasher::equal to another. As a consequence, when
+ building an unnamed version of the va_list, and trying to find the
+ cached variant, we'll won't find it, and the new type will have
+ TYPE_CANONICAL set to self and not match with the cached type.
+ So, we build a variant type copy, which is not in the type cache and
+ can be modified. */
+ sysv_va_list_type_node = build_variant_type_copy (sysv_va_list_type_node);
+ ms_va_list_type_node = build_variant_type_copy (ms_va_list_type_node);
+
return ((ix86_abi == MS_ABI)
? ms_va_list_type_node
: sysv_va_list_type_node);
new file mode 100644
@@ -0,0 +1,17 @@
+// { dg-do compile }
+
+void bar (__builtin_va_list &);
+
+struct c
+{
+ operator const __builtin_va_list &();
+ operator __builtin_va_list &();
+};
+
+void
+foo (void)
+{
+ struct c c1;
+
+ bar (c1);
+}