PR c++/90047 - ICE with enable_if alias template.

In order to make alias templates useful for SFINAE we instantiate them under
the prevailing 'complain' argument, so an error encountered while
instantiating during SFINAE context is silent.  The problem in this PR comes
when we later look up the erroneous instantiation and don't give an error at
that point.  Fixed by not adding an erroneous instantiation to the hash
table, so we instantiate it again when needed and get the error.  This
required changes to a number of tests, which previously said "substitution
failed:" with no explanation of what the failure was; now we properly
explain.

	* pt.c (tsubst_decl) [TYPE_DECL]: Don't put an erroneous decl in the
	hash table when we're in SFINAE context.

From-SVN: r270433
This commit is contained in:
Jason Merrill 2019-04-17 23:32:24 -04:00 committed by Jason Merrill
parent 19caab83ca
commit 5a58e967b5
33 changed files with 96 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2019-04-17 Jason Merrill <jason@redhat.com>
PR c++/90047 - ICE with enable_if alias template.
* pt.c (tsubst_decl) [TYPE_DECL]: Don't put an erroneous decl in the
hash table when we're in SFINAE context.
2019-04-17 Marek Polacek <polacek@redhat.com>
PR c++/90124 - bogus error with incomplete type in decltype.

View File

@ -13948,7 +13948,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec, false, hash);
if (!error_operand_p (r) || (complain & tf_error))
register_specialization (r, gen_tmpl, argvec, false, hash);
}
else
{

View File

@ -0,0 +1,30 @@
// PR c++/90047
// { dg-do compile { target c++11 } }
template <int a> struct b { static constexpr int c = a; };
template <typename> struct aa;
template <typename...> struct d;
template <typename e, typename f, typename g, typename... h>
struct d<e, f, g, h...> : aa<e>::i {};
template <typename> struct j;
template <typename k, long l> struct j<k[l]> : b<true> {};
struct m {
typedef b<0> i;
};
template <typename> struct n : m::i {};
template <bool> struct o;
template <typename p> struct aa { typedef p i; };
template <bool ab> using ac = typename o<ab>::i; // { dg-error "incomplete" }
class q {
template <typename k, typename> using ad = ac<d<n<k>, int, int>::c>;
template <typename k, typename = ad<k, void>> q(k &);
};
template <typename r> struct s {
s(r) { t; }
template <ac<!j<r>::c> *> void t();
};
class I {
friend char operator<<(char p1, I p2) { return p1 << p2; }
q ag;
};
int main() { s<char[10]> a = (char *)""; }

View File

@ -42,3 +42,5 @@ int main()
sort( a.begin(), a.end(),
pointer_to_binary_function<const Expr<int>, const Expr<int>, bool>(compare<>) );
}
// { dg-prune-output "enable_if" }

View File

@ -28,3 +28,5 @@ void test01(std::chrono::seconds s, X x)
s / x; // { dg-error "no match" }
s % x; // { dg-error "no match" }
}
// { dg-prune-output "enable_if" }

View File

@ -36,3 +36,5 @@ test01(const char* first, const char* last)
std::from_chars(first, last, c32); // { dg-error "no matching" }
std::from_chars(first, last, c32, 10); // { dg-error "no matching" }
}
// { dg-prune-output "enable_if" }

View File

@ -36,3 +36,5 @@ test01(const char* first, const char* last)
std::from_chars(first, last, c32); // { dg-error "no matching" }
std::from_chars(first, last, c32, 10); // { dg-error "no matching" }
}
// { dg-prune-output "enable_if" }

View File

@ -47,3 +47,4 @@ main()
}
// { dg-prune-output "cannot convert" }
// { dg-prune-output "enable_if" }

View File

@ -35,3 +35,5 @@ test01()
std::shared_ptr<B> b;
a = b; // { dg-error "no match" }
}
// { dg-prune-output "enable_if" }

View File

@ -43,3 +43,4 @@ main()
return 0;
}
// { dg-prune-output "initializing argument" }
// { dg-prune-output "enable_if" }

View File

@ -33,3 +33,5 @@ test01(char* first, char* last)
std::to_chars(first, last, U'\x1'); // { dg-error "no matching" }
std::to_chars(first, last, U'\x1', 10); // { dg-error "no matching" }
}
// { dg-prune-output "enable_if" }

View File

@ -59,3 +59,5 @@ test03()
std::get<6>(const_cast<const test_type&>(t)); // { dg-error "no match" }
std::get<6>(static_cast<test_type&&>(t)); // { dg-error "no match" }
}
// { dg-prune-output "no type named .type" }

View File

@ -51,3 +51,5 @@ main()
test02();
return 0;
}
// { dg-prune-output "enable_if" }

View File

@ -55,3 +55,5 @@ test02()
std::unique_ptr<const volatile A[]> cvA3;
cvA3.reset(p); // { dg-error "no matching function" }
}
// { dg-prune-output "enable_if" }

View File

@ -32,3 +32,5 @@ void f()
std::deque<A> d;
d.assign(10, 1); // { dg-error "no match|here" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -26,3 +26,5 @@ void f()
{
std::deque<std::deque<int> > d(10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -27,3 +27,5 @@ void f()
{
std::deque<std::deque<std::pair<char, char> > > d('a', 'b'); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -32,3 +32,5 @@ void f()
std::deque<A> d;
d.insert(d.begin(), 10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -30,3 +30,5 @@ void f()
test_type l;
l.assign(10, 1); // { dg-error "no matching" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -24,3 +24,5 @@ void f()
typedef std::forward_list<std::forward_list<int> > test_type;
test_type l(10, 1); // { dg-error "no matching" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -25,3 +25,5 @@ void f()
typedef std::forward_list<std::forward_list<std::pair<char, char> > > test_type;
test_type l('a', 'b'); // { dg-error "no matching" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -30,3 +30,5 @@ void f()
test_type l;
l.insert_after(l.begin(), 10, 1); // { dg-error "no matching" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -33,3 +33,5 @@ void f()
list_type l;
l.assign(10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -27,3 +27,5 @@ void f()
typedef std::list<std::list<int> > list_type;
list_type l(10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -28,3 +28,5 @@ void f()
typedef std::list<std::list<std::pair<char, char> > > list_type;
list_type l('a', 'b'); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -33,3 +33,5 @@ void f()
list_type l;
l.insert(l.begin(), 10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -32,3 +32,5 @@ void f()
std::vector<A> v;
v.assign(10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -26,3 +26,5 @@ void f()
{
std::vector<std::vector<int> > v(10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -27,3 +27,5 @@ void f()
{
std::vector<std::vector<std::pair<char, char> > > v('a', 'b'); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -32,3 +32,5 @@ void f()
std::vector<A> v;
v.insert(v.begin(), 10, 1); // { dg-error "here|no match" }
}
// { dg-prune-output "iterator_traits" }

View File

@ -50,3 +50,5 @@ main()
test02();
return 0;
}
// { dg-prune-output "enable_if" }

View File

@ -49,3 +49,5 @@ test03()
B * const b = nullptr;
std::experimental::shared_ptr<A[]> p(b); // { dg-error "no match" }
}
// { dg-prune-output "enable_if" }

View File

@ -43,3 +43,5 @@ test01()
p1.reset(new constA[5]); // { dg-error "no matching function" }
p1.reset(new constA[5], D()); // { dg-error "no matching function" }
}
// { dg-prune-output "enable_if" }