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:
parent
d448952a83
commit
736b81007e
6 changed files with 120 additions and 8 deletions
|
@ -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>
|
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
|
||||||
|
|
||||||
* typeck.c (build_binary_op): For templates build the
|
* typeck.c (build_binary_op): For templates build the
|
||||||
|
|
|
@ -1913,7 +1913,7 @@ static void cp_parser_template_declaration_after_export
|
||||||
static void cp_parser_perform_template_parameter_access_checks
|
static void cp_parser_perform_template_parameter_access_checks
|
||||||
(VEC (deferred_access_check,gc)*);
|
(VEC (deferred_access_check,gc)*);
|
||||||
static tree cp_parser_single_declaration
|
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
|
static tree cp_parser_functional_cast
|
||||||
(cp_parser *, tree);
|
(cp_parser *, tree);
|
||||||
static tree cp_parser_save_member_function_body
|
static tree cp_parser_save_member_function_body
|
||||||
|
@ -10225,6 +10225,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
|
||||||
cp_parser_single_declaration (parser,
|
cp_parser_single_declaration (parser,
|
||||||
/*checks=*/NULL,
|
/*checks=*/NULL,
|
||||||
/*member_p=*/false,
|
/*member_p=*/false,
|
||||||
|
/*explicit_specialization_p=*/true,
|
||||||
/*friend_p=*/NULL);
|
/*friend_p=*/NULL);
|
||||||
/* We're done with the specialization. */
|
/* We're done with the specialization. */
|
||||||
end_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,
|
decl = cp_parser_single_declaration (parser,
|
||||||
checks,
|
checks,
|
||||||
member_p,
|
member_p,
|
||||||
|
/*explicit_specialization_p=*/false,
|
||||||
&friend_p);
|
&friend_p);
|
||||||
pop_deferring_access_checks ();
|
pop_deferring_access_checks ();
|
||||||
|
|
||||||
|
@ -16575,6 +16577,7 @@ static tree
|
||||||
cp_parser_single_declaration (cp_parser* parser,
|
cp_parser_single_declaration (cp_parser* parser,
|
||||||
VEC (deferred_access_check,gc)* checks,
|
VEC (deferred_access_check,gc)* checks,
|
||||||
bool member_p,
|
bool member_p,
|
||||||
|
bool explicit_specialization_p,
|
||||||
bool* friend_p)
|
bool* friend_p)
|
||||||
{
|
{
|
||||||
int declares_class_or_enum;
|
int declares_class_or_enum;
|
||||||
|
@ -16648,13 +16651,27 @@ cp_parser_single_declaration (cp_parser* parser,
|
||||||
if (!decl
|
if (!decl
|
||||||
&& (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
|
&& (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
|
||||||
|| decl_specifiers.type != error_mark_node))
|
|| decl_specifiers.type != error_mark_node))
|
||||||
decl = cp_parser_init_declarator (parser,
|
{
|
||||||
&decl_specifiers,
|
decl = cp_parser_init_declarator (parser,
|
||||||
checks,
|
&decl_specifiers,
|
||||||
/*function_definition_allowed_p=*/true,
|
checks,
|
||||||
member_p,
|
/*function_definition_allowed_p=*/true,
|
||||||
declares_class_or_enum,
|
member_p,
|
||||||
&function_definition_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 ();
|
pop_deferring_access_checks ();
|
||||||
|
|
||||||
|
|
31
gcc/cp/pt.c
31
gcc/cp/pt.c
|
@ -2193,6 +2193,37 @@ check_explicit_specialization (tree declarator,
|
||||||
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
|
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
|
||||||
TREE_PROTECTED (decl) = TREE_PROTECTED (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
|
/* If DECL is a friend declaration, declared using an
|
||||||
unqualified name, the namespace associated with DECL may
|
unqualified name, the namespace associated with DECL may
|
||||||
have been set incorrectly. For example, in:
|
have been set incorrectly. For example, in:
|
||||||
|
|
|
@ -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>
|
2007-06-18 Kenneth Zadeck <zadeck@naturalbridge.com>
|
||||||
|
|
||||||
* gcc.c-torture/compile/pr32355.c: New testcase.
|
* gcc.c-torture/compile/pr32355.c: New testcase.
|
||||||
|
|
16
gcc/testsuite/g++.dg/template/error25.C
Normal file
16
gcc/testsuite/g++.dg/template/error25.C
Normal 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 ();
|
29
gcc/testsuite/g++.dg/template/spec35.C
Normal file
29
gcc/testsuite/g++.dg/template/spec35.C
Normal 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
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue