re PR c++/37962 (ICE with (auto*) casts)
authorJason Merrill <jason@redhat.com>
Tue, 18 Nov 2008 18:11:32 +0000 (13:11 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 18 Nov 2008 18:11:32 +0000 (13:11 -0500)
        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.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r141970

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/auto10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/auto3.C
gcc/testsuite/g++.dg/cpp0x/auto8.C
gcc/testsuite/g++.dg/cpp0x/auto9.C [new file with mode: 0644]

index f184028..4353263 100644 (file)
@@ -1,3 +1,15 @@
+2008-11-18  Jason Merrill  <jason@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+       
+       PR c++/37962
+       * 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.
+
 2008-11-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/36089
index 4d86a44..af3fd99 100644 (file)
@@ -814,8 +814,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
          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))
+      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 b79b819..9f10ed1 100644 (file)
@@ -2824,7 +2824,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #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))
+  (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 945b947..997c580 100644 (file)
@@ -8053,6 +8053,12 @@ grokdeclarator (const cp_declarator *declarator,
               || 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.  */
@@ -8246,23 +8252,29 @@ grokdeclarator (const cp_declarator *declarator,
              {
                if (type_uses_auto (type))
                  {
-                   if (!declarator->u.function.late_return_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"
+                       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);
+                       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);
+                          " with %<auto%> type specifier", name);
                    return error_mark_node;
                  }
              }
index ba8759c..5c1f849 100644 (file)
@@ -13693,6 +13693,13 @@ cp_parser_type_id (cp_parser* parser)
   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 0af6cad..8ed4c3b 100644 (file)
@@ -1,3 +1,11 @@
+2008-11-18  Jason Merrill  <jason@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/37962
+       * g++.dg/cpp0x/auto[38].C: Adjust expected errors.
+       * g++.dg/cpp0x/auto9.C: New test.
+       * g++.dg/cpp0x/auto10.C: New test.
+
 2008-11-17  Adam Nemet  <anemet@caviumnetworks.com>
 
        * gcc.c-torture/execute/20081117-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto10.C b/gcc/testsuite/g++.dg/cpp0x/auto10.C
new file mode 100644 (file)
index 0000000..9b89291
--- /dev/null
@@ -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 769d987..3cea856 100644 (file)
@@ -17,7 +17,7 @@ struct A { };
 
 A<int> A1;
 // CWG issue 625
-A<auto> A2 = A1;               // { dg-error "auto" }
+A<auto> A2 = A1;               // { dg-error "" }
 
 auto foo() { }                 // { dg-error "auto" }
 
index d724d79..e45204f 100644 (file)
@@ -4,13 +4,13 @@
 
 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" }
+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 "with auto type specifier" }
-  auto *f8 () -> int;  // { dg-error "not using auto" }
+  int f7 () -> int;    // { dg-error "late return type" }
+  auto *f8 () -> int;  // { dg-error "late return type" }
 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C
new file mode 100644 (file)
index 0000000..7dcf487
--- /dev/null
@@ -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" }