Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- Here we ICE since r14-8291 in C++11/C++14 modes. Fortunately this is an easy one.
The important bit of r14-8291 is this: @@ -20056,9 +20071,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) RETURN (retval); } if (IMPLICIT_CONV_EXPR_NONTYPE_ARG (t)) - /* We'll pass this to convert_nontype_argument again, we don't need - to actually perform any conversion here. */ - RETURN (expr); + { + tree r = convert_nontype_argument (type, expr, complain); + if (r == NULL_TREE) + r = error_mark_node; + RETURN (r); + } which obviously means that instead of returning right away we go to convert_nontype_argument. When type is error_mark_node and we're in C++17, in convert_nontype_argument we go down this path: else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type) || cxx_dialect >= cxx17) { expr = build_converted_constant_expr (type, expr, complain); if (expr == error_mark_node) return (complain & tf_error) ? NULL_TREE : error_mark_node; // ... } but pre-C++17, we take a different route and end up crashing on gcc_unreachable. It would of course also work to check for error_mark_node early in build_converted_constant_expr. PR c++/116384 gcc/cp/ChangeLog: * pt.cc (tsubst_expr) <case IMPLICIT_CONV_EXPR>: Bail if tsubst returns error_mark_node. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/vt-116384.C: New test. --- gcc/cp/pt.cc | 2 ++ gcc/testsuite/g++.dg/cpp0x/vt-116384.C | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-116384.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8725a5eeb3f..684ee0c8a60 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -20217,6 +20217,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case IMPLICIT_CONV_EXPR: { tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); + if (type == error_mark_node) + RETURN (error_mark_node); tree expr = RECUR (TREE_OPERAND (t, 0)); if (dependent_type_p (type) || type_dependent_expression_p (expr)) { diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-116384.C b/gcc/testsuite/g++.dg/cpp0x/vt-116384.C new file mode 100644 index 00000000000..54d7f0774c5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/vt-116384.C @@ -0,0 +1,26 @@ +// PR c++/116384 +// { dg-do compile { target c++11 } } + +namespace a { +template <bool, typename> struct c; +template <typename> struct d; +} +namespace e { +namespace g { +template <typename> using h = void; +template <typename, template <typename> class, typename...> struct detector {}; +template <template <typename> class i, typename... args> +struct detector<h<i<args...>>, i, args...>; +} +template <template <typename> class i, typename... args> +using j = g::detector<void, i, args...>; +template <bool b, typename k = void> using l = typename a::c<b, k>::m; +template <typename> struct conjunction; +namespace g { +template <typename k> using n = l<conjunction<a::d<k>>::p>; +} +template <typename k, g::n<k> = true> class o; +} +struct r; +template <typename k> using q = e::o<k>; +void s() { e::j<q, r> f; } base-commit: c8981bde45d365330a5e7c2e33c8dbaf3495248a -- 2.46.0