+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
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
#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)
|| 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. */
{
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;
}
}
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);
}
+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.
--- /dev/null
+// 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;
+ }
+}
A<int> A1;
// CWG issue 625
-A<auto> A2 = A1; // { dg-error "auto" }
+A<auto> A2 = A1; // { dg-error "" }
auto foo() { } // { dg-error "auto" }
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" }
};
--- /dev/null
+// 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" }