From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2122) id D3BC43858D39; Wed, 22 Sep 2021 04:03:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D3BC43858D39 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jason Merrill To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-3766] c++: fix template instantiation comparison in redeclarations X-Act-Checkin: gcc X-Git-Author: Barrett Adair X-Git-Refname: refs/heads/master X-Git-Oldrev: 2c41dd82e23c296681aa466693bfc726e2d919ce X-Git-Newrev: 72394d38d929c72cad6cf706a0e790b5934f2bf1 Message-Id: <20210922040321.D3BC43858D39@sourceware.org> Date: Wed, 22 Sep 2021 04:03:21 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Sep 2021 04:03:21 -0000 https://gcc.gnu.org/g:72394d38d929c72cad6cf706a0e790b5934f2bf1 commit r12-3766-g72394d38d929c72cad6cf706a0e790b5934f2bf1 Author: Barrett Adair Date: Wed Sep 15 15:26:22 2021 -0500 c++: fix template instantiation comparison in redeclarations This change fixes a primordial c++11 frontend defect where function template redeclarations with trailing return types that used dependent sizeof/alignof/noexcept expressions in template value arguments failed to compare as equivalent to the identical primary template declaration. By forcing structural AST comparison of the template arguments, we no longer require TYPE_CANONICAL to match in this case. The new canon-type-{15..18}.C tests failed with all prior GCC versions, where the redeclarations were incorrectly reported as ambiguous overloads. The new dependent-name{15,16}.C tests are regression tests for sneaky problems encountered during development of this fix. Note that this fix does not address the use of parm objects' constexpr members as template arguments within a declaration (a superficially similar longstanding defect). gcc/cp/ChangeLog: * pt.c (find_parm_usage_r): New walk_tree callback to find func parms. (any_template_arguments_need_structural_equality_p): New special case. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-52830.C: Remove unwanted dg-ice. * g++.dg/template/canon-type-15.C: New test. * g++.dg/template/canon-type-16.C: New test. * g++.dg/template/canon-type-17.C: New test. * g++.dg/template/canon-type-18.C: New test. * g++.dg/template/dependent-name15.C: New regression test. * g++.dg/template/dependent-name16.C: New regression test. Diff: --- gcc/cp/pt.c | 21 +++++++++++++++++++++ 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 ++++++ gcc/testsuite/g++.dg/template/dependent-name15.C | 18 ++++++++++++++++++ gcc/testsuite/g++.dg/template/dependent-name16.C | 14 ++++++++++++++ 8 files changed, 77 insertions(+), 1 deletion(-) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4d42899f28d..048bbc4622d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -27813,6 +27813,20 @@ 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 (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. */ @@ -27857,6 +27871,13 @@ 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; + /* Checking current_function_decl because this structural + comparison is only necessary for redeclaration. */ + 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 struct eif { typedef void type; }; template<> struct eif {}; 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 struct size_c{ static constexpr unsigned value = u; }; +namespace g { +template auto return_size(T t) -> size_c; +template auto return_size(T t) -> size_c; +} +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 struct bool_c{ static constexpr bool value = u; }; +template auto noexcepty(T t) -> bool_c; +template auto noexcepty(T t) -> bool_c; +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 struct size_c{ static constexpr unsigned value = u; }; +template auto return_size(T... t) -> size_c; +template auto return_size(T... t) -> size_c; +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 struct size_c{ static constexpr unsigned value = u; }; +template auto get_align(T t) -> size_c; +template auto get_align(T t) -> size_c; +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 struct A { static void foo(){} }; +template <> struct A { using foo = int; }; + +template void f(T t1) { + A::foo(); +} + +template void g(T t2) { + /* if the comparing_specializations check breaks in cp_tree_equal + case PARM_DECL, the error will incorrectly report A */ + A::foo(); // { dg-error "dependent-name .A::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 struct A { static void foo(){} }; +template <> struct A { using foo = int; }; + +template auto f(T1 t1) -> decltype(A::foo()); + +/* if the comparing_specializations check breaks in cp_tree_equal +case PARM_DECL, the error will incorrectly report A */ +template auto g(T2 t2) -> decltype(A::foo()); // { dg-error "dependent-name .A::foo" } + +void h() { + f(0); + g('0'); // { dg-error "no matching function" } +}