On 11/12/20 1:27 PM, Patrick Palka wrote:
The atom_cache in normalize_atom relies on the assumption that two
equivalent (templated) trees (in the sense of cp_tree_equal) must use
the same template parameters (according to find_template_parameters).
This assumption unfortunately doesn't always hold for TARGET_EXPRs,
because cp_tree_equal ignores an artificial target of a TARGET_EXPR, but
find_template_parameters walks this target (and its DECL_CONTEXT).
Hence two TARGET_EXPRs built by force_target_expr with the same
initializer but under different settings of current_function_decl may
compare equal according to cp_tree_equal, but find_template_parameters
returns a different set of template parameters for them. This breaks
the below testcase because during normalization we build two such
TARGET_EXPRs (one under current_function_decl=f and another under =g),
and then use the same ATOMIC_CONSTR for the two corresponding atoms,
leading to a crash during satisfaction of g's associated constraints.
This patch works around this assumption violation by removing the source
of these templated TARGET_EXPRs. The relevant call to get_target_expr was
added in r9-6043, but it seems it's no longer necessary (according to
https://gcc.gnu.org/pipermail/gcc-patches/2019-February/517323.html, the
call was added in order to avoid regressing on initlist109.C at the time).
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?
OK. I wonder what else asserting !processing_template_decl in
build_target_expr would find...
gcc/cp/ChangeLog:
* semantics.c (finish_compound_literal): Don't wrap the original
compound literal in a TARGET_EXPR when inside a template.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-decltype3.C: New test.
---
gcc/cp/semantics.c | 7 +------
gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C | 15 +++++++++++++++
2 files changed, 16 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 33d715edaec..172286922e7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3006,12 +3006,7 @@ finish_compound_literal (tree type, tree
compound_literal,
/* If we're in a template, return the original compound literal. */
if (orig_cl)
- {
- if (!VECTOR_TYPE_P (type))
- return get_target_expr_sfinae (orig_cl, complain);
- else
- return orig_cl;
- }
+ return orig_cl;
if (TREE_CODE (compound_literal) == CONSTRUCTOR)
{
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C
b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C
new file mode 100644
index 00000000000..837855ce8ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++20 } }
+
+template <class T> concept C = requires(T t) { t; };
+
+template <class T> using A = decltype((T{}, int{}));
+
+template <class T> concept D = C<A<T>>;
+
+template <class T, class U> void f() requires D<T>;
+template <class T> void g() requires D<T>;
+
+void h() {
+ f<int, int>();
+ g<int>();
+}