Bug 93275 - [9/10 Regression] ICE: unexpected expression 'N' of kind template_parm_index
Summary: [9/10 Regression] ICE: unexpected expression 'N' of kind template_parm_index
Status: RESOLVED DUPLICATE of bug 93279
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: 9.3
Assignee: Not yet assigned to anyone
URL: https://godbolt.org/z/5HjwcN
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2020-01-15 13:33 UTC by ahmet özhan
Modified: 2020-01-21 08:39 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 8.3.0
Known to fail: 10.0, 9.2.0
Last reconfirmed: 2020-01-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description ahmet özhan 2020-01-15 13:33:35 UTC
Clang and GCC 8 can compile the code without any errors. But GCC 9 gives an error.


#include <algorithm>
#include <array>
#include <iostream>

namespace math {

	/** forward declaration **/
	template <typename T, std::size_t N>
	struct array;

	/** is_array **/
	template <typename T>
	struct is_array: std::false_type {};

	template <typename T, std::size_t N>
	struct is_array<array<T, N>>: std::true_type {};

	template <typename T>
	inline constexpr bool is_array_v = is_array<T>::value;

	/** array_depth **/
	template <typename T>
	struct array_depth: std::integral_constant<std::size_t, 0> {};

	template <typename T, std::size_t N>
	struct array_depth<array<T, N>>:
		std::integral_constant<std::size_t, 1 + array_depth<T>::value> {};

	template <typename T>
	inline constexpr bool array_depth_v = array_depth<T>::value;

	/** array **/
	template <typename T, std::size_t N>
	struct array: std::array<T, N> {

		constexpr array operator * (const array& other) const {
			array result {};
			std::transform(
				std::begin(*this),
				std::end(*this),
				std::begin(other),
				std::begin(result),
				std::multiplies<T>());
			return result;
		}

		template <typename Other, std::enable_if_t<
			(array_depth_v<array> > array_depth_v<Other>),
			std::nullptr_t> = nullptr>
		constexpr array operator * (const Other& other) const {
			array result {};
			std::transform(
				std::begin(*this),
				std::end(*this),
				std::begin(result),
				[other](const T& t) { return t * other; });
			return result;
		}
		
		friend std::ostream&
		operator << (std::ostream& out, const array& source) {
			out << "<array" << N;
			if constexpr (!is_array_v<T>)
				out << typeid(T).name();
			for (auto it: source) {
				if constexpr (!is_array_v<T>)
					out << " ";
				out << it;
			}
			out << ">";
			return out;
		}
	};
}

int main() {
	math::array<math::array<float, 4>, 1> a0
		{{math::array<float, 4>{{1.f, 2.f, 3.f, 4.f}}}};
	std::cout << a0 * 4.f << std::endl;
	return 0;
}
Comment 1 ahmet özhan 2020-01-15 14:37:07 UTC
<source>: In substitution of 'template<class T, long unsigned int N> template<class Other, typename std::enable_if<(array_depth_v<math::array<T, N> > > array_depth_v<Other>), std::nullptr_t>::type <anonymous> > constexpr math::array<T, N> math::array<T, N>::operator*(const Other&) const [with Other = <missing>; typename std::enable_if<(array_depth_v<math::array<T, N> > > array_depth_v<Other>), std::nullptr_t>::type <anonymous> = <missing>; T = float; long unsigned int N = <missing>]':

<source>:56:36:   required from 'constexpr math::array<T, N> math::array<T, N>::operator*(const Other&) const [with Other = float; typename std::enable_if<(array_depth_v<math::array<T, N> > > array_depth_v<Other>), std::nullptr_t>::type <anonymous> = nullptr; T = math::array<float, 4>; long unsigned int N = 1]'

<source>:79:20:   required from here

<source>:48:5: internal compiler error: unexpected expression 'N' of kind template_parm_index

   48 |    (array_depth_v<array> > array_depth_v<Other>),

      |     ^~~~~~~~~~~~~~~~~~~~

Please submit a full bug report,

with preprocessed source if appropriate.

See <https://gcc.gnu.org/bugs/> for instructions.
Comment 2 ahmet özhan 2020-01-15 15:26:56 UTC
template <typename Other, std::enable_if_t<
	(array_depth_v<array> > array_depth_v<Other>),
	std::nullptr_t> = nullptr>
constexpr array operator * (const Other& other) const {
	array result {};
	std::transform(
		std::begin(*this),
		std::end(*this),
		std::begin(result),
		[other](const T& t) { return t * other; });
	return result;
}

but change this line and add -fconcepts
------
template <typename Other, std::enable_if_t<
	(array_depth_v<array> > array_depth_v<Other>),
	std::nullptr_t> = nullptr>
-----
template <typename Other>
requires (array_depth_v<array> > array_depth_v<Other>)

gcc 9.0 compile.
Comment 3 Martin Liška 2020-01-20 13:42:50 UTC
Confirmed, started with r9-6404-g1ce59b6cad83d5ca6f1efee83f910d8b677a976a.
Comment 4 Martin Liška 2020-01-20 13:52:49 UTC
Reduced test-case:

$ cat pr93275.ii
template <int __v> struct A { static constexpr int value = __v; };
template <bool, typename> struct B;
template <typename _Tp> struct B<true, _Tp> { typedef _Tp type; };
template <bool _Cond, typename _Tp>
using enable_if_t = typename B<_Cond, _Tp>::type;
template <typename> constexpr bool array_depth_v = A<1>::value;
template <typename T, int> struct C {
  template <typename Other,
            enable_if_t<array_depth_v<C>, decltype(nullptr)> = nullptr>
  void operator*(Other other) {
    [other](T t) { t *other; };
  }
};

int
main() {
  C<C<float, 4>, 1> a0;
  a0 * 4.f;
  return 0;
}

$ g++ -c pr93275.ii -std=c++17
pr93275.ii: In substitution of ‘template<class T, int <anonymous> > template<class Other, typename B<array_depth_v<C<T, <anonymous> > >, std::nullptr_t>::type <anonymous> > void C<T, <anonymous> >::operator*(Other) [with Other = <missing>; typename B<array_depth_v<C<T, <anonymous> > >, std::nullptr_t>::type <anonymous> = <missing>; T = float; int <anonymous> = <missing>]’:
pr93275.ii:11:22:   required from ‘void C<T, <anonymous> >::operator*(Other) [with Other = float; typename B<array_depth_v<C<T, <anonymous> > >, std::nullptr_t>::type <anonymous> = nullptr; T = C<float, 4>; int <anonymous> = 1]’
pr93275.ii:18:8:   required from here
pr93275.ii:9:25: internal compiler error: unexpected expression ‘<anonymous>’ of kind template_parm_index
    9 |             enable_if_t<array_depth_v<C>, decltype(nullptr)> = nullptr>
      |                         ^~~~~~~~~~~~~~~~
0x961234 cxx_eval_constant_expression
	/home/marxin/Programming/gcc/gcc/cp/constexpr.c:6125
0x96174e cxx_eval_outermost_constant_expr
	/home/marxin/Programming/gcc/gcc/cp/constexpr.c:6323
0x9660a4 maybe_constant_value(tree_node*, tree_node*, bool)
	/home/marxin/Programming/gcc/gcc/cp/constexpr.c:6593
0xa96124 convert_nontype_argument
	/home/marxin/Programming/gcc/gcc/cp/pt.c:7116
0xa96124 convert_template_argument
	/home/marxin/Programming/gcc/gcc/cp/pt.c:8350
0xa96124 convert_template_argument
	/home/marxin/Programming/gcc/gcc/cp/pt.c:8087
0xa9796b coerce_template_parms
	/home/marxin/Programming/gcc/gcc/cp/pt.c:8829
0xabce39 lookup_template_class_1
	/home/marxin/Programming/gcc/gcc/cp/pt.c:9666
0xabce39 lookup_template_class(tree_node*, tree_node*, tree_node*, tree_node*, int, int)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:10038
0xab88cf tsubst_aggr_type
	/home/marxin/Programming/gcc/gcc/cp/pt.c:13332
0xab0d3f tsubst(tree_node*, tree_node*, int, tree_node*)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:15033
0xab856b tsubst_template_args(tree_node*, tree_node*, int, tree_node*)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:13125
0xaab074 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:18999
0xa9f3b7 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:18590
0xab2c53 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:12047
0xab2c53 tsubst_template_arg(tree_node*, tree_node*, int, tree_node*)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:12058
0xab2c53 tsubst_template_arg(tree_node*, tree_node*, int, tree_node*)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:12046
0xab856b tsubst_template_args(tree_node*, tree_node*, int, tree_node*)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:13125
0xab88aa tsubst_aggr_type
	/home/marxin/Programming/gcc/gcc/cp/pt.c:13326
0xab08f5 tsubst(tree_node*, tree_node*, int, tree_node*)
	/home/marxin/Programming/gcc/gcc/cp/pt.c:15662
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Comment 5 Marek Polacek 2020-01-20 14:41:07 UTC
(In reply to Martin Liška from comment #3)
> Confirmed, started with r9-6404-g1ce59b6cad83d5ca6f1efee83f910d8b677a976a.

Are you sure?  It's only a daily bump.
Comment 6 Martin Liška 2020-01-21 08:35:09 UTC
(In reply to Marek Polacek from comment #5)
> (In reply to Martin Liška from comment #3)
> > Confirmed, started with r9-6404-g1ce59b6cad83d5ca6f1efee83f910d8b677a976a.
> 
> Are you sure?  It's only a daily bump.

Sorry, it's the commit right after it:
r9-6405-gbddee796d0b4800b5ac3d7e7e9e315c23799424d

For named function calls in a template, the result of unqualified lookup is
safed in CALL_EXPR_FN.  But for operator expressions, no unqualified lookup
is performed until we know whether the operands have class type.  So when we
see in a lambda a use of an operator that might be overloaded, we need to do
that lookup then and save it away somewhere.  One possibility would be in
the expression, but we can't really add extra conditional operands to
standard tree codes.  I mostly implemented another approach using a new
WITH_LOOKUP_EXPR code, but teaching everywhere how to handle a new tree code
is always complicated.  Then it occurred to me that we could associate the
lookups with the function, which is both simpler and smaller.  So this patch
stores any operator bindings needed by a lambda function in an internal
attribute on the lambda call operator.

	* name-lookup.c (op_unqualified_lookup)
	(maybe_save_operator_binding, discard_operator_bindings)
	(push_operator_bindings): New.
	* typeck.c (build_x_binary_op, build_x_unary_op): Call
	maybe_save_operator_binding.
	* decl.c (start_preparsed_function): Call push_operator_bindings.
	* tree.c (cp_free_lang_data): Call discard_operator_bindings.

From-SVN: r269477
Comment 7 Jakub Jelinek 2020-01-21 08:39:14 UTC
Dup.

*** This bug has been marked as a duplicate of bug 93279 ***