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 for c++/37962


Various cases where we were accepting C++0x auto in inappropriate places.

This is basically Jakub's second proposed patch using an unconditional error in cp_parser_type_id rather than conditioned on cp_parser_simulate_error; by the time we call groktypename we've committed to parsing a type-id, so we can go ahead and give an error.

I also added a diagnostic for parameters declared with auto.

The call.c and cp-tree.h hunks are unnecessary changes that I made while considering another approach, but they are more correct, so I'm inclined to put them in.

Tested x86_64-pc-linux-gnu, applied to trunk.

2008-11-18  Jason Merrill  <jason@redhat.com>

	PR c++/37962
cp/
	* parser.c (cp_parser_type_id): Complain about auto.
	* decl.c (grokdeclarator): Complain about parameters and
	conversion functions declared with auto.
	* call.c (standard_conversion): Use CLASS_TYPE_P instead of
	MAYBE_CLASS_TYPE_P.
	* cp-tree.h (TYPE_NON_AGGREGATE_CLASS): Likewise.
testsuite/
	* g++.dg/cpp0x/auto[38].C: Adjust expected errors.
	* g++.dg/cpp0x/auto9.C: New test.
	* g++.dg/cpp0x/auto10.C: New test.

Index: cp/decl.c
===================================================================
*** cp/decl.c	(revision 141842)
--- cp/decl.c	(working copy)
*************** grokdeclarator (const cp_declarator *dec
*** 8053,8058 ****
--- 8053,8064 ----
  	       || storage_class == sc_extern
  	       || thread_p)
  	error ("storage class specifiers invalid in parameter declarations");
+ 
+       if (type_uses_auto (type))
+ 	{
+ 	  error ("parameter declared %<auto%>");
+ 	  type = error_mark_node;
+ 	}
      }
  
    /* Give error if `virtual' is used outside of class declaration.  */
*************** grokdeclarator (const cp_declarator *dec
*** 8246,8268 ****
  	      {
  		if (type_uses_auto (type))
  		  {
! 		    if (!declarator->u.function.late_return_type)
  		      {
! 			error ("%qs function uses auto type specifier without"
  			       " late return type", name);
  			return error_mark_node;
  		      }
  		    else if (!is_auto (type))
  		      {
! 			error ("%qs function with late return type not using"
! 			       " auto type specifier as its type", name);
  			return error_mark_node;
  		      }
  		  }
  		else if (declarator->u.function.late_return_type)
  		  {
  		    error ("%qs function with late return type not declared"
! 			   " with auto type specifier", name);
  		    return error_mark_node;
  		  }
  	      }
--- 8252,8280 ----
  	      {
  		if (type_uses_auto (type))
  		  {
! 		    if (sfk == sfk_conversion)
! 		      {
! 			error ("invalid use of %<auto%> in conversion operator");
! 			return error_mark_node;
! 		      }
! 		    else if (!declarator->u.function.late_return_type)
  		      {
! 			error ("%qs function uses %<auto%> type specifier without"
  			       " late return type", name);
  			return error_mark_node;
  		      }
  		    else if (!is_auto (type))
  		      {
! 			error ("%qs function with late return type has"
! 			       " %qT as its type rather than plain %<auto%>",
! 			       name, type);
  			return error_mark_node;
  		      }
  		  }
  		else if (declarator->u.function.late_return_type)
  		  {
  		    error ("%qs function with late return type not declared"
! 			   " with %<auto%> type specifier", name);
  		    return error_mark_node;
  		  }
  	      }
Index: cp/call.c
===================================================================
*** cp/call.c	(revision 141865)
--- cp/call.c	(working copy)
*************** standard_conversion (tree to, tree from,
*** 814,821 ****
  	  else if (!same_type_p (fbase, tbase))
  	    return NULL;
  	}
!       else if (MAYBE_CLASS_TYPE_P (TREE_TYPE (from))
! 	       && MAYBE_CLASS_TYPE_P (TREE_TYPE (to))
  	       /* [conv.ptr]
  
  		  An rvalue of type "pointer to cv D," where D is a
--- 814,821 ----
  	  else if (!same_type_p (fbase, tbase))
  	    return NULL;
  	}
!       else if (CLASS_TYPE_P (TREE_TYPE (from))
! 	       && CLASS_TYPE_P (TREE_TYPE (to))
  	       /* [conv.ptr]
  
  		  An rvalue of type "pointer to cv D," where D is a
Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 141842)
--- cp/cp-tree.h	(working copy)
*************** more_aggr_init_expr_args_p (const aggr_i
*** 2824,2830 ****
  #define CLASSTYPE_NON_AGGREGATE(NODE) \
    (LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate)
  #define TYPE_NON_AGGREGATE_CLASS(NODE) \
!   (MAYBE_CLASS_TYPE_P (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
  
  /* Nonzero if there is a user-defined X::op=(x&) for this class.  */
  #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
--- 2824,2830 ----
  #define CLASSTYPE_NON_AGGREGATE(NODE) \
    (LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate)
  #define TYPE_NON_AGGREGATE_CLASS(NODE) \
!   (CLASS_TYPE_P (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
  
  /* Nonzero if there is a user-defined X::op=(x&) for this class.  */
  #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
Index: cp/parser.c
===================================================================
*** cp/parser.c	(revision 141842)
--- cp/parser.c	(working copy)
*************** cp_parser_type_id (cp_parser* parser)
*** 13693,13698 ****
--- 13693,13705 ----
    if (!cp_parser_parse_definitely (parser))
      abstract_declarator = NULL;
  
+   if (type_specifier_seq.type
+       && type_uses_auto (type_specifier_seq.type))
+     {
+       error ("invalid use of %<auto%>");
+       return error_mark_node;
+     }
+   
    return groktypename (&type_specifier_seq, abstract_declarator);
  }
  
Index: testsuite/g++.dg/cpp0x/auto3.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto3.C	(revision 141842)
--- testsuite/g++.dg/cpp0x/auto3.C	(working copy)
*************** struct A { };
*** 17,23 ****
  
  A<int> A1;
  // CWG issue 625
! A<auto> A2 = A1;		// { dg-error "auto" }
  
  auto foo() { }			// { dg-error "auto" }
  
--- 17,23 ----
  
  A<int> A1;
  // CWG issue 625
! A<auto> A2 = A1;		// { dg-error "" }
  
  auto foo() { }			// { dg-error "auto" }
  
Index: testsuite/g++.dg/cpp0x/auto10.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto10.C	(revision 0)
--- testsuite/g++.dg/cpp0x/auto10.C	(revision 0)
***************
*** 0 ****
--- 1,22 ----
+ // Positive test for auto
+ // { dg-do run }
+ // { dg-options "-std=c++0x" }
+ 
+ #include <typeinfo>
+ extern "C" void abort();
+ 
+ int main()
+ {
+   if (auto i = 42L)
+     {
+       if (typeid (i) != typeid (long int))
+ 	abort ();
+     }
+ 
+   while (auto i = 1)
+     {
+       if (typeid (i) != typeid (int))
+ 	abort ();
+       break;
+     }
+ }
Index: testsuite/g++.dg/cpp0x/auto8.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto8.C	(revision 141842)
--- testsuite/g++.dg/cpp0x/auto8.C	(working copy)
***************
*** 4,16 ****
  
  auto f1 () -> int;
  auto f2 ();		// { dg-error "without late return type" }
! int f3 () -> int;	// { dg-error "with auto type specifier" }
! auto *f4 () -> int;	// { dg-error "not using auto" }
  
  struct A
  {
    auto f5 () const -> int;
    auto f6 ();		// { dg-error "without late return type" }
!   int f7 () -> int;	// { dg-error "with auto type specifier" }
!   auto *f8 () -> int;	// { dg-error "not using auto" }
  };
--- 4,16 ----
  
  auto f1 () -> int;
  auto f2 ();		// { dg-error "without late return type" }
! int f3 () -> int;	// { dg-error "late return type" }
! auto *f4 () -> int;	// { dg-error "late return type" }
  
  struct A
  {
    auto f5 () const -> int;
    auto f6 ();		// { dg-error "without late return type" }
!   int f7 () -> int;	// { dg-error "late return type" }
!   auto *f8 () -> int;	// { dg-error "late return type" }
  };
Index: testsuite/g++.dg/cpp0x/auto9.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto9.C	(revision 0)
--- testsuite/g++.dg/cpp0x/auto9.C	(revision 0)
***************
*** 0 ****
--- 1,121 ----
+ // PR c++/37962
+ // Negative test for auto
+ // { dg-do compile }
+ // { dg-options "-std=c++0x" }
+ 
+ #include <typeinfo>
+ #include <stdarg.h>
+ #include <stddef.h>
+ 
+ int i = *(auto *) 0;				// { dg-error "auto" }
+ struct A *p = (auto *) 0;			// { dg-error "auto" }
+ int *q = static_cast <auto *>(0);		// { dg-error "auto" }
+ const int *r = const_cast <auto *>(q);		// { dg-error "auto" }
+ const std::type_info &t1 = typeid (auto);	// { dg-error "auto" }
+ const std::type_info &t2 = typeid (auto *);	// { dg-error "auto" }
+ 
+ struct A
+ {
+   operator auto ();				// { dg-error "auto" }
+   operator auto *();				// { dg-error "auto" }
+ };
+ 
+ struct A2
+ {
+   operator auto () -> int;			// { dg-error "invalid use of" }
+   operator auto *() -> int;			// { dg-error "auto" }
+ };
+ 
+ template <typename> struct B
+ {
+   enum { e };
+ };
+ 
+ template <typename T> struct C
+ {
+   C () : i () {}
+   int i;
+ };
+ 
+ bool d = (auto (A::*)()) 0;			// { dg-error "auto" }
+ 
+ void
+ foo ()
+ {
+   (auto) { 0 };					// { dg-error "auto" }
+   C<int> c;
+   dynamic_cast<auto> (c);			// { dg-error "auto" }
+   reinterpret_cast<auto> (c);			// { dg-error "auto" }
+   int i = auto (0);				// { dg-error "auto" }
+   auto p1 = new (auto);				// { dg-error "auto" }
+   auto p2 = new (auto) (42);			// { dg-error "invalid use of|deduce" }
+   offsetof (auto, fld);				// { dg-error "auto" }
+   offsetof (auto *, fld);			// { dg-error "auto" }
+   sizeof (auto);				// { dg-error "auto" }
+   sizeof (auto *);				// { dg-error "auto" }
+ }
+ 
+ void
+ foo2 (void)
+ {
+   __alignof__ (auto);				// { dg-error "auto" }
+   __alignof__ (auto *);				// { dg-error "auto" }
+   __typeof__ (auto) v1;				// { dg-error "auto" }
+   __typeof__ (auto *) v2;			// { dg-error "auto" }
+   __is_class (auto);				// { dg-error "auto|expected" }
+   __is_pod (auto *);				// { dg-error "auto|expected" }
+   __is_base_of (int, auto);			// { dg-error "auto|expected" }
+   __is_base_of (auto, int);			// { dg-error "auto|expected" }
+   __is_base_of (auto, auto *);			// { dg-error "auto|expected" }
+ }
+ 
+ B<auto> b;					// { dg-error "auto|invalid" }
+ C<auto> c;					// { dg-error "auto|invalid" }
+ C<auto *> c2;					// { dg-error "auto|invalid" }
+ 
+ enum : auto { EE = 0 };				// { dg-error "must be an integral type" }
+ enum struct D : auto * { FF = 0 };		// { dg-error "declar|expected" }
+ 
+ void
+ bar ()
+ {
+   try { } catch (auto i) { }			// { dg-error "invalid use of" }
+   try { } catch (auto) { }			// { dg-error "invalid use of" }
+   try { } catch (auto *i) { }			// { dg-error "invalid use of" }
+   try { } catch (auto *) { }			// { dg-error "invalid use of" }
+ }
+ 
+ void
+ baz (int i, ...)
+ {
+   va_list ap;
+   va_start (ap, i);
+   va_arg (ap, auto);				// { dg-error "invalid use of" }
+   va_arg (ap, auto *);				// { dg-error "invalid use of|expected" }
+   va_arg (ap, auto &);				// { dg-error "invalid use of|expected" }
+   va_end (ap);
+ }
+ 
+ template <typename T = auto> struct E {};	// { dg-error "invalid use of" }
+ template <class T = auto *> struct F {};	// { dg-error "invalid use of|expected" }
+ 
+ auto fnlate () -> auto;				// { dg-error "invalid use of" }
+ auto fnlate2 () -> auto *;			// { dg-error "invalid use of|expected" }
+ 
+ void
+ badthrow () throw (auto)			// { dg-error "invalid use of" }
+ {
+ }
+ 
+ void
+ badthrow2 () throw (auto &)			// { dg-error "invalid use of|expected" }
+ {
+ }
+ 
+ template <auto V = 4> struct G {};		// { dg-error "auto" }
+ 
+ template <typename T> struct H { H (); ~H (); };
+ H<auto> h;					// { dg-error "invalid" }
+ 
+ void qq (auto);			// { dg-error "auto" }
+ void qr (auto*);		// { dg-error "auto" }

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