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++ PATH: PR 14550


This patch fixes PR 14550, a PR where we ICE'd on new-expressions in
templates because we thought that they were constant-expressions.

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

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

2004-03-13  Mark Mitchell  <mark@codesourcery.com>

	PR c++/14550
	* parser.c (cp_parser_non_integral_constant_expression): Encode
	more of the idiom that surrounded calls to this function within
	the function itself
	(cp_parser_primary_expression): Adjust accordingly.
	(cp_parser_postfix_expression): Likewise.
	(cp_parser_unary_expression): Likewise.
	(cp_parser_cast_expression): Likewise.
	(cp_parser_assignment_expression): Likewise.
	(cp_parser_expression): Likewise.
	(cp_parser_new_expression): Note that new-expressions are not
	allowed in integral constant expressions.
	(cp_parser_delete_expression): Likewise.

2004-03-13  Mark Mitchell  <mark@codesourcery.com>

	PR c++/14550
	* g++.dg/parse/template14.C: New test.

Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.157.2.20
diff -c -5 -p -r1.157.2.20 parser.c
*** cp/parser.c	9 Mar 2004 15:41:35 -0000	1.157.2.20
--- cp/parser.c	13 Mar 2004 16:43:19 -0000
*************** static void cp_parser_check_type_definit
*** 1717,1728 ****
    (cp_parser *);
  static void cp_parser_check_for_definition_in_return_type
    (tree, int);
  static void cp_parser_check_for_invalid_template_id
    (cp_parser *, tree);
! static tree cp_parser_non_integral_constant_expression
!   (const char *);
  static bool cp_parser_diagnose_invalid_type_name
    (cp_parser *);
  static int cp_parser_skip_to_closing_parenthesis
    (cp_parser *, bool, bool, bool);
  static void cp_parser_skip_to_end_of_statement
--- 1717,1728 ----
    (cp_parser *);
  static void cp_parser_check_for_definition_in_return_type
    (tree, int);
  static void cp_parser_check_for_invalid_template_id
    (cp_parser *, tree);
! static bool cp_parser_non_integral_constant_expression
!   (cp_parser *, const char *);
  static bool cp_parser_diagnose_invalid_type_name
    (cp_parser *);
  static int cp_parser_skip_to_closing_parenthesis
    (cp_parser *, bool, bool, bool);
  static void cp_parser_skip_to_end_of_statement
*************** cp_parser_check_for_invalid_template_id 
*** 1916,1933 ****
  	  cp_lexer_purge_tokens_after (parser->lexer, token);
  	}
      }
  }
  
! /* Issue an error message about the fact that THING appeared in a
!    constant-expression.  Returns ERROR_MARK_NODE.  */
  
! static tree
! cp_parser_non_integral_constant_expression (const char *thing)
  {
!   error ("%s cannot appear in a constant-expression", thing);
!   return error_mark_node;
  }
  
  /* Check for a common situation where a type-name should be present,
     but is not, and issue a sensible error message.  Returns true if an
     invalid type-name was detected.  */
--- 1916,1943 ----
  	  cp_lexer_purge_tokens_after (parser->lexer, token);
  	}
      }
  }
  
! /* If parsing an integral constant-expression, issue an error message
!    about the fact that THING appeared and return true.  Otherwise,
!    return false, marking the current expression as non-constant.  */
  
! static bool
! cp_parser_non_integral_constant_expression (cp_parser  *parser,
! 					    const char *thing)
  {
!   if (parser->integral_constant_expression_p)
!     {
!       if (!parser->allow_non_integral_constant_expression_p)
! 	{
! 	  error ("%s cannot appear in a constant-expression", thing);
! 	  return true;
! 	}
!       parser->non_integral_constant_expression_p = true;
!     }
!   return false;
  }
  
  /* Check for a common situation where a type-name should be present,
     but is not, and issue a sensible error message.  Returns true if an
     invalid type-name was detected.  */
*************** cp_parser_primary_expression (cp_parser 
*** 2466,2481 ****
  	    {
  	      error ("`this' may not be used in this context");
  	      return error_mark_node;
  	    }
  	  /* Pointers cannot appear in constant-expressions.  */
! 	  if (parser->integral_constant_expression_p)
! 	    {
! 	      if (!parser->allow_non_integral_constant_expression_p)
! 		return cp_parser_non_integral_constant_expression ("`this'");
! 	      parser->non_integral_constant_expression_p = true;
! 	    }
  	  return finish_this_expr ();
  
  	  /* The `operator' keyword can be the beginning of an
  	     id-expression.  */
  	case RID_OPERATOR:
--- 2476,2488 ----
  	    {
  	      error ("`this' may not be used in this context");
  	      return error_mark_node;
  	    }
  	  /* Pointers cannot appear in constant-expressions.  */
! 	  if (cp_parser_non_integral_constant_expression (parser,
! 							  "`this'"))
! 	    return error_mark_node;
  	  return finish_this_expr ();
  
  	  /* The `operator' keyword can be the beginning of an
  	     id-expression.  */
  	case RID_OPERATOR:
*************** cp_parser_primary_expression (cp_parser 
*** 2513,2528 ****
  	    type = cp_parser_type_id (parser);
  	    /* Look for the closing `)'.  */
  	    cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	    /* Using `va_arg' in a constant-expression is not
  	       allowed.  */
! 	    if (parser->integral_constant_expression_p)
! 	      {
! 		if (!parser->allow_non_integral_constant_expression_p)
! 		  return cp_parser_non_integral_constant_expression ("`va_arg'");
! 		parser->non_integral_constant_expression_p = true;
! 	      }
  	    return build_x_va_arg (expression, type);
  	  }
  
  	case RID_OFFSETOF:
  	  {
--- 2520,2532 ----
  	    type = cp_parser_type_id (parser);
  	    /* Look for the closing `)'.  */
  	    cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	    /* Using `va_arg' in a constant-expression is not
  	       allowed.  */
! 	    if (cp_parser_non_integral_constant_expression (parser,
! 							    "`va_arg'"))
! 	      return error_mark_node;
  	    return build_x_va_arg (expression, type);
  	  }
  
  	case RID_OFFSETOF:
  	  {
*************** cp_parser_postfix_expression (cp_parser 
*** 3442,3459 ****
  	if (parser->integral_constant_expression_p
  	    && !dependent_type_p (type)
  	    && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
  	    /* A cast to pointer or reference type is allowed in the
  	       implementation of "offsetof".  */
! 	    && !(parser->in_offsetof_p && POINTER_TYPE_P (type)))
! 	  {
! 	    if (!parser->allow_non_integral_constant_expression_p)
! 	      return (cp_parser_non_integral_constant_expression 
! 		      ("a cast to a type other than an integral or "
! 		       "enumeration type"));
! 	    parser->non_integral_constant_expression_p = true;
! 	  }
  
  	switch (keyword)
  	  {
  	  case RID_DYNCAST:
  	    postfix_expression
--- 3446,3461 ----
  	if (parser->integral_constant_expression_p
  	    && !dependent_type_p (type)
  	    && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
  	    /* A cast to pointer or reference type is allowed in the
  	       implementation of "offsetof".  */
! 	    && !(parser->in_offsetof_p && POINTER_TYPE_P (type))
! 	    && (cp_parser_non_integral_constant_expression 
! 		(parser,
! 		 "a cast to a type other than an integral or "
! 		 "enumeration type")))
! 	  return error_mark_node;
  
  	switch (keyword)
  	  {
  	  case RID_DYNCAST:
  	    postfix_expression
*************** cp_parser_postfix_expression (cp_parser 
*** 3695,3711 ****
  	    postfix_expression 
  	      = grok_array_decl (postfix_expression, index);
  	    idk = CP_ID_KIND_NONE;
  	    /* Array references are not permitted in
  	       constant-expressions.  */
! 	    if (parser->integral_constant_expression_p)
! 	      {
! 		if (!parser->allow_non_integral_constant_expression_p)
! 		  postfix_expression 
! 		    = cp_parser_non_integral_constant_expression ("an array reference");
! 		parser->non_integral_constant_expression_p = true;
! 	      }
  	  }
  	  break;
  
  	case CPP_OPEN_PAREN:
  	  /* postfix-expression ( expression-list [opt] ) */
--- 3697,3709 ----
  	    postfix_expression 
  	      = grok_array_decl (postfix_expression, index);
  	    idk = CP_ID_KIND_NONE;
  	    /* Array references are not permitted in
  	       constant-expressions.  */
! 	    if (cp_parser_non_integral_constant_expression 
! 		(parser, "an array reference"))
! 	      postfix_expression = error_mark_node;
  	  }
  	  break;
  
  	case CPP_OPEN_PAREN:
  	  /* postfix-expression ( expression-list [opt] ) */
*************** cp_parser_postfix_expression (cp_parser 
*** 3720,3738 ****
  		break;
  	      }
  	    
  	    /* Function calls are not permitted in
  	       constant-expressions.  */
! 	    if (parser->integral_constant_expression_p)
  	      {
! 		if (!parser->allow_non_integral_constant_expression_p)
! 		  {
! 		    postfix_expression 
! 		      = cp_parser_non_integral_constant_expression ("a function call");
! 		    break;
! 		  }
! 		parser->non_integral_constant_expression_p = true;
  	      }
  
  	    koenig_p = false;
  	    if (idk == CP_ID_KIND_UNQUALIFIED)
  	      {
--- 3718,3732 ----
  		break;
  	      }
  	    
  	    /* Function calls are not permitted in
  	       constant-expressions.  */
! 	    if (cp_parser_non_integral_constant_expression (parser,
! 							    "a function call"))
  	      {
! 		postfix_expression = error_mark_node;
! 		break;
  	      }
  
  	    koenig_p = false;
  	    if (idk == CP_ID_KIND_UNQUALIFIED)
  	      {
*************** cp_parser_postfix_expression (cp_parser 
*** 3923,3944 ****
  	    /* We no longer need to look up names in the scope of the
  	       object on the left-hand side of the `.' or `->'
  	       operator.  */
  	    parser->context->object_type = NULL_TREE;
  	    /* These operators may not appear in constant-expressions.  */
! 	    if (parser->integral_constant_expression_p
! 		/* The "->" operator is allowed in the implementation
  		   of "offsetof".  The "." operator may appear in the
  		   name of the member.  */
! 		&& !parser->in_offsetof_p)
! 	      {
! 		if (!parser->allow_non_integral_constant_expression_p)
! 		  postfix_expression 
! 		    = (cp_parser_non_integral_constant_expression 
! 		       (token_type == CPP_DEREF ? "'->'" : "`.'"));
! 		parser->non_integral_constant_expression_p = true;
! 	      }
  	  }
  	  break;
  
  	case CPP_PLUS_PLUS:
  	  /* postfix-expression ++  */
--- 3917,3934 ----
  	    /* We no longer need to look up names in the scope of the
  	       object on the left-hand side of the `.' or `->'
  	       operator.  */
  	    parser->context->object_type = NULL_TREE;
  	    /* These operators may not appear in constant-expressions.  */
! 	    if (/* The "->" operator is allowed in the implementation
  		   of "offsetof".  The "." operator may appear in the
  		   name of the member.  */
! 		!parser->in_offsetof_p
! 		&& (cp_parser_non_integral_constant_expression 
! 		    (parser,
! 		     token_type == CPP_DEREF ? "'->'" : "`.'")))
! 	      postfix_expression = error_mark_node;
  	  }
  	  break;
  
  	case CPP_PLUS_PLUS:
  	  /* postfix-expression ++  */
*************** cp_parser_postfix_expression (cp_parser 
*** 3947,3963 ****
  	  /* Generate a representation for the complete expression.  */
  	  postfix_expression 
  	    = finish_increment_expr (postfix_expression, 
  				     POSTINCREMENT_EXPR);
  	  /* Increments may not appear in constant-expressions.  */
! 	  if (parser->integral_constant_expression_p)
! 	    {
! 	      if (!parser->allow_non_integral_constant_expression_p)
! 		postfix_expression 
! 		  = cp_parser_non_integral_constant_expression ("an increment");
! 	      parser->non_integral_constant_expression_p = true;
! 	    }
  	  idk = CP_ID_KIND_NONE;
  	  break;
  
  	case CPP_MINUS_MINUS:
  	  /* postfix-expression -- */
--- 3937,3949 ----
  	  /* Generate a representation for the complete expression.  */
  	  postfix_expression 
  	    = finish_increment_expr (postfix_expression, 
  				     POSTINCREMENT_EXPR);
  	  /* Increments may not appear in constant-expressions.  */
! 	  if (cp_parser_non_integral_constant_expression (parser,
! 							  "an increment"))
! 	    postfix_expression = error_mark_node;
  	  idk = CP_ID_KIND_NONE;
  	  break;
  
  	case CPP_MINUS_MINUS:
  	  /* postfix-expression -- */
*************** cp_parser_postfix_expression (cp_parser 
*** 3966,3982 ****
  	  /* Generate a representation for the complete expression.  */
  	  postfix_expression 
  	    = finish_increment_expr (postfix_expression, 
  				     POSTDECREMENT_EXPR);
  	  /* Decrements may not appear in constant-expressions.  */
! 	  if (parser->integral_constant_expression_p)
! 	    {
! 	      if (!parser->allow_non_integral_constant_expression_p)
! 		postfix_expression 
! 		  = cp_parser_non_integral_constant_expression ("a decrement");
! 	      parser->non_integral_constant_expression_p = true;
! 	    }
  	  idk = CP_ID_KIND_NONE;
  	  break;
  
  	default:
  	  return postfix_expression;
--- 3952,3964 ----
  	  /* Generate a representation for the complete expression.  */
  	  postfix_expression 
  	    = finish_increment_expr (postfix_expression, 
  				     POSTDECREMENT_EXPR);
  	  /* Decrements may not appear in constant-expressions.  */
! 	  if (cp_parser_non_integral_constant_expression (parser,
! 							  "a decrement"))
! 	    postfix_expression = error_mark_node;
  	  idk = CP_ID_KIND_NONE;
  	  break;
  
  	default:
  	  return postfix_expression;
*************** cp_parser_unary_expression (cp_parser *p
*** 4371,4386 ****
  
  	default:
  	  abort ();
  	}
  
!       if (non_constant_p && parser->integral_constant_expression_p)
! 	{
! 	  if (!parser->allow_non_integral_constant_expression_p)
! 	    return cp_parser_non_integral_constant_expression (non_constant_p);
! 	  parser->non_integral_constant_expression_p = true;
! 	}
  
        return expression;
      }
  
    return cp_parser_postfix_expression (parser, address_p);
--- 4353,4366 ----
  
  	default:
  	  abort ();
  	}
  
!       if (non_constant_p 
! 	  && cp_parser_non_integral_constant_expression (parser,
! 							 non_constant_p))
! 	expression = error_mark_node;
  
        return expression;
      }
  
    return cp_parser_postfix_expression (parser, address_p);
*************** cp_parser_new_expression (cp_parser* par
*** 4477,4486 ****
--- 4457,4471 ----
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
      initializer = cp_parser_new_initializer (parser);
    else
      initializer = NULL_TREE;
  
+   /* A new-expression may not appear in an integral constant
+      expression.  */
+   if (cp_parser_non_integral_constant_expression (parser, "`new'"))
+     return error_mark_node;
+ 
    /* Create a representation of the new-expression.  */
    return build_new (placement, type, initializer, global_scope_p);
  }
  
  /* Parse a new-placement.
*************** cp_parser_delete_expression (cp_parser* 
*** 4705,4714 ****
--- 4690,4704 ----
      array_p = false;
  
    /* Parse the cast-expression.  */
    expression = cp_parser_simple_cast_expression (parser);
  
+   /* A delete-expression may not appear in an integral constant
+      expression.  */
+   if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
+     return error_mark_node;
+ 
    return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
  }
  
  /* Parse a cast-expression.
  
*************** cp_parser_cast_expression (cp_parser *pa
*** 4802,4819 ****
  
  	  /* Only type conversions to integral or enumeration types
  	     can be used in constant-expressions.  */
  	  if (parser->integral_constant_expression_p
  	      && !dependent_type_p (type)
! 	      && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
! 	    {
! 	      if (!parser->allow_non_integral_constant_expression_p)
! 		return (cp_parser_non_integral_constant_expression 
! 			("a casts to a type other than an integral or "
! 			 "enumeration type"));
! 	      parser->non_integral_constant_expression_p = true;
! 	    }
  	  /* Perform the cast.  */
  	  expr = build_c_cast (type, expr);
  	  return expr;
  	}
      }
--- 4792,4808 ----
  
  	  /* Only type conversions to integral or enumeration types
  	     can be used in constant-expressions.  */
  	  if (parser->integral_constant_expression_p
  	      && !dependent_type_p (type)
! 	      && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
! 	      && (cp_parser_non_integral_constant_expression 
! 		  (parser,
! 		   "a casts to a type other than an integral or "
! 		   "enumeration type")))
! 	    return error_mark_node;
! 
  	  /* Perform the cast.  */
  	  expr = build_c_cast (type, expr);
  	  return expr;
  	}
      }
*************** cp_parser_assignment_expression (cp_pars
*** 5162,5177 ****
  
  	      /* Parse the right-hand side of the assignment.  */
  	      rhs = cp_parser_assignment_expression (parser);
  	      /* An assignment may not appear in a
  		 constant-expression.  */
! 	      if (parser->integral_constant_expression_p)
! 		{
! 		  if (!parser->allow_non_integral_constant_expression_p)
! 		    return cp_parser_non_integral_constant_expression ("an assignment");
! 		  parser->non_integral_constant_expression_p = true;
! 		}
  	      /* Build the assignment expression.  */
  	      expr = build_x_modify_expr (expr, 
  					  assignment_operator, 
  					  rhs);
  	    }
--- 5151,5163 ----
  
  	      /* Parse the right-hand side of the assignment.  */
  	      rhs = cp_parser_assignment_expression (parser);
  	      /* An assignment may not appear in a
  		 constant-expression.  */
! 	      if (cp_parser_non_integral_constant_expression (parser,
! 							      "an assignment"))
! 		return error_mark_node;
  	      /* Build the assignment expression.  */
  	      expr = build_x_modify_expr (expr, 
  					  assignment_operator, 
  					  rhs);
  	    }
*************** cp_parser_expression (cp_parser* parser)
*** 5305,5321 ****
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
  	break;
        /* Consume the `,'.  */
        cp_lexer_consume_token (parser->lexer);
        /* A comma operator cannot appear in a constant-expression.  */
!       if (parser->integral_constant_expression_p)
! 	{
! 	  if (!parser->allow_non_integral_constant_expression_p)
! 	    expression 
! 	      = cp_parser_non_integral_constant_expression ("a comma operator");
! 	  parser->non_integral_constant_expression_p = true;
! 	}
      }
  
    return expression;
  }
  
--- 5291,5303 ----
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
  	break;
        /* Consume the `,'.  */
        cp_lexer_consume_token (parser->lexer);
        /* A comma operator cannot appear in a constant-expression.  */
!       if (cp_parser_non_integral_constant_expression (parser,
! 						      "a comma operator"))
! 	expression = error_mark_node;
      }
  
    return expression;
  }
  
Index: testsuite/g++.dg/parse/template14.C
===================================================================
RCS file: testsuite/g++.dg/parse/template14.C
diff -N testsuite/g++.dg/parse/template14.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/template14.C	13 Mar 2004 16:43:19 -0000
***************
*** 0 ****
--- 1,17 ----
+ // PR c++/14550
+ 
+ struct A { 
+   A();
+ };
+ 
+ template <int> void foo()
+ {
+   A *p = new A;
+ }
+ 
+ void bar()
+ {
+   foo<0>();
+ }
+ 
+ 


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