Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-09-07 Thread Jason Merrill via Gcc-patches

On 9/6/23 18:09, Patrick Palka wrote:

On Mon, 28 Aug 2023, Jason Merrill wrote:


On 8/24/23 09:31, Patrick Palka wrote:

On Wed, 23 Aug 2023, Jason Merrill wrote:


On 8/21/23 21:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

+ /* We're checking only non-instantiating conversions.
+A conversion may instantiate only if it's to/from a
+class type that has a constructor template/conversion
+function template.  */
+ tree parm_nonref = non_reference (parm);
+ tree type_nonref = non_reference (type);
+
+ if (CLASS_TYPE_P (parm_nonref))
+   {
+ if (!COMPLETE_TYPE_P (parm_nonref)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
+   return unify_success (explain_p);
+
+ tree ctors = get_class_binding (parm_nonref,
+ complete_ctor_identifier);
+ for (tree ctor : lkp_range (ctors))
+   if (TREE_CODE (ctor) == TEMPLATE_DECL)
+ return unify_success (explain_p);


Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?


Done; all dups of this PR seem to use tag types that are aggregates, so this
seems like a good simplification.  I also made us punt if the arg type has a
constrained non-template conversion function.



Also, instantiation can also happen when checking for conversion to a
pointer
or reference to base class.


Oops, I suppose we just need to strip pointer types upfront as well.  The
!COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
sure we deem a potential derived-to-base conversion unsafe if appropriate
IIUC.

How does the following look?

-- >8 --

Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs
[PR99599]

PR c++/99599

gcc/cp/ChangeLog:

* config-lang.in (gtfiles): Add search.cc.
* pt.cc (check_non_deducible_conversions): Add bool parameter
passed down to check_non_deducible_conversion.
(fn_type_unification): Call check_non_deducible_conversions
an extra time before satisfaction with noninst_only_p=true.
(check_non_deducible_conversion): Add bool parameter controlling
whether to compute only conversions that are guaranteed to
not induce template instantiation.
* search.cc (conversions_cache): Define.
(lookup_conversions): Use it to cache the lookup.  Improve cache
rate by considering TYPE_MAIN_VARIANT of the type.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-nondep4.C: New test.
---
   gcc/cp/config-lang.in |  1 +
   gcc/cp/pt.cc  | 81 +--
   gcc/cp/search.cc  | 14 +++-
   gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C | 21 +
   4 files changed, 110 insertions(+), 7 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C

@@ -22921,6 +22933,65 @@ check_non_deducible_conversion (tree parm, tree
arg, unification_kind_t strict,
   {
 bool ok = false;
 tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
+  if (conv_p && *conv_p)
+   {
+ /* This conversion was already computed earlier (when
+computing only non-instantiating conversions).  */
+ gcc_checking_assert (!noninst_only_p);
+ return unify_success (explain_p);
+   }
+  if (noninst_only_p)
+   {
+ /* We're checking only non-instantiating conversions.
+Computing a conversion may induce template instantiation
+only if ... */


Let's factor this whole block out into another function.


Sounds good.



Incidentally, CWG1092 is a related problem with defaulted functions, which I
dealt with in a stricter way:

Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-09-06 Thread Patrick Palka via Gcc-patches
On Mon, 28 Aug 2023, Jason Merrill wrote:

> On 8/24/23 09:31, Patrick Palka wrote:
> > On Wed, 23 Aug 2023, Jason Merrill wrote:
> > 
> > > On 8/21/23 21:51, Patrick Palka wrote:
> > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
> > > > a reasonable approach?  I didn't observe any compile time/memory impact
> > > > of this change.
> > > > 
> > > > -- >8 --
> > > > 
> > > > As described in detail in the PR, CWG 2369 has the surprising
> > > > consequence of introducing constraint recursion in seemingly valid and
> > > > innocent code.
> > > > 
> > > > This patch attempts to fix this surpising behavior for the majority
> > > > of problematic use cases.  Rather than checking satisfaction before
> > > > _all_ non-dependent conversions, as specified by the CWG issue,
> > > > this patch makes us first check "safe" non-dependent conversions,
> > > > then satisfaction, then followed by "unsafe" non-dependent conversions.
> > > > In this case, a conversion is "safe" if computing it is guaranteed
> > > > to not induce template instantiation.  This patch heuristically
> > > > determines "safety" by checking for a constructor template or conversion
> > > > function template in the (class) parm or arg types respectively.
> > > > If neither type has such a member, then computing the conversion
> > > > should not induce instantiation (modulo satisfaction checking of
> > > > non-template constructor and conversion functions I suppose).
> > > > 
> > > > + /* We're checking only non-instantiating conversions.
> > > > +A conversion may instantiate only if it's to/from a
> > > > +class type that has a constructor template/conversion
> > > > +function template.  */
> > > > + tree parm_nonref = non_reference (parm);
> > > > + tree type_nonref = non_reference (type);
> > > > +
> > > > + if (CLASS_TYPE_P (parm_nonref))
> > > > +   {
> > > > + if (!COMPLETE_TYPE_P (parm_nonref)
> > > > + && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
> > > > +   return unify_success (explain_p);
> > > > +
> > > > + tree ctors = get_class_binding (parm_nonref,
> > > > + complete_ctor_identifier);
> > > > + for (tree ctor : lkp_range (ctors))
> > > > +   if (TREE_CODE (ctor) == TEMPLATE_DECL)
> > > > + return unify_success (explain_p);
> > > 
> > > Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?
> > 
> > Done; all dups of this PR seem to use tag types that are aggregates, so this
> > seems like a good simplification.  I also made us punt if the arg type has a
> > constrained non-template conversion function.
> > 
> > > 
> > > Also, instantiation can also happen when checking for conversion to a
> > > pointer
> > > or reference to base class.
> > 
> > Oops, I suppose we just need to strip pointer types upfront as well.  The
> > !COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
> > sure we deem a potential derived-to-base conversion unsafe if appropriate
> > IIUC.
> > 
> > How does the following look?
> > 
> > -- >8 --
> > 
> > Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs
> > [PR99599]
> > 
> > PR c++/99599
> > 
> > gcc/cp/ChangeLog:
> > 
> > * config-lang.in (gtfiles): Add search.cc.
> > * pt.cc (check_non_deducible_conversions): Add bool parameter
> > passed down to check_non_deducible_conversion.
> > (fn_type_unification): Call check_non_deducible_conversions
> > an extra time before satisfaction with noninst_only_p=true.
> > (check_non_deducible_conversion): Add bool parameter controlling
> > whether to compute only conversions that are guaranteed to
> > not induce template instantiation.
> > * search.cc (conversions_cache): Define.
> > (lookup_conversions): Use it to cache the lookup.  Improve cache
> > rate by considering TYPE_MAIN_VARIANT of the type.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp2a/concepts-nondep4.C: New test.
> > ---

Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-09-06 Thread Patrick Palka via Gcc-patches



On Mon, 28 Aug 2023, Jason Merrill wrote:

> On 8/24/23 09:31, Patrick Palka wrote:
> > On Wed, 23 Aug 2023, Jason Merrill wrote:
> > 
> > > On 8/21/23 21:51, Patrick Palka wrote:
> > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
> > > > a reasonable approach?  I didn't observe any compile time/memory impact
> > > > of this change.
> > > > 
> > > > -- >8 --
> > > > 
> > > > As described in detail in the PR, CWG 2369 has the surprising
> > > > consequence of introducing constraint recursion in seemingly valid and
> > > > innocent code.
> > > > 
> > > > This patch attempts to fix this surpising behavior for the majority
> > > > of problematic use cases.  Rather than checking satisfaction before
> > > > _all_ non-dependent conversions, as specified by the CWG issue,
> > > > this patch makes us first check "safe" non-dependent conversions,
> > > > then satisfaction, then followed by "unsafe" non-dependent conversions.
> > > > In this case, a conversion is "safe" if computing it is guaranteed
> > > > to not induce template instantiation.  This patch heuristically
> > > > determines "safety" by checking for a constructor template or conversion
> > > > function template in the (class) parm or arg types respectively.
> > > > If neither type has such a member, then computing the conversion
> > > > should not induce instantiation (modulo satisfaction checking of
> > > > non-template constructor and conversion functions I suppose).
> > > > 
> > > > + /* We're checking only non-instantiating conversions.
> > > > +A conversion may instantiate only if it's to/from a
> > > > +class type that has a constructor template/conversion
> > > > +function template.  */
> > > > + tree parm_nonref = non_reference (parm);
> > > > + tree type_nonref = non_reference (type);
> > > > +
> > > > + if (CLASS_TYPE_P (parm_nonref))
> > > > +   {
> > > > + if (!COMPLETE_TYPE_P (parm_nonref)
> > > > + && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
> > > > +   return unify_success (explain_p);
> > > > +
> > > > + tree ctors = get_class_binding (parm_nonref,
> > > > + complete_ctor_identifier);
> > > > + for (tree ctor : lkp_range (ctors))
> > > > +   if (TREE_CODE (ctor) == TEMPLATE_DECL)
> > > > + return unify_success (explain_p);
> > > 
> > > Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?
> > 
> > Done; all dups of this PR seem to use tag types that are aggregates, so this
> > seems like a good simplification.  I also made us punt if the arg type has a
> > constrained non-template conversion function.
> > 
> > > 
> > > Also, instantiation can also happen when checking for conversion to a
> > > pointer
> > > or reference to base class.
> > 
> > Oops, I suppose we just need to strip pointer types upfront as well.  The
> > !COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
> > sure we deem a potential derived-to-base conversion unsafe if appropriate
> > IIUC.
> > 
> > How does the following look?
> > 
> > -- >8 --
> > 
> > Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs
> > [PR99599]
> > 
> > PR c++/99599
> > 
> > gcc/cp/ChangeLog:
> > 
> > * config-lang.in (gtfiles): Add search.cc.
> > * pt.cc (check_non_deducible_conversions): Add bool parameter
> > passed down to check_non_deducible_conversion.
> > (fn_type_unification): Call check_non_deducible_conversions
> > an extra time before satisfaction with noninst_only_p=true.
> > (check_non_deducible_conversion): Add bool parameter controlling
> > whether to compute only conversions that are guaranteed to
> > not induce template instantiation.
> > * search.cc (conversions_cache): Define.
> > (lookup_conversions): Use it to cache the lookup.  Improve cache
> > rate by considering TYPE_MAIN_VARIANT of the type.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp2a/concepts-nondep4.C: New test.
> > ---

Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-08-28 Thread Jason Merrill via Gcc-patches

On 8/24/23 09:31, Patrick Palka wrote:

On Wed, 23 Aug 2023, Jason Merrill wrote:


On 8/21/23 21:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

+ /* We're checking only non-instantiating conversions.
+A conversion may instantiate only if it's to/from a
+class type that has a constructor template/conversion
+function template.  */
+ tree parm_nonref = non_reference (parm);
+ tree type_nonref = non_reference (type);
+
+ if (CLASS_TYPE_P (parm_nonref))
+   {
+ if (!COMPLETE_TYPE_P (parm_nonref)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
+   return unify_success (explain_p);
+
+ tree ctors = get_class_binding (parm_nonref,
+ complete_ctor_identifier);
+ for (tree ctor : lkp_range (ctors))
+   if (TREE_CODE (ctor) == TEMPLATE_DECL)
+ return unify_success (explain_p);


Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?


Done; all dups of this PR seem to use tag types that are aggregates, so this
seems like a good simplification.  I also made us punt if the arg type has a
constrained non-template conversion function.



Also, instantiation can also happen when checking for conversion to a pointer
or reference to base class.


Oops, I suppose we just need to strip pointer types upfront as well.  The
!COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
sure we deem a potential derived-to-base conversion unsafe if appropriate
IIUC.

How does the following look?

-- >8 --

Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

PR c++/99599

gcc/cp/ChangeLog:

* config-lang.in (gtfiles): Add search.cc.
* pt.cc (check_non_deducible_conversions): Add bool parameter
passed down to check_non_deducible_conversion.
(fn_type_unification): Call check_non_deducible_conversions
an extra time before satisfaction with noninst_only_p=true.
(check_non_deducible_conversion): Add bool parameter controlling
whether to compute only conversions that are guaranteed to
not induce template instantiation.
* search.cc (conversions_cache): Define.
(lookup_conversions): Use it to cache the lookup.  Improve cache
rate by considering TYPE_MAIN_VARIANT of the type.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-nondep4.C: New test.
---
  gcc/cp/config-lang.in |  1 +
  gcc/cp/pt.cc  | 81 +--
  gcc/cp/search.cc  | 14 +++-
  gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C | 21 +
  4 files changed, 110 insertions(+), 7 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C

@@ -22921,6 +22933,65 @@ check_non_deducible_conversion (tree parm, tree arg, 
unification_kind_t strict,
  {
bool ok = false;
tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
+  if (conv_p && *conv_p)
+   {
+ /* This conversion was already computed earlier (when
+computing only non-instantiating conversions).  */
+ gcc_checking_assert (!noninst_only_p);
+ return unify_success (explain_p);
+   }
+  if (noninst_only_p)
+   {
+ /* We're checking only non-instantiating conversions.
+Computing a conversion may induce template instantiation
+only if ... */


Let's factor this whole block out into another function.

Incidentally, CWG1092 is a related problem with defaulted functions, 
which I dealt with in a stricter way: when LOOKUP_DEFAULTED we ignore a 
conversion from the parameter being copied to a non-reference-related 
typ

Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-08-24 Thread Patrick Palka via Gcc-patches
On Wed, 23 Aug 2023, Jason Merrill wrote:

> On 8/21/23 21:51, Patrick Palka wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
> > a reasonable approach?  I didn't observe any compile time/memory impact
> > of this change.
> > 
> > -- >8 --
> > 
> > As described in detail in the PR, CWG 2369 has the surprising
> > consequence of introducing constraint recursion in seemingly valid and
> > innocent code.
> > 
> > This patch attempts to fix this surpising behavior for the majority
> > of problematic use cases.  Rather than checking satisfaction before
> > _all_ non-dependent conversions, as specified by the CWG issue,
> > this patch makes us first check "safe" non-dependent conversions,
> > then satisfaction, then followed by "unsafe" non-dependent conversions.
> > In this case, a conversion is "safe" if computing it is guaranteed
> > to not induce template instantiation.  This patch heuristically
> > determines "safety" by checking for a constructor template or conversion
> > function template in the (class) parm or arg types respectively.
> > If neither type has such a member, then computing the conversion
> > should not induce instantiation (modulo satisfaction checking of
> > non-template constructor and conversion functions I suppose).
> > 
> > + /* We're checking only non-instantiating conversions.
> > +A conversion may instantiate only if it's to/from a
> > +class type that has a constructor template/conversion
> > +function template.  */
> > + tree parm_nonref = non_reference (parm);
> > + tree type_nonref = non_reference (type);
> > +
> > + if (CLASS_TYPE_P (parm_nonref))
> > +   {
> > + if (!COMPLETE_TYPE_P (parm_nonref)
> > + && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
> > +   return unify_success (explain_p);
> > +
> > + tree ctors = get_class_binding (parm_nonref,
> > + complete_ctor_identifier);
> > + for (tree ctor : lkp_range (ctors))
> > +   if (TREE_CODE (ctor) == TEMPLATE_DECL)
> > + return unify_success (explain_p);
> 
> Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?

Done; all dups of this PR seem to use tag types that are aggregates, so this
seems like a good simplification.  I also made us punt if the arg type has a
constrained non-template conversion function.

> 
> Also, instantiation can also happen when checking for conversion to a pointer
> or reference to base class.

Oops, I suppose we just need to strip pointer types upfront as well.  The
!COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
sure we deem a potential derived-to-base conversion unsafe if appropriate
IIUC.

How does the following look?

-- >8 --

Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

PR c++/99599

gcc/cp/ChangeLog:

* config-lang.in (gtfiles): Add search.cc.
* pt.cc (check_non_deducible_conversions): Add bool parameter
passed down to check_non_deducible_conversion.
(fn_type_unification): Call check_non_deducible_conversions
an extra time before satisfaction with noninst_only_p=true.
(check_non_deducible_conversion): Add bool parameter controlling
whether to compute only conversions that are guaranteed to
not induce template instantiation.
* search.cc (conversions_cache): Define.
(lookup_conversions): Use it to cache the lookup.  Improve cache
rate by considering TYPE_MAIN_VARIANT of the type.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-nondep4.C: New test.
---
 gcc/cp/config-lang.in |  1 +
 gcc/cp/pt.cc  | 81 +--
 gcc/cp/search.cc  | 14 +++-
 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C | 21 +
 4 files changed, 110 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C

diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in
index a6c7883cc24..e34c392d208 100644
--- a/gcc/cp/config-lang.in
+++ b/gcc/cp/config-lang.in
@@ -52,6 +52,7 @@ gtfiles="\
 \$(srcdir)/cp/name-lookup.cc \
 \$(srcdir)/cp/parser.cc \$(srcdir)/cp/pt.cc \
 \$(srcdir)/cp/rtti.cc \
+\$(srcdir)/cp/search.cc \
 \$(srcdir)/cp/semantics.cc \
 \$(srcdir)/cp/tree.cc \$(srcdir)/cp/typeck2.cc \
 \$(srcdir)/cp/vtable-class-hierarchy.cc \
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a4809f034dc..3c77d2466eb 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -151,7 +151,7 @@ static tree get_partial_spec_bindings (tree, tre

Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-08-23 Thread Jason Merrill via Gcc-patches

On 8/21/23 21:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

+ /* We're checking only non-instantiating conversions.
+A conversion may instantiate only if it's to/from a
+class type that has a constructor template/conversion
+function template.  */
+ tree parm_nonref = non_reference (parm);
+ tree type_nonref = non_reference (type);
+
+ if (CLASS_TYPE_P (parm_nonref))
+   {
+ if (!COMPLETE_TYPE_P (parm_nonref)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
+   return unify_success (explain_p);
+
+ tree ctors = get_class_binding (parm_nonref,
+ complete_ctor_identifier);
+ for (tree ctor : lkp_range (ctors))
+   if (TREE_CODE (ctor) == TEMPLATE_DECL)
+ return unify_success (explain_p);


Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?

Also, instantiation can also happen when checking for conversion to a 
pointer or reference to base class.


Jason



[PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-08-21 Thread Patrick Palka via Gcc-patches
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

PR c++/99599

gcc/cp/ChangeLog:

* config-lang.in (gtfiles): Add search.cc.
* pt.cc (check_non_deducible_conversions): Add bool parameter
passed down to check_non_deducible_conversion.
(fn_type_unification): Call check_non_deducible_conversions
an extra time before satisfaction with noninst_only_p=true.
(check_non_deducible_conversion): Add bool parameter controlling
whether to compute only conversions that are guaranteed to
not induce template instantiation.
* search.cc (conversions_cache): Define.
(lookup_conversions): Use it to cache the lookup.  Improve cache
rate by considering TYPE_MAIN_VARIANT of the type.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-nondep4.C: New test.
* g++.dg/cpp2a/concepts-nondep4a.C: New test.
---
 gcc/cp/config-lang.in |  1 +
 gcc/cp/pt.cc  | 66 +--
 gcc/cp/search.cc  | 14 +++-
 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C | 21 ++
 .../g++.dg/cpp2a/concepts-nondep4a.C  | 30 +
 5 files changed, 125 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4a.C

diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in
index a6c7883cc24..e34c392d208 100644
--- a/gcc/cp/config-lang.in
+++ b/gcc/cp/config-lang.in
@@ -52,6 +52,7 @@ gtfiles="\
 \$(srcdir)/cp/name-lookup.cc \
 \$(srcdir)/cp/parser.cc \$(srcdir)/cp/pt.cc \
 \$(srcdir)/cp/rtti.cc \
+\$(srcdir)/cp/search.cc \
 \$(srcdir)/cp/semantics.cc \
 \$(srcdir)/cp/tree.cc \$(srcdir)/cp/typeck2.cc \
 \$(srcdir)/cp/vtable-class-hierarchy.cc \
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a4809f034dc..c761b73b771 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -151,7 +151,7 @@ static tree get_partial_spec_bindings (tree, tree, tree);
 static void tsubst_enum(tree, tree, tree);
 static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int check_non_deducible_conversion (tree, tree, unification_kind_t, int,
-  struct conversion **, bool);
+  struct conversion **, bool, bool);
 static int maybe_adjust_types_for_deduction (tree, unification_kind_t,
 tree*, tree*, tree);
 static int type_unification_real (tree, tree, tree, const tree *,
@@ -22315,7 +22315,8 @@ pack_deducible_p (tree parm, tree fn)
 static int
 check_non_deducible_conversions (tree parms, const tree *args, unsigned nargs,
 tree fn, unification_kind_t strict, int flags,
-struct conversion **convs, bool explain_p)
+struct conversion **convs, bool explain_p,
+bool noninst_only_p)
 {
   /* Non-constructor methods need to leave a conversion for 'this', which
  isn't included in nargs here.  */
@@ -22351,7 +22352,7 @@ check_non_deducible_conversions (tree parms, const tree 
*args, unsigned nargs,
  int lflags = conv_flags (ia, nargs, fn, arg, flags);
 
  if (check_non_deducible_conversion (parm, arg, strict, lflags,
- conv_p, explain_p))
+ conv_p, explain_p, 
noninst_only_p))
return 1;
}
 
@@ -22651,6 +22652,16 @@ fn_type_unification (tree fn,
 
  deduced:
 
+  /* As a refinement of CWG2369, check first and foremost non-dependent
+ conversions that we know are not going to induce template instantiation
+ (PR99599).  */
+  if (strict == DEDUCE_CALL
+  && incomplete
+  && check_non_deducible_conversions (parms, args, nargs, fn,