aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2008-11-18 13:11:32 -0500
committerJason Merrill <jason@gcc.gnu.org>2008-11-18 13:11:32 -0500
commit3f50c84611bd118046835a42512360c40d2aa299 (patch)
tree8602d347fb3d3d55d2e49fb14e9f56ed321f7a29
parent43db6c722af049642c4dd9e504f32cfca668c940 (diff)
downloadgcc-3f50c84611bd118046835a42512360c40d2aa299.zip
gcc-3f50c84611bd118046835a42512360c40d2aa299.tar.gz
gcc-3f50c84611bd118046835a42512360c40d2aa299.tar.bz2
re PR c++/37962 (ICE with (auto*) casts)
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
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c4
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c22
-rw-r--r--gcc/cp/parser.c7
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto10.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto8.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto9.C121
10 files changed, 195 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f184028..4353263 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4d86a44..af3fd99 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b79b819..9f10ed1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 945b947..997c580 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
}
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ba8759c..5c1f849 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0af6cad..8ed4c3b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..9b89291
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto10.C
@@ -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;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto3.C b/gcc/testsuite/g++.dg/cpp0x/auto3.C
index 769d987..3cea856 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto3.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto8.C b/gcc/testsuite/g++.dg/cpp0x/auto8.C
index d724d79..e45204f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto8.C
@@ -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
index 0000000..7dcf487
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C
@@ -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" }