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:
parent
19caab83ca
commit
5a58e967b5
@ -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.
|
||||
|
@ -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
|
||||
{
|
||||
|
30
gcc/testsuite/g++.dg/cpp0x/alias-decl-67.C
Normal file
30
gcc/testsuite/g++.dg/cpp0x/alias-decl-67.C
Normal 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 *)""; }
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -47,3 +47,4 @@ main()
|
||||
}
|
||||
|
||||
// { dg-prune-output "cannot convert" }
|
||||
// { dg-prune-output "enable_if" }
|
||||
|
@ -35,3 +35,5 @@ test01()
|
||||
std::shared_ptr<B> b;
|
||||
a = b; // { dg-error "no match" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "enable_if" }
|
||||
|
@ -43,3 +43,4 @@ main()
|
||||
return 0;
|
||||
}
|
||||
// { dg-prune-output "initializing argument" }
|
||||
// { dg-prune-output "enable_if" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -51,3 +51,5 @@ main()
|
||||
test02();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// { dg-prune-output "enable_if" }
|
||||
|
@ -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" }
|
||||
|
@ -32,3 +32,5 @@ void f()
|
||||
std::deque<A> d;
|
||||
d.assign(10, 1); // { dg-error "no match|here" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "iterator_traits" }
|
||||
|
@ -26,3 +26,5 @@ void f()
|
||||
{
|
||||
std::deque<std::deque<int> > d(10, 1); // { dg-error "here|no match" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "iterator_traits" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -30,3 +30,5 @@ void f()
|
||||
test_type l;
|
||||
l.assign(10, 1); // { dg-error "no matching" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "iterator_traits" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -33,3 +33,5 @@ void f()
|
||||
list_type l;
|
||||
l.assign(10, 1); // { dg-error "here|no match" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "iterator_traits" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -32,3 +32,5 @@ void f()
|
||||
std::vector<A> v;
|
||||
v.assign(10, 1); // { dg-error "here|no match" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "iterator_traits" }
|
||||
|
@ -26,3 +26,5 @@ void f()
|
||||
{
|
||||
std::vector<std::vector<int> > v(10, 1); // { dg-error "here|no match" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "iterator_traits" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -50,3 +50,5 @@ main()
|
||||
test02();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// { dg-prune-output "enable_if" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
Loading…
Reference in New Issue
Block a user