diff options
author | Simon Baldwin <simonb@google.com> | 2007-06-18 22:09:14 +0000 |
---|---|---|
committer | Simon Baldwin <simonb@gcc.gnu.org> | 2007-06-18 22:09:14 +0000 |
commit | 736b81007e965d4d1141dca6e45837d756741ddb (patch) | |
tree | ebe83019aac080d1a8f2fefc14cab3473f2d4579 /gcc/cp | |
parent | d448952a83fa71a5658c2f775e7c86316821f4fe (diff) | |
download | gcc-736b81007e965d4d1141dca6e45837d756741ddb.zip gcc-736b81007e965d4d1141dca6e45837d756741ddb.tar.gz gcc-736b81007e965d4d1141dca6e45837d756741ddb.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/parser.c | 33 | ||||
-rw-r--r-- | gcc/cp/pt.c | 31 |
3 files changed, 69 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5360fce..609b80c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7b41a56..ca6620c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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,13 +16651,27 @@ 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, - /*function_definition_allowed_p=*/true, - member_p, - declares_class_or_enum, - &function_definition_p); + { + 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 --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f3210dd..63f8247 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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: |