re PR c++/31923 (g++ accepts a storage-class-specifier on a template explicit specialization)

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.

From-SVN: r125829
This commit is contained in:
Simon Baldwin 2007-06-18 22:09:14 +00:00 committed by Simon Baldwin
parent d448952a83
commit 736b81007e
6 changed files with 120 additions and 8 deletions

View file

@ -1,3 +1,16 @@
2007-06-18 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.
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
* typeck.c (build_binary_op): For templates build the

View file

@ -1913,7 +1913,7 @@ static void cp_parser_template_declaration_after_export
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 *);
(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
@ -10225,6 +10225,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
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 ();
@ -16510,6 +16511,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
decl = cp_parser_single_declaration (parser,
checks,
member_p,
/*explicit_specialization_p=*/false,
&friend_p);
pop_deferring_access_checks ();
@ -16575,6 +16577,7 @@ static tree
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;
@ -16648,6 +16651,7 @@ cp_parser_single_declaration (cp_parser* parser,
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,
@ -16656,6 +16660,19 @@ cp_parser_single_declaration (cp_parser* parser,
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 ();
/* Clear any current qualification; whatever comes next is the start

View file

@ -2193,6 +2193,37 @@ check_explicit_specialization (tree declarator,
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:

View file

@ -1,3 +1,9 @@
2007-06-18 Simon Baldwin <simonb@google.com>
PR c++/31923
* g++.dg/template/error25.C: New.
* g++.dg/template/spec35.C: New.
2007-06-18 Kenneth Zadeck <zadeck@naturalbridge.com>
* gcc.c-torture/compile/pr32355.c: New testcase.

View file

@ -0,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 ();

View file

@ -0,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
}