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: PRs 19787, 19732, 19762, 19862, 19739


This patch fixes a handful of regressions:

* 19787 -- An ice-on-invalid where we were failing to check for
  error_mark_node.

* 19732 -- We were failing to check for various incorrect uses of
  destructor names to declare things that are not destructors.

* 19762 -- When encountering invalid destructor names, we crashed.
  (In general it's bad to create expressions that have an
  error_mark_node ntested in them somewhere; much better if the entire
  expression collapses to the error_mark_node.)

* 19826 -- A rejects-valid for uses of type-dependent expressions as
  array bounds in templates.

* 19739 -- An ice-on-valid for an obscure use of empty attribute
  lists. 

Tested on x86_64-unknown-linux-gnu, applied on the mainline.  Those
PRs that are 3.4 regressions will also go there, as soon as tests
complete. 

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

2005-02-09  Mark Mitchell  <mark@codesourcery.com>

	PR c++/19787
	* call.c (initialize_reference): Robustify.

	PR ++/19732
	* decl.c (grokdeclarator): Check for invalid use of destructor
	names.

	PR c++/19762
	* parser.c (cp_parser_unqualified_id): Avoid creating destructor
	names with invalid types.

	PR c++/19826
	* parser.c (cp_parser_direct_declarator): Allow type-dependent
	expressions as array bounds.

	PR c++/19739
	* parser.c (cp_parser_attributes_list): Allow empty lists.

2005-02-09  Mark Mitchell  <mark@codesourcery.com>

	PR c++/19787
	* g++.dg/conversion/ambig1.C: New test.

	PR c++/19739
	* g++.dg/ext/attrib19.C: New test.

	PR c++/19732
	* g++.dg/parse/dtor5.C: New test.

	PR c++/19762
	* g++.dg/template/dtor3.C: New test.

	PR c++/19826
	* g++.dg/template/static11.C: New test.
	* g++.dg/template/crash2.C: Remove dg-error marker.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.528
diff -c -5 -p -r1.528 call.c
*** cp/call.c	31 Jan 2005 01:16:53 -0000	1.528
--- cp/call.c	10 Feb 2005 00:26:04 -0000
*************** initialize_reference (tree type, tree ex
*** 6532,6616 ****
        expr = convert_like_real (conv, expr,
  				/*fn=*/NULL_TREE, /*argnum=*/0,
  				/*inner=*/-1,
  				/*issue_conversion_warnings=*/true,
  				/*c_cast_p=*/false);
!       if (!real_lvalue_p (expr))
  	{
! 	  tree init;
! 	  tree type;
! 
! 	  /* Create the temporary variable.  */
! 	  type = TREE_TYPE (expr);
! 	  var = make_temporary_var_for_ref_to_temp (decl, type);
! 	  layout_decl (var, 0);
! 	  /* If the rvalue is the result of a function call it will be
! 	     a TARGET_EXPR.  If it is some other construct (such as a
! 	     member access expression where the underlying object is
! 	     itself the result of a function call), turn it into a
! 	     TARGET_EXPR here.  It is important that EXPR be a
! 	     TARGET_EXPR below since otherwise the INIT_EXPR will
! 	     attempt to make a bitwise copy of EXPR to initialize
! 	     VAR.  */
! 	  if (TREE_CODE (expr) != TARGET_EXPR)
! 	    expr = get_target_expr (expr);
! 	  /* Create the INIT_EXPR that will initialize the temporary
! 	     variable.  */
! 	  init = build2 (INIT_EXPR, type, var, expr);
! 	  if (at_function_scope_p ())
  	    {
! 	      add_decl_expr (var);
! 	      *cleanup = cxx_maybe_build_cleanup (var);
  
! 	      /* We must be careful to destroy the temporary only
! 		 after its initialization has taken place.  If the
! 		 initialization throws an exception, then the
! 		 destructor should not be run.  We cannot simply
! 		 transform INIT into something like:
! 	     
! 		     (INIT, ({ CLEANUP_STMT; }))
! 
! 		 because emit_local_var always treats the
! 		 initializer as a full-expression.  Thus, the
! 		 destructor would run too early; it would run at the
! 		 end of initializing the reference variable, rather
! 		 than at the end of the block enclosing the
! 		 reference variable.
! 
! 		 The solution is to pass back a cleanup expression
! 		 which the caller is responsible for attaching to
! 		 the statement tree.  */
  	    }
  	  else
! 	    {
! 	      rest_of_decl_compilation (var, /*toplev=*/1, at_eof);
! 	      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
! 		static_aggregates = tree_cons (NULL_TREE, var,
! 					       static_aggregates);
! 	    }
! 	  /* Use its address to initialize the reference variable.  */
! 	  expr = build_address (var);
  	  if (base_conv_type)
! 	    expr = convert_to_base (expr, 
! 				    build_pointer_type (base_conv_type),
! 				    /*check_access=*/true,
! 				    /*nonnull=*/true);
! 	  expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
  	}
-       else
- 	/* Take the address of EXPR.  */
- 	expr = build_unary_op (ADDR_EXPR, expr, 0);
-       /* If a BASE_CONV was required, perform it now.  */
-       if (base_conv_type)
- 	expr = (perform_implicit_conversion 
- 		(build_pointer_type (base_conv_type), expr));
-       expr = build_nop (type, expr);
      }
    else
      /* Perform the conversion.  */
      expr = convert_like (conv, expr);
!   
    /* Free all the conversions we allocated.  */
    obstack_free (&conversion_obstack, p);
  
    return expr;
  }
--- 6532,6621 ----
        expr = convert_like_real (conv, expr,
  				/*fn=*/NULL_TREE, /*argnum=*/0,
  				/*inner=*/-1,
  				/*issue_conversion_warnings=*/true,
  				/*c_cast_p=*/false);
!       if (error_operand_p (expr))
! 	expr = error_mark_node;
!       else
  	{
! 	  if (!real_lvalue_p (expr))
  	    {
! 	      tree init;
! 	      tree type;
  
! 	      /* Create the temporary variable.  */
! 	      type = TREE_TYPE (expr);
! 	      var = make_temporary_var_for_ref_to_temp (decl, type);
! 	      layout_decl (var, 0);
! 	      /* If the rvalue is the result of a function call it will be
! 		 a TARGET_EXPR.  If it is some other construct (such as a
! 		 member access expression where the underlying object is
! 		 itself the result of a function call), turn it into a
! 		 TARGET_EXPR here.  It is important that EXPR be a
! 		 TARGET_EXPR below since otherwise the INIT_EXPR will
! 		 attempt to make a bitwise copy of EXPR to initialize
! 		 VAR.  */
! 	      if (TREE_CODE (expr) != TARGET_EXPR)
! 		expr = get_target_expr (expr);
! 	      /* Create the INIT_EXPR that will initialize the temporary
! 		 variable.  */
! 	      init = build2 (INIT_EXPR, type, var, expr);
! 	      if (at_function_scope_p ())
! 		{
! 		  add_decl_expr (var);
! 		  *cleanup = cxx_maybe_build_cleanup (var);
! 
! 		  /* We must be careful to destroy the temporary only
! 		     after its initialization has taken place.  If the
! 		     initialization throws an exception, then the
! 		     destructor should not be run.  We cannot simply
! 		     transform INIT into something like:
! 
! 			 (INIT, ({ CLEANUP_STMT; }))
! 
! 		     because emit_local_var always treats the
! 		     initializer as a full-expression.  Thus, the
! 		     destructor would run too early; it would run at the
! 		     end of initializing the reference variable, rather
! 		     than at the end of the block enclosing the
! 		     reference variable.
! 
! 		     The solution is to pass back a cleanup expression
! 		     which the caller is responsible for attaching to
! 		     the statement tree.  */
! 		}
! 	      else
! 		{
! 		  rest_of_decl_compilation (var, /*toplev=*/1, at_eof);
! 		  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
! 		    static_aggregates = tree_cons (NULL_TREE, var,
! 						   static_aggregates);
! 		}
! 	      /* Use its address to initialize the reference variable.  */
! 	      expr = build_address (var);
! 	      if (base_conv_type)
! 		expr = convert_to_base (expr, 
! 					build_pointer_type (base_conv_type),
! 					/*check_access=*/true,
! 					/*nonnull=*/true);
! 	      expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
  	    }
  	  else
! 	    /* Take the address of EXPR.  */
! 	    expr = build_unary_op (ADDR_EXPR, expr, 0);
! 	  /* If a BASE_CONV was required, perform it now.  */
  	  if (base_conv_type)
! 	    expr = (perform_implicit_conversion 
! 		    (build_pointer_type (base_conv_type), expr));
! 	  expr = build_nop (type, expr);
  	}
      }
    else
      /* Perform the conversion.  */
      expr = convert_like (conv, expr);
! 
    /* Free all the conversions we allocated.  */
    obstack_free (&conversion_obstack, p);
  
    return expr;
  }
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1360
diff -c -5 -p -r1.1360 decl.c
*** cp/decl.c	9 Feb 2005 02:53:37 -0000	1.1360
--- cp/decl.c	10 Feb 2005 00:26:04 -0000
*************** grokdeclarator (const cp_declarator *dec
*** 6551,6563 ****
  	      return error_mark_node;
  	    switch (TREE_CODE (decl))
  	      {
  	      case BIT_NOT_EXPR:
  		{
! 		  tree type = TREE_OPERAND (decl, 0);
! 		  type = constructor_name (type);
! 		  name = IDENTIFIER_POINTER (type);
  		}
  		break;
  
  	      case TEMPLATE_ID_EXPR:
  		{
--- 6551,6576 ----
  	      return error_mark_node;
  	    switch (TREE_CODE (decl))
  	      {
  	      case BIT_NOT_EXPR:
  		{
! 		  tree type;
! 
! 		  if (innermost_code != cdk_function)
! 		    {
! 		      error ("declaration of %qD as non-function", decl);
! 		      return error_mark_node;
! 		    }
! 		  else if (!qualifying_scope 
! 			   && !(current_class_type && at_class_scope_p ()))
! 		    {
! 		      error ("declaration of %qD as non-member", decl);
! 		      return error_mark_node;
! 		    }
! 		  
! 		  type = TREE_OPERAND (decl, 0);
! 		  name = IDENTIFIER_POINTER (constructor_name (type));
  		}
  		break;
  
  	      case TEMPLATE_ID_EXPR:
  		{
*************** grokdeclarator (const cp_declarator *dec
*** 7801,7819 ****
  	else if (TREE_CODE (type) == FUNCTION_TYPE)
  	  {
  	    int publicp = 0;
  	    tree function_context;
  
- 	    /* We catch the others as conflicts with the builtin
- 	       typedefs.  */
- 	    if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED])
- 	      {
- 		error ("function %qD cannot be declared friend",
- 		       unqualified_id);
- 		friendp = 0;
- 	      }
- 
  	    if (friendp == 0)
  	      {
  		if (ctype == NULL_TREE)
  		  ctype = current_class_type;
  
--- 7814,7823 ----
*************** grokdeclarator (const cp_declarator *dec
*** 7847,7856 ****
--- 7851,7872 ----
  		  type = build_method_type_directly (ctype,
  						     TREE_TYPE (type),
  						     TYPE_ARG_TYPES (type));
  	      }
  
+ 	    /* Check that the name used for a destructor makes sense.  */
+ 	    if (sfk == sfk_destructor
+ 		&& !same_type_p (TREE_OPERAND 
+ 				 (id_declarator->u.id.unqualified_name, 0),
+ 				 ctype))
+ 	      {
+ 		error ("declaration of %qD as member of %qT", 
+ 		       id_declarator->u.id.unqualified_name,
+ 		       ctype);
+ 		return error_mark_node;
+ 	      }
+ 
  	    /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
  	    function_context = (ctype != NULL_TREE) ?
  	      decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
  	    publicp = (! friendp || ! staticp)
  	      && function_context == NULL_TREE;
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.313
diff -c -5 -p -r1.313 parser.c
*** cp/parser.c	9 Feb 2005 02:53:38 -0000	1.313
--- cp/parser.c	10 Feb 2005 00:26:06 -0000
*************** cp_parser_unqualified_id (cp_parser* par
*** 3171,3180 ****
--- 3171,3181 ----
        {
  	tree type_decl;
  	tree qualifying_scope;
  	tree object_scope;
  	tree scope;
+ 	bool done;
  
  	/* Consume the `~' token.  */
  	cp_lexer_consume_token (parser->lexer);
  	/* Parse the class-name.  The standard, as written, seems to
  	   say that:
*************** cp_parser_unqualified_id (cp_parser* par
*** 3227,3236 ****
--- 3228,3238 ----
  	    return build_nt (BIT_NOT_EXPR, scope);
  	  }
  
  	/* If there was an explicit qualification (S::~T), first look
  	   in the scope given by the qualification (i.e., S).  */
+ 	done = false;
  	if (scope)
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    type_decl = cp_parser_class_name (parser,
  					      /*typename_keyword_p=*/false,
*************** cp_parser_unqualified_id (cp_parser* par
*** 3238,3251 ****
  					      none_type,
  					      /*check_dependency=*/false,
  					      /*class_head_p=*/false,
  					      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
! 	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
  	  }
  	/* In "N::S::~S", look in "N" as well.  */
! 	if (scope && qualifying_scope)
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    parser->scope = qualifying_scope;
  	    parser->object_scope = NULL_TREE;
  	    parser->qualifying_scope = NULL_TREE;
--- 3240,3253 ----
  					      none_type,
  					      /*check_dependency=*/false,
  					      /*class_head_p=*/false,
  					      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
! 	      done = true;
  	  }
  	/* In "N::S::~S", look in "N" as well.  */
! 	if (!done && scope && qualifying_scope)
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    parser->scope = qualifying_scope;
  	    parser->object_scope = NULL_TREE;
  	    parser->qualifying_scope = NULL_TREE;
*************** cp_parser_unqualified_id (cp_parser* par
*** 3256,3269 ****
  				      none_type,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
! 	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
  	  }
  	/* In "p->S::~T", look in the scope given by "*p" as well.  */
! 	else if (object_scope)
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    parser->scope = object_scope;
  	    parser->object_scope = NULL_TREE;
  	    parser->qualifying_scope = NULL_TREE;
--- 3258,3271 ----
  				      none_type,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
! 	      done = true;
  	  }
  	/* In "p->S::~T", look in the scope given by "*p" as well.  */
! 	else if (!done && object_scope)
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    parser->scope = object_scope;
  	    parser->object_scope = NULL_TREE;
  	    parser->qualifying_scope = NULL_TREE;
*************** cp_parser_unqualified_id (cp_parser* par
*** 3274,3297 ****
  				      none_type,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
! 	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
  	  }
  	/* Look in the surrounding context.  */
! 	parser->scope = NULL_TREE;
! 	parser->object_scope = NULL_TREE;
! 	parser->qualifying_scope = NULL_TREE;
! 	type_decl
! 	  = cp_parser_class_name (parser,
! 				  /*typename_keyword_p=*/false,
! 				  /*template_keyword_p=*/false,
! 				  none_type,
! 				  /*check_dependency=*/false,
! 				  /*class_head_p=*/false,
! 				  declarator_p);
  	/* If an error occurred, assume that the name of the
  	   destructor is the same as the name of the qualifying
  	   class.  That allows us to keep parsing after running
  	   into ill-formed destructor names.  */
  	if (type_decl == error_mark_node && scope && TYPE_P (scope))
--- 3276,3302 ----
  				      none_type,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
! 	      done = true;
  	  }
  	/* Look in the surrounding context.  */
! 	if (!done)
! 	  {
! 	    parser->scope = NULL_TREE;
! 	    parser->object_scope = NULL_TREE;
! 	    parser->qualifying_scope = NULL_TREE;
! 	    type_decl
! 	      = cp_parser_class_name (parser,
! 				      /*typename_keyword_p=*/false,
! 				      /*template_keyword_p=*/false,
! 				      none_type,
! 				      /*check_dependency=*/false,
! 				      /*class_head_p=*/false,
! 				      declarator_p);
! 	  }
  	/* If an error occurred, assume that the name of the
  	   destructor is the same as the name of the qualifying
  	   class.  That allows us to keep parsing after running
  	   into ill-formed destructor names.  */
  	if (type_decl == error_mark_node && scope && TYPE_P (scope))
*************** cp_parser_direct_declarator (cp_parser* 
*** 11097,11107 ****
  		= cp_parser_constant_expression (parser,
  						 /*allow_non_constant=*/true,
  						 &non_constant_p);
  	      if (!non_constant_p)
  		bounds = fold_non_dependent_expr (bounds);
! 	      else if (!at_function_scope_p ())
  		{
  		  error ("array bound is not an integer constant");
  		  bounds = error_mark_node;
  		}
  	    }
--- 11102,11122 ----
  		= cp_parser_constant_expression (parser,
  						 /*allow_non_constant=*/true,
  						 &non_constant_p);
  	      if (!non_constant_p)
  		bounds = fold_non_dependent_expr (bounds);
! 	      /* Normally, the array bound must be an integral constant
! 		 expression.  However, as an extension, we allow VLAs
! 		 in function scopes.  And, we allow type-dependent
! 		 expressions in templates; sometimes we don't know for
! 		 sure whether or not something is a valid integral
! 		 constant expression until instantiation time.  (It
! 		 doesn't make sense to check for value-dependency, as
! 		 an expression is only value-dependent when it is a
! 		 constant expression.)  */  
! 	      else if (!type_dependent_expression_p (bounds)
! 		       && !at_function_scope_p ())
  		{
  		  error ("array bound is not an integer constant");
  		  bounds = error_mark_node;
  		}
  	    }
*************** cp_parser_attributes_opt (cp_parser* par
*** 14040,14053 ****
       identifier
       identifier ( identifier )
       identifier ( identifier , expression-list )
       identifier ( expression-list )
  
!    Returns a TREE_LIST.  Each node corresponds to an attribute.  THe
!    TREE_PURPOSE of each node is the identifier indicating which
!    attribute is in use.  The TREE_VALUE represents the arguments, if
!    any.  */
  
  static tree
  cp_parser_attribute_list (cp_parser* parser)
  {
    tree attribute_list = NULL_TREE;
--- 14055,14068 ----
       identifier
       identifier ( identifier )
       identifier ( identifier , expression-list )
       identifier ( expression-list )
  
!    Returns a TREE_LIST, or NULL_TREE on error.  Each node corresponds
!    to an attribute.  The TREE_PURPOSE of each node is the identifier
!    indicating which attribute is in use.  The TREE_VALUE represents
!    the arguments, if any.  */
  
  static tree
  cp_parser_attribute_list (cp_parser* parser)
  {
    tree attribute_list = NULL_TREE;
*************** cp_parser_attribute_list (cp_parser* par
*** 14061,14101 ****
        tree attribute;
  
        /* Look for the identifier.  We also allow keywords here; for
  	 example `__attribute__ ((const))' is legal.  */
        token = cp_lexer_peek_token (parser->lexer);
!       if (token->type != CPP_NAME
! 	  && token->type != CPP_KEYWORD)
! 	return error_mark_node;
!       /* Consume the token.  */
!       token = cp_lexer_consume_token (parser->lexer);
  
!       /* Save away the identifier that indicates which attribute this is.  */
!       identifier = token->value;
!       attribute = build_tree_list (identifier, NULL_TREE);
  
!       /* Peek at the next token.  */
!       token = cp_lexer_peek_token (parser->lexer);
!       /* If it's an `(', then parse the attribute arguments.  */
!       if (token->type == CPP_OPEN_PAREN)
! 	{
! 	  tree arguments;
  
! 	  arguments = (cp_parser_parenthesized_expression_list
! 		       (parser, true, /*cast_p=*/false, 
! 			/*non_constant_p=*/NULL));
! 	  /* Save the identifier and arguments away.  */
! 	  TREE_VALUE (attribute) = arguments;
! 	}
  
!       /* Add this attribute to the list.  */
!       TREE_CHAIN (attribute) = attribute_list;
!       attribute_list = attribute;
  
!       /* Now, look for more attributes.  */
!       token = cp_lexer_peek_token (parser->lexer);
!       /* If the next token isn't a `,', we're done.  */
        if (token->type != CPP_COMMA)
  	break;
  
        /* Consume the comma and keep going.  */
        cp_lexer_consume_token (parser->lexer);
--- 14076,14118 ----
        tree attribute;
  
        /* Look for the identifier.  We also allow keywords here; for
  	 example `__attribute__ ((const))' is legal.  */
        token = cp_lexer_peek_token (parser->lexer);
!       if (token->type == CPP_NAME
! 	  || token->type == CPP_KEYWORD)
! 	{
! 	  /* Consume the token.  */
! 	  token = cp_lexer_consume_token (parser->lexer);
  
! 	  /* Save away the identifier that indicates which attribute
! 	     this is.  */ 
! 	  identifier = token->value;
! 	  attribute = build_tree_list (identifier, NULL_TREE);
  
! 	  /* Peek at the next token.  */
! 	  token = cp_lexer_peek_token (parser->lexer);
! 	  /* If it's an `(', then parse the attribute arguments.  */
! 	  if (token->type == CPP_OPEN_PAREN)
! 	    {
! 	      tree arguments;
  
! 	      arguments = (cp_parser_parenthesized_expression_list
! 			   (parser, true, /*cast_p=*/false, 
! 			    /*non_constant_p=*/NULL));
! 	      /* Save the identifier and arguments away.  */
! 	      TREE_VALUE (attribute) = arguments;
! 	    }
  
! 	  /* Add this attribute to the list.  */
! 	  TREE_CHAIN (attribute) = attribute_list;
! 	  attribute_list = attribute;
  
! 	  token = cp_lexer_peek_token (parser->lexer);
! 	}
!       /* Now, look for more attributes.  If the next token isn't a
! 	 `,', we're done.  */
        if (token->type != CPP_COMMA)
  	break;
  
        /* Consume the comma and keep going.  */
        cp_lexer_consume_token (parser->lexer);
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/ChangeLog,v
retrieving revision 1.5005
diff -c -5 -p -r1.5005 ChangeLog
*** testsuite/ChangeLog	9 Feb 2005 02:53:21 -0000	1.5005
--- testsuite/ChangeLog	10 Feb 2005 00:26:20 -0000
***************
*** 1,5 ****
--- 1,23 ----
+ 2005-02-09  Mark Mitchell  <mark@codesourcery.com>
+ 
+ 	PR c++/19787
+ 	* g++.dg/conversion/ambig1.C: New test.
+ 
+ 	PR c++/19739
+ 	* g++.dg/ext/attrib19.C: New test.
+ 
+ 	PR c++/19732
+ 	* g++.dg/parse/dtor5.C: New test.
+ 
+ 	PR c++/19762
+ 	* g++.dg/template/dtor3.C: New test.
+ 
+ 	PR c++/19826
+ 	* g++.dg/template/static11.C: New test.
+ 	* g++.dg/template/crash2.C: Remove dg-error marker.
+ 
  2005-02-08  Mark Mitchell  <mark@codesourcery.com>
  
  	PR c++/19733
  	* g++.dg/parse/crash23.C: New test.
  	* g++.dg/warn/Weff1.C: New test.
Index: testsuite/g++.dg/conversion/ambig1.C
===================================================================
RCS file: testsuite/g++.dg/conversion/ambig1.C
diff -N testsuite/g++.dg/conversion/ambig1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/conversion/ambig1.C	10 Feb 2005 00:26:46 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/19787
+ 
+ struct H {
+   operator char(); // { dg-error "" }
+   operator short(); // { dg-error "" }
+ };
+ 
+ int const& ref = H(); // { dg-error "" }
Index: testsuite/g++.dg/ext/attrib19.C
===================================================================
RCS file: testsuite/g++.dg/ext/attrib19.C
diff -N testsuite/g++.dg/ext/attrib19.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/attrib19.C	10 Feb 2005 00:26:46 -0000
***************
*** 0 ****
--- 1,10 ----
+ // PR c++/19739
+ 
+ void Dummy() __attribute__(( , ));
+ void Dummy() {}
+ 
+ int main (int argc, char **argv)
+ {
+     Dummy();
+     return 0;
+ }
Index: testsuite/g++.dg/parse/dtor5.C
===================================================================
RCS file: testsuite/g++.dg/parse/dtor5.C
diff -N testsuite/g++.dg/parse/dtor5.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/dtor5.C	10 Feb 2005 00:27:03 -0000
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/19732
+ 
+ struct A;
+ typedef int ~A; // { dg-error "non-function" }
+ struct B { 
+   ~A(); // { dg-error "" }
+   typedef int ~A; // { dg-error "non-function" }
+   void f() {
+     extern ~B(); // { dg-error "non-member" }
+   }
+ };
+ void ~A(); // { dg-error "non-member" }
Index: testsuite/g++.dg/template/crash2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/crash2.C,v
retrieving revision 1.3
diff -c -5 -p -r1.3 crash2.C
*** testsuite/g++.dg/template/crash2.C	12 Nov 2004 21:47:13 -0000	1.3
--- testsuite/g++.dg/template/crash2.C	10 Feb 2005 00:27:03 -0000
***************
*** 3,13 ****
  template <class EnumType>
  class A
  {
  public:
    static const EnumType size = max; // { dg-error "" }
!   int table[size]; // { dg-error "" }
  };
  template <class EnumType>
  const EnumType A<EnumType>::size;
   
   
--- 3,13 ----
  template <class EnumType>
  class A
  {
  public:
    static const EnumType size = max; // { dg-error "" }
!   int table[size];
  };
  template <class EnumType>
  const EnumType A<EnumType>::size;
   
   
Index: testsuite/g++.dg/template/dtor3.C
===================================================================
RCS file: testsuite/g++.dg/template/dtor3.C
diff -N testsuite/g++.dg/template/dtor3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/dtor3.C	10 Feb 2005 00:27:03 -0000
***************
*** 0 ****
--- 1,4 ----
+ // PR c++/19762
+ 
+ template<int> struct A { ~A(){} }; // { dg-error "" }
+ template A<>::~A(); // { dg-error "" }
Index: testsuite/g++.dg/template/static11.C
===================================================================
RCS file: testsuite/g++.dg/template/static11.C
diff -N testsuite/g++.dg/template/static11.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/static11.C	10 Feb 2005 00:27:03 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/19826
+ 
+ template<typename T> struct A
+ {
+   static const T i = 1;
+   char a[i];
+ };
+ 


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