[v4] c++: Fix cp_tree_equal for template value args using dependent sizeof/alignof/noexcept expressions
Commit Message
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 assign@gnu.org.
Comments
On 9/17/21 12:44, Barrett Adair wrote:
> 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
> assign@gnu.org <mailto:assign@gnu.org>.
> +/* Identify any expressions that use function parms */
A comment should end with a period and two spaces.
> +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))
PACK_EXPANSION_P is wrong here; a pack expansion might not involve a
function parameter (pack) at all. And walk_tree should already recurse
into the pattern of a pack expansion, so handling them specifically here
shouldn't be necessary.
> + else if (!current_function_decl
This needs a comment about why we're checking current_function_decl
(because we only need structural comparison for redeclaration comparisons)
> + && dependent_template_arg_p (arg)
> + && cp_walk_tree_without_duplicates (&arg,
> + find_parm_usage_r, NULL))
Here the second line of args needs to line up with the args on the
previous line. When that's too far to the right, like here, I tend to
write e.g.
> + && (cp_walk_tree_without_duplicates
> + (&arg, find_parm_usage_r, NULL)))
Jason
From 9bea055c84d307ade7095fa2cdf7432b42ee0897 Mon Sep 17 00:00:00 2001
From: Barrett Adair <barrettellisadair@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
@@ -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;
}
}
}
@@ -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> {};
new file mode 100644
@@ -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, "");
new file mode 100644
@@ -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, "");
new file mode 100644
@@ -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, "");
new file mode 100644
@@ -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, "");
new file mode 100644
@@ -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');
+}
new file mode 100644
@@ -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