This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 9127


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;
+ }
+ 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]