On Thu, Nov 12, 2020 at 01:27:23PM -0500, 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?

Looks OK to me, thanks!

> 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>();
> +}
> -- 
> 2.29.2.260.ge31aba42fb
> 

Marek

Reply via email to