C++ PATCH: PR 18124, 18155, 18177

Mark Mitchell mark@codesourcery.com
Wed Nov 3 02:55:00 GMT 2004


This patch fixes three minor C++ regressions.  PR 18124 was a case
where we just didn't check for error_mark_node.  PR 18155 was a case
where we didn't check for invalid template typedefs when no
typedef-name was specified.  I was able to improve error recovery
there a little bit too, which removed a pointless error on
g++.dg/parse/crash13.C.  And PR 18177 was an ice-on-invalid when using
a const_cast on an undeclared variable.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com


2004-11-02  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18124
	* parser.c (cp_parser_type_parameter): Robustify.

	PR c++/18155
	* parser.c (cp_parser_single_declaration): Disallow template
	typedefs.

	PR c++/18177
	* typeck.c (build_const_cast): Use error_operand_p.

2004-11-02  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18124
	* g++.dg/template/crash25.C: New test.

	PR c++/18155
	* g++.dg/template/typedef2.C: New test.
	* g++.dg/parse/crash13.C: Adjust error markers.

	PR c++/18177
	* g++.dg/conversion/const3.C: New test.

Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.275
diff -c -5 -p -r1.275 parser.c
*** cp/parser.c	1 Nov 2004 09:47:57 -0000	1.275
--- cp/parser.c	3 Nov 2004 02:24:28 -0000
*************** cp_parser_type_parameter (cp_parser* par
*** 8184,8196 ****
  	   the end of the parameter-list.  If the next token is a `,',
  	   then we are at the end of this parameter.  */
  	if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
  	    && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)
  	    && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
! 	  identifier = cp_parser_identifier (parser);
  	else
  	  identifier = NULL_TREE;
  	/* Create the template parameter.  */
  	parameter = finish_template_template_parm (class_type_node,
  						   identifier);
  
  	/* If the next token is an `=', then there is a
--- 8184,8202 ----
  	   the end of the parameter-list.  If the next token is a `,',
  	   then we are at the end of this parameter.  */
  	if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
  	    && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)
  	    && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
! 	  {
! 	    identifier = cp_parser_identifier (parser);
! 	    /* Treat invalid names as if the parameter were nameless. */
! 	    if (identifier == error_mark_node)
! 	      identifier = NULL_TREE;
! 	  }
  	else
  	  identifier = NULL_TREE;
+ 
  	/* Create the template parameter.  */
  	parameter = finish_template_template_parm (class_type_node,
  						   identifier);
  
  	/* If the next token is an `=', then there is a
*************** cp_parser_type_parameter (cp_parser* par
*** 8229,8247 ****
  	else
  	  default_argument = NULL_TREE;
  
  	/* Create the combined representation of the parameter and the
  	   default argument.  */
! 	parameter =  build_tree_list (default_argument, parameter);
        }
        break;
  
      default:
!       /* Anything else is an error.  */
!       cp_parser_error (parser,
! 		       "expected %<class%>, %<typename%>, or %<template%>");
!       parameter = error_mark_node;
      }
  
    return parameter;
  }
  
--- 8235,8251 ----
  	else
  	  default_argument = NULL_TREE;
  
  	/* Create the combined representation of the parameter and the
  	   default argument.  */
! 	parameter = build_tree_list (default_argument, parameter);
        }
        break;
  
      default:
!       gcc_unreachable ();
!       break;
      }
  
    return parameter;
  }
  
*************** cp_parser_single_declaration (cp_parser*
*** 14799,14808 ****
--- 14803,14817 ----
    int declares_class_or_enum;
    tree decl = NULL_TREE;
    cp_decl_specifier_seq decl_specifiers;
    bool function_definition_p = false;
  
+   /* This function is only used when processing a template
+      declaration.  */
+   gcc_assert (innermost_scope_kind () == sk_template_parms
+ 	      || innermost_scope_kind () == sk_template_spec);
+ 
    /* Defer access checks until we know what is being declared.  */
    push_deferring_access_checks (dk_deferred);
  
    /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
       alternative.  */
*************** cp_parser_single_declaration (cp_parser*
*** 14810,14819 ****
--- 14819,14836 ----
  				CP_PARSER_FLAGS_OPTIONAL,
  				&decl_specifiers,
  				&declares_class_or_enum);
    if (friend_p)
      *friend_p = cp_parser_friend_p (&decl_specifiers);
+ 
+   /* There are no template typedefs.  */
+   if (decl_specifiers.specs[(int) ds_typedef])
+     {
+       error ("template declaration of %qs", "typedef");
+       decl = error_mark_node;
+     }
+ 
    /* Gather up the access checks that occurred the
       decl-specifier-seq.  */
    stop_deferring_access_checks ();
  
    /* Check for the declaration of a template class.  */
*************** cp_parser_single_declaration (cp_parser*
*** 14841,14852 ****
  	    decl = TYPE_NAME (decl);
  	  else
  	    decl = error_mark_node;
  	}
      }
-   else
-     decl = NULL_TREE;
    /* If it's not a template class, try for a template function.  If
       the next token is a `;', then this declaration does not declare
       anything.  But, if there were errors in the decl-specifiers, then
       the error might well have come from an attempted class-specifier.
       In that case, there's no need to warn about a missing declarator.  */
--- 14858,14867 ----
*************** cp_parser_single_declaration (cp_parser*
*** 14867,14877 ****
    parser->scope = NULL_TREE;
    parser->qualifying_scope = NULL_TREE;
    parser->object_scope = NULL_TREE;
    /* Look for a trailing `;' after the declaration.  */
    if (!function_definition_p
!       && !cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
      cp_parser_skip_to_end_of_block_or_statement (parser);
  
    return decl;
  }
  
--- 14882,14893 ----
    parser->scope = NULL_TREE;
    parser->qualifying_scope = NULL_TREE;
    parser->object_scope = NULL_TREE;
    /* Look for a trailing `;' after the declaration.  */
    if (!function_definition_p
!       && (decl == error_mark_node
! 	  || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
      cp_parser_skip_to_end_of_block_or_statement (parser);
  
    return decl;
  }
  
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.418
diff -c -5 -p -r1.418 tree.c
*** cp/tree.c	18 Oct 2004 17:21:28 -0000	1.418
--- cp/tree.c	3 Nov 2004 02:24:28 -0000
*************** pod_type_p (tree t)
*** 1714,1724 ****
      return 1; /* pointer to non-member */
    if (TYPE_PTR_TO_MEMBER_P (t))
      return 1; /* pointer to member */
  
    if (TREE_CODE (t) == VECTOR_TYPE)
!     return 1; /* vectors are (small) arrays if scalars */
  
    if (! CLASS_TYPE_P (t))
      return 0; /* other non-class type (reference or function) */
    if (CLASSTYPE_NON_POD_P (t))
      return 0;
--- 1714,1724 ----
      return 1; /* pointer to non-member */
    if (TYPE_PTR_TO_MEMBER_P (t))
      return 1; /* pointer to member */
  
    if (TREE_CODE (t) == VECTOR_TYPE)
!     return 1; /* vectors are (small) arrays of scalars */
  
    if (! CLASS_TYPE_P (t))
      return 0; /* other non-class type (reference or function) */
    if (CLASSTYPE_NON_POD_P (t))
      return 0;
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.591
diff -c -5 -p -r1.591 typeck.c
*** cp/typeck.c	1 Nov 2004 09:47:59 -0000	1.591
--- cp/typeck.c	3 Nov 2004 02:24:31 -0000
*************** build_const_cast_1 (tree dst_type, tree 
*** 5097,5107 ****
  }
  
  tree
  build_const_cast (tree type, tree expr)
  {
!   if (type == error_mark_node || expr == error_mark_node)
      return error_mark_node;
  
    if (processing_template_decl)
      {
        tree t = build_min (CONST_CAST_EXPR, type, expr);
--- 5097,5107 ----
  }
  
  tree
  build_const_cast (tree type, tree expr)
  {
!   if (type == error_mark_node || error_operand_p (expr))
      return error_mark_node;
  
    if (processing_template_decl)
      {
        tree t = build_min (CONST_CAST_EXPR, type, expr);
Index: testsuite/g++.dg/conversion/const3.C
===================================================================
RCS file: testsuite/g++.dg/conversion/const3.C
diff -N testsuite/g++.dg/conversion/const3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/conversion/const3.C	3 Nov 2004 02:24:31 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/18177
+ 
+ void foo()
+ {
+   X; // { dg-error "" }
+   const_cast<int&>(X);
+ }
Index: testsuite/g++.dg/parse/crash13.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/parse/crash13.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 crash13.C
*** testsuite/g++.dg/parse/crash13.C	9 Mar 2004 08:16:49 -0000	1.2
--- testsuite/g++.dg/parse/crash13.C	3 Nov 2004 02:24:31 -0000
*************** struct A 
*** 11,21 ****
      {};
  };
  
  template <typename T> 
  void func(A<T>::B* )	// { dg-error "variable|template|expression" }
! {			// { dg-error ";" }
  }
  
  int main() 
  {
    func<void>(0);	// { dg-error "not declared|expression|;" }
--- 11,21 ----
      {};
  };
  
  template <typename T> 
  void func(A<T>::B* )	// { dg-error "variable|template|expression" }
! {
  }
  
  int main() 
  {
    func<void>(0);	// { dg-error "not declared|expression|;" }
Index: testsuite/g++.dg/template/crash25.C
===================================================================
RCS file: testsuite/g++.dg/template/crash25.C
diff -N testsuite/g++.dg/template/crash25.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/crash25.C	3 Nov 2004 02:24:31 -0000
***************
*** 0 ****
--- 1,3 ----
+ // PR c++/18124
+ 
+ template <template <int> class class> class A {}; // { dg-error "" }
Index: testsuite/g++.dg/template/typedef2.C
===================================================================
RCS file: testsuite/g++.dg/template/typedef2.C
diff -N testsuite/g++.dg/template/typedef2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/typedef2.C	3 Nov 2004 02:24:31 -0000
***************
*** 0 ****
--- 1,3 ----
+ // PR c++/18155
+ 
+ template<int> typedef struct A; // { dg-error "" }



More information about the Gcc-patches mailing list