+2018-02-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/81917 - ICE with void_t and partial specialization.
+ * pt.c (instantiate_class_template_1): Set TYPE_BEING_DEFINED before
+ calling most_specialized_partial_spec.
+
2018-02-09 Nathan Sidwell <nathan@acm.org>
PR c/84293
templ = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
+ /* Mark the type as in the process of being defined. */
+ TYPE_BEING_DEFINED (type) = 1;
+
/* Determine what specialization of the original template to
instantiate. */
t = most_specialized_partial_spec (type, tf_warning_or_error);
if (t == error_mark_node)
- {
- TYPE_BEING_DEFINED (type) = 1;
- return error_mark_node;
- }
+ return error_mark_node;
else if (t)
{
/* This TYPE is actually an instantiation of a partial
/* If the template we're instantiating is incomplete, then clearly
there's nothing we can do. */
if (!COMPLETE_TYPE_P (pattern))
- return type;
+ {
+ /* We can try again later. */
+ TYPE_BEING_DEFINED (type) = 0;
+ return type;
+ }
/* If we've recursively instantiated too many templates, stop. */
if (! push_tinst_level (type))
return type;
- /* Now we're really doing the instantiation. Mark the type as in
- the process of being defined. */
- TYPE_BEING_DEFINED (type) = 1;
-
/* We may be in the middle of deferred access check. Disable
it now. */
push_deferring_access_checks (dk_no_deferred);
--- /dev/null
+// PR c++/81917
+// { dg-do compile { target c++11 } }
+
+template <typename> using a = void;
+template <typename, typename = void> struct b
+{
+ typedef int c;
+};
+template <typename d> class b<d, a<typename d::e>>;
+template <typename d, typename = typename b<d>::c> class f;
+template <typename> class g { };
+template <typename, typename> class h
+{
+ class i;
+ typedef g<f<i>> j;
+ class i
+ {
+ j k; // { dg-error "incomplete" }
+ };
+};
+h<int, int> H;
+
// PR c++/71747
// { dg-do compile { target c++11 } }
-// { dg-options -ftemplate-depth=20 }
template < bool > struct A
{
template < bool, typename = int > struct F;
template < bool X >
// should be: struct F < X, typename A < A < X > {} () >::type >
-struct F < X, typename A < F < X > {} () >::type > // { dg-error "" }
+struct F < X, typename A < F < X > {} () >::type >
{
};
-F < true > f;
-
-// { dg-prune-output "compilation terminated" }
+F < true > f; // { dg-error "" }
typedef void Complete;
};
-Swappable<int> s; // { dg-error "depth" }
-
-// { dg-prune-output "compilation terminated" }
+Swappable<int> s; // { dg-error "" }
template<class T,class U=void> struct s;
template<class T> struct s<T,typename s<T>::a> {};
-s<int> ca; // { dg-error "depth" }
-
-// { dg-prune-output "compilation terminated" }
+s<int> ca; // { dg-error "" }
-// { dg-options "-ftemplate-depth-8" }
-
template< typename T > struct type_wrapper {
};
typedef char (&yes_tag)[2];
};
template< typename T > struct has_type {
struct gcc_3_2_wknd {
- template< typename U > static yes_tag test( type_wrapper<U> const volatile* // { dg-message "required" }
+ template< typename U > static yes_tag test( type_wrapper<U> const volatile* // { dg-message "" }
, type_wrapper<typename U::type>* = 0 );
};
typedef type_wrapper<T> t_;
- static const bool value = sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) == // { dg-message "required" }
+ static const bool value = sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) == // { dg-message "" }
sizeof(yes_tag);
};
template <class K, class T, class=void> struct Get_type {
!has_type<Get_type<K, FT_tag> >::value >::type> { }; // { dg-message "required" }
template <class K> struct Get_type<K, FT_tag, typename if_c<
!has_type<Get_type<K, RT_tag> >::value >::type> { }; // { dg-message "required" }
-typedef Get_type<int, FT_tag>::type P;
-
-// { dg-prune-output "-ftemplate-depth" }
-// { dg-prune-output "compilation terminated" }
+typedef Get_type<int, FT_tag>::type P; // { dg-message "" }