diff mbox

C++ PATCH to template argument abi_tag handling

Message ID 5417A211.6010101@redhat.com
State New
Headers show

Commit Message

Jason Merrill Sept. 16, 2014, 2:36 a.m. UTC
Jon sent me a test that crashed with an abi_tag on a template argument. 
  We need to propagate tags from template arguments when we first look 
up the specialization, not wait until instantiation.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 44db0cad1ad6b651616ab144896c358274eacf4f
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Sep 13 10:52:56 2014 -0400

    	* pt.c (lookup_template_class_1): Splice out abi_tag attribute if
    	necessary.  Call inherit_targ_abi_tags here.
    	* class.c (check_bases_and_members): Not here.
    	(inherit_targ_abi_tags): Check CLASS_TYPE_P.
    	* cp-tree.h: Declare inherit_targ_abi_tags.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 09f946f..6b86ef4 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1441,7 +1441,8 @@  check_abi_tags (tree t, tree subob)
 void
 inherit_targ_abi_tags (tree t)
 {
-  if (CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
+  if (!CLASS_TYPE_P (t)
+      || CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
     return;
 
   mark_type_abi_tags (t, true);
@@ -5460,9 +5461,6 @@  check_bases_and_members (tree t)
   bool saved_nontrivial_dtor;
   tree fn;
 
-  /* Pick up any abi_tags from our template arguments before checking.  */
-  inherit_targ_abi_tags (t);
-
   /* By default, we use const reference arguments and generate default
      constructors.  */
   cant_have_const_ctor = 0;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 19f5232..5d8badc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5206,6 +5206,7 @@  extern bool type_has_user_declared_move_assign(tree);
 extern bool type_build_ctor_call		(tree);
 extern bool type_build_dtor_call		(tree);
 extern void explain_non_literal_class		(tree);
+extern void inherit_targ_abi_tags		(tree);
 extern void defaulted_late_check		(tree);
 extern bool defaultable_fn_check		(tree);
 extern void fixup_type_variants			(tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 008879b..b3a9c95 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7823,9 +7823,18 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 
       if (OVERLOAD_TYPE_P (t)
 	  && !DECL_ALIAS_TEMPLATE_P (gen_tmpl))
-	if (tree attributes
-	    = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (template_type)))
-	  TYPE_ATTRIBUTES (t) = attributes;
+	{
+	  if (tree attributes
+	      = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (template_type)))
+	    {
+	      if (!TREE_CHAIN (attributes))
+		TYPE_ATTRIBUTES (t) = attributes;
+	      else
+		TYPE_ATTRIBUTES (t)
+		  = build_tree_list (TREE_PURPOSE (attributes),
+				     TREE_VALUE (attributes));
+	    }
+	}
 
       /* Let's consider the explicit specialization of a member
          of a class template specialization that is implicitly instantiated,
@@ -7950,6 +7959,8 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
       TREE_PUBLIC (type_decl) = 1;
       determine_visibility (type_decl);
 
+      inherit_targ_abi_tags (t);
+
       return t;
     }
 }
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag10.C b/gcc/testsuite/g++.dg/abi/abi-tag10.C
new file mode 100644
index 0000000..f320828
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag10.C
@@ -0,0 +1,28 @@ 
+#ifndef ABI_TAG
+#define ABI_TAG __attribute__((__abi_tag__("cxx11")))
+#endif
+
+typedef unsigned long size_t;
+
+template<typename C>
+struct char_traits { };
+template<typename C>
+struct allocator { };
+
+template<typename C, typename T = char_traits<C>, typename A = allocator<C> >
+struct ABI_TAG basic_string { };
+
+typedef basic_string<char> string;
+
+template<typename T>
+struct hash
+{
+  size_t
+  operator()(T val) const;
+};
+
+template<>
+size_t
+hash<string>::operator()(string) const { return 0; }
+
+// { dg-final { scan-assembler "_ZNK4hashI12basic_stringB5cxx11Ic11char_traitsIcE9allocatorIcEEEclES5_" } }