This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 9127
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 3 Dec 2003 23:02:54 -0800
- Subject: C++ PATCH: PR 9127
- Reply-to: mark at codesourcery dot com
This patch improves error-recovery for invalid explicit
specializations (i.e., explicit specializations that are not preceded
by "template <>" as required).
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-12-03 Mark Mitchell <mark@codesourcery.com>
PR c++/9127
* cp-tree.h (at_namespace_scope_p): New function.
* parser.c (cp_parser_class_head): Handle invalid explicit
specializations.
* search.c (at_namespace_scope_p): New function.
2003-12-03 Mark Mitchell <mark@codesourcery.com>
PR c++/9127
* g++.dg/template/error6.C: New test.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.934
diff -c -5 -p -r1.934 cp-tree.h
*** cp/cp-tree.h 22 Nov 2003 06:49:17 -0000 1.934
--- cp/cp-tree.h 4 Dec 2003 06:59:29 -0000
*************** extern void print_search_statistics (vo
*** 3964,3973 ****
--- 3964,3974 ----
extern void init_search_processing (void);
extern void reinit_search_statistics (void);
extern tree current_scope (void);
extern int at_function_scope_p (void);
extern bool at_class_scope_p (void);
+ extern bool at_namespace_scope_p (void);
extern tree context_for_name_lookup (tree);
extern tree lookup_conversions (tree);
extern tree binfo_for_vtable (tree);
extern tree binfo_from_vbase (tree);
extern tree look_for_overrides_here (tree, tree);
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.125
diff -c -5 -p -r1.125 parser.c
*** cp/parser.c 3 Dec 2003 19:05:10 -0000 1.125
--- cp/parser.c 4 Dec 2003 06:59:30 -0000
*************** cp_parser_class_head (cp_parser* parser,
*** 11582,11591 ****
--- 11582,11592 ----
tree type = NULL_TREE;
tree attributes;
bool template_id_p = false;
bool qualified_p = false;
bool invalid_nested_name_p = false;
+ bool invalid_explicit_specialization_p = false;
unsigned num_templates;
/* Assume no nested-name-specifier will be present. */
*nested_name_specifier_p = false;
/* Assume no template parameter lists will be used in defining the
*************** cp_parser_class_head (cp_parser* parser,
*** 11730,11745 ****
cp_parser_error (parser,
"global qualification of class name is invalid");
else if (invalid_nested_name_p)
cp_parser_error (parser,
"qualified name does not name a class");
/* Make sure that the right number of template parameters were
present. */
if (!cp_parser_check_template_parameters (parser, num_templates))
! /* If something went wrong, there is no point in even trying to
! process the class-definition. */
! return NULL_TREE;
/* Look up the type. */
if (template_id_p)
{
type = TREE_TYPE (id);
--- 11731,11765 ----
cp_parser_error (parser,
"global qualification of class name is invalid");
else if (invalid_nested_name_p)
cp_parser_error (parser,
"qualified name does not name a class");
+ /* An explicit-specialization must be preceded by "template <>". If
+ it is not, try to recover gracefully. */
+ if (at_namespace_scope_p ()
+ && parser->num_template_parameter_lists == 0
+ && num_templates == 1)
+ {
+ error ("an explicit specialization must be preceded by 'template <>'");
+ invalid_explicit_specialization_p = true;
+ /* Take the same action that would have been taken by
+ cp_parser_explicit_specialization. */
+ ++parser->num_template_parameter_lists;
+ begin_specialization ();
+ }
+ /* There must be no "return" statements between this point and the
+ end of this function; set "type "to the correct return value and
+ use "goto done;" to return. */
/* Make sure that the right number of template parameters were
present. */
if (!cp_parser_check_template_parameters (parser, num_templates))
! {
! /* If something went wrong, there is no point in even trying to
! process the class-definition. */
! type = NULL_TREE;
! goto done;
! }
/* Look up the type. */
if (template_id_p)
{
type = TREE_TYPE (id);
*************** cp_parser_class_head (cp_parser* parser,
*** 11787,11797 ****
class was originally declared, the program is invalid. */
if (scope && !is_ancestor (scope, CP_DECL_CONTEXT (type)))
{
error ("declaration of `%D' in `%D' which does not "
"enclose `%D'", type, scope, nested_name_specifier);
! return NULL_TREE;
}
/* [dcl.meaning]
A declarator-id shall not be qualified exception of the
definition of a ... nested class outside of its class
--- 11807,11818 ----
class was originally declared, the program is invalid. */
if (scope && !is_ancestor (scope, CP_DECL_CONTEXT (type)))
{
error ("declaration of `%D' in `%D' which does not "
"enclose `%D'", type, scope, nested_name_specifier);
! type = NULL_TREE;
! goto done;
}
/* [dcl.meaning]
A declarator-id shall not be qualified exception of the
definition of a ... nested class outside of its class
*************** cp_parser_class_head (cp_parser* parser,
*** 11846,11855 ****
--- 11867,11882 ----
/* Leave the scope given by the nested-name-specifier. We will
enter the class scope itself while processing the members. */
if (nested_name_specifier)
pop_scope (nested_name_specifier);
+ done:
+ if (invalid_explicit_specialization_p)
+ {
+ end_specialization ();
+ --parser->num_template_parameter_lists;
+ }
return type;
}
/* Parse a class-key.
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.282
diff -c -5 -p -r1.282 search.c
*** cp/search.c 21 Oct 2003 02:16:15 -0000 1.282
--- cp/search.c 4 Dec 2003 06:59:30 -0000
*************** at_class_scope_p (void)
*** 578,587 ****
--- 578,597 ----
{
tree cs = current_scope ();
return cs && TYPE_P (cs);
}
+ /* Returns true if the innermost active scope is a namespace scope. */
+
+ bool
+ at_namespace_scope_p (void)
+ {
+ /* We are in a namespace scope if we are not it a class scope or a
+ function scope. */
+ return !current_scope();
+ }
+
/* Return the scope of DECL, as appropriate when doing name-lookup. */
tree
context_for_name_lookup (tree decl)
{
Index: testsuite/g++.dg/template/error6.C
===================================================================
RCS file: testsuite/g++.dg/template/error6.C
diff -N testsuite/g++.dg/template/error6.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/error6.C 4 Dec 2003 06:59:31 -0000
***************
*** 0 ****
--- 1,13 ----
+ template<int n>
+ struct tento {
+ enum {value = 10*tento<n-1>::value};
+ };
+
+ struct tento<0> { // { dg-error "" }
+ enum {value=1};
+ };
+
+ int main() {
+ if (tento<4>::value != 10000) return -1;
+ }
+