public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit template specialization
@ 2007-06-15 18:19 Simon Baldwin
  2007-06-15 19:32 ` Mark Mitchell
  0 siblings, 1 reply; 12+ messages in thread
From: Simon Baldwin @ 2007-06-15 18:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: mark

Attached is a revised version of a pending patch first distributed as

  http://gcc.gnu.org/ml/gcc-patches/2007-05/msg02033.html

The attached patch implements section 7.1.1-1 of the C++ standard by
preventing storage class specifiers on explicit specializations of templated
functions.  It also adjusts the linkage of such explicit specializations that
now cannot specify a storage class so that they meet the recommendations of
the C++ Core Language Working Group for Defect Report 605:

  http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605

The patch includes two new tests, to verify parsing and linkage of explicit
specializations of templated functions.

Regression tested with the full g++ testsuite.


gcc/cp/ChangeLog
2007-06-15  Simon Baldwin <simonb@google.com>

	PR c++/31923
	* parser.c (cp_parser_single_declaration): Added check for storage
	class other than sc_none in parsed declaration, and a flag to indicate
	if the call is part of an explicit template specialization parse.
	* (cp_parser_explicit_specialization): Specialization check flag added
	to call to cp_parser_single_declaration(), set true.
	* (cp_parser_template_declaration_after_export): Specialization check
	flag added to call to cp_parser_single_declaration(), set false.
	* pt.c (check_explicit_specialization): Added code to copy visiblity
	and linkage from the templated function to the explicit specialization.

gcc/testsuite/ChangeLog
2007-06-15  Simon Baldwin <simonb@google.com>

	PR c++/31923
	* g++.dg/template/error25.C: New.
	* g++.dg/template/spec35.C: New.


diff -Nrcp3 gcc_orig/gcc/cp/parser.c gcc/gcc/cp/parser.c
*** gcc_orig/gcc/cp/parser.c	Tue Jun 12 10:21:25 2007
--- gcc/gcc/cp/parser.c	Fri Jun 15 09:45:58 2007
*************** static void cp_parser_template_declarati
*** 1913,1919 ****
  static void cp_parser_perform_template_parameter_access_checks
    (VEC (deferred_access_check,gc)*);
  static tree cp_parser_single_declaration
!   (cp_parser *, VEC (deferred_access_check,gc)*, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
  static tree cp_parser_save_member_function_body
--- 1913,1919 ----
  static void cp_parser_perform_template_parameter_access_checks
    (VEC (deferred_access_check,gc)*);
  static tree cp_parser_single_declaration
!   (cp_parser *, VEC (deferred_access_check,gc)*, bool, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
  static tree cp_parser_save_member_function_body
*************** cp_parser_explicit_specialization (cp_pa
*** 10225,10230 ****
--- 10225,10231 ----
      cp_parser_single_declaration (parser,
  				  /*checks=*/NULL,
  				  /*member_p=*/false,
+                                   /*explicit_specialization_p=*/true,
  				  /*friend_p=*/NULL);
    /* We're done with the specialization.  */
    end_specialization ();
*************** cp_parser_template_declaration_after_exp
*** 16510,16515 ****
--- 16511,16517 ----
        decl = cp_parser_single_declaration (parser,
  					   checks,
  					   member_p,
+                                            /*explicit_specialization_p=*/false,
  					   &friend_p);
        pop_deferring_access_checks ();
  
*************** static tree
*** 16575,16580 ****
--- 16577,16583 ----
  cp_parser_single_declaration (cp_parser* parser,
  			      VEC (deferred_access_check,gc)* checks,
  			      bool member_p,
+                               bool explicit_specialization_p,
  			      bool* friend_p)
  {
    int declares_class_or_enum;
*************** cp_parser_single_declaration (cp_parser*
*** 16648,16660 ****
    if (!decl
        && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
  	  || decl_specifiers.type != error_mark_node))
!     decl = cp_parser_init_declarator (parser,
! 				      &decl_specifiers,
! 				      checks,
! 				      /*function_definition_allowed_p=*/true,
! 				      member_p,
! 				      declares_class_or_enum,
! 				      &function_definition_p);
  
    pop_deferring_access_checks ();
  
--- 16651,16677 ----
    if (!decl
        && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
  	  || decl_specifiers.type != error_mark_node))
!     {
!       decl = cp_parser_init_declarator (parser,
! 				        &decl_specifiers,
! 				        checks,
! 				        /*function_definition_allowed_p=*/true,
! 				        member_p,
! 				        declares_class_or_enum,
! 				        &function_definition_p);
! 
!     /* 7.1.1-1 [dcl.stc]
! 
!        A storage-class-specifier shall not be specified in an explicit
!        specialization...  */
!     if (decl
!         && explicit_specialization_p
!         && decl_specifiers.storage_class != sc_none)
!       {
!         error ("explicit template specialization cannot have a storage class");
!         decl = error_mark_node;
!       }
!     }
  
    pop_deferring_access_checks ();
  
diff -Nrcp3 gcc_orig/gcc/cp/pt.c gcc/gcc/cp/pt.c
*** gcc_orig/gcc/cp/pt.c	Tue Jun 12 10:21:25 2007
--- gcc/gcc/cp/pt.c	Fri Jun 15 10:40:03 2007
*************** check_explicit_specialization (tree decl
*** 2193,2198 ****
--- 2193,2227 ----
  	  TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
  	  TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
  
+           /* 7.1.1-1 [dcl.stc]
+ 
+              A storage-class-specifier shall not be specified in an
+              explicit specialization...
+ 
+              The parser rejects these, so unless action is taken here,
+              explicit function specializations will always appear with
+              global linkage.
+ 
+              The action recommended by the C++ CWG in response to C++
+              defect report 605 is to make the storage class and linkage
+              of the explicit specialization match the templated function:
+ 
+              http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605
+            */
+           if (tsk == tsk_expl_spec
+               && TREE_CODE (decl) == FUNCTION_DECL
+               && DECL_TEMPLATE_INFO (decl) && DECL_USE_TEMPLATE (decl)
+               && DECL_FUNCTION_TEMPLATE_P (gen_tmpl))
+             {
+               tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
+               gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
+ 
+               /* This specialization has the same linkage and visiblity as
+                  the function template it specializes.  */
+               TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
+               DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
+             }
+ 
  	  /* If DECL is a friend declaration, declared using an
  	     unqualified name, the namespace associated with DECL may
  	     have been set incorrectly.  For example, in:
diff -Nrcp3 gcc_orig/gcc/testsuite/g++.dg/template/error25.C gcc/gcc/testsuite/g++.dg/template/error25.C
*** gcc_orig/gcc/testsuite/g++.dg/template/error25.C	Wed Dec 31 16:00:00 1969
--- gcc/gcc/testsuite/g++.dg/template/error25.C	Tue Jun 12 14:02:38 2007
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/31923
+ 
+ template<class T>
+ static void f1 ();
+ 
+ template<>
+ static void f1<void> ();  // { dg-error "explicit template specialization cannot have a storage class" }
+ 
+ template<class T>
+ extern void f2 ();
+ 
+ template<>
+ extern void f2<void> ();  // { dg-error "explicit template specialization cannot have a storage class" }
+ 
+ export template<class T>  // { dg-warning "keyword 'export' not implemented" }
+ static void* f3 ();
diff -Nrcp3 gcc_orig/gcc/testsuite/g++.dg/template/spec35.C gcc/gcc/testsuite/g++.dg/template/spec35.C
*** gcc_orig/gcc/testsuite/g++.dg/template/spec35.C	Wed Dec 31 16:00:00 1969
--- gcc/gcc/testsuite/g++.dg/template/spec35.C	Fri Jun 15 10:35:33 2007
***************
*** 0 ****
--- 1,29 ----
+ // PR c++/31923
+ // C++ DR 605 -- "...the linkage of an explicit specialization must be that of
+ // the template."
+ 
+ // { dg-do compile { target i?86-*-* x86_64-*-* } }
+ // { dg-require-weak "" }
+ 
+ template<class T>
+ static void f1 (T) { }
+ 
+ // { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IfEvT_" } }
+ template<>
+ void f1<float> (float) { }  // Expected to have static linkage
+ 
+ template<class T>
+ void f2 (T) { }
+ 
+ // { dg-final { scan-assembler ".glob(a|)l\[\t \]*_Z2f2IfEvT_" } }
+ template<>
+ void f2<float> (float) { }  // Expected to have global linkage
+ 
+ void instantiator ()
+ {
+   // { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IiEvT_" } }
+   f1(0);  // Expected to have static linkage
+ 
+   // { dg-final { scan-assembler ".weak\[\t \]*_Z2f2IiEvT_" } }
+   f2(0);  // Expected to have weak global linkage
+ }

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit  template specialization
  2007-06-15 18:19 [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit template specialization Simon Baldwin
@ 2007-06-15 19:32 ` Mark Mitchell
  2007-06-15 20:08   ` Simon Baldwin
  0 siblings, 1 reply; 12+ messages in thread
From: Mark Mitchell @ 2007-06-15 19:32 UTC (permalink / raw)
  To: Simon Baldwin; +Cc: gcc-patches

Simon Baldwin wrote:

> gcc/cp/ChangeLog
> 2007-06-15  Simon Baldwin <simonb@google.com>
> 
> 	PR c++/31923
> 	* parser.c (cp_parser_single_declaration): Added check for storage
> 	class other than sc_none in parsed declaration, and a flag to indicate
> 	if the call is part of an explicit template specialization parse.
> 	* (cp_parser_explicit_specialization): Specialization check flag added
> 	to call to cp_parser_single_declaration(), set true.
> 	* (cp_parser_template_declaration_after_export): Specialization check
> 	flag added to call to cp_parser_single_declaration(), set false.
> 	* pt.c (check_explicit_specialization): Added code to copy visiblity
> 	and linkage from the templated function to the explicit specialization.

This looks good.  A couple of questions:

> +           if (tsk == tsk_expl_spec
> +               && TREE_CODE (decl) == FUNCTION_DECL
> +               && DECL_TEMPLATE_INFO (decl) && DECL_USE_TEMPLATE (decl)
> +               && DECL_FUNCTION_TEMPLATE_P (gen_tmpl))
> +             {
> +               tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
> +               gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
> + 
> +               /* This specialization has the same linkage and visiblity as
> +                  the function template it specializes.  */
> +               TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
> +               DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
> +             }

The condition seems complicated.  What are you trying to check exactly?
 Why isn't just

  tsk == tsk_expl_spec && DECL_FUNCTION_TEMPLATE_P (gen_tmpl)

enough?

Also, shouldn't we copy ELF symbol visibility here too?

> +   // { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IiEvT_" } }
> +   f1(0);  // Expected to have static linkage
> + 
> +   // { dg-final { scan-assembler ".weak\[\t \]*_Z2f2IiEvT_" } }
> +   f2(0);  // Expected to have weak global linkage

Do we have a DejaGNU function to check for weakness?  If not, we should.
 And, we may as well add one to check for external/global-ness too.

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit  template specialization
  2007-06-15 19:32 ` Mark Mitchell
@ 2007-06-15 20:08   ` Simon Baldwin
  2007-06-15 22:44     ` Mark Mitchell
  2007-08-15 18:50     ` [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923) Jakub Jelinek
  0 siblings, 2 replies; 12+ messages in thread
From: Simon Baldwin @ 2007-06-15 20:08 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2758 bytes --]

Thanks for the review; inlined stuff below...

Mark Mitchell wrote:

> ...
>
>>+           if (tsk == tsk_expl_spec
>>+               && TREE_CODE (decl) == FUNCTION_DECL
>>+               && DECL_TEMPLATE_INFO (decl) && DECL_USE_TEMPLATE (decl)
>>+               && DECL_FUNCTION_TEMPLATE_P (gen_tmpl))
>>+             {
>>+               tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
>>+               gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
>>+ 
>>+               /* This specialization has the same linkage and visiblity as
>>+                  the function template it specializes.  */
>>+               TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
>>+               DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
>>+             }
>>    
>>
>
>The condition seems complicated.  What are you trying to check exactly?
> Why isn't just
>
>  tsk == tsk_expl_spec && DECL_FUNCTION_TEMPLATE_P (gen_tmpl)
>
>enough?
>  
>

Thanks for the note.  I triangulated to this condition through a series 
of swipes at narrowing down problems with early versions, which may 
explain any redundancies.  I wanted complete certainty here that this 
code wouldn't be triggered for explicit specializations of class 
templates, but only for function templates, and I wasn't entirely sure 
from the surrounding code that this would reliably be the case without 
checking.

If we're sure that decl here is always a FUNCTION_DECL then the simpler 
condition ought to be fine.  I've retested with this change in place, 
and all regression tests continue to pass.

>Also, shouldn't we copy ELF symbol visibility here too?
>  
>

Added.  Thanks for the note.  Revised patch appended below.

>>+   // { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IiEvT_" } }
>>+   f1(0);  // Expected to have static linkage
>>+ 
>>+   // { dg-final { scan-assembler ".weak\[\t \]*_Z2f2IiEvT_" } }
>>+   f2(0);  // Expected to have weak global linkage
>>    
>>
>
>Do we have a DejaGNU function to check for weakness?  If not, we should.
> And, we may as well add one to check for external/global-ness too.
>  
>

I couldn't find anything in DejaGNU to check either of these 
explicitly.  Several existing tests currently use scan-assembler in a 
similar way (g++.dg/rtti/tinfo1.C, g++.dg/ext/visibility/anon{1,2}.C, 
obj-c++.dg/template-{5,6}.mm, and g++.dg/abi/rtti3.C), suggesting that 
there's nothing available at the moment.

I could perhaps add suitable DejaGNU functions, but TCL/expect aren't my 
strong points.  Adding these functions might also be tricky for multiple 
architectures.  I didn't want this g++ patch to get hung up on testing 
framework changes that I might not be able to complete.  Can we live 
with this test for now?

Thanks,

--S


[-- Attachment #2: pr31923.patch --]
[-- Type: text/x-patch, Size: 8726 bytes --]

Attached is a revised version of a pending patch first distributed as

  http://gcc.gnu.org/ml/gcc-patches/2007-05/msg02033.html

The attached patch implements section 7.1.1-1 of the C++ standard by
preventing storage class specifiers on explicit specializations of templated
functions.  It also adjusts the linkage of such explicit specializations that
now cannot specify a storage class so that they meet the recommendations of
the C++ Core Language Working Group for Defect Report 605:

  http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605

The patch includes two new tests, to verify parsing and linkage of explicit
specializations of templated functions.

Regression tested with the full g++ testsuite.


gcc/cp/ChangeLog
2007-06-15  Simon Baldwin <simonb@google.com>

	PR c++/31923
	* parser.c (cp_parser_single_declaration): Added check for storage
	class other than sc_none in parsed declaration, and a flag to indicate
	if the call is part of an explicit template specialization parse.
	* (cp_parser_explicit_specialization): Specialization check flag added
	to call to cp_parser_single_declaration(), set true.
	* (cp_parser_template_declaration_after_export): Specialization check
	flag added to call to cp_parser_single_declaration(), set false.
	* pt.c (check_explicit_specialization): Added code to copy visiblity
	and linkage from the templated function to the explicit specialization.

gcc/testsuite/ChangeLog
2007-06-15  Simon Baldwin <simonb@google.com>

	PR c++/31923
	* g++.dg/template/error25.C: New.
	* g++.dg/template/spec35.C: New.


diff -Nrcp3 gcc_orig/gcc/cp/parser.c gcc/gcc/cp/parser.c
*** gcc_orig/gcc/cp/parser.c	Tue Jun 12 10:21:25 2007
--- gcc/gcc/cp/parser.c	Fri Jun 15 09:45:58 2007
*************** static void cp_parser_template_declarati
*** 1913,1919 ****
  static void cp_parser_perform_template_parameter_access_checks
    (VEC (deferred_access_check,gc)*);
  static tree cp_parser_single_declaration
!   (cp_parser *, VEC (deferred_access_check,gc)*, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
  static tree cp_parser_save_member_function_body
--- 1913,1919 ----
  static void cp_parser_perform_template_parameter_access_checks
    (VEC (deferred_access_check,gc)*);
  static tree cp_parser_single_declaration
!   (cp_parser *, VEC (deferred_access_check,gc)*, bool, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
  static tree cp_parser_save_member_function_body
*************** cp_parser_explicit_specialization (cp_pa
*** 10225,10230 ****
--- 10225,10231 ----
      cp_parser_single_declaration (parser,
  				  /*checks=*/NULL,
  				  /*member_p=*/false,
+                                   /*explicit_specialization_p=*/true,
  				  /*friend_p=*/NULL);
    /* We're done with the specialization.  */
    end_specialization ();
*************** cp_parser_template_declaration_after_exp
*** 16510,16515 ****
--- 16511,16517 ----
        decl = cp_parser_single_declaration (parser,
  					   checks,
  					   member_p,
+                                            /*explicit_specialization_p=*/false,
  					   &friend_p);
        pop_deferring_access_checks ();
  
*************** static tree
*** 16575,16580 ****
--- 16577,16583 ----
  cp_parser_single_declaration (cp_parser* parser,
  			      VEC (deferred_access_check,gc)* checks,
  			      bool member_p,
+                               bool explicit_specialization_p,
  			      bool* friend_p)
  {
    int declares_class_or_enum;
*************** cp_parser_single_declaration (cp_parser*
*** 16648,16660 ****
    if (!decl
        && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
  	  || decl_specifiers.type != error_mark_node))
!     decl = cp_parser_init_declarator (parser,
! 				      &decl_specifiers,
! 				      checks,
! 				      /*function_definition_allowed_p=*/true,
! 				      member_p,
! 				      declares_class_or_enum,
! 				      &function_definition_p);
  
    pop_deferring_access_checks ();
  
--- 16651,16677 ----
    if (!decl
        && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
  	  || decl_specifiers.type != error_mark_node))
!     {
!       decl = cp_parser_init_declarator (parser,
! 				        &decl_specifiers,
! 				        checks,
! 				        /*function_definition_allowed_p=*/true,
! 				        member_p,
! 				        declares_class_or_enum,
! 				        &function_definition_p);
! 
!     /* 7.1.1-1 [dcl.stc]
! 
!        A storage-class-specifier shall not be specified in an explicit
!        specialization...  */
!     if (decl
!         && explicit_specialization_p
!         && decl_specifiers.storage_class != sc_none)
!       {
!         error ("explicit template specialization cannot have a storage class");
!         decl = error_mark_node;
!       }
!     }
  
    pop_deferring_access_checks ();
  
diff -Nrcp3 gcc_orig/gcc/cp/pt.c gcc/gcc/cp/pt.c
*** gcc_orig/gcc/cp/pt.c	Tue Jun 12 10:21:25 2007
--- gcc/gcc/cp/pt.c	Fri Jun 15 12:06:21 2007
*************** check_explicit_specialization (tree decl
*** 2193,2198 ****
--- 2193,2229 ----
  	  TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
  	  TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
  
+           /* 7.1.1-1 [dcl.stc]
+ 
+              A storage-class-specifier shall not be specified in an
+              explicit specialization...
+ 
+              The parser rejects these, so unless action is taken here,
+              explicit function specializations will always appear with
+              global linkage.
+ 
+              The action recommended by the C++ CWG in response to C++
+              defect report 605 is to make the storage class and linkage
+              of the explicit specialization match the templated function:
+ 
+              http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605
+            */
+           if (tsk == tsk_expl_spec && DECL_FUNCTION_TEMPLATE_P (gen_tmpl))
+             {
+               tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
+               gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
+ 
+               /* This specialization has the same linkage and visiblity as
+                  the function template it specializes.  */
+               TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
+               DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
+               if (DECL_VISIBILITY_SPECIFIED (tmpl_func))
+                 {
+                   DECL_VISIBILITY_SPECIFIED (decl) = 1;
+                   DECL_VISIBILITY (decl) = DECL_VISIBILITY (tmpl_func);
+                 }
+             }
+ 
  	  /* If DECL is a friend declaration, declared using an
  	     unqualified name, the namespace associated with DECL may
  	     have been set incorrectly.  For example, in:
diff -Nrcp3 gcc_orig/gcc/testsuite/g++.dg/template/error25.C gcc/gcc/testsuite/g++.dg/template/error25.C
*** gcc_orig/gcc/testsuite/g++.dg/template/error25.C	Wed Dec 31 16:00:00 1969
--- gcc/gcc/testsuite/g++.dg/template/error25.C	Tue Jun 12 14:02:38 2007
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/31923
+ 
+ template<class T>
+ static void f1 ();
+ 
+ template<>
+ static void f1<void> ();  // { dg-error "explicit template specialization cannot have a storage class" }
+ 
+ template<class T>
+ extern void f2 ();
+ 
+ template<>
+ extern void f2<void> ();  // { dg-error "explicit template specialization cannot have a storage class" }
+ 
+ export template<class T>  // { dg-warning "keyword 'export' not implemented" }
+ static void* f3 ();
diff -Nrcp3 gcc_orig/gcc/testsuite/g++.dg/template/spec35.C gcc/gcc/testsuite/g++.dg/template/spec35.C
*** gcc_orig/gcc/testsuite/g++.dg/template/spec35.C	Wed Dec 31 16:00:00 1969
--- gcc/gcc/testsuite/g++.dg/template/spec35.C	Fri Jun 15 12:33:28 2007
***************
*** 0 ****
--- 1,29 ----
+ // PR c++/31923
+ // C++ DR 605 -- "...the linkage of an explicit specialization must be that of
+ // the template."
+ 
+ // { dg-require-weak "" }
+ // { dg-do compile { target i?86-*-* x86_64-*-* } }
+ 
+ template<class T>
+ static void f1 (T) { }
+ 
+ // { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IfEvT_" } }
+ template<>
+ void f1<float> (float) { }  // Expected to have static linkage
+ 
+ template<class T>
+ void f2 (T) { }
+ 
+ // { dg-final { scan-assembler ".glob(a|)l\[\t \]*_Z2f2IfEvT_" } }
+ template<>
+ void f2<float> (float) { }  // Expected to have global linkage
+ 
+ void instantiator ()
+ {
+   // { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IiEvT_" } }
+   f1(0);  // Expected to have static linkage
+ 
+   // { dg-final { scan-assembler ".weak\[\t \]*_Z2f2IiEvT_" } }
+   f2(0);  // Expected to have weak global linkage
+ }

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit  template specialization
  2007-06-15 20:08   ` Simon Baldwin
@ 2007-06-15 22:44     ` Mark Mitchell
  2007-06-18 22:33       ` Simon Baldwin
  2007-08-15 18:50     ` [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923) Jakub Jelinek
  1 sibling, 1 reply; 12+ messages in thread
From: Mark Mitchell @ 2007-06-15 22:44 UTC (permalink / raw)
  To: Simon Baldwin; +Cc: gcc-patches

Simon Baldwin wrote:

> If we're sure that decl here is always a FUNCTION_DECL then the simpler
> condition ought to be fine.  I've retested with this change in place,
> and all regression tests continue to pass.

If GEN_TMPL (the most general template of which DECL is a
specialization) is DECL_FUNCTION_TEMPLATE_P then DECL had better be a
FUNCTION_DECL. :-)

> I could perhaps add suitable DejaGNU functions, but TCL/expect aren't my
> strong points.  Adding these functions might also be tricky for multiple
> architectures.  I didn't want this g++ patch to get hung up on testing
> framework changes that I might not be able to complete.  Can we live
> with this test for now?

This version is OK.

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit  template specialization
  2007-06-15 22:44     ` Mark Mitchell
@ 2007-06-18 22:33       ` Simon Baldwin
  0 siblings, 0 replies; 12+ messages in thread
From: Simon Baldwin @ 2007-06-18 22:33 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: gcc-patches

Mark Mitchell wrote:

>Simon Baldwin wrote:
>  
>
> ...
>
>>I could perhaps add suitable DejaGNU functions, but TCL/expect aren't my
>>strong points.  Adding these functions might also be tricky for multiple
>>architectures.  I didn't want this g++ patch to get hung up on testing
>>framework changes that I might not be able to complete.  Can we live
>>with this test for now?
>>    
>>
>
>This version is OK.
>
>Thanks,
>  
>

Many thanks for the review.  Committed as revision 125829.

--S

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923)
  2007-06-15 20:08   ` Simon Baldwin
  2007-06-15 22:44     ` Mark Mitchell
@ 2007-08-15 18:50     ` Jakub Jelinek
  2007-08-15 19:08       ` Paolo Carlini
                         ` (2 more replies)
  1 sibling, 3 replies; 12+ messages in thread
From: Jakub Jelinek @ 2007-08-15 18:50 UTC (permalink / raw)
  To: Mark Mitchell, Simon Baldwin; +Cc: gcc-patches

Hi!

On Fri, Jun 15, 2007 at 12:55:54PM -0700, Simon Baldwin wrote:

2007-06-15  Simon Baldwin <simonb@google.com>

	PR c++/31923
	* parser.c (cp_parser_single_declaration): Added check for storage
	class other than sc_none in parsed declaration, and a flag to indicate
	if the call is part of an explicit template specialization parse.
	* (cp_parser_explicit_specialization): Specialization check flag added
	to call to cp_parser_single_declaration(), set true.
	* (cp_parser_template_declaration_after_export): Specialization check 
	flag added to call to cp_parser_single_declaration(), set false.
        * pt.c (check_explicit_specialization): Added code to copy visiblity
	and linkage from the templated function to the explicit specialization.

The above change causes PR c++/32596 regression.
When we copy TREE_PUBLIC from the template to the specialization and
the template is !TREE_PUBLIC because of constrain_visibility (xx, VISIBILITY_ANON),
it means the following determine_visibility will be a nop.  So we need
to ensure all other effects of constrain_visibility (xx, VISIBILITY_ANON)
are copied as well.
The following patch copies just DECL_INTERFACE_KNOWN which is enough to fix
this bug and didn't cause any make check-g++ or make check-libstdc++-v3
failure, but I wonder if we shouldn't copy DECL_NOT_REALLY_EXTERN as well,
or if DECL_INTERFACE_KNOWN can be copied over unconditionally.

BTW, the ChangeLog entry is badly formatted (replace "* (" with just "(").

2007-08-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/32596
	* pt.c (check_explicit_specialization): Set DECL_INTERFACE_KNOWN
	if tmpl_func is not public and has DECL_INTERFACE_KNOWN set.

	* g++.dg/ext/visibility/anon5.C: New test.

--- gcc/cp/pt.c.jj	2007-08-15 15:44:59.000000000 +0200
+++ gcc/cp/pt.c	2007-08-15 17:45:39.000000000 +0200
@@ -2215,6 +2215,8 @@ check_explicit_specialization (tree decl
               /* This specialization has the same linkage and visibility as
                  the function template it specializes.  */
               TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
+	      if (! TREE_PUBLIC (decl) && DECL_INTERFACE_KNOWN (tmpl_func))
+		DECL_INTERFACE_KNOWN (decl) = 1;
               DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
               if (DECL_VISIBILITY_SPECIFIED (tmpl_func))
                 {
--- gcc/testsuite/g++.dg/ext/visibility/anon5.C.jj	2007-08-15 17:47:03.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/visibility/anon5.C	2007-08-15 17:46:09.000000000 +0200
@@ -0,0 +1,8 @@
+// PR c++/32596
+// { dg-do compile }
+
+namespace
+{
+  template<class T> inline void char_less(void) { }
+  template<> inline void char_less<char>(void) { }
+}


	Jakub

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [C++ PATCH] Fix check_explicit_specialization (PR c++/32596,  regression caused by PR c++/31923)
  2007-08-15 18:50     ` [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923) Jakub Jelinek
@ 2007-08-15 19:08       ` Paolo Carlini
  2007-08-17  4:20       ` Mark Mitchell
  2007-08-27 16:02       ` Jason Merrill
  2 siblings, 0 replies; 12+ messages in thread
From: Paolo Carlini @ 2007-08-15 19:08 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Mark Mitchell, Simon Baldwin, gcc-patches

... by the way, c++/32400 seems closely related, and indeed Jakub your 
patch fixes both!

Thanks,
Paolo.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [C++ PATCH] Fix check_explicit_specialization (PR c++/32596,  regression caused by PR c++/31923)
  2007-08-15 18:50     ` [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923) Jakub Jelinek
  2007-08-15 19:08       ` Paolo Carlini
@ 2007-08-17  4:20       ` Mark Mitchell
  2007-08-17 16:03         ` Jakub Jelinek
  2007-08-27 16:02       ` Jason Merrill
  2 siblings, 1 reply; 12+ messages in thread
From: Mark Mitchell @ 2007-08-17  4:20 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Simon Baldwin, gcc-patches

Jakub Jelinek wrote:

> The above change causes PR c++/32596 regression.

> The following patch copies just DECL_INTERFACE_KNOWN which is enough to fix
> this bug and didn't cause any make check-g++ or make check-libstdc++-v3
> failure, but I wonder if we shouldn't copy DECL_NOT_REALLY_EXTERN as well,
> or if DECL_INTERFACE_KNOWN can be copied over unconditionally.

I don't think DECL_NOT_REALLY_EXTERN has any meaning for a template.
(It certainly does for an instantiation, but not for the template
itself.)  At least, I hope it doesn't have any meaning...

> 2007-08-15  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/32596
> 	* pt.c (check_explicit_specialization): Set DECL_INTERFACE_KNOWN
> 	if tmpl_func is not public and has DECL_INTERFACE_KNOWN set.
> 
> 	* g++.dg/ext/visibility/anon5.C: New test.

I think you should copy DECL_INTERFACE_KNOWN unconditionally.  If that
passes testing, this change is OK.

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [C++ PATCH] Fix check_explicit_specialization (PR c++/32596,  regression caused by PR c++/31923)
  2007-08-17  4:20       ` Mark Mitchell
@ 2007-08-17 16:03         ` Jakub Jelinek
  0 siblings, 0 replies; 12+ messages in thread
From: Jakub Jelinek @ 2007-08-17 16:03 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Simon Baldwin, gcc-patches

On Thu, Aug 16, 2007 at 09:19:52PM -0700, Mark Mitchell wrote:
> > 2007-08-15  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	PR c++/32596
> > 	* pt.c (check_explicit_specialization): Set DECL_INTERFACE_KNOWN
> > 	if tmpl_func is not public and has DECL_INTERFACE_KNOWN set.
> > 
> > 	* g++.dg/ext/visibility/anon5.C: New test.
> 
> I think you should copy DECL_INTERFACE_KNOWN unconditionally.  If that
> passes testing, this change is OK.

Copying DECL_INTERFACE_KNOWN unconditionally, even when TREE_PUBLIC
(tmpl_func), causes many regressions.
As an example pretty3.C.

Here tmpl_func has TREE_PUBLIC set and DECL_INTERFACE_KNOWN set as well.
If we set DECL_INTERFACE_KNOWN on decl and reach
start_preparsed_function around line 11030:

  if (DECL_INTERFACE_KNOWN (decl1))
    {
      tree ctx = decl_function_context (decl1);

      if (DECL_NOT_REALLY_EXTERN (decl1))
        DECL_EXTERNAL (decl1) = 0;

      if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx)
          && TREE_PUBLIC (ctx))
        /* This is a function in a local class in an extern inline
           function.  */
        comdat_linkage (decl1);
    }
  else if ...
  else if ...
  else
    {
      /* This is a definition, not a reference.
         So clear DECL_EXTERNAL.  */
      DECL_EXTERNAL (decl1) = 0;

      if ((DECL_DECLARED_INLINE_P (decl1)
           || DECL_TEMPLATE_INSTANTIATION (decl1))
          && ! DECL_INTERFACE_KNOWN (decl1)
          /* Don't try to defer nested functions for now.  */
          && ! decl_function_context (decl1))
        DECL_DEFER_OUTPUT (decl1) = 1;
      else
        DECL_INTERFACE_KNOWN (decl1) = 1;
    }

Without the unconditional copy of DECL_INTERFACE_KNOWN in
check_explicit_specialization this will clear DECL_EXTERNAL,
but as DECL_NOT_REALLY_EXTERN is not set (and no, tmpl_func
didn't have it set either, so copying that over wouldn't help)
if we set there DECL_INTERFACE_KNOWN, DECL_EXTERNAL will still
be set and thus the explicit instantiation is not emitted.
Other regressions:

FAIL: g++.dg/ext/pretty1.C scan-assembler int bar\\(T\\).*with T = int
FAIL: g++.dg/ext/pretty2.C (test for excess errors)
FAIL: g++.dg/ext/visibility/template4.C scan-hidden hidden[ \t_]*_Z3fooIdEvT_
FAIL: g++.dg/ext/visibility/template4.C scan-hidden hidden[ \t_]*_Z3fooIcEvT_
FAIL: g++.dg/ext/visibility/template4.C scan-hidden hidden[ \t_]*_Z3barIdEvT_
FAIL: g++.dg/ext/visibility/template4.C scan-hidden hidden[ \t_]*_Z3barIcEvT_
FAIL: g++.dg/template/spec29.C (test for excess errors)
FAIL: g++.dg/template/spec35.C scan-assembler .glob(a|)l[\t ]*_Z2f2IfEvT_
FAIL: g++.old-deja/g++.ext/pretty3.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/explicit23.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/explicit28.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/explicit51.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/explicit57.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/explicit64.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/explicit65.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/spec33.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/ttp28.C (test for excess errors)

	Jakub

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [C++ PATCH] Fix check_explicit_specialization (PR c++/32596,  regression caused by PR c++/31923)
  2007-08-15 18:50     ` [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923) Jakub Jelinek
  2007-08-15 19:08       ` Paolo Carlini
  2007-08-17  4:20       ` Mark Mitchell
@ 2007-08-27 16:02       ` Jason Merrill
  2007-08-28 11:58         ` Jakub Jelinek
  2 siblings, 1 reply; 12+ messages in thread
From: Jason Merrill @ 2007-08-27 16:02 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Mark Mitchell, Simon Baldwin,
	gcc-patches@gcc.gnu.org >> gcc-patches List

Jakub Jelinek wrote:
> The following patch copies just DECL_INTERFACE_KNOWN which is enough to fix
> this bug and didn't cause any make check-g++ or make check-libstdc++-v3
> failure, but I wonder if we shouldn't copy DECL_NOT_REALLY_EXTERN as well,
> or if DECL_INTERFACE_KNOWN can be copied over unconditionally.

> +	      if (! TREE_PUBLIC (decl) && DECL_INTERFACE_KNOWN (tmpl_func))
> +		DECL_INTERFACE_KNOWN (decl) = 1;

The right fix is to do what grokfndecl does: if !TREE_PUBLIC, set 
DECL_INTERFACE_KNOWN and DECL_NOT_REALLY_EXTERN.  No need to check 
DECL_INTERFACE_KNOWN on the template.

Incidentally, it seems wrong to me to be propagating DECL_VISIBILITY 
here, since a specialization can have less visibility than its template.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [C++ PATCH] Fix check_explicit_specialization (PR c++/32596,  regression caused by PR c++/31923)
  2007-08-27 16:02       ` Jason Merrill
@ 2007-08-28 11:58         ` Jakub Jelinek
  2007-08-28 13:49           ` Jason Merrill
  0 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2007-08-28 11:58 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Mark Mitchell, Simon Baldwin, gcc-patches

On Mon, Aug 27, 2007 at 11:56:38AM -0400, Jason Merrill wrote:
> Jakub Jelinek wrote:
> >The following patch copies just DECL_INTERFACE_KNOWN which is enough to fix
> >this bug and didn't cause any make check-g++ or make check-libstdc++-v3
> >failure, but I wonder if we shouldn't copy DECL_NOT_REALLY_EXTERN as well,
> >or if DECL_INTERFACE_KNOWN can be copied over unconditionally.
> 
> >+	      if (! TREE_PUBLIC (decl) && DECL_INTERFACE_KNOWN (tmpl_func))
> >+		DECL_INTERFACE_KNOWN (decl) = 1;
> 
> The right fix is to do what grokfndecl does: if !TREE_PUBLIC, set 
> DECL_INTERFACE_KNOWN and DECL_NOT_REALLY_EXTERN.  No need to check 
> DECL_INTERFACE_KNOWN on the template.

Following bootstraps on x86_64-linux and ia64-linux with no regressions.

2007-08-28  Jakub Jelinek  <jakub@redhat.com>

	PR c++/32596
	* pt.c (check_explicit_specialization): Set DECL_INTERFACE_KNOWN
	and DECL_NOT_REALLY_EXTERN if tmpl_func is not public.

	* g++.dg/ext/visibility/anon5.C: New test.

--- gcc/cp/pt.c.jj	2007-08-27 20:56:18.000000000 +0200
+++ gcc/cp/pt.c	2007-08-27 20:56:19.000000000 +0200
@@ -2217,6 +2217,11 @@ check_explicit_specialization (tree decl
               /* This specialization has the same linkage and visibility as
                  the function template it specializes.  */
               TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
+	      if (! TREE_PUBLIC (decl))
+		{
+		  DECL_INTERFACE_KNOWN (decl) = 1;
+		  DECL_NOT_REALLY_EXTERN (decl) = 1;
+		}
               DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
               if (DECL_VISIBILITY_SPECIFIED (tmpl_func))
                 {
--- gcc/testsuite/g++.dg/ext/visibility/anon5.C.jj	2007-08-15 17:47:03.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/visibility/anon5.C	2007-08-15 17:46:09.000000000 +0200
@@ -0,0 +1,8 @@
+// PR c++/32596
+// { dg-do compile }
+
+namespace
+{
+  template<class T> inline void char_less(void) { }
+  template<> inline void char_less<char>(void) { }
+}

> Incidentally, it seems wrong to me to be propagating DECL_VISIBILITY 
> here, since a specialization can have less visibility than its template.

If you want to change this instead, guess I'd pass the buck to you...

	Jakub

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [C++ PATCH] Fix check_explicit_specialization (PR c++/32596,   regression caused by PR c++/31923)
  2007-08-28 11:58         ` Jakub Jelinek
@ 2007-08-28 13:49           ` Jason Merrill
  0 siblings, 0 replies; 12+ messages in thread
From: Jason Merrill @ 2007-08-28 13:49 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Mark Mitchell, Simon Baldwin, gcc-patches

OK.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2007-08-28 13:44 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-15 18:19 [REVISED PATCH][RFC] Fix PR c++/31923: Storage class with explicit template specialization Simon Baldwin
2007-06-15 19:32 ` Mark Mitchell
2007-06-15 20:08   ` Simon Baldwin
2007-06-15 22:44     ` Mark Mitchell
2007-06-18 22:33       ` Simon Baldwin
2007-08-15 18:50     ` [C++ PATCH] Fix check_explicit_specialization (PR c++/32596, regression caused by PR c++/31923) Jakub Jelinek
2007-08-15 19:08       ` Paolo Carlini
2007-08-17  4:20       ` Mark Mitchell
2007-08-17 16:03         ` Jakub Jelinek
2007-08-27 16:02       ` Jason Merrill
2007-08-28 11:58         ` Jakub Jelinek
2007-08-28 13:49           ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).