I think the patch is in good shape now, thanks for the help. canon-type*.C fail with trunk and pass with patch, dependent-name*.C are regression tests that pass with both. I removed the dg-ice from constexpr-52830.C. I didn't dig much into the churn history there, but the test code looks valid to me and clang agrees.
I also returned the copyright assignment form yesterday to ass...@gnu.org.
From 9bea055c84d307ade7095fa2cdf7432b42ee0897 Mon Sep 17 00:00:00 2001 From: Barrett Adair <barrettellisad...@gmail.com> Date: Wed, 15 Sep 2021 15:26:22 -0500 Subject: [PATCH] Fix template instantiation comparison outside function body --- gcc/cp/pt.c | 18 ++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C | 1 - gcc/testsuite/g++.dg/template/canon-type-15.C | 7 +++++++ gcc/testsuite/g++.dg/template/canon-type-16.C | 6 ++++++ gcc/testsuite/g++.dg/template/canon-type-17.C | 5 +++++ gcc/testsuite/g++.dg/template/canon-type-18.C | 6 ++++++ .../g++.dg/template/dependent-name15.C | 18 ++++++++++++++++++ .../g++.dg/template/dependent-name16.C | 14 ++++++++++++++ 8 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/canon-type-15.C create mode 100644 gcc/testsuite/g++.dg/template/canon-type-16.C create mode 100644 gcc/testsuite/g++.dg/template/canon-type-17.C create mode 100644 gcc/testsuite/g++.dg/template/canon-type-18.C create mode 100644 gcc/testsuite/g++.dg/template/dependent-name15.C create mode 100644 gcc/testsuite/g++.dg/template/dependent-name16.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 224dd9ebd2b..597422045d3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -27766,6 +27766,19 @@ dependent_template_arg_p (tree arg) return value_dependent_expression_p (arg); } +/* Identify any expressions that use function parms */ +static tree +find_parm_usage_r (tree *tp, int *walk_subtrees, void*) +{ + tree t = *tp; + if (PACK_EXPANSION_P (t) || (TREE_CODE (t) == PARM_DECL)) + { + *walk_subtrees = 0; + return t; + } + return NULL_TREE; +} + /* Returns true if ARGS (a collection of template arguments) contains any types that require structural equality testing. */ @@ -27810,6 +27823,11 @@ any_template_arguments_need_structural_equality_p (tree args) else if (!TYPE_P (arg) && TREE_TYPE (arg) && TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (arg))) return true; + else if (!current_function_decl + && dependent_template_arg_p (arg) + && cp_walk_tree_without_duplicates (&arg, + find_parm_usage_r, NULL)) + return true; } } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C index eae0d8c377b..d6057f13497 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-52830.C @@ -1,7 +1,6 @@ // PR c++/52830 // { dg-do compile { target c++11 } } // { dg-additional-options "-fchecking" } -// { dg-ice "comptypes" } template<bool b> struct eif { typedef void type; }; template<> struct eif<false> {}; diff --git a/gcc/testsuite/g++.dg/template/canon-type-15.C b/gcc/testsuite/g++.dg/template/canon-type-15.C new file mode 100644 index 00000000000..b001b5c841d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/canon-type-15.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++11 } } +template<unsigned u> struct size_c{ static constexpr unsigned value = u; }; +namespace g { +template<class T> auto return_size(T t) -> size_c<sizeof(t)>; +template<class T> auto return_size(T t) -> size_c<sizeof(t)>; +} +static_assert(decltype(g::return_size('a'))::value == 1u, ""); diff --git a/gcc/testsuite/g++.dg/template/canon-type-16.C b/gcc/testsuite/g++.dg/template/canon-type-16.C new file mode 100644 index 00000000000..99361cbac30 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/canon-type-16.C @@ -0,0 +1,6 @@ +// { dg-do compile { target c++11 } } +template<bool u> struct bool_c{ static constexpr bool value = u; }; +template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>; +template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>; +struct foo { void operator()() noexcept; }; +static_assert(decltype(noexcepty(foo{}))::value, ""); diff --git a/gcc/testsuite/g++.dg/template/canon-type-17.C b/gcc/testsuite/g++.dg/template/canon-type-17.C new file mode 100644 index 00000000000..0555c8d0a42 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/canon-type-17.C @@ -0,0 +1,5 @@ +// { dg-do compile { target c++11 } } +template<unsigned u> struct size_c{ static constexpr unsigned value = u; }; +template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>; +template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>; +static_assert(decltype(return_size('a'))::value == 1u, ""); diff --git a/gcc/testsuite/g++.dg/template/canon-type-18.C b/gcc/testsuite/g++.dg/template/canon-type-18.C new file mode 100644 index 00000000000..2510181725c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/canon-type-18.C @@ -0,0 +1,6 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-pedantic" } +template<unsigned u> struct size_c{ static constexpr unsigned value = u; }; +template<class T> auto get_align(T t) -> size_c<alignof(t)>; +template<class T> auto get_align(T t) -> size_c<alignof(t)>; +static_assert(decltype(get_align('a'))::value == 1u, ""); diff --git a/gcc/testsuite/g++.dg/template/dependent-name15.C b/gcc/testsuite/g++.dg/template/dependent-name15.C new file mode 100644 index 00000000000..1c34bc704f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-name15.C @@ -0,0 +1,18 @@ +// { dg-do compile { target c++11 } } +template <int N> struct A { static void foo(){} }; +template <> struct A<sizeof(char)> { using foo = int; }; + +template <class T> void f(T t1) { + A<sizeof(t1)>::foo(); +} + +template <class T> void g(T t2) { + /* if the comparing_specializations check breaks in cp_tree_equal + case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */ + A<sizeof(t2)>::foo(); // { dg-error "dependent-name .A<sizeof .t2.>::foo" } +} + +void h() { + f(0); + g('0'); +} diff --git a/gcc/testsuite/g++.dg/template/dependent-name16.C b/gcc/testsuite/g++.dg/template/dependent-name16.C new file mode 100644 index 00000000000..ef8c4f23077 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-name16.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++11 } } +template <int N> struct A { static void foo(){} }; +template <> struct A<sizeof(char)> { using foo = int; }; + +template<class T1> auto f(T1 t1) -> decltype(A<sizeof(t1)>::foo()); + +/* if the comparing_specializations check breaks in cp_tree_equal +case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */ +template<class T2> auto g(T2 t2) -> decltype(A<sizeof(t2)>::foo()); // { dg-error "dependent-name .A<sizeof .t2.>::foo" } + +void h() { + f(0); + g('0'); // { dg-error "no matching function" } +} -- 2.30.2