aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-04-17 23:32:24 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-04-17 23:32:24 -0400
commit5a58e967b526eba3d9b850cd7bc76dcc580bf708 (patch)
tree844ecad256d70dffae00df101a967a92775604d0 /gcc
parent19caab83ca8b30a1a37ec968aaea8086b096d113 (diff)
downloadgcc-5a58e967b526eba3d9b850cd7bc76dcc580bf708.zip
gcc-5a58e967b526eba3d9b850cd7bc76dcc580bf708.tar.gz
gcc-5a58e967b526eba3d9b850cd7bc76dcc580bf708.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-67.C30
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb43.C2
4 files changed, 40 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a37a6c2..bfaf355 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f800131..3a11eaa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-67.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-67.C
new file mode 100644
index 0000000..55961cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-67.C
@@ -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 *)""; }
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C
index 1dc4328..90afbe4 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C
@@ -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" }