diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-11-12 19:07:40 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-11-12 19:07:40 -0500 |
commit | de6f64f9556ae39317186f3486135f1ef308a096 (patch) | |
tree | 00607233a1cdce8e34b9d7f9f6d8f2e705ab87c0 /gcc | |
parent | 93fc47746815ea9dac413322fcade2931f757e7f (diff) | |
download | gcc-de6f64f9556ae39317186f3486135f1ef308a096.zip gcc-de6f64f9556ae39317186f3486135f1ef308a096.tar.gz gcc-de6f64f9556ae39317186f3486135f1ef308a096.tar.bz2 |
c++: Don't form a templated TARGET_EXPR in finish_compound_literal
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 and under different settings of current_function_decl will
compare equal according to cp_tree_equal, but find_template_parameters
may return 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 share 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 issue by removing the source of these
templated TARGET_EXPRs. The relevant call to get_target_expr_sfinae was
added in r9-6043, and 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).
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/semantics.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-decltype3.C | 15 |
2 files changed, 16 insertions, 6 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index df698d5..0389198 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 0000000..837855c --- /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>(); +} |