* decl.c (xref_basetypes): Complain about incomplete template base.
* class.c (finish_struct): Adjust variants in templates, too.
From-SVN: r189583
2012-07-17 Jason Merrill <jason@redhat.com>
+ * decl.c (xref_basetypes): Complain about incomplete template base.
+ * class.c (finish_struct): Adjust variants in templates, too.
+
PR c++/53549
* parser.c (cp_parser_class_head): Call xref_basetypes here.
(cp_parser_class_specifier_1): Not here.
/* Remember current #pragma pack value. */
TYPE_PRECISION (t) = maximum_field_alignment;
+
+ /* Fix up any variants we've already built. */
+ for (x = TYPE_NEXT_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
+ {
+ TYPE_SIZE (x) = TYPE_SIZE (t);
+ TYPE_SIZE_UNIT (x) = TYPE_SIZE_UNIT (t);
+ TYPE_FIELDS (x) = TYPE_FIELDS (t);
+ TYPE_METHODS (x) = TYPE_METHODS (t);
+ }
}
else
finish_struct_1 (t);
{
tree basetype = TREE_VALUE (*basep);
- if (!(processing_template_decl && uses_template_parms (basetype))
+ /* The dependent_type_p call below should really be dependent_scope_p
+ so that we give a hard error about using an incomplete type as a
+ base, but we allow it with a pedwarn for backward
+ compatibility. */
+ if (processing_template_decl
+ && CLASS_TYPE_P (basetype) && TYPE_BEING_DEFINED (basetype))
+ cxx_incomplete_type_diagnostic (NULL_TREE, basetype, DK_PEDWARN);
+ if (!dependent_type_p (basetype)
&& !complete_type_or_else (basetype, NULL))
/* An incomplete type. Remove it from the list. */
*basep = TREE_CHAIN (*basep);
2012-07-17 Jason Merrill <jason@redhat.com>
+ * g++.dg/template/inherit8.C: Adjust.
+ * g++.dg/template/using21.C: Adjust.
+ * g++.dg/template/using22.C: Adjust.
+
PR c++/53549
* g++.dg/template/current-inst1.C: New.
* g++.dg/parse/crash35.C: Adjust.
struct A
{
template <typename U>
- struct B : public A <B<U> >
+ struct B : public A <B<U> > // { dg-error "declaration" }
{
- struct C : public B<U>
+ struct C : public B<U> // { dg-error "incomplete" }
{
};
};
template<typename T>
struct A
{
- int foo;
+ int foo;
- struct B : A<T>
- {
- using A::foo;
- };
+ struct B;
+ struct C;
+ struct D;
+ struct E;
+};
- struct C : A
- {
- using A::foo;
- };
+template <class T>
+struct A<T>::B : A<T>
+{
+ using A::foo;
+};
- struct D : A<T>
- {
- using A<T>::foo;
- };
+template <class T>
+struct A<T>::C : A
+{
+ using A::foo;
+};
- struct E : A
- {
- using A<T>::foo;
- };
+template <class T>
+struct A<T>::D : A<T>
+{
+ using A<T>::foo;
+};
+
+template <class T>
+struct A<T>::E : A
+{
+ using A<T>::foo;
};
template<typename T>
struct A
{
- struct B : A<T>
- {
- using A::nonexist; // { dg-error "no members matching" }
- };
+ struct B;
+ struct C;
+ struct D;
+ struct E;
+ struct F;
+};
- struct C : A
- {
- using A::nonexist; // { dg-error "no members matching" }
- };
+template <class T>
+struct A<T>::B : A<T>
+{
+ using A::nonexist; // { dg-error "no members matching" }
+};
- struct D : A<T>
- {
- using A<T>::nonexist; // { dg-error "no members matching" }
- };
+template <class T>
+struct A<T>::C : A
+{
+ using A::nonexist; // { dg-error "no members matching" }
+};
- struct E : A
- {
- using A<T>::nonexist; // { dg-error "no members matching" }
- };
+template <class T>
+struct A<T>::D : A<T>
+{
+ using A<T>::nonexist; // { dg-error "no members matching" }
+};
- struct F : Z<T>
- {
- using Z<T>::nonexist;
- };
+template <class T>
+struct A<T>::E : A
+{
+ using A<T>::nonexist; // { dg-error "no members matching" }
+};
+
+template <class T>
+struct A<T>::F : Z<T>
+{
+ using Z<T>::nonexist;
};