Patchwork C++ PATCH for c++/55275 (abi_tag and explicit specialization)

login
register
mail settings
Submitter Jason Merrill
Date Nov. 15, 2012, 1:51 a.m.
Message ID <50A44A85.2000203@redhat.com>
Download mbox | patch
Permalink /patch/199100/
State New
Headers show

Comments

Jason Merrill - Nov. 15, 2012, 1:51 a.m.
This bug arose because I was using DECL_SOURCE_LOCATION to determine 
whether this is the first declaration of the class.  Which may be 
fragile, but I don't see another way to do it.  But for an explicit 
specialization we were treating the template declaration as the initial 
declaration, so the specialization looked like a redeclaration.  Fixed 
by adjusting the DECL_SOURCE_LOCATION when we decide that we're dealing 
with a new explicit specialization.  This also improves some error 
message locations.

Tested x86_64-pc-linux-gnu, applying to trunk.
Jonathan Wakely - Nov. 15, 2012, 2:31 a.m.
On 15 November 2012 01:51, Jason Merrill wrote:
> This bug arose because I was using DECL_SOURCE_LOCATION to determine whether
> this is the first declaration of the class.  Which may be fragile, but I
> don't see another way to do it.  But for an explicit specialization we were
> treating the template declaration as the initial declaration, so the
> specialization looked like a redeclaration.  Fixed by adjusting the
> DECL_SOURCE_LOCATION when we decide that we're dealing with a new explicit
> specialization.  This also improves some error message locations.

The improved error locations fix PR c++/47343, thanks!

Patch

commit e2eaf69b6bcc24c5ecf491256f3a0a90ffda78c9
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Nov 13 06:15:20 2012 -0500

    	PR c++/55275
    	* pt.c (maybe_process_partial_specialization): Update
    	DECL_SOURCE_LOCATION for new specializations.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 802c79b..3c9bb56 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -838,6 +838,7 @@  maybe_process_partial_specialization (tree type)
 	{
 	  check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
 	  SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+	  DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location;
 	  if (processing_template_decl)
 	    {
 	      if (push_template_decl (TYPE_MAIN_DECL (type))
@@ -934,6 +935,7 @@  maybe_process_partial_specialization (tree type)
 	     have one level of template argument for the innermost
 	     class template.  */
 	  SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+	  DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location;
 	  CLASSTYPE_TI_ARGS (type)
 	    = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
 	}
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag3.C b/gcc/testsuite/g++.dg/abi/abi-tag3.C
new file mode 100644
index 0000000..05fd58e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag3.C
@@ -0,0 +1,36 @@ 
+// An explicit specialization doesn't get the tag from its template unless
+// it is specified there, too.
+
+// { dg-final { scan-assembler "_ZN3FooB5cxx11IcE1fEv" } }
+template<typename T>
+struct __attribute ((abi_tag("cxx11"))) Foo
+{
+  int f();
+};
+
+// { dg-final { scan-assembler "_ZN3FooB5cxx11IiE1fEv" } }
+template<>
+struct
+__attribute ((abi_tag("cxx11")))
+Foo<int>
+{
+  int f();
+};
+
+// { dg-final { scan-assembler "_ZN3FooIdE1fEv" } }
+template<>
+struct
+Foo<double>
+{
+  int f();
+};
+
+int main()
+{
+  Foo<int> f;
+  f.f();
+  Foo<char> f1;
+  f1.f();
+  Foo<double> f2;
+  f2.f();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31439.C b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
index 9d22b56..c64bc31 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31439.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
@@ -1,7 +1,7 @@ 
 // { dg-options "-std=c++0x" }
-template<typename...> struct A; // { dg-error "declaration" }
+template<typename...> struct A;
 
-template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous" }
+template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous|declaration" }
 
 template<typename T, typename... U> struct A<T, U...> : A<U...> {}; // { dg-error "incomplete type" }
 
diff --git a/gcc/testsuite/g++.dg/template/crash98.C b/gcc/testsuite/g++.dg/template/crash98.C
index e3c224d..a79ab02 100644
--- a/gcc/testsuite/g++.dg/template/crash98.C
+++ b/gcc/testsuite/g++.dg/template/crash98.C
@@ -1,8 +1,8 @@ 
 // PR c++/43630
 
-template < typename > struct A; // { dg-error "declaration" }
+template < typename > struct A;
 
-template < typename > struct A < int > // { dg-error "not used|template\\-parameter" }
+template < typename > struct A < int > // { dg-error "not used|template\\-parameter|declaration" }
 {
   int i;
   int f ();
diff --git a/libstdc++-v3/testsuite/ext/type_traits/add_unsigned_integer_neg.cc b/libstdc++-v3/testsuite/ext/type_traits/add_unsigned_integer_neg.cc
index b976de0..bdd27cc 100644
--- a/libstdc++-v3/testsuite/ext/type_traits/add_unsigned_integer_neg.cc
+++ b/libstdc++-v3/testsuite/ext/type_traits/add_unsigned_integer_neg.cc
@@ -36,4 +36,5 @@  int main()
 }
 
 // { dg-error "invalid use of incomplete" "" { target *-*-* } 28 } 
-// { dg-error "declaration of" "" { target *-*-* } 63 }
+// { dg-error "declaration of" "" { target *-*-* } 98 }
+// { dg-error "declaration of" "" { target *-*-* } 101 }
diff --git a/libstdc++-v3/testsuite/ext/type_traits/remove_unsigned_integer_neg.cc b/libstdc++-v3/testsuite/ext/type_traits/remove_unsigned_integer_neg.cc
index bd5c423..099178e 100644
--- a/libstdc++-v3/testsuite/ext/type_traits/remove_unsigned_integer_neg.cc
+++ b/libstdc++-v3/testsuite/ext/type_traits/remove_unsigned_integer_neg.cc
@@ -36,4 +36,5 @@  int main()
 }
 
 // { dg-error "invalid use of incomplete" "" { target *-*-* } 28 } 
-// { dg-error "declaration of" "" { target *-*-* } 106 }
+// { dg-error "declaration of" "" { target *-*-* } 141 }
+// { dg-error "declaration of" "" { target *-*-* } 144 }