From 736b81007e965d4d1141dca6e45837d756741ddb Mon Sep 17 00:00:00 2001 From: Simon Baldwin Date: Mon, 18 Jun 2007 22:09:14 +0000 Subject: re PR c++/31923 (g++ accepts a storage-class-specifier on a template explicit specialization) gcc/cp/ChangeLog 2007-06-15 Simon Baldwin 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 PR c++/31923 * g++.dg/template/error25.C: New. * g++.dg/template/spec35.C: New. From-SVN: r125829 --- gcc/cp/ChangeLog | 13 +++++++++++++ gcc/cp/parser.c | 33 +++++++++++++++++++++++++-------- gcc/cp/pt.c | 31 +++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/template/error25.C | 16 ++++++++++++++++ gcc/testsuite/g++.dg/template/spec35.C | 29 +++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/error25.C create mode 100644 gcc/testsuite/g++.dg/template/spec35.C (limited to 'gcc') 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 + + 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 * 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: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7550286..dbfb12b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-06-18 Simon Baldwin + + PR c++/31923 + * g++.dg/template/error25.C: New. + * g++.dg/template/spec35.C: New. + 2007-06-18 Kenneth Zadeck * gcc.c-torture/compile/pr32355.c: New testcase. diff --git a/gcc/testsuite/g++.dg/template/error25.C b/gcc/testsuite/g++.dg/template/error25.C new file mode 100644 index 0000000..8901157 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error25.C @@ -0,0 +1,16 @@ +// PR c++/31923 + +template +static void f1 (); + +template<> +static void f1 (); // { dg-error "explicit template specialization cannot have a storage class" } + +template +extern void f2 (); + +template<> +extern void f2 (); // { dg-error "explicit template specialization cannot have a storage class" } + +export template // { dg-warning "keyword 'export' not implemented" } +static void* f3 (); diff --git a/gcc/testsuite/g++.dg/template/spec35.C b/gcc/testsuite/g++.dg/template/spec35.C new file mode 100644 index 0000000..801b744 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec35.C @@ -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 +static void f1 (T) { } + +// { dg-final { scan-assembler-not ".glob(a|)l\[\t \]*_Z2f1IfEvT_" } } +template<> +void f1 (float) { } // Expected to have static linkage + +template +void f2 (T) { } + +// { dg-final { scan-assembler ".glob(a|)l\[\t \]*_Z2f2IfEvT_" } } +template<> +void f2 (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 +} -- cgit v1.1