[gcc r14-10890] c++: reference variable as default targ [PR101463]

2024-11-05 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:124f2f62e01c6f110279608ad09e0f1d378e4899

commit r14-10890-g124f2f62e01c6f110279608ad09e0f1d378e4899
Author: Patrick Palka 
Date:   Tue Nov 5 15:18:26 2024 -0500

c++: reference variable as default targ [PR101463]

Here during default template argument substitution we wrongly consider
the (substituted) default arguments v and vt as value-dependent
which ultimately leads to deduction failure for the calls.

The bogus value_dependent_expression_p result aside, I noticed
type_unification_real during default targ substitution keeps track of
whether all previous targs are known and non-dependent, as is the case
for these calls.  And in such cases it should be safe to avoid checking
dependence of the substituted default targ and just assume it's not.
This patch implements this optimization for GCC 14, which lets us accept
both testcases by sidestepping the value_dependent_expression_p issue
altogether.  (Note that for GCC 15 we fixed this differently, see
r15-3038-g5348e3cb9bc99d.)

PR c++/101463

gcc/cp/ChangeLog:

* pt.cc (type_unification_real): Avoid checking dependence of
a substituted default template argument if we can assume it's
non-dependent.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/nontype6.C: New test.
* g++.dg/cpp1z/nontype6a.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc   |  4 +++-
 gcc/testsuite/g++.dg/cpp1z/nontype6.C  | 24 
 gcc/testsuite/g++.dg/cpp1z/nontype6a.C | 25 +
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 818d5b65edce..4f83426fb56c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23651,12 +23651,14 @@ type_unification_real (tree tparms,
/* We replaced all the tparms, substitute again out of
   template context.  */
substed = NULL_TREE;
+ else
+   processing_template_decl = 1;
}
  if (!substed)
substed = tsubst_template_arg (arg, full_targs, complain,
   NULL_TREE);
 
- if (!uses_template_parms (substed))
+ if (!processing_template_decl || !uses_template_parms (substed))
arg = convert_template_argument (parm, substed, full_targs,
 complain, i, NULL_TREE);
  else if (saw_undeduced == 1)
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype6.C
new file mode 100644
index ..06cd234cc61a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype6.C
@@ -0,0 +1,24 @@
+// PR c++/101463
+// { dg-do compile { target c++17 } }
+
+int a;
+
+int& v = a;
+
+template
+void f(int) { }
+
+template
+void g(T) { }
+
+template
+int& vt = a;
+
+template>
+void h(T) { }
+
+int main() {
+  f(0);
+  g(0);
+  h(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6a.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype6a.C
new file mode 100644
index ..8bc40a0505c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype6a.C
@@ -0,0 +1,25 @@
+// PR c++/101463
+// A version of nontype6.C where v and vt are constexpr.
+// { dg-do compile { target c++17 } }
+
+int a;
+
+constexpr int& v = a;
+
+template
+void f(int) { }
+
+template
+void g(T) { }
+
+template
+constexpr int& vt = a;
+
+template>
+void h(T) { }
+
+int main() {
+  f(0);
+  g(0);
+  h(0);
+}


[gcc r15-4544] c++: redundant hashing in register_specialization

2024-10-22 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:ae614b8a3d7866764bfea6f30605f90268db572b

commit r15-4544-gae614b8a3d7866764bfea6f30605f90268db572b
Author: Patrick Palka 
Date:   Tue Oct 22 08:01:16 2024 -0400

c++: redundant hashing in register_specialization

After r15-4050-g5dad738c1dd164 register_specialization needs to set
elt.hash to the (maybe) precomputed hash so that the lookup uses it
rather than redundantly computing it from scratch.

gcc/cp/ChangeLog:

* pt.cc (register_specialization): Set elt.hash.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 0141c53b617c..b590c32345f6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1546,9 +1546,7 @@ register_specialization (tree spec, tree tmpl, tree args, 
bool is_friend,
   elt.tmpl = tmpl;
   elt.args = args;
   elt.spec = spec;
-
-  if (hash == 0)
-hash = spec_hasher::hash (&elt);
+  elt.hash = hash;
 
   spec_entry **slot = decl_specializations->find_slot (&elt, INSERT);
   if (*slot)


[gcc r14-10820] libstdc++: Implement LWG 3664 changes to ranges::distance

2024-10-21 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:f381a217e9b6c8276bb580a22d12445ed7a7dc8c

commit r14-10820-gf381a217e9b6c8276bb580a22d12445ed7a7dc8c
Author: Patrick Palka 
Date:   Sat Oct 5 13:48:06 2024 -0400

libstdc++: Implement LWG 3664 changes to ranges::distance

libstdc++-v3/ChangeLog:

* include/bits/ranges_base.h (__distance_fn::operator()):
Adjust iterator/sentinel overloads as per LWG 3664.
* testsuite/24_iterators/range_operations/distance.cc:
Test LWG 3664 example.

Reviewed-by: Jonathan Wakely 
(cherry picked from commit 7c0d1e9f2a2f1d41d9eb755c36c871d92638c4b7)

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h| 14 +++---
 .../testsuite/24_iterators/range_operations/distance.cc| 11 +++
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index 23c0b56ff225..67ac8db8b469 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -930,7 +930,9 @@ namespace ranges
 
   struct __distance_fn final
   {
-template _Sent>
+// _GLIBCXX_RESOLVE_LIB_DEFECTS
+// 3664. LWG 3392 broke std::ranges::distance(a, a+3)
+template _Sent>
   requires (!sized_sentinel_for<_Sent, _It>)
   constexpr iter_difference_t<_It>
   operator()[[nodiscard]](_It __first, _Sent __last) const
@@ -944,13 +946,11 @@ namespace ranges
return __n;
   }
 
-template _Sent>
+template> _Sent>
   [[nodiscard]]
-  constexpr iter_difference_t<_It>
-  operator()(const _It& __first, const _Sent& __last) const
-  {
-   return __last - __first;
-  }
+  constexpr iter_difference_t>
+  operator()(_It&& __first, _Sent __last) const
+  { return __last - static_cast&>(__first); }
 
 template
   [[nodiscard]]
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc 
b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
index 9a1d0c3efe83..336956936c22 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
@@ -144,6 +144,16 @@ test05()
   VERIFY( std::ranges::distance(c4) == 5 );
 }
 
+void
+test06()
+{
+  // LWG 3664 - LWG 3392 broke std::ranges::distance(a, a+3)
+  int a[] = {1, 2, 3};
+  VERIFY( std::ranges::distance(a, a+3) == 3 );
+  VERIFY( std::ranges::distance(a, a) == 0 );
+  VERIFY( std::ranges::distance(a+3, a) == -3 );
+}
+
 int
 main()
 {
@@ -152,4 +162,5 @@ main()
   test03();
   test04();
   test05();
+  test06();
 }


[gcc r14-10817] libstdc++: Implement P2997R1 changes to the indirect invocability concepts

2024-10-21 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:0b2f2a7e126cf8017626793446110aac892b00f6

commit r14-10817-g0b2f2a7e126cf8017626793446110aac892b00f6
Author: Patrick Palka 
Date:   Thu Aug 22 09:24:20 2024 -0400

libstdc++: Implement P2997R1 changes to the indirect invocability concepts

This implements the changes of this C++26 paper as a DR against C++20.

In passing this patch removes the std/ranges/version_c++23.cc test which
is now mostly obsolete after the version.def FTM refactoring, and instead
expands the __cpp_lib_ranges checks in another test so that it verifies
the exact value of the FTM on a per language version basis.

libstdc++-v3/ChangeLog:

* include/bits/iterator_concepts.h (indirectly_unary_invocable):
Relax as per P2997R1.
(indirectly_regular_unary_invocable): Likewise.
(indirect_unary_predicate): Likewise.
(indirect_binary_predicate): Likewise.
(indirect_equivalence_relation): Likewise.
(indirect_strict_weak_order): Likewise.
* include/bits/version.def (ranges): Update value for C++26.
* include/bits/version.h: Regenerate.
* testsuite/24_iterators/indirect_callable/p2997r1.cc: New test.
* testsuite/std/ranges/version_c++23.cc: Remove.
* testsuite/std/ranges/headers/ranges/synopsis.cc: Refine the
__cpp_lib_ranges checks.

Reviewed-by: Jonathan Wakely 
(cherry picked from commit 620232426bd83a79c81cd2be6f485834c618e920)

Diff:
---
 libstdc++-v3/include/bits/iterator_concepts.h  | 17 ++
 libstdc++-v3/include/bits/version.def  |  5 ++
 libstdc++-v3/include/bits/version.h|  7 ++-
 .../24_iterators/indirect_callable/p2997r1.cc  | 37 
 .../std/ranges/headers/ranges/synopsis.cc  |  6 +-
 libstdc++-v3/testsuite/std/ranges/version_c++23.cc | 70 --
 6 files changed, 57 insertions(+), 85 deletions(-)

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h 
b/libstdc++-v3/include/bits/iterator_concepts.h
index 9306b7bd194c..d849ddc32fc2 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -724,7 +724,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 concept indirectly_unary_invocable = indirectly_readable<_Iter>
   && copy_constructible<_Fn> && invocable<_Fn&, __indirect_value_t<_Iter>>
   && invocable<_Fn&, iter_reference_t<_Iter>>
-  && invocable<_Fn&, iter_common_reference_t<_Iter>>
   && common_reference_with>,
   invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
 
@@ -733,15 +732,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   && copy_constructible<_Fn>
   && regular_invocable<_Fn&, __indirect_value_t<_Iter>>
   && regular_invocable<_Fn&, iter_reference_t<_Iter>>
-  && regular_invocable<_Fn&, iter_common_reference_t<_Iter>>
   && common_reference_with>,
   invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
 
   template
 concept indirect_unary_predicate = indirectly_readable<_Iter>
   && copy_constructible<_Fn> && predicate<_Fn&, __indirect_value_t<_Iter>>
-  && predicate<_Fn&, iter_reference_t<_Iter>>
-  && predicate<_Fn&, iter_common_reference_t<_Iter>>;
+  && predicate<_Fn&, iter_reference_t<_Iter>>;
 
   template
 concept indirect_binary_predicate
@@ -750,9 +747,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   && predicate<_Fn&, __indirect_value_t<_I1>, __indirect_value_t<_I2>>
   && predicate<_Fn&, __indirect_value_t<_I1>, iter_reference_t<_I2>>
   && predicate<_Fn&, iter_reference_t<_I1>, __indirect_value_t<_I2>>
-  && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
-  && predicate<_Fn&, iter_common_reference_t<_I1>,
-  iter_common_reference_t<_I2>>;
+  && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>;
 
   template
 concept indirect_equivalence_relation
@@ -762,9 +757,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   && equivalence_relation<_Fn&, __indirect_value_t<_I1>, 
iter_reference_t<_I2>>
   && equivalence_relation<_Fn&, iter_reference_t<_I1>, 
__indirect_value_t<_I2>>
   && equivalence_relation<_Fn&, iter_reference_t<_I1>,
- iter_reference_t<_I2>>
-  && equivalence_relation<_Fn&, iter_common_reference_t<_I1>,
- iter_common_reference_t<_I2>>;
+ iter_reference_t<_I2>>;
 
   template
 concept indirect_strict_weak_order
@@ -773,9 +766,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   && strict_weak_order<_Fn&, __indirect_value_t<_I1>, 
__indirect_value_t<_I2>>
   && strict_weak_order<_Fn&, __indirect_value_t<_I1>, 
iter_reference_t<_I2>>
   && strict_weak_order<_Fn&, iter_reference_t<_I1>, 
__indirect_value_t<_I2>>
-  && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
-  

[gcc r14-10801] c++: checking ICE w/ constexpr if and lambda as def targ [PR117054]

2024-10-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:c468a0051a5ff3f91498d955edb8f684d27afe0d

commit r14-10801-gc468a0051a5ff3f91498d955edb8f684d27afe0d
Author: Patrick Palka 
Date:   Tue Oct 15 13:13:15 2024 -0400

c++: checking ICE w/ constexpr if and lambda as def targ [PR117054]

Here we're tripping over the assert in extract_locals_r which enforces
that an extra-args tree appearing inside another extra-args tree doesn't
actually have extra args.  This invariant doesn't always hold for lambdas
(which recently gained the extra-args mechanism) but that should be
harmless since cp_walk_subtrees doesn't walk LAMBDA_EXPR_EXTRA_ARGS and
so should be immune to the PR114303 issue for now.  So let's just disable
this assert for lambdas.

PR c++/117054

gcc/cp/ChangeLog:

* pt.cc (extract_locals_r): Disable tree_extra_args assert
for LAMBDA_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-targ9.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit bb2bfdb2048aed18ef7dc01b51816a800e83ce54)

Diff:
---
 gcc/cp/pt.cc  |  7 ++-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C | 16 
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 85228b9f9435..818d5b65edce 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13364,7 +13364,12 @@ extract_locals_r (tree *tp, int *walk_subtrees, void 
*data_)
outermost tree.  Nested *_EXTRA_ARGS should naturally be empty since
the outermost (extra-args) tree will intercept any substitution before
a nested tree can.  */
-gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE);
+gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE
+   /* Except a lambda nested inside an extra-args tree
+  can have extra args if we deferred partial
+  substitution into it at template parse time.  But
+  we don't walk LAMBDA_EXPR_EXTRA_ARGS anyway.  */
+|| TREE_CODE (*tp) == LAMBDA_EXPR);
 
   if (TREE_CODE (*tp) == DECL_EXPR)
 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
new file mode 100644
index ..41f8526184a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
@@ -0,0 +1,16 @@
+// PR c++/117054
+// { dg-do compile { target c++20 } }
+
+template
+constexpr bool v = true;
+
+template
+void f() {
+  [](auto) {
+if constexpr (v<>) { }
+  }(0);
+}
+
+int main() {
+  f();
+}


[gcc r15-4412] doc: remove outdated C++ Concepts section

2024-10-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:c962153633048a506107a3ce13906edd19bfeb5c

commit r15-4412-gc962153633048a506107a3ce13906edd19bfeb5c
Author: Patrick Palka 
Date:   Thu Oct 17 09:12:16 2024 -0400

doc: remove outdated C++ Concepts section

This was added as part of the initial Concepts TS implementation and
reflects an early version of the Concepts TS paper, which is very
different from standard C++20 concepts (and even from more recent
versions of the Concepts TS, support for which we deprecated in GCC 14
and removed for GCC 15).  So there's not much to salvage from this
section besides the __is_same trait documentation which we can
conveniently move to the previous Type Traits section.

gcc/ChangeLog:

* doc/extend.texi (C++ Concepts): Remove section.  Move
__is_same documentation to the previous Type Traits section.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/doc/extend.texi | 44 
 1 file changed, 44 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 9bb263f9510e..42bd567119de 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -29268,7 +29268,6 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
 * C++ Attributes::  Variable, function, and type attributes for C++ only.
 * Function Multiversioning::   Declaring multiple function versions.
 * Type Traits:: Compiler support for type traits.
-* C++ Concepts::Improved support for generic programming.
 * Deprecated Features:: Things will disappear from G++.
 * Backwards Compatibility:: Compatibilities with earlier definitions of C++.
 @end menu
@@ -30145,49 +30144,6 @@ from @code{0} to @code{@var{length}-1}.  This is 
provided for
 efficient implementation of @code{std::make_integer_sequence}.
 @enddefbuiltin
 
-
-@node C++ Concepts
-@section C++ Concepts
-
-C++ concepts provide much-improved support for generic programming. In
-particular, they allow the specification of constraints on template arguments.
-The constraints are used to extend the usual overloading and partial
-specialization capabilities of the language, allowing generic data structures
-and algorithms to be ``refined'' based on their properties rather than their
-type names.
-
-The following keywords are reserved for concepts.
-
-@table @code
-@kindex assumes
-@item assumes
-States an expression as an assumption, and if possible, verifies that the
-assumption is valid. For example, @code{assume(n > 0)}.
-
-@kindex axiom
-@item axiom
-Introduces an axiom definition. Axioms introduce requirements on values.
-
-@kindex forall
-@item forall
-Introduces a universally quantified object in an axiom. For example,
-@code{forall (int n) n + 0 == n}.
-
-@kindex concept
-@item concept
-Introduces a concept definition. Concepts are sets of syntactic and semantic
-requirements on types and their values.
-
-@kindex requires
-@item requires
-Introduces constraints on template arguments or requirements for a member
-function of a class template.
-@end table
-
-The front end also exposes a number of internal mechanism that can be used
-to simplify the writing of type traits. Note that some of these traits are
-likely to be removed in the future.
-
 @defbuiltin{bool __is_same (@var{type1}, @var{type2})}
 A binary type trait: @code{true} whenever the @var{type1} and
 @var{type2} refer to the same type.


[gcc r15-4368] c++: add fixed testcase [PR80637]

2024-10-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:b110e092d260906432931796c1d96cba305c60e4

commit r15-4368-gb110e092d260906432931796c1d96cba305c60e4
Author: Patrick Palka 
Date:   Tue Oct 15 13:43:29 2024 -0400

c++: add fixed testcase [PR80637]

Fixed by r15-4340-gcacbb4daac3e9a.

PR c++/80637

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-fn9.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/cpp2a/concepts-fn9.C | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn9.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-fn9.C
new file mode 100644
index ..eb2963afcc96
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-fn9.C
@@ -0,0 +1,15 @@
+// PR c++/80637
+// { dg-do compile { target c++20 } }
+
+template
+concept same_as = __is_same(T, U);
+
+template
+struct A {
+  void f(int) requires same_as;
+  void f(...) requires (!same_as);
+};
+
+auto fptr = &A::f;
+using type = decltype(fptr);
+using type = void (A::*)(int);


[gcc r15-4366] c++: unifying lvalue vs rvalue (non-forwarding) ref [PR116710]

2024-10-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:8161c4adea7f1842f9d28633d82e912ebb7a4cf9

commit r15-4366-g8161c4adea7f1842f9d28633d82e912ebb7a4cf9
Author: Patrick Palka 
Date:   Tue Oct 15 13:23:17 2024 -0400

c++: unifying lvalue vs rvalue (non-forwarding) ref [PR116710]

When unifying two (non-forwarding) reference types, unify immediately
recurses into the referenced type without first comparing rvalueness.
(Note that at this point forwarding references and other reference
parameters have already been stripped to their referenced type by
maybe_adjust_types_for_deduction, so this code path applies only to
nested reference types.)

PR c++/116710

gcc/cp/ChangeLog:

* pt.cc (unify) : Compare rvalueness.

gcc/testsuite/ChangeLog:

* g++.dg/template/unify12.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc|  3 ++-
 gcc/testsuite/g++.dg/template/unify12.C | 24 
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c9219d5b3a5a..0141c53b617c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -25161,7 +25161,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
   }
 
 case REFERENCE_TYPE:
-  if (!TYPE_REF_P (arg))
+  if (!TYPE_REF_P (arg)
+ || TYPE_REF_IS_RVALUE (parm) != TYPE_REF_IS_RVALUE (arg))
return unify_type_mismatch (explain_p, parm, arg);
   return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
diff --git a/gcc/testsuite/g++.dg/template/unify12.C 
b/gcc/testsuite/g++.dg/template/unify12.C
new file mode 100644
index ..bed52d0fa36c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/unify12.C
@@ -0,0 +1,24 @@
+// PR c++/116710
+// { dg-do compile { target c++11 } }
+
+template struct A : T {};
+
+template
+void f(void (*)(T &), typename A::type * = 0);
+
+void f(...);
+
+void g(int &&);
+
+void q() { f(g); } // OK
+
+template
+struct B { operator B(); };
+
+template
+void h(B);
+
+int main() {
+  B b;
+  h(b); // { dg-error "no match" }
+}


[gcc r15-4365] c++: checking ICE w/ constexpr if and lambda as def targ [PR117054]

2024-10-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:bb2bfdb2048aed18ef7dc01b51816a800e83ce54

commit r15-4365-gbb2bfdb2048aed18ef7dc01b51816a800e83ce54
Author: Patrick Palka 
Date:   Tue Oct 15 13:13:15 2024 -0400

c++: checking ICE w/ constexpr if and lambda as def targ [PR117054]

Here we're tripping over the assert in extract_locals_r which enforces
that an extra-args tree appearing inside another extra-args tree doesn't
actually have extra args.  This invariant doesn't always hold for lambdas
(which recently gained the extra-args mechanism) but that should be
harmless since cp_walk_subtrees doesn't walk LAMBDA_EXPR_EXTRA_ARGS and
so should be immune to the PR114303 issue for now.  So let's just disable
this assert for lambdas.

PR c++/117054

gcc/cp/ChangeLog:

* pt.cc (extract_locals_r): Disable tree_extra_args assert
for LAMBDA_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-targ9.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc  |  7 ++-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C | 16 
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c0a37a51cba3..c9219d5b3a5a 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13480,7 +13480,12 @@ extract_locals_r (tree *tp, int *walk_subtrees, void 
*data_)
outermost tree.  Nested *_EXTRA_ARGS should naturally be empty since
the outermost (extra-args) tree will intercept any substitution before
a nested tree can.  */
-gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE);
+gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE
+   /* Except a lambda nested inside an extra-args tree
+  can have extra args if we deferred partial
+  substitution into it at template parse time.  But
+  we don't walk LAMBDA_EXPR_EXTRA_ARGS anyway.  */
+|| TREE_CODE (*tp) == LAMBDA_EXPR);
 
   if (TREE_CODE (*tp) == DECL_EXPR)
 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
new file mode 100644
index ..41f8526184a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ9.C
@@ -0,0 +1,16 @@
+// PR c++/117054
+// { dg-do compile { target c++20 } }
+
+template
+constexpr bool v = true;
+
+template
+void f() {
+  [](auto) {
+if constexpr (v<>) { }
+  }(0);
+}
+
+int main() {
+  f();
+}


[gcc r14-10697] c++: decltype(auto) deduction of statement-expression [PR116418]

2024-09-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:abdea396e12e66185d810435bbc363845cf4664a

commit r14-10697-gabdea396e12e66185d810435bbc363845cf4664a
Author: Patrick Palka 
Date:   Thu Sep 12 12:45:03 2024 -0400

c++: decltype(auto) deduction of statement-expression [PR116418]

r8-7538 for PR84968 made strip_typedefs_expr diagnose STATEMENT_LIST
so that we reject statement-expressions in noexcept-specifiers to
match our behavior in template arguments (which the parser diagnoses
directly).

Later r11-7452 made decltype(auto) deduction canonicalize the expression
(as an implementation detail) which in turn calls strip_typedefs_expr,
and so ever since we inadvertently reject decltype(auto) deduction of a
statement-expression.

This patch just removes the diagnostic in strip_typedefs_expr and instead
treats statement-expressions similar to lambda-expressions.  The function
doesn't seem like the right place for such a diagnostic and so it seems
easier to just accept rather than try to reject them in a suitable place.

PR c++/116418

gcc/cp/ChangeLog:

* tree.cc (strip_typedefs_expr) : Replace
this error path with ...
: ... this, returning the original tree.

gcc/testsuite/ChangeLog:

* g++.dg/eh/pr84968.C: No longer expect an ahead of time diagnostic
for the statement-expresssion.  Instantiate the template and expect
an incomplete type error instead.
* g++.dg/ext/stmtexpr26.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 12bdcc3d7970860b9d66ed4dea203bde8fd68d4d)

Diff:
---
 gcc/cp/tree.cc|  5 +
 gcc/testsuite/g++.dg/eh/pr84968.C |  4 +++-
 gcc/testsuite/g++.dg/ext/stmtexpr26.C | 10 ++
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index d90244609c8a..a056237e8669 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2008,12 +2008,9 @@ strip_typedefs_expr (tree t, bool *remove_attributes, 
unsigned int flags)
   }
 
 case LAMBDA_EXPR:
+case STMT_EXPR:
   return t;
 
-case STATEMENT_LIST:
-  error ("statement-expression in a constant expression");
-  return error_mark_node;
-
 default:
   break;
 }
diff --git a/gcc/testsuite/g++.dg/eh/pr84968.C 
b/gcc/testsuite/g++.dg/eh/pr84968.C
index 23c49f477a88..a6e21914eed1 100644
--- a/gcc/testsuite/g++.dg/eh/pr84968.C
+++ b/gcc/testsuite/g++.dg/eh/pr84968.C
@@ -9,7 +9,9 @@ struct S {
   void a()
 try {
 } catch (int ()
-noexcept (({ union b a; true; }))) // { dg-error "constant" }
+noexcept (({ union b a; true; }))) // { dg-error "'b a' has 
incomplete type" }
   {
   }
 };
+
+template void S::a(); // { dg-message "required from here" }
diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr26.C 
b/gcc/testsuite/g++.dg/ext/stmtexpr26.C
new file mode 100644
index ..2250df550d48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/stmtexpr26.C
@@ -0,0 +1,10 @@
+// PR c++/116418
+// { dg-do compile { target c++14 } }
+// { dg-options "" }
+
+void foo ();
+template 
+void bar ()
+{
+  decltype(auto) v = ({ foo (); 3; });
+}


[gcc r14-10696] c++: CWG 2789 and usings [PR116492]

2024-09-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:659f32ea9de57661f8a37dcfb0b9a01bfe29acce

commit r14-10696-g659f32ea9de57661f8a37dcfb0b9a01bfe29acce
Author: Patrick Palka 
Date:   Fri Sep 20 17:37:03 2024 -0400

c++: CWG 2789 and usings [PR116492]

For GCC 14, narrowly fix this PR by implementing the missing

  - if they are member functions, both are direct members of the same
class, and

part of CWG 2789 for constructors only.

PR c++/116492
DR 2789

gcc/cp/ChangeLog:

* call.cc (cand_parms_match): Return false for constructors that
come from different classes.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc   |  8 
 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 
 2 files changed, 24 insertions(+)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 0f4eeeb53951..492d17b17446 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12826,6 +12826,14 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, 
pmatch match_kind)
&& DECL_FUNCTION_MEMBER_P (fn2)))
 /* Early escape.  */;
 
+  else if ((DECL_INHERITED_CTOR (fn1) || DECL_INHERITED_CTOR (fn2))
+  && (DECL_CONTEXT (strip_inheriting_ctors (fn1))
+  != DECL_CONTEXT (strip_inheriting_ctors (fn2
+/* This should really be checked for all member functions as per
+   CWG2789, but for GCC 14 we check this only for constructors since
+   without r15-3740 doing so would result in inconsistent handling
+   of object parameters (such as in concepts-memfun4.C).  */
+return false;
   /* CWG2789 is not adequate, it should specify corresponding object
  parameters, not same typed object parameters.  */
   else if (!object_parms_correspond (c1, fn1, c2, fn2))
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
new file mode 100644
index ..3e5dbfc37ad0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
@@ -0,0 +1,16 @@
+// PR c++/116492
+// CWG 2789
+// { dg-do compile { target c++20 } }
+
+template
+struct A {
+  A() requires true = delete;
+};
+
+struct B : A {
+  B();
+  using A::A;
+};
+
+B b; // OK, selects the non-inherited constructor over the more constrained
+ // inherited constructor.


[gcc r15-3744] c++: CWG 2789 and reversed operator candidates

2024-09-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:1f70503232d4183b4b58f2910c460569d05907b9

commit r15-3744-g1f70503232d4183b4b58f2910c460569d05907b9
Author: Patrick Palka 
Date:   Fri Sep 20 15:41:42 2024 -0400

c++: CWG 2789 and reversed operator candidates

As a follow-up to r15-3741-gee3efe06c9c49c, which was specifically
concerned with usings, it seems the CWG 2789 refinement should also
compare contexts of a reversed vs non-reversed (member) candidate
during operator overload resolution.

DR 2789

gcc/cp/ChangeLog:

* call.cc (cand_parms_match): Check for matching class contexts
even in the reversed case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-memfun4.C: Adjust expected result
involving reversed candidate.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc| 11 +++
 gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C |  6 +++---
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index f2ce50857ece..70783baac242 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12865,10 +12865,6 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, 
pmatch match_kind)
}
 }
 
-  else if (reversed)
-return (reversed_match (c1, c2)
-   && reversed_match (c2, c1));
-
   tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
   tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
 
@@ -12880,6 +12876,10 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, 
pmatch match_kind)
   if (base1 != base2)
return false;
 
+  if (reversed)
+   return (reversed_match (c1, c2)
+   && reversed_match (c2, c1));
+
   /* Use object_parms_correspond to simplify comparing iobj/xobj/static
 member functions.  */
   if (!object_parms_correspond (fn1, fn2, base1))
@@ -12897,6 +12897,9 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, 
pmatch match_kind)
   parms1 = skip_parms (fn1, parms1);
   parms2 = skip_parms (fn2, parms2);
 }
+  else if (reversed)
+return (reversed_match (c1, c2)
+   && reversed_match (c2, c1));
   return compparms (parms1, parms2);
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C
index cf7f13c007d1..d849e9129a3b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C
@@ -91,7 +91,7 @@ namespace N1 {
 
   A<> a;
   B<> b;
-  // when comparing the A op== to the reversed B op==, we compare them in
-  // reverse order, so they match, and we choose the more constrained.
-  static_assert (a == b);
+  // A op== and B op== are defined in different classes so constraints
+  // aren't considered, and the tie is broken via reversedness.
+  static_assert (!(a == b));
 }


[gcc r15-3740] c++: CWG 2273 and non-constructors

2024-09-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:06557ba12b64c57368673c46a21b14cf4e6afb50

commit r15-3740-g06557ba12b64c57368673c46a21b14cf4e6afb50
Author: Patrick Palka 
Date:   Fri Sep 20 12:31:40 2024 -0400

c++: CWG 2273 and non-constructors

Our implementation of the CWG 2273 inheritedness tiebreaker seems to be
incorrectly considering all member functions introduced via using, not
just constructors.  This patch restricts the tiebreaker accordingly.

DR 2273

gcc/cp/ChangeLog:

* call.cc (joust): Restrict inheritedness tiebreaker to
constructors.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/using1.C: Expect ambiguity for non-constructor call.
* g++.dg/overload/using5.C: Likewise.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc | 11 ---
 gcc/testsuite/g++.dg/cpp1z/using1.C|  8 
 gcc/testsuite/g++.dg/overload/using5.C |  2 +-
 3 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 3f753e2d2f98..6229dc452636 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13350,13 +13350,10 @@ joust (struct z_candidate *cand1, struct z_candidate 
*cand2, bool warn,
}
 }
 
-  /* F1 is a member of a class D, F2 is a member of a base class B of D, and
- for all arguments the corresponding parameters of F1 and F2 have the same
- type (CWG 2273/2277). */
-  if (DECL_P (cand1->fn) && DECL_CLASS_SCOPE_P (cand1->fn)
-  && !DECL_CONV_FN_P (cand1->fn)
-  && DECL_P (cand2->fn) && DECL_CLASS_SCOPE_P (cand2->fn)
-  && !DECL_CONV_FN_P (cand2->fn))
+  /* F1 is a constructor for a class D, F2 is a constructor for a base class B
+ of D, and for all arguments the corresponding parameters of F1 and F2 have
+ the same type (CWG 2273/2277).  */
+  if (DECL_INHERITED_CTOR (cand1->fn) || DECL_INHERITED_CTOR (cand2->fn))
 {
   tree base1 = DECL_CONTEXT (strip_inheriting_ctors (cand1->fn));
   tree base2 = DECL_CONTEXT (strip_inheriting_ctors (cand2->fn));
diff --git a/gcc/testsuite/g++.dg/cpp1z/using1.C 
b/gcc/testsuite/g++.dg/cpp1z/using1.C
index 1ed939d45fd4..d8a045255795 100644
--- a/gcc/testsuite/g++.dg/cpp1z/using1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/using1.C
@@ -1,5 +1,5 @@
-// Test for hiding of used base functions when all the conversion sequences are
-// equivalent, needed to avoid a regression on inherited default ctors.
+// Test the CWG 2273 inheritedness tiebreaker doesn't apply to
+// non-constructors.
 
 struct A
 {
@@ -17,7 +17,7 @@ struct B:A
 
 int main()
 {
-  B().f(1);// OK, derived f hides base f for single arg
+  B().f(1);// { dg-error "ambiguous" }
   B().f(1,2);  // OK, base f can still be called with two args
-  B().g(1);// { dg-error "" } signatures differ, ambiguous
+  B().g(1);// { dg-error "ambiguous" }
 }
diff --git a/gcc/testsuite/g++.dg/overload/using5.C 
b/gcc/testsuite/g++.dg/overload/using5.C
index ad17c78a561e..0933a9f0fac3 100644
--- a/gcc/testsuite/g++.dg/overload/using5.C
+++ b/gcc/testsuite/g++.dg/overload/using5.C
@@ -24,5 +24,5 @@ struct C: B {
 int main()
 {
   C c (42);
-  c.f();
+  c.f(); // { dg-error "ambiguous" }
 }


[gcc r15-3741] c++: CWG 2789 and usings [PR116492]

2024-09-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:ee3efe06c9c49c04eaa4e195a7ae8774a1b3faa2

commit r15-3741-gee3efe06c9c49c04eaa4e195a7ae8774a1b3faa2
Author: Patrick Palka 
Date:   Fri Sep 20 12:33:13 2024 -0400

c++: CWG 2789 and usings [PR116492]

After CWG 2789, the "more constrained" tiebreaker for non-template
functions should exclude member functions that are defined in
different classes.  This patch implements this missing refinement.

In turn we can get rid of four-parameter version of object_parms_correspond
and call the main overload directly since now correspondence is only
only checked for members from the same class.

PR c++/116492
DR 2789

gcc/cp/ChangeLog:

* call.cc (object_parms_correspond): Remove.
(cand_parms_match): Return false for member functions that come
from different classes.  Adjust call to object_parms_correspond.
(joust): Update comment for the non-template "more constrained"
case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-memfun4.C: Also compile in C++20 mode.
Expect ambiguity when candidates come from different classes.
* g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc | 54 --
 .../g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 +++
 gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C  | 24 +-
 3 files changed, 49 insertions(+), 45 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 6229dc452636..f2ce50857ece 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12808,27 +12808,6 @@ class_of_implicit_object (z_candidate *cand)
   return BINFO_TYPE (cand->conversion_path);
 }
 
-/* True if candidates C1 and C2 have corresponding object parameters per
-   [basic.scope.scope].  */
-
-static bool
-object_parms_correspond (z_candidate *c1, tree fn1, z_candidate *c2, tree fn2)
-{
-  tree context = class_of_implicit_object (c1);
-  tree ctx2 = class_of_implicit_object (c2);
-  if (!ctx2)
-/* Leave context as is. */;
-  else if (!context)
-context = ctx2;
-  else if (context != ctx2)
-/* This can't happen for normal function calls, since it means finding
-   functions in multiple bases which would fail with an ambiguous lookup,
-   but it can occur with reversed operators.  */
-return false;
-
-  return object_parms_correspond (fn1, fn2, context);
-}
-
 /* Return whether the first parameter of C1 matches the second parameter
of C2.  */
 
@@ -12893,16 +12872,19 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, 
pmatch match_kind)
   tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
   tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
 
-  if (!(DECL_FUNCTION_MEMBER_P (fn1)
-   && DECL_FUNCTION_MEMBER_P (fn2)))
-/* Early escape.  */;
-
-  /* CWG2789 is not adequate, it should specify corresponding object
- parameters, not same typed object parameters.  */
-  else if (!object_parms_correspond (c1, fn1, c2, fn2))
-return false;
-  else
+  if (DECL_FUNCTION_MEMBER_P (fn1)
+  && DECL_FUNCTION_MEMBER_P (fn2))
 {
+  tree base1 = DECL_CONTEXT (strip_inheriting_ctors (fn1));
+  tree base2 = DECL_CONTEXT (strip_inheriting_ctors (fn2));
+  if (base1 != base2)
+   return false;
+
+  /* Use object_parms_correspond to simplify comparing iobj/xobj/static
+member functions.  */
+  if (!object_parms_correspond (fn1, fn2, base1))
+   return false;
+
   /* We just compared the object parameters, if they don't correspond
 we already returned false.  */
   auto skip_parms = [] (tree fn, tree parms)
@@ -13269,10 +13251,14 @@ joust (struct z_candidate *cand1, struct z_candidate 
*cand2, bool warn,
return winner;
 }
 
-  /* Concepts: F1 and F2 are non-template functions with the same
- parameter-type-lists, and F1 is more constrained than F2 according to the
- partial ordering of constraints described in 13.5.4.  */
-
+  /* F1 and F2 are non-template functions and
+ - they have the same non-object-parameter-type-lists ([dcl.fct]), and
+ - if they are member functions, both are direct members of the same
+   class, and
+ - if both are non-static member functions, they have the same types for
+   their object parameters, and
+ - F1 is more constrained than F2 according to the partial ordering of
+   constraints described in [temp.constr.order].  */
   if (flag_concepts && DECL_P (cand1->fn) && DECL_P (cand2->fn)
   && !cand1->template_decl && !cand2->template_decl
   && cand_parms_match (cand1, cand2, pmatch::current))
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
new file mode 100644
index ..3e5dbfc37ad0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concep

[gcc r15-3694] c++: alias of decltype(lambda) is opaque [PR116714, PR107390]

2024-09-18 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:82c2acd0bc4411524a8248fcdce219927d921a71

commit r15-3694-g82c2acd0bc4411524a8248fcdce219927d921a71
Author: Patrick Palka 
Date:   Wed Sep 18 13:50:43 2024 -0400

c++: alias of decltype(lambda) is opaque [PR116714, PR107390]

Here for

  using type = decltype([]{});
  static_assert(is_same_v);

we strip the alias ahead of time during template argument coercion
which effectively transforms the template-id into

  is_same_v

which is wrong because later substitution into the template-id will
produce two new lambdas with distinct types and cause is_same_v to
return false.

This demonstrates that such aliases should be considered opaque (a
notion that we recently introduced in r15-2331-g523836716137d0).
(An alternative solution might be to consider memoizing lambda-expr
substitution rather than always producing a new lambda, but this is
much simpler.)

PR c++/116714
PR c++/107390

gcc/cp/ChangeLog:

* pt.cc (dependent_opaque_alias_p): Also return true for a
decltype(lambda) alias.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-uneval18.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc | 11 ++--
 gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C | 39 
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 769e7999dac1..e826206be164 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6759,8 +6759,15 @@ dependent_opaque_alias_p (const_tree t)
 {
   return (TYPE_P (t)
  && typedef_variant_p (t)
- && any_dependent_type_attributes_p (DECL_ATTRIBUTES
- (TYPE_NAME (t;
+ && (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+  (TYPE_NAME (t)))
+ /* Treat a dependent decltype(lambda) alias as opaque so that we
+don't prematurely strip it when used as a template argument.
+Otherwise substitution into each occurrence of the (stripped)
+alias would incorrectly yield a distinct lambda type.  */
+ || (TREE_CODE (t) == DECLTYPE_TYPE
+ && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == LAMBDA_EXPR
+ && !typedef_variant_p (DECL_ORIGINAL_TYPE (TYPE_NAME (t));
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
new file mode 100644
index ..b7d864c62453
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval18.C
@@ -0,0 +1,39 @@
+// PR c++/116714
+// PR c++/107390
+// { dg-do compile { target c++20 } }
+
+template
+inline constexpr bool is_same_v = __is_same(T, U);
+
+template
+struct is_same { static constexpr bool value = false; };
+
+template
+struct is_same { static constexpr bool value = true; };
+
+template
+void f() {
+  using type = decltype([]{});
+  static_assert(is_same_v);
+  static_assert(is_same::value);
+};
+
+template
+void g() {
+  using ty1 = decltype([]{});
+  using ty2 = ty1;
+  static_assert(is_same_v);
+  static_assert(is_same::value);
+};
+
+template
+void h() {
+  using ty1 = decltype([]{});
+  using ty2 = decltype([]{});
+  static_assert(!is_same_v);
+  static_assert(!is_same::value);
+};
+
+template void f();
+template void g();
+template void h();


[gcc r15-3611] c++: decltype(auto) deduction of statement-expression [PR116418]

2024-09-12 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:12bdcc3d7970860b9d66ed4dea203bde8fd68d4d

commit r15-3611-g12bdcc3d7970860b9d66ed4dea203bde8fd68d4d
Author: Patrick Palka 
Date:   Thu Sep 12 12:45:03 2024 -0400

c++: decltype(auto) deduction of statement-expression [PR116418]

r8-7538 for PR84968 made strip_typedefs_expr diagnose STATEMENT_LIST
so that we reject statement-expressions in noexcept-specifiers to
match our behavior in template arguments (which the parser diagnoses
directly).

Later r11-7452 made decltype(auto) deduction canonicalize the expression
(as an implementation detail) which in turn calls strip_typedefs_expr,
and so ever since we inadvertently reject decltype(auto) deduction of a
statement-expression.

This patch just removes the diagnostic in strip_typedefs_expr and instead
treats statement-expressions similar to lambda-expressions.  The function
doesn't seem like the right place for such a diagnostic and so it seems
easier to just accept rather than try to reject them in a suitable place.

PR c++/116418

gcc/cp/ChangeLog:

* tree.cc (strip_typedefs_expr) : Replace
this error path with ...
: ... this, returning the original tree.

gcc/testsuite/ChangeLog:

* g++.dg/eh/pr84968.C: No longer expect an ahead of time diagnostic
for the statement-expresssion.  Instantiate the template and expect
an incomplete type error instead.
* g++.dg/ext/stmtexpr26.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/tree.cc|  5 +
 gcc/testsuite/g++.dg/eh/pr84968.C |  4 +++-
 gcc/testsuite/g++.dg/ext/stmtexpr26.C | 10 ++
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index c3a38de4f486..99088da9cee0 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2009,12 +2009,9 @@ strip_typedefs_expr (tree t, bool *remove_attributes, 
unsigned int flags)
   }
 
 case LAMBDA_EXPR:
+case STMT_EXPR:
   return t;
 
-case STATEMENT_LIST:
-  error ("statement-expression in a constant expression");
-  return error_mark_node;
-
 default:
   break;
 }
diff --git a/gcc/testsuite/g++.dg/eh/pr84968.C 
b/gcc/testsuite/g++.dg/eh/pr84968.C
index 23c49f477a88..a6e21914eed1 100644
--- a/gcc/testsuite/g++.dg/eh/pr84968.C
+++ b/gcc/testsuite/g++.dg/eh/pr84968.C
@@ -9,7 +9,9 @@ struct S {
   void a()
 try {
 } catch (int ()
-noexcept (({ union b a; true; }))) // { dg-error "constant" }
+noexcept (({ union b a; true; }))) // { dg-error "'b a' has 
incomplete type" }
   {
   }
 };
+
+template void S::a(); // { dg-message "required from here" }
diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr26.C 
b/gcc/testsuite/g++.dg/ext/stmtexpr26.C
new file mode 100644
index ..2250df550d48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/stmtexpr26.C
@@ -0,0 +1,10 @@
+// PR c++/116418
+// { dg-do compile { target c++14 } }
+// { dg-options "" }
+
+void foo ();
+template 
+void bar ()
+{
+  decltype(auto) v = ({ foo (); 3; });
+}


[gcc r14-10656] c++: c->B::m access resolved through current inst [PR116320]

2024-09-08 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:149d87fbe661da29d8a0aa671b42bd532206a8b8

commit r14-10656-g149d87fbe661da29d8a0aa671b42bd532206a8b8
Author: Patrick Palka 
Date:   Thu Aug 15 10:23:54 2024 -0400

c++: c->B::m access resolved through current inst [PR116320]

Here when checking the access of (the injected-class-name) B in c->B::m
at parse time, we notice its context B (now the type) is a base of the
object type C, so we proceed to use C as the effective qualifying
type.  But this C is the dependent specialization not the primary
template type, so it has empty TYPE_BINFO, which leads to a segfault later
from perform_or_defer_access_check.

The reason the DERIVED_FROM_P (B, C) test guarding this code path works
despite C having empty TYPE_BINFO is because of its currently_open_class
logic (added in r9-713-gd9338471b91bbe) which replaces a dependent
specialization with the primary template type if we're inside it.  So the
safest fix seems to be to call currently_open_class in the caller as well.

PR c++/116320

gcc/cp/ChangeLog:

* semantics.cc (check_accessibility_of_qualified_id): Try
currently_open_class when using the object type as the
effective qualifying type.

gcc/testsuite/ChangeLog:

* g++.dg/template/access42.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 484f139ccd3b631a777802e810a632678b42ffab)

Diff:
---
 gcc/cp/semantics.cc  | 11 ---
 gcc/testsuite/g++.dg/template/access42.C | 17 +
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b5569066708e..ceeac82fa081 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2497,9 +2497,14 @@ check_accessibility_of_qualified_id (tree decl,
 OBJECT_TYPE.  */
   && CLASS_TYPE_P (object_type)
   && DERIVED_FROM_P (scope, object_type))
-/* If we are processing a `->' or `.' expression, use the type of the
-   left-hand side.  */
-qualifying_type = object_type;
+{
+  /* If we are processing a `->' or `.' expression, use the type of the
+left-hand side.  */
+  if (tree open = currently_open_class (object_type))
+   qualifying_type = open;
+  else
+   qualifying_type = object_type;
+}
   else if (nested_name_specifier)
 {
   /* If the reference is to a non-static member of the
diff --git a/gcc/testsuite/g++.dg/template/access42.C 
b/gcc/testsuite/g++.dg/template/access42.C
new file mode 100644
index ..f1dcbce80c24
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access42.C
@@ -0,0 +1,17 @@
+// PR c++/116320
+// { dg-do compile { target c++11 } }
+
+template struct C;
+template using C_ptr = C*;
+
+struct B { int m; using B_typedef = B; };
+
+template
+struct C : B {
+  void f(C_ptr c) {
+c->B::m;
+c->B_typedef::m;
+  }
+};
+
+template struct C;


[gcc r14-10655] c++: inherited CTAD fixes [PR116276]

2024-09-08 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:b5ed381d05e0ed9edf2f320b71f8775ea96a4866

commit r14-10655-gb5ed381d05e0ed9edf2f320b71f8775ea96a4866
Author: Patrick Palka 
Date:   Fri Aug 9 21:15:25 2024 -0400

c++: inherited CTAD fixes [PR116276]

This implements the overlooked inherited vs non-inherited guide
tiebreaker from P2582R1.  This requires tracking inherited-ness of a
guide, for which it seems natural to reuse the lang_decl_fn::context
field which for a constructor tracks its inherited-ness.

This patch also works around CLASSTYPE_CONSTRUCTORS not reliably
returning all inherited constructors (due to some using-decl handling
quirks in in push_class_level_binding) by iterating over TYPE_FIELDS
instead.

This patch also makes us recognize another written form of inherited
constructor, 'using Base::Base::Base' whose USING_DECL_SCOPE is a
TYPENAME_TYPE.

PR c++/116276

gcc/cp/ChangeLog:

* call.cc (joust): Implement P2582R1 inherited vs non-inherited
guide tiebreaker.
* cp-tree.h (lang_decl_fn::context): Document usage in
deduction_guide_p FUNCTION_DECLs.
(inherited_guide_p): Declare.
* pt.cc (inherited_guide_p): Define.
(set_inherited_guide_context): Define.
(alias_ctad_tweaks): Use set_inherited_guide_context.
(inherited_ctad_tweaks): Recognize some inherited constructors
whose scope is a TYPENAME_TYPE.
(ctor_deduction_guides_for): For C++23 inherited CTAD, iterate
over TYPE_FIELDS instead of CLASSTYPE_CONSTRUCTORS to recognize
all inherited constructors.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/class-deduction-inherited4.C: Remove an xfail.
* g++.dg/cpp23/class-deduction-inherited5.C: New test.
* g++.dg/cpp23/class-deduction-inherited6.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 8cc67b520968ca9a13fd96896522aa66e39a99e2)

Diff:
---
 gcc/cp/call.cc | 27 -
 gcc/cp/cp-tree.h   |  8 ++--
 gcc/cp/pt.cc   | 43 
 .../g++.dg/cpp23/class-deduction-inherited4.C  |  4 +-
 .../g++.dg/cpp23/class-deduction-inherited5.C  | 25 
 .../g++.dg/cpp23/class-deduction-inherited6.C  | 46 ++
 6 files changed, 139 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 793b98347124..0f4eeeb53951 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13226,10 +13226,35 @@ joust (struct z_candidate *cand1, struct z_candidate 
*cand2, bool warn,
   else if (cand2->rewritten ())
 return 1;
 
-  /* F1 is generated from a deduction-guide (13.3.1.8) and F2 is not */
   if (deduction_guide_p (cand1->fn))
 {
   gcc_assert (deduction_guide_p (cand2->fn));
+
+  /* F1 and F2 are generated from class template argument deduction for a
+class D, and F2 is generated from inheriting constructors from a base
+class of D while F1 is not, and for each explicit function argument,
+the corresponding parameters of F1 and F2 are either both ellipses or
+have the same type.  */
+  bool inherited1 = inherited_guide_p (cand1->fn);
+  bool inherited2 = inherited_guide_p (cand2->fn);
+  if (int diff = inherited2 - inherited1)
+   {
+ for (i = 0; i < len; ++i)
+   {
+ conversion *t1 = cand1->convs[i + off1];
+ conversion *t2 = cand2->convs[i + off2];
+ /* ??? It seems the ellipses part of this tiebreaker isn't
+needed since a mismatch should have broken the tie earlier
+during ICS comparison.  */
+ gcc_checking_assert (t1->ellipsis_p == t2->ellipsis_p);
+ if (!same_type_p (t1->type, t2->type))
+   break;
+   }
+ if (i == len)
+   return diff;
+   }
+
+  /* F1 is generated from a deduction-guide (13.3.1.8) and F2 is not */
   /* We distinguish between candidates from an explicit deduction guide and
 candidates built from a constructor based on DECL_ARTIFICIAL.  */
   int art1 = DECL_ARTIFICIAL (cand1->fn);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3f607313db61..ab2b0904ed60 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2981,9 +2981,10 @@ struct GTY(()) lang_decl_fn {
  this pointer and result pointer adjusting thunks are
  chained here.  This pointer thunks to return pointer thunks
  will be chained on the return pointer thunk.
- For a DECL_CONSTUCTOR_P FUNCTION_DECL, this is the base from
- whence we inherit.  Otherwise, it is the class in which a
- (namespace-scope) friend is defined (if any).   */
+ For a DECL_CONSTRUCTOR_P or deduction_guide_p FUNCTION_DECL,
+ this i

[gcc r14-10652] c++: template depth of lambda in default targ [PR116567]

2024-09-07 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:0c80216b7bb0938bff7db230cbefa5bc3e8b3034

commit r14-10652-g0c80216b7bb0938bff7db230cbefa5bc3e8b3034
Author: Patrick Palka 
Date:   Sat Sep 7 14:10:09 2024 -0400

c++: template depth of lambda in default targ [PR116567]

For GCC 14, let's narrowly fix this bug by just pruning the result of
add_extra_args after the fact to get rid of any unwanted outer levels.

PR c++/116567

gcc/cp/ChangeLog:

* pt.cc (tsubst_lambda_expr): For a deferred-substitution lambda,
trim the augmented template arguments to match the template depth
of the lambda.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-targ7.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc  | 12 +
 gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C | 42 +++
 2 files changed, 54 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8e6a7d1a64a4..7135105fc375 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19679,6 +19679,18 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
   LAMBDA_EXPR_EXTRA_ARGS (t) = build_extra_args (t, args, complain);
   return t;
 }
+  if (LAMBDA_EXPR_EXTRA_ARGS (t))
+{
+  /* If we deferred substitution into this lambda, then its original
+context (e.g. default template argument context) might be unrelated
+to the current context it's embedded in.  After add_extra_args though,
+the innermost levels of 'args' will correspond to the lambda context,
+so get rid of all unrelated levels.  */
+  tree ctx_parms = DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (oldfn));
+  if (generic_lambda_fn_p (oldfn))
+   ctx_parms = TREE_CHAIN (ctx_parms);
+  args = get_innermost_template_args (args, TMPL_PARMS_DEPTH (ctx_parms));
+}
 
   tree r = build_lambda_expr ();
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C
new file mode 100644
index ..97b42d6ed0c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C
@@ -0,0 +1,42 @@
+// PR c++/116567
+// { dg-do compile { target c++20 } }
+
+struct X { int n; };
+
+template
+auto v1 = F;
+
+template
+auto v1g = F;
+
+template
+struct A {
+  template
+  static inline auto v2 = F;
+
+  template
+  static inline auto v2g = F;
+
+  template
+  struct B {
+template
+static inline auto v3 = F;
+
+template
+static inline auto v3g = F;
+
+template
+static void f() {
+  static_assert(v1().n == 1);
+  static_assert(v1g(42).n == 1 + 42);
+  static_assert(v2().n == 2);
+  static_assert(v2g(42).n == 2 + 42);
+  static_assert(v3().n == 3);
+  static_assert(v3g(42).n == 3 + 42);
+}
+  };
+};
+
+int main() {
+  A::B::f();
+}


[gcc r15-3530] c++: deferring partial substitution into lambda [PR116567]

2024-09-07 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:dfb63765e994bee74d533c810fdf75d3269530ad

commit r15-3530-gdfb63765e994bee74d533c810fdf75d3269530ad
Author: Patrick Palka 
Date:   Sat Sep 7 14:06:37 2024 -0400

c++: deferring partial substitution into lambda [PR116567]

Here we correctly defer partial substitution into the lambda used as
a default template argument, but then incorrectly perform the full
substitution, because add_extra_args adds outer template arguments from
the full substitution that are not related to the original template
context of the lambda.  For example, the template depth of the first
lambda is 1 but add_extra_args return a set of args with 3 levels, with
the inner level corresponding to the parameters of v1 (good) and the
outer levels corresponding to those of A and B (bad).

For the cases that we're interested in, add_extra_args can assume that
the deferred args are a full set of template arguments, and so it
suffices to just substitute into the deferred args and not do any
additional merging.

This patch refines add_extra_args accordingly, and additionally
makes it look for the tf_partial flag instead of for dependent args to
decide if the deferred substitution is a partial one.  This reveals we
were neglecting to set tf_partial when substituting into a default
template argument in a template context.

PR c++/116567

gcc/cp/ChangeLog:

* pt.cc (coerce_template_parms): Set tf_partial when substituting
into a default template argument in a template context.
(build_extra_args): Set TREE_STATIC on the deferred args if this
is a partial substitution.
(add_extra_args): Check TREE_STATIC instead of dependence of args.
Adjust merging behavior in that case.
(tsubst_lammda_expr): Check for tf_partial instead of dependence
of args when determining whether to defer substitution.
(tsubst_expr) : Remove tf_partial early exit.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-targ7.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc  | 35 +-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C | 42 +++
 2 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 72b17fdd8a76..310e5dfff033 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -9326,7 +9326,9 @@ coerce_template_parms (tree parms,
{
  /* There must be a default arg in this case.  */
  arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
-complain, in_decl);
+complain | (processing_template_decl
+? tf_partial : tf_none),
+in_decl);
  /* The position of the first default template argument,
 is also the number of non-defaulted arguments in NEW_INNER_ARGS.
 Record that.  */
@@ -13569,6 +13571,9 @@ build_extra_args (tree pattern, tree args, 
tsubst_flags_t complain)
   /* Make a copy of the extra arguments so that they won't get changed
  out from under us.  */
   tree extra = preserve_args (copy_template_args (args), /*cow_p=*/false);
+  if (complain & tf_partial)
+/* Remember whether this is a partial substitution.  */
+TREE_STATIC (extra) = true;
   if (local_specializations)
 if (tree locals = extract_local_specs (pattern, complain))
   extra = tree_cons (NULL_TREE, extra, locals);
@@ -13581,7 +13586,10 @@ build_extra_args (tree pattern, tree args, 
tsubst_flags_t complain)
 tree
 add_extra_args (tree extra, tree args, tsubst_flags_t complain, tree in_decl)
 {
-  if (extra && TREE_CODE (extra) == TREE_LIST)
+  if (!extra)
+return args;
+
+  if (TREE_CODE (extra) == TREE_LIST)
 {
   for (tree elt = TREE_CHAIN (extra); elt; elt = TREE_CHAIN (elt))
{
@@ -13599,13 +13607,13 @@ add_extra_args (tree extra, tree args, tsubst_flags_t 
complain, tree in_decl)
   gcc_assert (!TREE_PURPOSE (extra));
   extra = TREE_VALUE (extra);
 }
-  if (uses_template_parms (extra))
-{
-  /* This can happen after dependent substitution into a
-requires-expr or a lambda that uses constexpr if.  */
-  extra = tsubst_template_args (extra, args, complain, in_decl);
-  args = add_outermost_template_args (args, extra);
-}
+  gcc_checking_assert (TREE_STATIC (extra) == uses_template_parms (extra));
+  if (TREE_STATIC (extra))
+/* This is a partial substitution into e.g. a requires-expr or lambda-expr
+   inside a default template argument; we expect 'extra' to be a full set
+   of template arguments for the template context, so it suffices to just
+   substitute into them.  */
+args = tsubst_template_args (extra, args

[gcc r15-3491] c++: local class memfn synth from noexcept context [PR113063]

2024-09-05 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:37977343ff4f9dcb047d966d8cbaa222964763f9

commit r15-3491-g37977343ff4f9dcb047d966d8cbaa222964763f9
Author: Patrick Palka 
Date:   Thu Sep 5 14:31:00 2024 -0400

c++: local class memfn synth from noexcept context [PR113063]

Extending the PR113063 testcase to additionally constant evaluate the <=>
expression causes us to trip over the assert in cxx_eval_call_expression

  /* We used to shortcut trivial constructor/op= here, but nowadays
 we can only get a trivial function here with -fno-elide-constructors.  
*/
  gcc_checking_assert (!trivial_fn_p (fun)
   || !flag_elide_constructors
   /* We don't elide constructors when processing
  a noexcept-expression.  */
   || cp_noexcept_operand);

since the local class's <=> was first used and therefore synthesized in
a noexcept context and so its definition contains unelided trivial
constructors.

This patch fixes this by clearing cp_noexcept_operand alongside
cp_unevaluated_context in the function-local case of
maybe_push_to_top_level.

PR c++/113063

gcc/cp/ChangeLog:

* name-lookup.cc (local_state_t): Clear and restore
cp_noexcept_operand as well.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/spaceship-synth16.C: Also constant evaluate
the <=> expression.
* g++.dg/cpp2a/spaceship-synth16a.C: Likewise.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/name-lookup.cc   | 4 
 gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C  | 1 +
 gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C | 1 +
 3 files changed, 6 insertions(+)

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index cd3947cbe4f..bfe17b7cb2f 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8781,6 +8781,7 @@ struct local_state_t
 {
   int cp_unevaluated_operand;
   int c_inhibit_evaluation_warnings;
+  int cp_noexcept_operand_;
 
   static local_state_t
   save_and_clear ()
@@ -8790,6 +8791,8 @@ struct local_state_t
 ::cp_unevaluated_operand = 0;
 s.c_inhibit_evaluation_warnings = ::c_inhibit_evaluation_warnings;
 ::c_inhibit_evaluation_warnings = 0;
+s.cp_noexcept_operand_ = ::cp_noexcept_operand;
+::cp_noexcept_operand = 0;
 return s;
   }
 
@@ -8798,6 +8801,7 @@ struct local_state_t
   {
 ::cp_unevaluated_operand = this->cp_unevaluated_operand;
 ::c_inhibit_evaluation_warnings = this->c_inhibit_evaluation_warnings;
+::cp_noexcept_operand = this->cp_noexcept_operand_;
   }
 };
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C 
b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C
index 37a183de0f5..7dbe7e1db75 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C
@@ -10,4 +10,5 @@ int main() {
   X x;
   static_assert(noexcept(x <=> x));
   x <=> x;
+  constexpr auto r = x <=> x;
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C 
b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
index 68388a680b2..bc0e7a54b7e 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
@@ -13,4 +13,5 @@ int main() {
   X x;
   static_assert(noexcept(x <=> x));
   x <=> x;
+  constexpr auto r = X{} <=> X{};
 }


[gcc r15-3089] libstdc++: Implement P2609R3 changes to the indirect invocability concepts

2024-08-22 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:b552730faf36f1eae1dc6e73ccc93a016dec5401

commit r15-3089-gb552730faf36f1eae1dc6e73ccc93a016dec5401
Author: Patrick Palka 
Date:   Thu Aug 22 09:24:11 2024 -0400

libstdc++: Implement P2609R3 changes to the indirect invocability concepts

This implements the changes of this C++23 paper as a DR against C++20.

Note that after the later P2538R1 "ADL-proof std::projected" (which we
already implement), we can't use a simple partial specialization to match
specializations of the 'projected' alias template.  So instead we identify
such specializations using a pair of distinguishing member aliases.

libstdc++-v3/ChangeLog:

* include/bits/iterator_concepts.h (__detail::__indirect_value):
Define.
(__indirect_value_t): Define as per P2609R3.
(iter_common_reference_t): Adjust as per P2609R3.
(indirectly_unary_invocable): Likewise.
(indirectly_regular_unary_invocable): Likewise.
(indirect_unary_predicate): Likewise.
(indirect_binary_predicate): Likewise.
(indirect_equivalence_relation): Likewise.
(indirect_strict_weak_order): Likewise.
(__detail::__projected::__type): Define member aliases
__projected_Iter and __projected_Proj providing the
template arguments of the current specialization.
* include/bits/version.def (ranges): Update value.
* include/bits/version.h: Regenerate.
* testsuite/24_iterators/indirect_callable/p2609r3.cc: New test.
* testsuite/std/ranges/version_c++23.cc: Update expected value
of __cpp_lib_ranges macro.

Reviewed-by: Jonathan Wakely 

Diff:
---
 libstdc++-v3/include/bits/iterator_concepts.h  | 61 --
 libstdc++-v3/include/bits/version.def  |  2 +-
 libstdc++-v3/include/bits/version.h|  4 +-
 .../24_iterators/indirect_callable/p2609r3.cc  | 27 ++
 libstdc++-v3/testsuite/std/ranges/version_c++23.cc |  2 +-
 5 files changed, 77 insertions(+), 19 deletions(-)

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h 
b/libstdc++-v3/include/bits/iterator_concepts.h
index ce0b8a10f88f..9306b7bd194c 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -552,9 +552,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 concept indirectly_readable
   = __detail::__indirectly_readable_impl>;
 
+  namespace __detail
+  {
+template
+  struct __indirect_value
+  { using type = iter_value_t<_Tp>&; };
+
+// __indirect_value> is defined later.
+  } // namespace __detail
+
+  template
+using __indirect_value_t = typename __detail::__indirect_value<_Tp>::type;
+
   template
 using iter_common_reference_t
-  = common_reference_t, iter_value_t<_Tp>&>;
+  = common_reference_t, __indirect_value_t<_Tp>>;
 
   /// Requirements for writing a value into an iterator's referenced object.
   template
@@ -710,24 +722,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
 concept indirectly_unary_invocable = indirectly_readable<_Iter>
-  && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&>
+  && copy_constructible<_Fn> && invocable<_Fn&, __indirect_value_t<_Iter>>
   && invocable<_Fn&, iter_reference_t<_Iter>>
   && invocable<_Fn&, iter_common_reference_t<_Iter>>
-  && common_reference_with&>,
+  && common_reference_with>,
   invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
 
   template
 concept indirectly_regular_unary_invocable = indirectly_readable<_Iter>
   && copy_constructible<_Fn>
-  && regular_invocable<_Fn&, iter_value_t<_Iter>&>
+  && regular_invocable<_Fn&, __indirect_value_t<_Iter>>
   && regular_invocable<_Fn&, iter_reference_t<_Iter>>
   && regular_invocable<_Fn&, iter_common_reference_t<_Iter>>
-  && common_reference_with&>,
+  && common_reference_with>,
   invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
 
   template
 concept indirect_unary_predicate = indirectly_readable<_Iter>
-  && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&>
+  && copy_constructible<_Fn> && predicate<_Fn&, __indirect_value_t<_Iter>>
   && predicate<_Fn&, iter_reference_t<_Iter>>
   && predicate<_Fn&, iter_common_reference_t<_Iter>>;
 
@@ -735,9 +747,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 concept indirect_binary_predicate
   = indirectly_readable<_I1> && indirectly_readable<_I2>
   && copy_constructible<_Fn>
-  && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
-  && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
-  && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+  && predicate<_Fn&, __indirect_value_t<_I1>, __indirect_value_t<_I2>>
+  && predicate<_Fn&, __indirect_value

[gcc r15-3038] c++: default targ eligibility refinement [PR101463]

2024-08-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931

commit r15-3038-g5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931
Author: Patrick Palka 
Date:   Tue Aug 20 08:34:36 2024 -0400

c++: default targ eligibility refinement [PR101463]

On Tue, 9 Jan 2024, Jason Merrill wrote:
> On 1/5/24 15:01, Patrick Palka wrote[1]:
> > Here during default template argument substitution we wrongly consider
> > the (substituted) default arguments v and vt as value-dependent[1]
> > which ultimately leads to deduction failure for the calls.
> >
> > The bogus value_dependent_expression_p result aside, I noticed
> > type_unification_real during default targ substitution keeps track of
> > whether all previous targs are known and non-dependent, as is the case
> > for these calls.  And in such cases it should be safe to avoid checking
> > dependence of the substituted default targ and just assume it's not.
> > This patch implements this optimization, which lets us accept both
> > testcases by sidestepping the value_dependent_expression_p issue
> > altogether.
>
> Hmm, maybe instead of substituting and asking if it's dependent, we should
> specifically look for undeduced parameters.

This patch implements this refinement, which incidentally fixes PR101463
just as well.

[1]: https://gcc.gnu.org/pipermail/gcc-patches/2024-January/641957.html

PR c++/101463

gcc/cp/ChangeLog:

* pt.cc (type_unification_real): Directly look for undeduced
parameters in the default argument instead of doing a trial
substitution.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/nontype6.C: New test.
* g++.dg/cpp1z/nontype6a.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc   | 41 ++
 gcc/testsuite/g++.dg/cpp1z/nontype6.C  | 24 
 gcc/testsuite/g++.dg/cpp1z/nontype6a.C | 25 +
 3 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ea660a5a5c6..bc3ad5edcc5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23619,28 +23619,31 @@ type_unification_real (tree tparms,
 is important if the default argument contains something that
 might be instantiation-dependent like access (87480).  */
  processing_template_decl_sentinel s (!any_dependent_targs);
- tree substed = NULL_TREE;
- if (saw_undeduced == 1 && !any_dependent_targs)
+
+ tree used_tparms = NULL_TREE;
+ if (saw_undeduced == 1)
{
- /* First instatiate in template context, in case we still
-depend on undeduced template parameters.  */
- ++processing_template_decl;
- substed = tsubst_template_arg (arg, full_targs, complain,
-NULL_TREE);
- --processing_template_decl;
- if (substed != error_mark_node
- && !uses_template_parms (substed))
-   /* We replaced all the tparms, substitute again out of
-  template context.  */
-   substed = NULL_TREE;
+ tree tparms_list = build_tree_list (size_int (1), tparms);
+ used_tparms = find_template_parameters (arg, tparms_list);
+ for (; used_tparms; used_tparms = TREE_CHAIN (used_tparms))
+   {
+ int level, index;
+ template_parm_level_and_index (TREE_VALUE (used_tparms),
+&level, &index);
+ if (TREE_VEC_ELT (targs, index) == NULL_TREE)
+   break;
+   }
}
- if (!substed)
-   substed = tsubst_template_arg (arg, full_targs, complain,
-  NULL_TREE);
 
- if (!uses_template_parms (substed))
-   arg = convert_template_argument (parm, substed, full_targs,
-complain, i, NULL_TREE);
+ if (!used_tparms)
+   {
+ /* All template parameters within this default argument are
+deduced, so we can use it.  */
+ arg = tsubst_template_arg (arg, full_targs, complain,
+NULL_TREE);
+ arg = convert_template_argument (parm, arg, full_targs,
+  complain, i, NULL_TREE);
+   }
  else if (saw_undeduced == 1)
arg = NULL_TREE;
  else if (!any_dependent_targs)
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6.C 
b/gcc/testsuite/g++.dg/cpp1z/non

[gcc r15-2938] c++: fix up cpp23/consteval-if3.C test [PR115583]

2024-08-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:580fe7979f3c873eae885568d2c17c9e110670b4

commit r15-2938-g580fe7979f3c873eae885568d2c17c9e110670b4
Author: Patrick Palka 
Date:   Thu Aug 15 14:38:47 2024 -0400

c++: fix up cpp23/consteval-if3.C test [PR115583]

Compiling with optimizations is needed to trigger the bug fixed
by r15-2369.

PR c++/115583

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/consteval-if13.C: Compile with -O.

Diff:
---
 gcc/testsuite/g++.dg/cpp23/consteval-if13.C | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/testsuite/g++.dg/cpp23/consteval-if13.C 
b/gcc/testsuite/g++.dg/cpp23/consteval-if13.C
index b98bbc33d13..b10ec18b3c6 100644
--- a/gcc/testsuite/g++.dg/cpp23/consteval-if13.C
+++ b/gcc/testsuite/g++.dg/cpp23/consteval-if13.C
@@ -1,5 +1,6 @@
 // PR c++/115583
 // { dg-do compile { target c++23 } }
+// { dg-additional-options -O }
 
 consteval int f(int i) {
   return i;


[gcc r14-10586] c++/coroutines: fix passing *this to promise type, again [PR116327]

2024-08-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:63c51e09d160a44fdce1199e8efe9d293f773a2c

commit r14-10586-g63c51e09d160a44fdce1199e8efe9d293f773a2c
Author: Patrick Palka 
Date:   Thu Aug 15 10:20:18 2024 -0400

c++/coroutines: fix passing *this to promise type, again [PR116327]

In r15-2210 we got rid of the unnecessary cast to lvalue reference when
passing *this to the promise type ctor, and as a drive-by change we also
simplified the code to use cp_build_fold_indirect_ref.

But it turns out cp_build_fold_indirect_ref does too much here, namely
it has a shortcut for returning current_class_ref if the operand is
current_class_ptr.  The problem with that shortcut is current_class_ref
might have gotten clobbered earlier if it appeared in the function body,
since rewrite_param_uses walks and rewrites in-place all local variable
uses to their corresponding frame copy.

So later cp_build_fold_indirect_ref for *this will instead return the
clobbered current_class_ref i.e. *frame_ptr->this, which doesn't make
sense here since we're in the ramp function and not the actor function
where frame_ptr is in scope.

This patch fixes this by using the build_fold_indirect_ref instead of
cp_build_fold_indirect_ref.

PR c++/116327
PR c++/104981
PR c++/115550

gcc/cp/ChangeLog:

* coroutines.cc (morph_fn_to_coro): Use build_fold_indirect_ref
instead of cp_build_fold_indirect_ref.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/pr104981-preview-this.C: Improve coverage by
adding a non-static data member use within the coroutine member
function.
* g++.dg/coroutines/pr116327-preview-this.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 303bed670af962c01b77a4f0c51de97f70e8167e)

Diff:
---
 gcc/cp/coroutines.cc   |  8 ++--
 .../g++.dg/coroutines/pr104981-preview-this.C  |  4 +++-
 .../g++.dg/coroutines/pr116327-preview-this.C  | 22 ++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 71e64960c5a..f5cfc80ca39 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4618,7 +4618,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm_i->this_ptr || parm_i->lambda_cobj)
{
  /* We pass a reference to *this to the allocator lookup.  */
- tree this_ref = cp_build_fold_indirect_ref (arg);
+ /* It's unsafe to use the cp_ version here since current_class_ref
+might've gotten clobbered earlier during rewrite_param_uses.  
*/
+ tree this_ref = build_fold_indirect_ref (arg);
  vec_safe_push (args, this_ref);
}
  else
@@ -4838,7 +4840,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm.this_ptr || parm.lambda_cobj)
{
  /* We pass a reference to *this to the param preview.  */
- tree this_ref = cp_build_fold_indirect_ref (arg);
+ /* It's unsafe to use the cp_ version here since current_class_ref
+might've gotten clobbered earlier during rewrite_param_uses.  
*/
+ tree this_ref = build_fold_indirect_ref (arg);
  vec_safe_push (promise_args, this_ref);
}
  else if (parm.rv_ref)
diff --git a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
index 81eb963db4a..9f1e3970ce3 100644
--- a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
+++ b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
@@ -23,8 +23,10 @@ struct PromiseType {
 };
 
 struct Derived : Base {
+  int m = 41;
   Result f() {
-   co_return 42;
+   ++m;
+   co_return m;
   }
 };
 
diff --git a/gcc/testsuite/g++.dg/coroutines/pr116327-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr116327-preview-this.C
new file mode 100644
index 000..27b69a41392
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr116327-preview-this.C
@@ -0,0 +1,22 @@
+// PR c++/116327 - ICE in coroutine with parameter preview on lambda with 
captures
+
+#include 
+
+struct coroutine{
+  struct promise_type{
+promise_type(const auto &...){}
+std::suspend_never initial_suspend(){ return {}; }
+std::suspend_always final_suspend()noexcept{ return {}; }
+void unhandled_exception(){}
+coroutine get_return_object(){ return {}; }
+void return_value(int)noexcept{}
+  };
+};
+
+int main(){
+  auto f = [a=0](auto) -> coroutine {
+co_return 2;
+  };
+  f(0);
+  return 0;
+}


[gcc r15-2933] c++: c->B::m access resolved through current inst [PR116320]

2024-08-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:484f139ccd3b631a777802e810a632678b42ffab

commit r15-2933-g484f139ccd3b631a777802e810a632678b42ffab
Author: Patrick Palka 
Date:   Thu Aug 15 10:23:54 2024 -0400

c++: c->B::m access resolved through current inst [PR116320]

Here when checking the access of (the injected-class-name) B in c->B::m
at parse time, we notice its context B (now the type) is a base of the
object type C, so we proceed to use C as the effective qualifying
type.  But this C is the dependent specialization not the primary
template type, so it has empty TYPE_BINFO, which leads to a segfault later
from perform_or_defer_access_check.

The reason the DERIVED_FROM_P (B, C) test guarding this code path works
despite C having empty TYPE_BINFO is because of its currently_open_class
logic (added in r9-713-gd9338471b91bbe) which replaces a dependent
specialization with the primary template type if we're inside it.  So the
safest fix seems to be to call currently_open_class in the caller as well.

PR c++/116320

gcc/cp/ChangeLog:

* semantics.cc (check_accessibility_of_qualified_id): Try
currently_open_class when using the object type as the
effective qualifying type.

gcc/testsuite/ChangeLog:

* g++.dg/template/access42.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/semantics.cc  | 11 ---
 gcc/testsuite/g++.dg/template/access42.C | 17 +
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index e58612660c9..5ab2076b673 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2516,9 +2516,14 @@ check_accessibility_of_qualified_id (tree decl,
 OBJECT_TYPE.  */
   && CLASS_TYPE_P (object_type)
   && DERIVED_FROM_P (scope, object_type))
-/* If we are processing a `->' or `.' expression, use the type of the
-   left-hand side.  */
-qualifying_type = object_type;
+{
+  /* If we are processing a `->' or `.' expression, use the type of the
+left-hand side.  */
+  if (tree open = currently_open_class (object_type))
+   qualifying_type = open;
+  else
+   qualifying_type = object_type;
+}
   else if (nested_name_specifier)
 {
   /* If the reference is to a non-static member of the
diff --git a/gcc/testsuite/g++.dg/template/access42.C 
b/gcc/testsuite/g++.dg/template/access42.C
new file mode 100644
index 000..f1dcbce80c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access42.C
@@ -0,0 +1,17 @@
+// PR c++/116320
+// { dg-do compile { target c++11 } }
+
+template struct C;
+template using C_ptr = C*;
+
+struct B { int m; using B_typedef = B; };
+
+template
+struct C : B {
+  void f(C_ptr c) {
+c->B::m;
+c->B_typedef::m;
+  }
+};
+
+template struct C;


[gcc r15-2932] c++/coroutines: fix passing *this to promise type, again [PR116327]

2024-08-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:303bed670af962c01b77a4f0c51de97f70e8167e

commit r15-2932-g303bed670af962c01b77a4f0c51de97f70e8167e
Author: Patrick Palka 
Date:   Thu Aug 15 10:20:18 2024 -0400

c++/coroutines: fix passing *this to promise type, again [PR116327]

In r15-2210 we got rid of the unnecessary cast to lvalue reference when
passing *this to the promise type ctor, and as a drive-by change we also
simplified the code to use cp_build_fold_indirect_ref.

But it turns out cp_build_fold_indirect_ref does too much here, namely
it has a shortcut for returning current_class_ref if the operand is
current_class_ptr.  The problem with that shortcut is current_class_ref
might have gotten clobbered earlier if it appeared in the function body,
since rewrite_param_uses walks and rewrites in-place all local variable
uses to their corresponding frame copy.

So later cp_build_fold_indirect_ref for *this will instead return the
clobbered current_class_ref i.e. *frame_ptr->this, which doesn't make
sense here since we're in the ramp function and not the actor function
where frame_ptr is in scope.

This patch fixes this by using the build_fold_indirect_ref instead of
cp_build_fold_indirect_ref.

PR c++/116327
PR c++/104981
PR c++/115550

gcc/cp/ChangeLog:

* coroutines.cc (morph_fn_to_coro): Use build_fold_indirect_ref
instead of cp_build_fold_indirect_ref.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/pr104981-preview-this.C: Improve coverage by
adding a non-static data member use within the coroutine member
function.
* g++.dg/coroutines/pr116327-preview-this.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/coroutines.cc   |  8 ++--
 .../g++.dg/coroutines/pr104981-preview-this.C  |  4 +++-
 .../g++.dg/coroutines/pr116327-preview-this.C  | 22 ++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 145ec4b1d16..f7791cbfb9a 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4850,7 +4850,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm_i->this_ptr || parm_i->lambda_cobj)
{
  /* We pass a reference to *this to the allocator lookup.  */
- tree this_ref = cp_build_fold_indirect_ref (arg);
+ /* It's unsafe to use the cp_ version here since current_class_ref
+might've gotten clobbered earlier during rewrite_param_uses.  
*/
+ tree this_ref = build_fold_indirect_ref (arg);
  vec_safe_push (args, this_ref);
}
  else
@@ -5070,7 +5072,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm.this_ptr || parm.lambda_cobj)
{
  /* We pass a reference to *this to the param preview.  */
- tree this_ref = cp_build_fold_indirect_ref (arg);
+ /* It's unsafe to use the cp_ version here since current_class_ref
+might've gotten clobbered earlier during rewrite_param_uses.  
*/
+ tree this_ref = build_fold_indirect_ref (arg);
  vec_safe_push (promise_args, this_ref);
}
  else if (parm.rv_ref)
diff --git a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
index 81eb963db4a..9f1e3970ce3 100644
--- a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
+++ b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
@@ -23,8 +23,10 @@ struct PromiseType {
 };
 
 struct Derived : Base {
+  int m = 41;
   Result f() {
-   co_return 42;
+   ++m;
+   co_return m;
   }
 };
 
diff --git a/gcc/testsuite/g++.dg/coroutines/pr116327-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr116327-preview-this.C
new file mode 100644
index 000..27b69a41392
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr116327-preview-this.C
@@ -0,0 +1,22 @@
+// PR c++/116327 - ICE in coroutine with parameter preview on lambda with 
captures
+
+#include 
+
+struct coroutine{
+  struct promise_type{
+promise_type(const auto &...){}
+std::suspend_never initial_suspend(){ return {}; }
+std::suspend_always final_suspend()noexcept{ return {}; }
+void unhandled_exception(){}
+coroutine get_return_object(){ return {}; }
+void return_value(int)noexcept{}
+  };
+};
+
+int main(){
+  auto f = [a=0](auto) -> coroutine {
+co_return 2;
+  };
+  f(0);
+  return 0;
+}


[gcc r15-2864] c++: inherited CTAD fixes [PR116276]

2024-08-09 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:8cc67b520968ca9a13fd96896522aa66e39a99e2

commit r15-2864-g8cc67b520968ca9a13fd96896522aa66e39a99e2
Author: Patrick Palka 
Date:   Fri Aug 9 21:15:25 2024 -0400

c++: inherited CTAD fixes [PR116276]

This implements the overlooked inherited vs non-inherited guide
tiebreaker from P2582R1.  This requires tracking inherited-ness of a
guide, for which it seems natural to reuse the lang_decl_fn::context
field which for a constructor tracks its inherited-ness.

This patch also works around CLASSTYPE_CONSTRUCTORS not reliably
returning all inherited constructors (due to some using-decl handling
quirks in in push_class_level_binding) by iterating over TYPE_FIELDS
instead.

This patch also makes us recognize another written form of inherited
constructor, 'using Base::Base::Base' whose USING_DECL_SCOPE is a
TYPENAME_TYPE.

PR c++/116276

gcc/cp/ChangeLog:

* call.cc (joust): Implement P2582R1 inherited vs non-inherited
guide tiebreaker.
* cp-tree.h (lang_decl_fn::context): Document usage in
deduction_guide_p FUNCTION_DECLs.
(inherited_guide_p): Declare.
* pt.cc (inherited_guide_p): Define.
(set_inherited_guide_context): Define.
(alias_ctad_tweaks): Use set_inherited_guide_context.
(inherited_ctad_tweaks): Recognize some inherited constructors
whose scope is a TYPENAME_TYPE.
(ctor_deduction_guides_for): For C++23 inherited CTAD, iterate
over TYPE_FIELDS instead of CLASSTYPE_CONSTRUCTORS to recognize
all inherited constructors.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/class-deduction-inherited4.C: Remove an xfail.
* g++.dg/cpp23/class-deduction-inherited5.C: New test.
* g++.dg/cpp23/class-deduction-inherited6.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc | 27 -
 gcc/cp/cp-tree.h   |  8 ++--
 gcc/cp/pt.cc   | 43 
 .../g++.dg/cpp23/class-deduction-inherited4.C  |  4 +-
 .../g++.dg/cpp23/class-deduction-inherited5.C  | 25 
 .../g++.dg/cpp23/class-deduction-inherited6.C  | 46 ++
 6 files changed, 139 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 67d38e2a78a7..94015db4e650 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13262,10 +13262,35 @@ joust (struct z_candidate *cand1, struct z_candidate 
*cand2, bool warn,
   else if (cand2->rewritten ())
 return 1;
 
-  /* F1 is generated from a deduction-guide (13.3.1.8) and F2 is not */
   if (deduction_guide_p (cand1->fn))
 {
   gcc_assert (deduction_guide_p (cand2->fn));
+
+  /* F1 and F2 are generated from class template argument deduction for a
+class D, and F2 is generated from inheriting constructors from a base
+class of D while F1 is not, and for each explicit function argument,
+the corresponding parameters of F1 and F2 are either both ellipses or
+have the same type.  */
+  bool inherited1 = inherited_guide_p (cand1->fn);
+  bool inherited2 = inherited_guide_p (cand2->fn);
+  if (int diff = inherited2 - inherited1)
+   {
+ for (i = 0; i < len; ++i)
+   {
+ conversion *t1 = cand1->convs[i + off1];
+ conversion *t2 = cand2->convs[i + off2];
+ /* ??? It seems the ellipses part of this tiebreaker isn't
+needed since a mismatch should have broken the tie earlier
+during ICS comparison.  */
+ gcc_checking_assert (t1->ellipsis_p == t2->ellipsis_p);
+ if (!same_type_p (t1->type, t2->type))
+   break;
+   }
+ if (i == len)
+   return diff;
+   }
+
+  /* F1 is generated from a deduction-guide (13.3.1.8) and F2 is not */
   /* We distinguish between candidates from an explicit deduction guide and
 candidates built from a constructor based on DECL_ARTIFICIAL.  */
   int art1 = DECL_ARTIFICIAL (cand1->fn);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5807f4e0edb3..a53fbcb43ec4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2972,9 +2972,10 @@ struct GTY(()) lang_decl_fn {
  this pointer and result pointer adjusting thunks are
  chained here.  This pointer thunks to return pointer thunks
  will be chained on the return pointer thunk.
- For a DECL_CONSTUCTOR_P FUNCTION_DECL, this is the base from
- whence we inherit.  Otherwise, it is the class in which a
- (namespace-scope) friend is defined (if any).   */
+ For a DECL_CONSTRUCTOR_P or deduction_guide_p FUNCTION_DECL,
+ this is the base from whence we inherit.
+ Otherwise, it is the class in whi

[gcc r15-2863] c++: DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P tweaks

2024-08-09 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:70da0ca1239faefa6dec0494a85e998eae34beff

commit r15-2863-g70da0ca1239faefa6dec0494a85e998eae34beff
Author: Patrick Palka 
Date:   Fri Aug 9 21:13:05 2024 -0400

c++: DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P tweaks

DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P templates can only appear as part
of a template friend declaration, and in turn get partially instantiated
only from tsubst_friend_function or tsubst_friend_class.  So rather than
having tsubst_template_decl clear the flag, let's leave it up to the
tsubst friend routines to clear it so that template friend handling stays
localized (note that tsubst_friend_function was already clearing it).

Also the template depth comparison test within tsubst_friend_function is
equivalent to DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P since such templates
belong to the class context (and so always have more levels than the
context), and conversely and it isn't possible to directly refer to an
existing template that has more levels than the class context.

gcc/cp/ChangeLog:

* pt.cc (tsubst_friend_class): Simplify depth comparison test
in the redeclaration code path to
DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P.  Clear the flag after
partial instantiation here ...
(tsubst_template_decl): ... instead of here.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1dde7d167fd6..c1d4cdc7e259 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11772,8 +11772,7 @@ tsubst_friend_class (tree friend_tmpl, tree args)
   compatible with the attachment of the friend template.  */
module_may_redeclare (tmpl, friend_tmpl);
 
-  if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (friend_tmpl))
- > TMPL_ARGS_DEPTH (args))
+  if (DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (friend_tmpl))
{
  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
  args, tf_warning_or_error);
@@ -11815,6 +11814,7 @@ tsubst_friend_class (tree friend_tmpl, tree args)
  CLASSTYPE_USE_TEMPLATE (TREE_TYPE (tmpl)) = 0;
  CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
+ DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (tmpl) = false;
 
  /* Substitute into and set the constraints on the new declaration.  */
  if (tree ci = get_constraints (friend_tmpl))
@@ -15044,8 +15044,6 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t 
complain,
   if (PRIMARY_TEMPLATE_P (t))
 DECL_PRIMARY_TEMPLATE (r) = r;
 
-  DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (r) = false;
-
   if (!lambda_fntype && !class_p)
 {
   /* Record this non-type partial instantiation.  */


[gcc r15-2862] c++: clean up cp_identifier_kind checks

2024-08-09 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:cf7feae517d4819cd33ef6bb123217ea39845fd1

commit r15-2862-gcf7feae517d4819cd33ef6bb123217ea39845fd1
Author: Patrick Palka 
Date:   Fri Aug 9 21:13:03 2024 -0400

c++: clean up cp_identifier_kind checks

The predicates for checking an IDENTIFIER node's cp_identifier_kind
currently directly test the three flag bits that encode the kind.  This
patch instead makes the checks first reconstruct the cp_identifier_kind
in its entirety and then compare that.

gcc/cp/ChangeLog:

* cp-tree.h (get_identifier_kind): Define.
(IDENTIFIER_KEYWORD_P): Redefine in terms of get_identifier_kind.
(IDENTIFIER_CDTOR_P): Likewise.
(IDENTIFIER_CTOR_P): Likewise.
(IDENTIFIER_DTOR_P): Likewise.
(IDENTIFIER_ANY_OP_P): Likewise.
(IDENTIFIER_OVL_OP_P): Likewise.
(IDENTIFIER_ASSIGN_OP_P): Likewise.
(IDENTIFIER_CONV_OP_P): Likewise.
(IDENTIFIER_TRAIT_P): Likewise.
* parser.cc (cp_lexer_peek_trait): Mark IDENTIFIER_TRAIT_P
check UNLIKELY.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-tree.h | 41 +
 gcc/cp/parser.cc |  3 ++-
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b1693051231b..5807f4e0edb3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1255,56 +1255,57 @@ enum cp_identifier_kind {
 #define IDENTIFIER_VIRTUAL_P(NODE) \
   TREE_LANG_FLAG_5 (IDENTIFIER_NODE_CHECK (NODE))
 
+/* Return the cp_identifier_kind of the given IDENTIFIER node ID.  */
+
+ATTRIBUTE_PURE inline cp_identifier_kind
+get_identifier_kind (tree id)
+{
+  unsigned bit0 = IDENTIFIER_KIND_BIT_0 (id);
+  unsigned bit1 = IDENTIFIER_KIND_BIT_1 (id);
+  unsigned bit2 = IDENTIFIER_KIND_BIT_2 (id);
+  return cp_identifier_kind ((bit2 << 2) | (bit1 << 1) | bit0);
+}
+
 /* True if this identifier is a reserved word.  C_RID_CODE (node) is
then the RID_* value of the keyword.  Value 1.  */
 #define IDENTIFIER_KEYWORD_P(NODE) \
-  ((!IDENTIFIER_KIND_BIT_2 (NODE)) \
-   & (!IDENTIFIER_KIND_BIT_1 (NODE))   \
-   & IDENTIFIER_KIND_BIT_0 (NODE))
+  (get_identifier_kind (NODE) == cik_keyword)
 
 /* True if this identifier is the name of a constructor or
destructor.  Value 2 or 3.  */
 #define IDENTIFIER_CDTOR_P(NODE)   \
-  ((!IDENTIFIER_KIND_BIT_2 (NODE)) \
-   & IDENTIFIER_KIND_BIT_1 (NODE))
+  (IDENTIFIER_CTOR_P (NODE) || IDENTIFIER_DTOR_P (NODE))
 
 /* True if this identifier is the name of a constructor.  Value 2.  */
 #define IDENTIFIER_CTOR_P(NODE)\
-  (IDENTIFIER_CDTOR_P(NODE)\
-& (!IDENTIFIER_KIND_BIT_0 (NODE)))
+  (get_identifier_kind (NODE) == cik_ctor)
 
 /* True if this identifier is the name of a destructor.  Value 3.  */
 #define IDENTIFIER_DTOR_P(NODE)\
-  (IDENTIFIER_CDTOR_P(NODE)\
-& IDENTIFIER_KIND_BIT_0 (NODE))
+  (get_identifier_kind (NODE) == cik_dtor)
 
 /* True if this identifier is for any operator name (including
conversions).  Value 4, 5, or 6.  */
 #define IDENTIFIER_ANY_OP_P(NODE)  \
-  (IDENTIFIER_KIND_BIT_2 (NODE) && !IDENTIFIER_TRAIT_P (NODE))
+  (IDENTIFIER_OVL_OP_P (NODE) || IDENTIFIER_CONV_OP_P (NODE))
 
 /* True if this identifier is for an overloaded operator. Values 4, 5.  */
 #define IDENTIFIER_OVL_OP_P(NODE)  \
-  (IDENTIFIER_ANY_OP_P (NODE)  \
-   & (!IDENTIFIER_KIND_BIT_1 (NODE)))
+  (get_identifier_kind (NODE) == cik_simple_op  \
+   || get_identifier_kind (NODE) == cik_assign_op)
 
 /* True if this identifier is for any assignment. Values 5.  */
 #define IDENTIFIER_ASSIGN_OP_P(NODE)   \
-  (IDENTIFIER_OVL_OP_P (NODE)  \
-   & IDENTIFIER_KIND_BIT_0 (NODE))
+  (get_identifier_kind (NODE) == cik_assign_op)
 
 /* True if this identifier is the name of a type-conversion
operator.  Value 6.  */
 #define IDENTIFIER_CONV_OP_P(NODE) \
-  (IDENTIFIER_ANY_OP_P (NODE)  \
-   & IDENTIFIER_KIND_BIT_1 (NODE)  \
-   & (!IDENTIFIER_KIND_BIT_0 (NODE)))
+  (get_identifier_kind (NODE) == cik_conv_op)
 
 /* True if this identifier is the name of a built-in trait.  */
 #define IDENTIFIER_TRAIT_P(NODE)   \
-  (IDENTIFIER_KIND_BIT_0 (NODE)\
-   & IDENTIFIER_KIND_BIT_1 (NODE)  \
-   & IDENTIFIER_KIND_BIT_2 (NODE))
+  (get_identifier_kind (NODE) == cik_trait)
 
 /* True if this identifier is a new or delete operator.  */
 #define IDENTIFIER_NEWDEL_OP_P(NODE)   \
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 82f3903838e2..852efe45076f 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -1198,7 +1198,8 @@ static const cp_trait *
 cp_lexer_peek_trait (cp_lexer *lexer)
 {
   const cp_token *token1 = cp_lexer_peek_toke

[gcc r15-2849] c-family: regenerate c.opt.urls

2024-08-09 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:f91f7201ac0ab6805b517341c0ba7a0c48b7971c

commit r15-2849-gf91f7201ac0ab6805b517341c0ba7a0c48b7971c
Author: Patrick Palka 
Date:   Fri Aug 9 09:35:17 2024 -0400

c-family: regenerate c.opt.urls

The addition of -Wtemplate-body in r15-2774-g596d1ed9d40b10 means
we need to regenerate c.opt.urls.

gcc/c-family/ChangeLog:

* c.opt.urls: Regenerate.

Diff:
---
 gcc/c-family/c.opt.urls | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls
index df5f58a1eeed..e40b8e5c3a0d 100644
--- a/gcc/c-family/c.opt.urls
+++ b/gcc/c-family/c.opt.urls
@@ -837,6 +837,9 @@ 
UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-templates)
 Wtautological-compare
 UrlSuffix(gcc/Warning-Options.html#index-Wno-tautological-compare)
 
+Wtemplate-body
+UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-template-body)
+
 Wtemplate-id-cdtor
 UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-template-id-cdtor)


[gcc r15-2848] c++: add fixed testcase [PR116289]

2024-08-09 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:4aa89badc8c16637e0d9a39a08da7d18e209631b

commit r15-2848-g4aa89badc8c16637e0d9a39a08da7d18e209631b
Author: Patrick Palka 
Date:   Fri Aug 9 09:16:45 2024 -0400

c++: add fixed testcase [PR116289]

Fully fixed since r14-6724-gfced59166f95e9.

PR c++/116289
PR c++/113063

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/spaceship-synth16a.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C | 16 
 1 file changed, 16 insertions(+)

diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C 
b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
new file mode 100644
index ..68388a680b20
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
@@ -0,0 +1,16 @@
+// PR c++/116289
+// PR c++/113063
+// { dg-do link { target c++20 } }
+// A version of spaceship-synth16.C where the local class isn't empty.
+
+#include 
+
+int main() {
+  struct X {
+int m = 0;
+auto operator<=>(const X&) const = default;
+  };
+  X x;
+  static_assert(noexcept(x <=> x));
+  x <=> x;
+}


[gcc r13-8967] c++: local class memfn synth from uneval context [PR113063]

2024-08-09 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:12ba140ee93adc56a3426f0c6c05f4d6c6a3d08e

commit r13-8967-g12ba140ee93adc56a3426f0c6c05f4d6c6a3d08e
Author: Patrick Palka 
Date:   Fri Aug 9 09:03:14 2024 -0400

c++: local class memfn synth from uneval context [PR113063]

This is essentially a narrow backport of r14-6724-gfced59166f95e9 that
instead uses cp_evaluated instead of maybe_push_to_top_level to clear
cp_unevaluated_operand within synthesize_method, which turns out is
sufficient to also fix the 13.3 regression PR116289 (whose immediate
trigger is a  change backport r13-7739-gd919309679334a).

PR c++/113063
PR c++/116289

gcc/cp/ChangeLog:

* method.cc (synthesize_method): Use cp_evaluated.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/spaceship-synth16.C: New test.
* g++.dg/cpp2a/spaceship-synth16a.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/method.cc|  1 +
 gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C  | 13 +
 gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C | 16 
 3 files changed, 30 insertions(+)

diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 9fd5567e97fd..09ea6d732dfc 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1797,6 +1797,7 @@ synthesize_method (tree fndecl)
  it now.  */
   push_deferring_access_checks (dk_no_deferred);
 
+  cp_evaluated ev;
   if (! context)
 push_to_top_level ();
   else if (nested)
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C 
b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C
new file mode 100644
index ..37a183de0f5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C
@@ -0,0 +1,13 @@
+// PR c++/113063
+// { dg-do link { target c++20 } }
+
+#include 
+
+int main() {
+  struct X {
+auto operator<=>(const X&) const = default;
+  };
+  X x;
+  static_assert(noexcept(x <=> x));
+  x <=> x;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C 
b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
new file mode 100644
index ..68388a680b20
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C
@@ -0,0 +1,16 @@
+// PR c++/116289
+// PR c++/113063
+// { dg-do link { target c++20 } }
+// A version of spaceship-synth16.C where the local class isn't empty.
+
+#include 
+
+int main() {
+  struct X {
+int m = 0;
+auto operator<=>(const X&) const = default;
+  };
+  X x;
+  static_assert(noexcept(x <=> x));
+  x <=> x;
+}


[gcc r15-2802] c++: erroneous partial spec vs primary tmpl [PR116064]

2024-08-07 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:d1fc9816df81e953308428641685d6ec6d84c9ac

commit r15-2802-gd1fc9816df81e953308428641685d6ec6d84c9ac
Author: Patrick Palka 
Date:   Wed Aug 7 14:28:26 2024 -0400

c++: erroneous partial spec vs primary tmpl [PR116064]

When a partial specialization is deemed erroneous at parse time, we
currently flag the primary template as erroneous instead.  Later
at instantiation time we check if the primary template is erroneous
rather than the selected partial specialization, so at least we're
consistent.

But it's better not to conflate a partial specialization with the
primary template since they're instantiated independenty.  This avoids
rejecting the instantiation of A in the below testcase.

PR c++/116064

gcc/cp/ChangeLog:

* error.cc (get_current_template): If the current scope is
a partial specialization, return it instead of the primary
template.
* pt.cc (instantiate_class_template): Pass the partial
specialization if any to maybe_diagnose_erroneous_template
instead of the primary template.

gcc/testsuite/ChangeLog:

* g++.dg/template/permissive-error2.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/error.cc   |  6 +-
 gcc/cp/pt.cc  |  2 +-
 gcc/testsuite/g++.dg/template/permissive-error2.C | 15 +++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 6c22ff55b463..879e5a115cfe 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -173,7 +173,11 @@ get_current_template ()
 {
   if (scope_chain && in_template_context && !current_instantiation ())
 if (tree ti = get_template_info (current_scope ()))
-  return TI_TEMPLATE (ti);
+  {
+   if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)) && TI_PARTIAL_INFO (ti))
+ ti = TI_PARTIAL_INFO (ti);
+   return TI_TEMPLATE (ti);
+  }
 
   return NULL_TREE;
 }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 542962b6387f..3e55d5c0fea5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -12381,7 +12381,7 @@ instantiate_class_template (tree type)
   if (! push_tinst_level (type))
 return type;
 
-  maybe_diagnose_erroneous_template (templ);
+  maybe_diagnose_erroneous_template (t ? TI_TEMPLATE (t) : templ);
 
   int saved_unevaluated_operand = cp_unevaluated_operand;
   int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
diff --git a/gcc/testsuite/g++.dg/template/permissive-error2.C 
b/gcc/testsuite/g++.dg/template/permissive-error2.C
new file mode 100644
index ..692e7c7ac82c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/permissive-error2.C
@@ -0,0 +1,15 @@
+// PR c++/116064
+// { dg-additional-options -fpermissive }
+// Verify we correctly mark a partial specialization as erroneous
+// instead its primary template.
+
+template
+struct A { };
+
+template
+struct A { // { dg-error "instantiating erroneous template" }
+  void f(typename A::type); // { dg-warning "does not name a type" }
+};
+
+A a;  // { dg-bogus "" }
+A b; // { dg-message "required from here" }


[gcc r15-2774] c++: permit errors inside uninstantiated templates [PR116064]

2024-08-06 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:596d1ed9d40b1081fcc6c6161a0135952829b88f

commit r15-2774-g596d1ed9d40b1081fcc6c6161a0135952829b88f
Author: Patrick Palka 
Date:   Tue Aug 6 20:54:03 2024 -0400

c++: permit errors inside uninstantiated templates [PR116064]

In recent versions of GCC we've been diagnosing more and more kinds of
errors inside a template ahead of time.  This is a largely good thing
because it catches bugs, typos, dead code etc sooner.

But if the template never gets instantiated then such errors are harmless
and can be inconvenient to work around if say the code in question is
third party and in maintenance mode.  So it'd be handy to be able to
prevent these template errors from rendering the entire TU uncompilable.
(Note that such code is "ill-formed no diagnostic required" according
the standard.)

To that end this patch turns any errors issued within a template into
permerrors associated with a new -Wtemplate-body flag so that they can
be downgraded via e.g. -fpermissive or -Wno-error=template-body.  If
the template containing a downgraded error later needs to be instantiated,
we'll issue an error then.  But if the template never gets instantiated
then the downgraded error won't affect validity of the rest of the TU.

This is implemented via a diagnostic hook that gets called for each
diagnostic, and which adjusts an error diagnostic appropriately if we
detect it's occurring from a template context, and additionally flags
the template as erroneous.

For example the new testcase permissive-error1a.C gives:

gcc/testsuite/g++.dg/template/permissive-error1a.C: In function 'void f()':
gcc/testsuite/g++.dg/template/permissive-error1a.C:7:5: warning: increment 
of read-only variable 'n' [-Wtemplate-body]
7 |   ++n;
  | ^
...
gcc/testsuite/g++.dg/template/permissive-error1a.C: In instantiation of 
'void f() [with T = int]':
gcc/testsuite/g++.dg/template/permissive-error1a.C:26:9:   required from 
here
   26 |   f();
  |   ~~^~
gcc/testsuite/g++.dg/template/permissive-error1a.C:5:6: error: 
instantiating erroneous template
5 | void f() {
  |  ^
gcc/testsuite/g++.dg/template/permissive-error1a.C:7:5: note: first error 
appeared here
7 |   ++n; // {
  | ^
...

PR c++/116064

gcc/c-family/ChangeLog:

* c.opt (Wtemplate-body): New warning.

gcc/cp/ChangeLog:

* cp-tree.h (erroneous_templates_t): Declare.
(erroneous_templates): Declare.
(cp_seen_error): Declare.
(seen_error): #define to cp_seen_error.
* error.cc (get_current_template): Define.
(relaxed_template_errors): Define.
(cp_adjust_diagnostic_info): Define.
(cp_seen_error): Define.
(cxx_initialize_diagnostics): Set
diagnostic_context::m_adjust_diagnostic_info.
* module.cc (finish_module_processing): Don't write the
module if it contains an erroneous template.
* pt.cc (maybe_diagnose_erroneous_template): Define.
(instantiate_class_template): Call it.
(instantiate_decl): Likewise.

gcc/ChangeLog:

* diagnostic.cc (diagnostic_context::initialize): Set
m_adjust_diagnostic_info.
(diagnostic_context::report_diagnostic): Call
m_adjust_diagnostic_info.
* diagnostic.h (diagnostic_context::m_adjust_diagnostic_info):
New data member.
* doc/invoke.texi (-Wno-template-body): Document.
(-fpermissive): Mention -Wtemplate-body.

gcc/testsuite/ChangeLog:

* g++.dg/ext/typedef-init.C: Downgrade error inside template
to warning due to -fpermissive.
* g++.dg/pr84492.C: Likewise.
* g++.old-deja/g++.pt/crash51.C: Remove unneeded dg-options.
* g++.dg/template/permissive-error1.C: New test.
* g++.dg/template/permissive-error1a.C: New test.
* g++.dg/template/permissive-error1b.C: New test.
* g++.dg/template/permissive-error1c.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/c-family/c.opt |  4 ++
 gcc/cp/cp-tree.h   |  7 +++
 gcc/cp/error.cc| 67 ++
 gcc/cp/module.cc   |  5 +-
 gcc/cp/pt.cc   | 22 +++
 gcc/diagnostic.cc  |  4 ++
 gcc/diagnostic.h   |  4 ++
 gcc/doc/invoke.texi| 12 +++-
 gcc/testsuite/g++.dg/ext/typedef-init.C|  2 +-
 gcc/testsuite/g++.dg/pr84492.C |  4 +-
 gcc/testsuite/g++.dg/templa

[gcc r15-2756] c++: fold calls to std::forward_like [PR96780]

2024-08-06 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:180625ae72b3f733813a360fae4f0d6ce79eccdc

commit r15-2756-g180625ae72b3f733813a360fae4f0d6ce79eccdc
Author: Patrick Palka 
Date:   Tue Aug 6 11:51:45 2024 -0400

c++: fold calls to std::forward_like [PR96780]

This extends our folding of cast-like standard library functions
to also include C++23's std::forward_like.

PR c++/96780

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_fold) : Fold calls
to std::forward_like as well.

gcc/testsuite/ChangeLog:

* g++.dg/opt/pr96780.C: Also test std::forward_like folding.

Reviewed-by: Marek Polacek 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-gimplify.cc  | 1 +
 gcc/testsuite/g++.dg/opt/pr96780.C | 5 +
 2 files changed, 6 insertions(+)

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index b88c3b7f370b..0c589eeaaec4 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -3313,6 +3313,7 @@ cp_fold (tree x, fold_flags_t flags)
&& DECL_NAME (callee) != NULL_TREE
&& (id_equal (DECL_NAME (callee), "move")
|| id_equal (DECL_NAME (callee), "forward")
+   || id_equal (DECL_NAME (callee), "forward_like")
|| id_equal (DECL_NAME (callee), "addressof")
/* This addressof equivalent is used heavily in libstdc++.  */
|| id_equal (DECL_NAME (callee), "__addressof")
diff --git a/gcc/testsuite/g++.dg/opt/pr96780.C 
b/gcc/testsuite/g++.dg/opt/pr96780.C
index 61e11855eeb3..a29cda8b836e 100644
--- a/gcc/testsuite/g++.dg/opt/pr96780.C
+++ b/gcc/testsuite/g++.dg/opt/pr96780.C
@@ -29,6 +29,10 @@ void f() {
   auto&& x11 = std::as_const(a);
   auto&& x12 = std::as_const(ca);
 #endif
+#if __cpp_lib_forward_like
+  auto&& x13 = std::forward_like(a);
+  auto&& x14 = std::forward_like(ca);
+#endif
 }
 
 // { dg-final { scan-tree-dump-not "= std::move" "gimple" } }
@@ -36,3 +40,4 @@ void f() {
 // { dg-final { scan-tree-dump-not "= std::addressof" "gimple" } }
 // { dg-final { scan-tree-dump-not "= std::__addressof" "gimple" } }
 // { dg-final { scan-tree-dump-not "= std::as_const" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::forward_like" "gimple" } }


[gcc r14-10548] c++: generic lambda in default template argument [PR88313]

2024-08-01 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:81db6857686c2d7932949afb948419a575bc0b3f

commit r14-10548-g81db6857686c2d7932949afb948419a575bc0b3f
Author: Patrick Palka 
Date:   Mon Jul 29 16:37:19 2024 -0400

c++: generic lambda in default template argument [PR88313]

Here we're rejecting the generic lambda inside the default template
argument ultimately because auto_is_implicit_function_template_parm_p
doesn't get set during parsing of the lambda's parameter list, due
to the !processing_template_parmlist restriction.  But when parsing a
lambda parameter list we should always set that flag regardless of where
the lambda appears.  This patch makes sure of this via a local lambda_p
flag.

PR c++/88313

gcc/cp/ChangeLog:

* parser.cc (cp_parser_lambda_declarator_opt): Pass
lambda_p=true to cp_parser_parameter_declaration_clause.
(cp_parser_direct_declarator): Pass lambda_p=false to
to cp_parser_parameter_declaration_clause.
(cp_parser_parameter_declaration_clause): Add bool lambda_p
parameter.  Consider lambda_p instead of current_class_type
when setting parser->auto_is_implicit_function_template_parm_p.
Don't consider processing_template_parmlist.
(cp_parser_requirement_parameter_list): Pass lambda_p=false
to cp_parser_parameter_declaration_clause.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-targ6.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 72a7ab891ae0061841c4eb641ef6ab7719bf0369)

Diff:
---
 gcc/cp/parser.cc  | 34 ++-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C | 15 ++
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7e81c1010c45..00cf128522a7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2598,7 +2598,7 @@ static tree cp_parser_type_id_1
 static void cp_parser_type_specifier_seq
   (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
-  (cp_parser *, cp_parser_flags);
+  (cp_parser *, cp_parser_flags, bool);
 static tree cp_parser_parameter_declaration_list
   (cp_parser *, cp_parser_flags, auto_vec *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
@@ -11867,7 +11867,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
   /* Parse parameters.  */
   param_list
= cp_parser_parameter_declaration_clause
-   (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL);
+   (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, /*lambda_p=*/true);
 
   /* Default arguments shall not be specified in the
 parameter-declaration-clause of a lambda-declarator.  */
@@ -23903,7 +23903,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 
  /* Parse the parameter-declaration-clause.  */
  params
-   = cp_parser_parameter_declaration_clause (parser, flags);
+   = cp_parser_parameter_declaration_clause (parser, flags,
+ /*lambda_p=*/false);
  const location_t parens_end
= cp_lexer_peek_token (parser->lexer)->location;
 
@@ -25252,13 +25253,17 @@ function_being_declared_is_template_p (cp_parser* 
parser)
 
The parser flags FLAGS is used to control type-specifier parsing.
 
+   LAMBDA_P is true if this is the parameter-declaration-clause of
+   a lambda-declarator.
+
Returns a representation for the parameter declarations.  A return
value of NULL indicates a parameter-declaration-clause consisting
only of an ellipsis.  */
 
 static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser,
-   cp_parser_flags flags)
+   cp_parser_flags flags,
+   bool lambda_p)
 {
   tree parameters;
   cp_token *token;
@@ -25267,15 +25272,15 @@ cp_parser_parameter_declaration_clause (cp_parser* 
parser,
   auto cleanup = make_temp_override
 (parser->auto_is_implicit_function_template_parm_p);
 
-  if (!processing_specialization
-  && !processing_template_parmlist
-  && !processing_explicit_instantiation
-  /* default_arg_ok_p tracks whether this is a parameter-clause for an
- actual function or a random abstract declarator.  */
-  && parser->default_arg_ok_p)
-if (!current_function_decl
-   || (current_class_type && LAMBDA_TYPE_P (current_class_type)))
-  parser->auto_is_implicit_function_template_parm_p = true;
+  if (lambda_p
+  || (!processing_specialization
+ && !processing_template_parmlist
+ && !processing_explicit_instantiation
+ /* default_arg_ok_p tracks whether this is a parameter-clause for an
+actual function or a

[gcc r14-10547] c++: alias of alias tmpl with dependent attrs [PR115897]

2024-08-01 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:37e54ffd2a0a18eec23c90bdf438c01a0393328a

commit r14-10547-g37e54ffd2a0a18eec23c90bdf438c01a0393328a
Author: Patrick Palka 
Date:   Thu Jul 25 19:00:23 2024 -0400

c++: alias of alias tmpl with dependent attrs [PR115897]

As a follow-up to r15-2047-g7954bb4fcb6fa8, we also need to consider
dependent attributes when recursing into a non-template alias that names
a dependent alias template specialization (and so STF_STRIP_DEPENDENT
is set), otherwise in the first testcase below we undesirably strip B
all the way to T instead of to A.

We also need to move the typedef recursion case of strip_typedefs up to
get checked before the compound type recursion cases.  Otherwise for C
below (which ultimately aliases T*) we end up stripping it to T* instead
of to A because the POINTER_TYPE recursion dominates the typedef
recursion.  It also means we issue an unexpected extra error in the
third testcase below.

Ideally we would also want to consider dependent attributes on
non-template aliases, so that we accept the second testcase below, but
making that work correctly would require broader changes to e.g.
structural_comptypes.

PR c++/115897

gcc/cp/ChangeLog:

* tree.cc (strip_typedefs): Move up the typedef recursion case.
Never strip a dependent alias template-id that has dependent
attributes.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alias-decl-78.C: New test.
* g++.dg/cpp0x/alias-decl-79.C: New test.
* g++.dg/cpp0x/alias-decl-pr92206-1a.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 9bcad238837e2100978cd839c343c488f72e1d4a)

Diff:
---
 gcc/cp/tree.cc | 51 --
 gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C | 34 +++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-79.C | 37 
 gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-1a.C | 10 +
 4 files changed, 110 insertions(+), 22 deletions(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 41fdf67f7574..d90244609c8a 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -1607,11 +1607,32 @@ strip_typedefs (tree t, bool *remove_attributes /* = 
NULL */,
   if (t == TYPE_CANONICAL (t))
 return t;
 
-  if (!(flags & STF_STRIP_DEPENDENT)
-  && dependent_alias_template_spec_p (t, nt_opaque))
-/* DR 1558: However, if the template-id is dependent, subsequent
-   template argument substitution still applies to the template-id.  */
-return t;
+  if (typedef_variant_p (t))
+{
+  if ((flags & STF_USER_VISIBLE)
+ && !user_facing_original_type_p (t))
+   return t;
+
+  if (alias_template_specialization_p (t, nt_opaque))
+   {
+ if (dependent_alias_template_spec_p (t, nt_opaque)
+ && (!(flags & STF_STRIP_DEPENDENT)
+ || any_dependent_type_attributes_p (DECL_ATTRIBUTES
+ (TYPE_NAME (t)
+   /* DR 1558: However, if the template-id is dependent, subsequent
+  template argument substitution still applies to the template-id. 
 */
+   return t;
+   }
+  else
+   /* If T is a non-template alias or typedef, we can assume that
+  instantiating its definition will hit any substitution failure,
+  so we don't need to retain it here as well.  */
+   flags |= STF_STRIP_DEPENDENT;
+
+  result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
+  remove_attributes, flags);
+  goto stripped;
+}
 
   switch (TREE_CODE (t))
 {
@@ -1805,23 +1826,9 @@ strip_typedefs (tree t, bool *remove_attributes /* = 
NULL */,
 }
 
   if (!result)
-{
-  if (typedef_variant_p (t))
-   {
- if ((flags & STF_USER_VISIBLE)
- && !user_facing_original_type_p (t))
-   return t;
- /* If T is a non-template alias or typedef, we can assume that
-instantiating its definition will hit any substitution failure,
-so we don't need to retain it here as well.  */
- if (!alias_template_specialization_p (t, nt_opaque))
-   flags |= STF_STRIP_DEPENDENT;
- result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
-  remove_attributes, flags);
-   }
-  else
-   result = TYPE_MAIN_VARIANT (t);
-}
+result = TYPE_MAIN_VARIANT (t);
+
+stripped:
   /*gcc_assert (!typedef_variant_p (result)
  || dependent_alias_template_spec_p (result, nt_opaque)
  || ((flags & STF_USER_VISIBLE)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C
new file mode 100644
index ..a52c0622e46d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C
@@ -0,0 +1,

[gcc r14-10545] c++: normalizing ttp constraints [PR115656]

2024-08-01 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:241f710c851aa6a8627c3ddba1e126d8e503e1b0

commit r14-10545-g241f710c851aa6a8627c3ddba1e126d8e503e1b0
Author: Patrick Palka 
Date:   Tue Jul 23 13:16:14 2024 -0400

c++: normalizing ttp constraints [PR115656]

Here we normalize the constraint same_as for the first
time during ttp coercion of B / UU, specifically constraint subsumption
checking.  During this normalization the set of in-scope template
parameters i.e. current_template_parms is empty, which we rely on
during normalization of the ttp constraints since we pass in_decl=NULL_TREE
to norm_info.  And this tricks the satisfaction cache into thinking that
the satisfaction value of same_as is independent of its template
parameters, and we incorrectly conflate the satisfaction value with
T = bool vs T = long and accept the specialization A.

Since is_compatible_template_arg rewrites the ttp's constraints to
be in terms of the argument template's parameters, and since it's
the only caller of weakly_subsumes, the latter funcion can instead
pass in_decl=tmpl to avoid relying on current_template_parms.  This
patch implements this, and in turns renames weakly_subsumes to
ttp_subsumes to reflect that this predicate is now hardcoded for this
one caller.

PR c++/115656

gcc/cp/ChangeLog:

* constraint.cc (weakly_subsumes): Pass in_decl=tmpl to
get_normalized_constraints_from_info.  Rename to ...
(ttp_subsumes): ... this.
* cp-tree.h (weakly_subsumes): Rename to ...
(ttp_subsumes): ... this.
* pt.cc (is_compatible_template_arg): Adjust after renaming.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-ttp7.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 2861eb34e30973cb991a7964af7cfeae014a98b0)

Diff:
---
 gcc/cp/constraint.cc   |  9 +
 gcc/cp/cp-tree.h   |  2 +-
 gcc/cp/pt.cc   |  2 +-
 gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C | 12 
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8a3b5d80ba7c..b6c6a5e23306 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3610,13 +3610,14 @@ strictly_subsumes (tree ci, tree tmpl)
   return subsumes (n1, n2) && !subsumes (n2, n1);
 }
 
-/* Returns true when the constraints in CI subsume the
-   associated constraints of TMPL.  */
+/* Returns true when the template template parameter constraints in CI
+   subsume the associated constraints of the template template argument
+   TMPL.  */
 
 bool
-weakly_subsumes (tree ci, tree tmpl)
+ttp_subsumes (tree ci, tree tmpl)
 {
-  tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE);
+  tree n1 = get_normalized_constraints_from_info (ci, tmpl);
   tree n2 = get_normalized_constraints_from_decl (tmpl);
 
   return subsumes (n1, n2);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ed637015a931..3f607313db61 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8606,7 +8606,7 @@ extern tree find_template_parameters  (tree, 
tree);
 extern bool equivalent_constraints  (tree, tree);
 extern bool equivalently_constrained(tree, tree);
 extern bool strictly_subsumes  (tree, tree);
-extern bool weakly_subsumes(tree, tree);
+extern bool ttp_subsumes   (tree, tree);
 extern int more_constrained (tree, tree);
 extern bool at_least_as_constrained (tree, tree);
 extern bool constraints_equivalent_p(tree, tree);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 13907858273e..ea4a6c9bf530 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8504,7 +8504,7 @@ is_compatible_template_arg (tree parm, tree arg, tree 
args)
 return false;
 }
 
-  return weakly_subsumes (parm_cons, arg);
+  return ttp_subsumes (parm_cons, arg);
 }
 
 // Convert a placeholder argument into a binding to the original
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C
new file mode 100644
index ..2ce884b995c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C
@@ -0,0 +1,12 @@
+// PR c++/115656
+// { dg-do compile { target c++20 } }
+
+template concept same_as = __is_same(T, U);
+
+template T, template> class UU>
+struct A { };
+
+template> class B;
+
+A a1;
+A a2; // { dg-error "constraint failure" }


[gcc r14-10544] c++: missing SFINAE during alias CTAD [PR115296]

2024-08-01 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:e548a881a4540378151f6195e47e8413fe75a0d6

commit r14-10544-ge548a881a4540378151f6195e47e8413fe75a0d6
Author: Patrick Palka 
Date:   Tue Jul 23 11:37:31 2024 -0400

c++: missing SFINAE during alias CTAD [PR115296]

During the alias CTAD transformation, if substitution failed for some
guide we should just silently discard the guide.  We currently do
discard the guide, but not silently, as in the below testcase which
we diagnose forming a too-large array type when transforming the
user-defined deduction guides.

This patch fixes this by using complain=tf_none instead of
tf_warning_or_error throughout alias_ctad_tweaks.

PR c++/115296

gcc/cp/ChangeLog:

* pt.cc (alias_ctad_tweaks): Use complain=tf_none instead of
tf_warning_or_error.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias23.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit f70281222df432a7bec1271904c5ebefd7f2c934)

Diff:
---
 gcc/cp/pt.cc |  2 +-
 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C | 19 +++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 713946a1ff17..13907858273e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30369,7 +30369,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  (INNERMOST_TEMPLATE_PARMS (fullatparms)));
 }
 
-  tsubst_flags_t complain = tf_warning_or_error;
+  tsubst_flags_t complain = tf_none;
   tree aguides = NULL_TREE;
   tree atparms = INNERMOST_TEMPLATE_PARMS (fullatparms);
   unsigned natparms = TREE_VEC_LENGTH (atparms);
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C
new file mode 100644
index ..117212c67de7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C
@@ -0,0 +1,19 @@
+// PR c++/115296
+// { dg-do compile { target c++20 } }
+
+using size_t = decltype(sizeof(0));
+
+template
+struct span { span(T); };
+
+template
+span(T(&)[N]) -> span; // { dg-bogus "array exceeds maximum" }
+
+template
+requires (sizeof(T[N]) != 42) // { dg-bogus "array exceeds maximum" }
+span(T*) -> span;
+
+template
+using array_view = span;
+
+array_view x = 0;


[gcc r14-10543] c++: prev declared hidden tmpl friend inst [PR112288]

2024-08-01 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:1287b4abc67a915ef6b63fb0753a0bea41de47f1

commit r14-10543-g1287b4abc67a915ef6b63fb0753a0bea41de47f1
Author: Patrick Palka 
Date:   Wed Jul 17 21:02:52 2024 -0400

c++: prev declared hidden tmpl friend inst [PR112288]

When partially instantiating a previously declared hidden template
friend definition (at class template scope) such as slot_allocated in
the first testcase below, tsubst_friend_function needs to go through
all existing specializations thereof and make them point to the new
definition.

But when the previous declaration was also at class template scope,
old_decl is not the most general template, instead it's the partial
instantiation, and since instantiations are relative to the most general
template, old_decl's DECL_TEMPLATE_INSTANTIATIONS is empty.  So we
to consistently use the most general template here.  And when adjusting
DECL_TI_ARGS to match, only the innermost template arguments should be
preserved; the outer ones should correspond to the new definition.

Otherwise we fail a checking-only sanity check in instantiate_decl in
the first testcase, and in the second/third we end up emitting multiple
definitions of the template friend instantiation, resulting in a link
failure.

PR c++/112288

gcc/cp/ChangeLog:

* pt.cc (tsubst_friend_function): When adjusting existing
specializations after defining a previously declared template
friend, consider the most general template and correct
DECL_TI_ARGS adjustment.

gcc/testsuite/ChangeLog:

* g++.dg/template/friend80.C: New test.
* g++.dg/template/friend81.C: New test.
* g++.dg/template/friend81a.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 30dd420a06ad7d2adf4a672d176caee632f8168a)

Diff:
---
 gcc/cp/pt.cc  | 13 +++--
 gcc/testsuite/g++.dg/template/friend80.C  | 25 +
 gcc/testsuite/g++.dg/template/friend81.C  | 28 
 gcc/testsuite/g++.dg/template/friend81a.C | 30 ++
 4 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 80d0ca6d0dde..713946a1ff17 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11582,6 +11582,7 @@ tsubst_friend_function (tree decl, tree args)
;
  else
{
+ tree old_template = most_general_template (old_decl);
  tree new_template = TI_TEMPLATE (new_friend_template_info);
  tree new_args = TI_ARGS (new_friend_template_info);
 
@@ -11619,7 +11620,7 @@ tsubst_friend_function (tree decl, tree args)
  /* Reassign any specializations already in the hash table
 to the new more general template, and add the
 additional template args.  */
- for (t = DECL_TEMPLATE_INSTANTIATIONS (old_decl);
+ for (t = DECL_TEMPLATE_INSTANTIATIONS (old_template);
   t != NULL_TREE;
   t = TREE_CHAIN (t))
{
@@ -11632,15 +11633,15 @@ tsubst_friend_function (tree decl, tree args)
 
  decl_specializations->remove_elt (&elt);
 
- DECL_TI_ARGS (spec)
-   = add_outermost_template_args (new_args,
-  DECL_TI_ARGS (spec));
+ tree& spec_args = DECL_TI_ARGS (spec);
+ spec_args = add_outermost_template_args
+   (new_args, INNERMOST_TEMPLATE_ARGS (spec_args));
 
  register_specialization
-   (spec, new_template, DECL_TI_ARGS (spec), true, 0);
+   (spec, new_template, spec_args, true, 0);
 
}
- DECL_TEMPLATE_INSTANTIATIONS (old_decl) = NULL_TREE;
+ DECL_TEMPLATE_INSTANTIATIONS (old_template) = NULL_TREE;
}
}
 
diff --git a/gcc/testsuite/g++.dg/template/friend80.C 
b/gcc/testsuite/g++.dg/template/friend80.C
new file mode 100644
index ..5c417e12dd0c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend80.C
@@ -0,0 +1,25 @@
+// PR c++/112288
+// { dg-do compile { target c++11 } }
+
+template
+struct slot {
+  template
+  friend constexpr bool slot_allocated(slot, U);
+};
+
+template
+struct allocate_slot {
+  template
+  friend constexpr bool slot_allocated(slot, U) { return true; }
+};
+
+template{}, 42)>
+constexpr int next(int) { return 1; }
+
+template
+constexpr int next(...) { return (allocate_slot{}, 0); }
+
+// slot_allocated, int>() not defined yet
+static_assert(next(0) == 0, "");
+// now it's defined, need to make existing spec point to defn or else ICE
+static_assert(next(0) == 1, "");
diff --git a/gcc/testsuite/g++.dg

[gcc r15-2387] c++: generic lambda in default template argument [PR88313]

2024-07-29 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:72a7ab891ae0061841c4eb641ef6ab7719bf0369

commit r15-2387-g72a7ab891ae0061841c4eb641ef6ab7719bf0369
Author: Patrick Palka 
Date:   Mon Jul 29 16:37:19 2024 -0400

c++: generic lambda in default template argument [PR88313]

Here we're rejecting the generic lambda inside the default template
argument ultimately because auto_is_implicit_function_template_parm_p
doesn't get set during parsing of the lambda's parameter list, due
to the !processing_template_parmlist restriction.  But when parsing a
lambda parameter list we should always set that flag regardless of where
the lambda appears.  This patch makes sure of this via a local lambda_p
flag.

PR c++/88313

gcc/cp/ChangeLog:

* parser.cc (cp_parser_lambda_declarator_opt): Pass
lambda_p=true to cp_parser_parameter_declaration_clause.
(cp_parser_direct_declarator): Pass lambda_p=false to
to cp_parser_parameter_declaration_clause.
(cp_parser_parameter_declaration_clause): Add bool lambda_p
parameter.  Consider lambda_p instead of current_class_type
when setting parser->auto_is_implicit_function_template_parm_p.
Don't consider processing_template_parmlist.
(cp_parser_requirement_parameter_list): Pass lambda_p=false
to cp_parser_parameter_declaration_clause.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-targ6.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/parser.cc  | 34 ++-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C | 15 ++
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f79736c17ac6..e46cdfd20e19 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2600,7 +2600,7 @@ static tree cp_parser_type_id_1
 static void cp_parser_type_specifier_seq
   (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
-  (cp_parser *, cp_parser_flags);
+  (cp_parser *, cp_parser_flags, bool);
 static tree cp_parser_parameter_declaration_list
   (cp_parser *, cp_parser_flags, auto_vec *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
@@ -11889,7 +11889,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
   /* Parse parameters.  */
   param_list
= cp_parser_parameter_declaration_clause
-   (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL);
+   (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, /*lambda_p=*/true);
 
   /* Default arguments shall not be specified in the
 parameter-declaration-clause of a lambda-declarator.  */
@@ -24097,7 +24097,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 
  /* Parse the parameter-declaration-clause.  */
  params
-   = cp_parser_parameter_declaration_clause (parser, flags);
+   = cp_parser_parameter_declaration_clause (parser, flags,
+ /*lambda_p=*/false);
  const location_t parens_end
= cp_lexer_peek_token (parser->lexer)->location;
 
@@ -25444,13 +25445,17 @@ function_being_declared_is_template_p (cp_parser* 
parser)
 
The parser flags FLAGS is used to control type-specifier parsing.
 
+   LAMBDA_P is true if this is the parameter-declaration-clause of
+   a lambda-declarator.
+
Returns a representation for the parameter declarations.  A return
value of NULL indicates a parameter-declaration-clause consisting
only of an ellipsis.  */
 
 static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser,
-   cp_parser_flags flags)
+   cp_parser_flags flags,
+   bool lambda_p)
 {
   tree parameters;
   cp_token *token;
@@ -25459,15 +25464,15 @@ cp_parser_parameter_declaration_clause (cp_parser* 
parser,
   auto cleanup = make_temp_override
 (parser->auto_is_implicit_function_template_parm_p);
 
-  if (!processing_specialization
-  && !processing_template_parmlist
-  && !processing_explicit_instantiation
-  /* default_arg_ok_p tracks whether this is a parameter-clause for an
- actual function or a random abstract declarator.  */
-  && parser->default_arg_ok_p)
-if (!current_function_decl
-   || (current_class_type && LAMBDA_TYPE_P (current_class_type)))
-  parser->auto_is_implicit_function_template_parm_p = true;
+  if (lambda_p
+  || (!processing_specialization
+ && !processing_template_parmlist
+ && !processing_explicit_instantiation
+ /* default_arg_ok_p tracks whether this is a parameter-clause for an
+actual function or a random abstract declarator.  */
+ && parser->default_arg_ok_p
+  

[gcc r15-2331] c++: non-template alias with dependent attributes [PR115897]

2024-07-25 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:523836716137d0f7f4088c85752a980f5f971b36

commit r15-2331-g523836716137d0f7f4088c85752a980f5f971b36
Author: Patrick Palka 
Date:   Thu Jul 25 19:05:19 2024 -0400

c++: non-template alias with dependent attributes [PR115897]

This patch generalizes our support for dependent attributes on alias
templates to also support them on non-template aliases.  The main
addition is a new predicate dependent_opaque_alias_p controlling whether
we can treat an alias (template or non-template) as type-equivalent to
its expansion.

PR c++/115897

gcc/cp/ChangeLog:

* cp-tree.h (dependent_opaque_alias_p): Declare.
* pt.cc (push_template_decl): Manually mark a dependent opaque
alias or dependent alias template specialization as dependent,
and use structural equality for them.
(dependent_opaque_alias_p): Define.
(alias_template_specialization_p): Don't look through an
opaque alias.
(complex_alias_template_p): Use dependent_opaque_alias_p instead of
any_dependent_template_arguments_p directly.
(dependent_alias_template_spec_p): Don't look through an
opaque alias.
(get_underlying_template): Use dependent_opaque_alias_p instead of
any_dependent_template_arguments_p.
(instantiate_alias_template): Mention same logic in
push_template_decl.
(dependent_type_p_r): Remove dependent_alias_template_spec_p check.
(any_template_arguments_need_structural_equality_p): Return true
for a dependent opaque alias.
(alias_ctad_tweaks): Use template_args_equal instead of same_type_p
followed by dependent_alias_template_spec_p.
* tree.cc (strip_typedefs): Don't strip an opaque alias.
* typeck.cc (structural_comptypes): Compare declaration attributes
for an opaque alias.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alias-decl-79.C: Remove xfails.
* g++.dg/cpp0x/alias-decl-79a.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-tree.h|  1 +
 gcc/cp/pt.cc| 55 -
 gcc/cp/tree.cc  |  7 ++--
 gcc/cp/typeck.cc| 17 ++---
 gcc/testsuite/g++.dg/cpp0x/alias-decl-79.C  | 16 -
 gcc/testsuite/g++.dg/cpp0x/alias-decl-79a.C | 41 +
 6 files changed, 106 insertions(+), 31 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7d50aac4b6b8..238d786b0674 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7621,6 +7621,7 @@ extern bool alias_type_or_template_p(tree);
 enum { nt_opaque = false, nt_transparent = true };
 extern tree alias_template_specialization_p (const_tree, bool);
 extern tree dependent_alias_template_spec_p (const_tree, bool);
+extern bool dependent_opaque_alias_p(const_tree);
 extern tree get_template_parm_object   (tree expr, tree mangle);
 extern tree tparm_object_argument  (tree);
 extern bool explicit_class_specialization_p (tree);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e102e3ea490f..39f7e8a4e688 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6271,6 +6271,18 @@ push_template_decl (tree decl, bool is_friend)
}
 }
 
+  if (is_typedef_decl (decl)
+  && (dependent_opaque_alias_p (TREE_TYPE (decl))
+ || dependent_alias_template_spec_p (TREE_TYPE (decl), nt_opaque)))
+{
+  /* Manually mark such aliases as dependent so that dependent_type_p_r
+doesn't have to handle them.  */
+  TYPE_DEPENDENT_P_VALID (TREE_TYPE (decl)) = true;
+  TYPE_DEPENDENT_P (TREE_TYPE (decl)) = true;
+  /* The identity of such aliases is hairy; see structural_comptypes.  */
+  SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (decl));
+}
+
   if (flag_implicit_templates
   && !is_friend
   && TREE_PUBLIC (decl)
@@ -6530,7 +6542,7 @@ alias_template_specialization_p (const_tree t,
   if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)))
  return CONST_CAST_TREE (t);
-  if (transparent_typedefs)
+  if (transparent_typedefs && !dependent_opaque_alias_p (t))
return alias_template_specialization_p (DECL_ORIGINAL_TYPE
(TYPE_NAME (t)),
transparent_typedefs);
@@ -6635,8 +6647,7 @@ complex_alias_template_p (const_tree tmpl, tree *seen_out)
 return true;
 
   /* An alias with dependent type attributes is complex.  */
-  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
-  (DECL_TEMPLATE_RESULT (tmpl
+  if (dependent_opaque_alias_p (TREE_TYPE (tmpl)))
 return true

[gcc r15-2330] c++: alias of alias tmpl with dependent attrs [PR115897]

2024-07-25 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:9bcad238837e2100978cd839c343c488f72e1d4a

commit r15-2330-g9bcad238837e2100978cd839c343c488f72e1d4a
Author: Patrick Palka 
Date:   Thu Jul 25 19:00:23 2024 -0400

c++: alias of alias tmpl with dependent attrs [PR115897]

As a follow-up to r15-2047-g7954bb4fcb6fa8, we also need to consider
dependent attributes when recursing into a non-template alias that names
a dependent alias template specialization (and so STF_STRIP_DEPENDENT
is set), otherwise in the first testcase below we undesirably strip B
all the way to T instead of to A.

We also need to move the typedef recursion case of strip_typedefs up to
get checked before the compound type recursion cases.  Otherwise for C
below (which ultimately aliases T*) we end up stripping it to T* instead
of to A because the POINTER_TYPE recursion dominates the typedef
recursion.  It also means we issue an unexpected extra error in the
third testcase below.

Ideally we would also want to consider dependent attributes on
non-template aliases, so that we accept the second testcase below, but
making that work correctly would require broader changes to e.g.
structural_comptypes.

PR c++/115897

gcc/cp/ChangeLog:

* tree.cc (strip_typedefs): Move up the typedef recursion case.
Never strip a dependent alias template-id that has dependent
attributes.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alias-decl-78.C: New test.
* g++.dg/cpp0x/alias-decl-79.C: New test.
* g++.dg/cpp0x/alias-decl-pr92206-1a.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/tree.cc | 51 --
 gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C | 34 +++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-79.C | 37 
 gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-1a.C | 10 +
 4 files changed, 110 insertions(+), 22 deletions(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 250239e4e3ae..f2001ace6db0 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -1607,11 +1607,32 @@ strip_typedefs (tree t, bool *remove_attributes /* = 
NULL */,
   if (t == TYPE_CANONICAL (t))
 return t;
 
-  if (!(flags & STF_STRIP_DEPENDENT)
-  && dependent_alias_template_spec_p (t, nt_opaque))
-/* DR 1558: However, if the template-id is dependent, subsequent
-   template argument substitution still applies to the template-id.  */
-return t;
+  if (typedef_variant_p (t))
+{
+  if ((flags & STF_USER_VISIBLE)
+ && !user_facing_original_type_p (t))
+   return t;
+
+  if (alias_template_specialization_p (t, nt_opaque))
+   {
+ if (dependent_alias_template_spec_p (t, nt_opaque)
+ && (!(flags & STF_STRIP_DEPENDENT)
+ || any_dependent_type_attributes_p (DECL_ATTRIBUTES
+ (TYPE_NAME (t)
+   /* DR 1558: However, if the template-id is dependent, subsequent
+  template argument substitution still applies to the template-id. 
 */
+   return t;
+   }
+  else
+   /* If T is a non-template alias or typedef, we can assume that
+  instantiating its definition will hit any substitution failure,
+  so we don't need to retain it here as well.  */
+   flags |= STF_STRIP_DEPENDENT;
+
+  result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
+  remove_attributes, flags);
+  goto stripped;
+}
 
   switch (TREE_CODE (t))
 {
@@ -1805,23 +1826,9 @@ strip_typedefs (tree t, bool *remove_attributes /* = 
NULL */,
 }
 
   if (!result)
-{
-  if (typedef_variant_p (t))
-   {
- if ((flags & STF_USER_VISIBLE)
- && !user_facing_original_type_p (t))
-   return t;
- /* If T is a non-template alias or typedef, we can assume that
-instantiating its definition will hit any substitution failure,
-so we don't need to retain it here as well.  */
- if (!alias_template_specialization_p (t, nt_opaque))
-   flags |= STF_STRIP_DEPENDENT;
- result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
-  remove_attributes, flags);
-   }
-  else
-   result = TYPE_MAIN_VARIANT (t);
-}
+result = TYPE_MAIN_VARIANT (t);
+
+stripped:
   /*gcc_assert (!typedef_variant_p (result)
  || dependent_alias_template_spec_p (result, nt_opaque)
  || ((flags & STF_USER_VISIBLE)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C
new file mode 100644
index ..a52c0622e46d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-78.C
@@ -0,0 +1,34 @@
+// PR c++/115897
+// { dg-do compile { target c++11 } }
+
+template

[gcc r15-2230] c++: normalizing ttp constraints [PR115656]

2024-07-23 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:2861eb34e30973cb991a7964af7cfeae014a98b0

commit r15-2230-g2861eb34e30973cb991a7964af7cfeae014a98b0
Author: Patrick Palka 
Date:   Tue Jul 23 13:16:14 2024 -0400

c++: normalizing ttp constraints [PR115656]

Here we normalize the constraint same_as for the first
time during ttp coercion of B / UU, specifically constraint subsumption
checking.  During this normalization the set of in-scope template
parameters i.e. current_template_parms is empty, which we rely on
during normalization of the ttp constraints since we pass in_decl=NULL_TREE
to norm_info.  And this tricks the satisfaction cache into thinking that
the satisfaction value of same_as is independent of its template
parameters, and we incorrectly conflate the satisfaction value with
T = bool vs T = long and accept the specialization A.

Since is_compatible_template_arg rewrites the ttp's constraints to
be in terms of the argument template's parameters, and since it's
the only caller of weakly_subsumes, the latter funcion can instead
pass in_decl=tmpl to avoid relying on current_template_parms.  This
patch implements this, and in turns renames weakly_subsumes to
ttp_subsumes to reflect that this predicate is now hardcoded for this
one caller.

PR c++/115656

gcc/cp/ChangeLog:

* constraint.cc (weakly_subsumes): Pass in_decl=tmpl to
get_normalized_constraints_from_info.  Rename to ...
(ttp_subsumes): ... this.
* cp-tree.h (weakly_subsumes): Rename to ...
(ttp_subsumes): ... this.
* pt.cc (is_compatible_template_arg): Adjust after renaming.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-ttp7.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constraint.cc   |  9 +
 gcc/cp/cp-tree.h   |  2 +-
 gcc/cp/pt.cc   |  2 +-
 gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C | 12 
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index afd5435cc3ed..7fce78f508e9 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3328,13 +3328,14 @@ strictly_subsumes (tree ci, tree tmpl)
   return subsumes (n1, n2) && !subsumes (n2, n1);
 }
 
-/* Returns true when the constraints in CI subsume the
-   associated constraints of TMPL.  */
+/* Returns true when the template template parameter constraints in CI
+   subsume the associated constraints of the template template argument
+   TMPL.  */
 
 bool
-weakly_subsumes (tree ci, tree tmpl)
+ttp_subsumes (tree ci, tree tmpl)
 {
-  tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE);
+  tree n1 = get_normalized_constraints_from_info (ci, tmpl);
   tree n2 = get_normalized_constraints_from_decl (tmpl);
 
   return subsumes (n1, n2);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 76ac9c31763c..856699de82f2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8609,7 +8609,7 @@ extern tree find_template_parameters  (tree, 
tree);
 extern bool equivalent_constraints  (tree, tree);
 extern bool equivalently_constrained(tree, tree);
 extern bool strictly_subsumes  (tree, tree);
-extern bool weakly_subsumes(tree, tree);
+extern bool ttp_subsumes   (tree, tree);
 extern int more_constrained (tree, tree);
 extern bool at_least_as_constrained (tree, tree);
 extern bool constraints_equivalent_p(tree, tree);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8cc5e21c520d..393913294b50 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8482,7 +8482,7 @@ is_compatible_template_arg (tree parm, tree arg, tree 
args)
 return false;
 }
 
-  return weakly_subsumes (parm_cons, arg);
+  return ttp_subsumes (parm_cons, arg);
 }
 
 // Convert a placeholder argument into a binding to the original
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C
new file mode 100644
index ..2ce884b995c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp7.C
@@ -0,0 +1,12 @@
+// PR c++/115656
+// { dg-do compile { target c++20 } }
+
+template concept same_as = __is_same(T, U);
+
+template T, template> class UU>
+struct A { };
+
+template> class B;
+
+A a1;
+A a2; // { dg-error "constraint failure" }


[gcc r15-2229] c++: missing SFINAE during alias CTAD [PR115296]

2024-07-23 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:f70281222df432a7bec1271904c5ebefd7f2c934

commit r15-2229-gf70281222df432a7bec1271904c5ebefd7f2c934
Author: Patrick Palka 
Date:   Tue Jul 23 11:37:31 2024 -0400

c++: missing SFINAE during alias CTAD [PR115296]

During the alias CTAD transformation, if substitution failed for some
guide we should just silently discard the guide.  We currently do
discard the guide, but not silently, as in the below testcase which
we diagnose forming a too-large array type when transforming the
user-defined deduction guides.

This patch fixes this by using complain=tf_none instead of
tf_warning_or_error throughout alias_ctad_tweaks.

PR c++/115296

gcc/cp/ChangeLog:

* pt.cc (alias_ctad_tweaks): Use complain=tf_none instead of
tf_warning_or_error.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias23.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc |  2 +-
 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C | 19 +++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 108e929b8ee6..8cc5e21c520d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30287,7 +30287,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  (INNERMOST_TEMPLATE_PARMS (fullatparms)));
 }
 
-  tsubst_flags_t complain = tf_warning_or_error;
+  tsubst_flags_t complain = tf_none;
   tree aguides = NULL_TREE;
   tree atparms = INNERMOST_TEMPLATE_PARMS (fullatparms);
   unsigned natparms = TREE_VEC_LENGTH (atparms);
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C
new file mode 100644
index ..117212c67de7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias23.C
@@ -0,0 +1,19 @@
+// PR c++/115296
+// { dg-do compile { target c++20 } }
+
+using size_t = decltype(sizeof(0));
+
+template
+struct span { span(T); };
+
+template
+span(T(&)[N]) -> span; // { dg-bogus "array exceeds maximum" }
+
+template
+requires (sizeof(T[N]) != 42) // { dg-bogus "array exceeds maximum" }
+span(T*) -> span;
+
+template
+using array_view = span;
+
+array_view x = 0;


[gcc r14-10498] c++/coroutines: correct passing *this to promise type [PR104981]

2024-07-22 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:066c7893eae0bfc7d9b33b931f115f455246c914

commit r14-10498-g066c7893eae0bfc7d9b33b931f115f455246c914
Author: Patrick Palka 
Date:   Mon Jul 22 21:30:49 2024 -0400

c++/coroutines: correct passing *this to promise type [PR104981]

When passing *this to the promise type ctor (or to its operator new)
(as per [dcl.fct.def.coroutine]/4), we add an explicit cast to lvalue
reference.  But this is unnecessary since *this is already always an
lvalue.  And doing so means we need to call convert_from_reference
afterward to lower the reference expression to an implicit dereference,
which we're currently neglecting to do and which causes overload
resolution to get confused when computing argument conversions.

So this patch removes this unneeded reference cast when passing *this
to the promise ctor, and removes both the cast and implicit deref when
passing *this to operator new, for consistency.  While we're here, use
cp_build_fold_indirect_ref instead of directly building INDIRECT_REF.

PR c++/104981
PR c++/115550

gcc/cp/ChangeLog:

* coroutines.cc (morph_fn_to_coro): Remove unneeded calls
to convert_to_reference and convert_from_reference when
passing *this.  Use cp_build_fold_indirect_ref instead
of directly building INDIRECT_REF.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/pr104981-preview-this.C: New test.
* g++.dg/coroutines/pr115550-preview-this.C: New test.

Reviewed-by: Iain Sandoe 
Reviewed-by: Jason Merrill 
(cherry picked from commit 7c5a9bf1d206fe20cb050200d4a30f11c76b1b19)

Diff:
---
 gcc/cp/coroutines.cc   | 18 ++---
 .../g++.dg/coroutines/pr104981-preview-this.C  | 34 
 .../g++.dg/coroutines/pr115550-preview-this.C  | 47 ++
 3 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index b05cb9eb3302..71e64960c5a8 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4618,13 +4618,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm_i->this_ptr || parm_i->lambda_cobj)
{
  /* We pass a reference to *this to the allocator lookup.  */
- tree tt = TREE_TYPE (TREE_TYPE (arg));
- tree this_ref = build1 (INDIRECT_REF, tt, arg);
- tt = cp_build_reference_type (tt, false);
- this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
-  LOOKUP_NORMAL , NULL_TREE,
-  tf_warning_or_error);
- vec_safe_push (args, convert_from_reference (this_ref));
+ tree this_ref = cp_build_fold_indirect_ref (arg);
+ vec_safe_push (args, this_ref);
}
  else
vec_safe_push (args, convert_from_reference (arg));
@@ -4843,14 +4838,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm.this_ptr || parm.lambda_cobj)
{
  /* We pass a reference to *this to the param preview.  */
- tree tt = TREE_TYPE (arg);
- gcc_checking_assert (POINTER_TYPE_P (tt));
- tree ct = TREE_TYPE (tt);
- tree this_ref = build1 (INDIRECT_REF, ct, arg);
- tree rt = cp_build_reference_type (ct, false);
- this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
-  LOOKUP_NORMAL, NULL_TREE,
-  tf_warning_or_error);
+ tree this_ref = cp_build_fold_indirect_ref (arg);
  vec_safe_push (promise_args, this_ref);
}
  else if (parm.rv_ref)
diff --git a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
new file mode 100644
index ..81eb963db4a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
@@ -0,0 +1,34 @@
+// PR c++/104981 - ICE from convert_to_base when passing *this to promise ctor
+
+#include 
+
+class Base {};
+
+struct PromiseType;
+
+struct Result {
+ using promise_type = PromiseType;
+};
+
+struct PromiseType {
+  PromiseType(const Base& parser, auto&&...) {}
+
+  Result get_return_object() { return {}; }
+
+  static std::suspend_never initial_suspend() { return {}; }
+  static std::suspend_always final_suspend() noexcept { return {}; }
+  [[noreturn]] static void unhandled_exception() { throw; }
+
+  void return_value(int) {}
+};
+
+struct Derived : Base {
+  Result f() {
+   co_return 42;
+  }
+};
+
+int main() {
+  Derived d;
+  d.f();
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C
new file mode 100644
index 

[gcc r14-10497] c++: xobj fn call without obj [PR115783]

2024-07-22 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:50ff112d17ec53ccff2858f6ded9dc04b1d5d2bc

commit r14-10497-g50ff112d17ec53ccff2858f6ded9dc04b1d5d2bc
Author: Patrick Palka 
Date:   Fri Jul 19 13:48:12 2024 -0400

c++: xobj fn call without obj [PR115783]

The code path for rejecting an object-less call to a non-static member
function should also consider xobj member functions (so that we correctly
reject the below calls with a "cannot call member function without object"
diagnostic).

PR c++/115783

gcc/cp/ChangeLog:

* call.cc (build_new_method_call): Generalize METHOD_TYPE
check to DECL_OBJECT_MEMBER_FUNCTION_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/explicit-obj-diagnostics11.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 2ee70c9f83a1033f2897a35bff9e9ffdd03cc651)

Diff:
---
 gcc/cp/call.cc |  2 +-
 .../g++.dg/cpp23/explicit-obj-diagnostics11.C  | 48 ++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 844a7e2b35d7..793b98347124 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -11820,7 +11820,7 @@ build_new_method_call (tree instance, tree fns, 
vec **args,
 fn);
}
 
- if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+ if (DECL_OBJECT_MEMBER_FUNCTION_P (fn)
  && !DECL_CONSTRUCTOR_P (fn)
  && is_dummy_object (instance))
{
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics11.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics11.C
new file mode 100644
index ..cc2571f62a2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics11.C
@@ -0,0 +1,48 @@
+// PR c++/115783
+// { dg-do compile { target c++23 } }
+
+struct A {
+  int f(this auto);
+
+  static void s() {
+f(); // { dg-error "without object" }
+  }
+};
+
+int n = A::f(); // { dg-error "without object" }
+
+struct B {
+  void ns() {
+A::f(); // { dg-error "without object" }
+  }
+
+  static void s() {
+A::f(); // { dg-error "without object" }
+  }
+};
+
+template
+struct C {
+  void ns() {
+A::f(); // { dg-error "without object" }
+T::f(); // { dg-error "without object" }
+  }
+
+  static void s() {
+A::f(); // { dg-error "without object" }
+T::f(); // { dg-error "without object" }
+  };
+};
+
+template struct C;
+
+template
+struct D : T {
+  void ns() {
+A::f(); // { dg-error "without object" }
+T::f(); // { dg-error "not a member of 'B'" }
+  }
+};
+
+template struct D; // { dg-message "required from here" }
+template struct D; // { dg-bogus "required from here" }


[gcc r15-2210] c++/coroutines: correct passing *this to promise type [PR104981]

2024-07-22 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:7c5a9bf1d206fe20cb050200d4a30f11c76b1b19

commit r15-2210-g7c5a9bf1d206fe20cb050200d4a30f11c76b1b19
Author: Patrick Palka 
Date:   Mon Jul 22 21:30:49 2024 -0400

c++/coroutines: correct passing *this to promise type [PR104981]

When passing *this to the promise type ctor (or to its operator new)
(as per [dcl.fct.def.coroutine]/4), we add an explicit cast to lvalue
reference.  But this is unnecessary since *this is already always an
lvalue.  And doing so means we need to call convert_from_reference
afterward to lower the reference expression to an implicit dereference,
which we're currently neglecting to do and which causes overload
resolution to get confused when computing argument conversions.

So this patch removes this unneeded reference cast when passing *this
to the promise ctor, and removes both the cast and implicit deref when
passing *this to operator new, for consistency.  While we're here, use
cp_build_fold_indirect_ref instead of directly building INDIRECT_REF.

PR c++/104981
PR c++/115550

gcc/cp/ChangeLog:

* coroutines.cc (morph_fn_to_coro): Remove unneeded calls
to convert_to_reference and convert_from_reference when
passing *this.  Use cp_build_fold_indirect_ref instead
of directly building INDIRECT_REF.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/pr104981-preview-this.C: New test.
* g++.dg/coroutines/pr115550-preview-this.C: New test.

Reviewed-by: Iain Sandoe 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/coroutines.cc   | 18 ++---
 .../g++.dg/coroutines/pr104981-preview-this.C  | 34 
 .../g++.dg/coroutines/pr115550-preview-this.C  | 47 ++
 3 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index f350fc33e9b4..e8f028df3adb 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4620,13 +4620,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm_i->this_ptr || parm_i->lambda_cobj)
{
  /* We pass a reference to *this to the allocator lookup.  */
- tree tt = TREE_TYPE (TREE_TYPE (arg));
- tree this_ref = build1 (INDIRECT_REF, tt, arg);
- tt = cp_build_reference_type (tt, false);
- this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
-  LOOKUP_NORMAL , NULL_TREE,
-  tf_warning_or_error);
- vec_safe_push (args, convert_from_reference (this_ref));
+ tree this_ref = cp_build_fold_indirect_ref (arg);
+ vec_safe_push (args, this_ref);
}
  else
vec_safe_push (args, convert_from_reference (arg));
@@ -4845,14 +4840,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
  if (parm.this_ptr || parm.lambda_cobj)
{
  /* We pass a reference to *this to the param preview.  */
- tree tt = TREE_TYPE (arg);
- gcc_checking_assert (POINTER_TYPE_P (tt));
- tree ct = TREE_TYPE (tt);
- tree this_ref = build1 (INDIRECT_REF, ct, arg);
- tree rt = cp_build_reference_type (ct, false);
- this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
-  LOOKUP_NORMAL, NULL_TREE,
-  tf_warning_or_error);
+ tree this_ref = cp_build_fold_indirect_ref (arg);
  vec_safe_push (promise_args, this_ref);
}
  else if (parm.rv_ref)
diff --git a/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
new file mode 100644
index ..81eb963db4a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr104981-preview-this.C
@@ -0,0 +1,34 @@
+// PR c++/104981 - ICE from convert_to_base when passing *this to promise ctor
+
+#include 
+
+class Base {};
+
+struct PromiseType;
+
+struct Result {
+ using promise_type = PromiseType;
+};
+
+struct PromiseType {
+  PromiseType(const Base& parser, auto&&...) {}
+
+  Result get_return_object() { return {}; }
+
+  static std::suspend_never initial_suspend() { return {}; }
+  static std::suspend_always final_suspend() noexcept { return {}; }
+  [[noreturn]] static void unhandled_exception() { throw; }
+
+  void return_value(int) {}
+};
+
+struct Derived : Base {
+  Result f() {
+   co_return 42;
+  }
+};
+
+int main() {
+  Derived d;
+  d.f();
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C 
b/gcc/testsuite/g++.dg/coroutines/pr115550-preview-this.C
new file mode 100644
index ..f62c07096b61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines

[gcc r15-2159] c++: xobj fn call without obj [PR115783]

2024-07-19 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:2ee70c9f83a1033f2897a35bff9e9ffdd03cc651

commit r15-2159-g2ee70c9f83a1033f2897a35bff9e9ffdd03cc651
Author: Patrick Palka 
Date:   Fri Jul 19 13:48:12 2024 -0400

c++: xobj fn call without obj [PR115783]

The code path for rejecting an object-less call to a non-static member
function should also consider xobj member functions (so that we correctly
reject the below calls with a "cannot call member function without object"
diagnostic).

PR c++/115783

gcc/cp/ChangeLog:

* call.cc (build_new_method_call): Generalize METHOD_TYPE
check to DECL_OBJECT_MEMBER_FUNCTION_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/explicit-obj-diagnostics11.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc |  2 +-
 .../g++.dg/cpp23/explicit-obj-diagnostics11.C  | 48 ++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index a5d3426b70c4..40cb582acc70 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -11855,7 +11855,7 @@ build_new_method_call (tree instance, tree fns, 
vec **args,
 fn);
}
 
- if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+ if (DECL_OBJECT_MEMBER_FUNCTION_P (fn)
  && !DECL_CONSTRUCTOR_P (fn)
  && is_dummy_object (instance))
{
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics11.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics11.C
new file mode 100644
index ..cc2571f62a2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics11.C
@@ -0,0 +1,48 @@
+// PR c++/115783
+// { dg-do compile { target c++23 } }
+
+struct A {
+  int f(this auto);
+
+  static void s() {
+f(); // { dg-error "without object" }
+  }
+};
+
+int n = A::f(); // { dg-error "without object" }
+
+struct B {
+  void ns() {
+A::f(); // { dg-error "without object" }
+  }
+
+  static void s() {
+A::f(); // { dg-error "without object" }
+  }
+};
+
+template
+struct C {
+  void ns() {
+A::f(); // { dg-error "without object" }
+T::f(); // { dg-error "without object" }
+  }
+
+  static void s() {
+A::f(); // { dg-error "without object" }
+T::f(); // { dg-error "without object" }
+  };
+};
+
+template struct C;
+
+template
+struct D : T {
+  void ns() {
+A::f(); // { dg-error "without object" }
+T::f(); // { dg-error "not a member of 'B'" }
+  }
+};
+
+template struct D; // { dg-message "required from here" }
+template struct D; // { dg-bogus "required from here" }


[gcc r15-2154] c++: add fixed testcase [PR109464]

2024-07-19 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:58a9f3ded1a0ccc2c8b0a42f976950041734798e

commit r15-2154-g58a9f3ded1a0ccc2c8b0a42f976950041734798e
Author: Patrick Palka 
Date:   Fri Jul 19 11:08:09 2024 -0400

c++: add fixed testcase [PR109464]

Seems to be fixed by r15-521-g6ad7ca1bb90573.

PR c++/109464

gcc/testsuite/ChangeLog:

* g++.dg/template/explicit-instantiation8.C: New test.

Diff:
---
 .../g++.dg/template/explicit-instantiation8.C  | 24 ++
 1 file changed, 24 insertions(+)

diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation8.C 
b/gcc/testsuite/g++.dg/template/explicit-instantiation8.C
new file mode 100644
index ..92152a2992e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-instantiation8.C
@@ -0,0 +1,24 @@
+// PR c++/109464
+// { dg-do compile { target c++11 } }
+
+template
+struct shallow
+ {
+   int len;
+   constexpr shallow() : len(0) { }
+  };
+
+template
+struct use_shallow
+  {
+   static constexpr shallow s_zstr = { };
+   static_assert(s_zstr.len == 0, "");
+  };
+
+extern template struct shallow;
+extern template struct use_shallow;
+
+template struct shallow;
+template struct use_shallow;
+
+// { dg-final { scan-assembler "_ZN7shallowIcEC2Ev" } }


[gcc r15-2120] c++: prev declared hidden tmpl friend inst [PR112288]

2024-07-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:30dd420a06ad7d2adf4a672d176caee632f8168a

commit r15-2120-g30dd420a06ad7d2adf4a672d176caee632f8168a
Author: Patrick Palka 
Date:   Wed Jul 17 21:02:52 2024 -0400

c++: prev declared hidden tmpl friend inst [PR112288]

When partially instantiating a previously declared hidden template
friend definition (at class template scope) such as slot_allocated in
the first testcase below, tsubst_friend_function needs to go through
all existing specializations thereof and make them point to the new
definition.

But when the previous declaration was also at class template scope,
old_decl is not the most general template, instead it's the partial
instantiation, and since instantiations are relative to the most general
template, old_decl's DECL_TEMPLATE_INSTANTIATIONS is empty.  So we
to consistently use the most general template here.  And when adjusting
DECL_TI_ARGS to match, only the innermost template arguments should be
preserved; the outer ones should correspond to the new definition.

Otherwise we fail a checking-only sanity check in instantiate_decl in
the first testcase, and in the second/third we end up emitting multiple
definitions of the template friend instantiation, resulting in a link
failure.

PR c++/112288

gcc/cp/ChangeLog:

* pt.cc (tsubst_friend_function): When adjusting existing
specializations after defining a previously declared template
friend, consider the most general template and correct
DECL_TI_ARGS adjustment.

gcc/testsuite/ChangeLog:

* g++.dg/template/friend80.C: New test.
* g++.dg/template/friend81.C: New test.
* g++.dg/template/friend81a.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc  | 13 +++--
 gcc/testsuite/g++.dg/template/friend80.C  | 25 +
 gcc/testsuite/g++.dg/template/friend81.C  | 28 
 gcc/testsuite/g++.dg/template/friend81a.C | 30 ++
 4 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 0620c8c023a2..057797f213f5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11582,6 +11582,7 @@ tsubst_friend_function (tree decl, tree args)
;
  else
{
+ tree old_template = most_general_template (old_decl);
  tree new_template = TI_TEMPLATE (new_friend_template_info);
  tree new_args = TI_ARGS (new_friend_template_info);
 
@@ -11619,7 +11620,7 @@ tsubst_friend_function (tree decl, tree args)
  /* Reassign any specializations already in the hash table
 to the new more general template, and add the
 additional template args.  */
- for (t = DECL_TEMPLATE_INSTANTIATIONS (old_decl);
+ for (t = DECL_TEMPLATE_INSTANTIATIONS (old_template);
   t != NULL_TREE;
   t = TREE_CHAIN (t))
{
@@ -11632,15 +11633,15 @@ tsubst_friend_function (tree decl, tree args)
 
  decl_specializations->remove_elt (&elt);
 
- DECL_TI_ARGS (spec)
-   = add_outermost_template_args (new_args,
-  DECL_TI_ARGS (spec));
+ tree& spec_args = DECL_TI_ARGS (spec);
+ spec_args = add_outermost_template_args
+   (new_args, INNERMOST_TEMPLATE_ARGS (spec_args));
 
  register_specialization
-   (spec, new_template, DECL_TI_ARGS (spec), true, 0);
+   (spec, new_template, spec_args, true, 0);
 
}
- DECL_TEMPLATE_INSTANTIATIONS (old_decl) = NULL_TREE;
+ DECL_TEMPLATE_INSTANTIATIONS (old_template) = NULL_TREE;
}
}
 
diff --git a/gcc/testsuite/g++.dg/template/friend80.C 
b/gcc/testsuite/g++.dg/template/friend80.C
new file mode 100644
index ..5c417e12dd0c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend80.C
@@ -0,0 +1,25 @@
+// PR c++/112288
+// { dg-do compile { target c++11 } }
+
+template
+struct slot {
+  template
+  friend constexpr bool slot_allocated(slot, U);
+};
+
+template
+struct allocate_slot {
+  template
+  friend constexpr bool slot_allocated(slot, U) { return true; }
+};
+
+template{}, 42)>
+constexpr int next(int) { return 1; }
+
+template
+constexpr int next(...) { return (allocate_slot{}, 0); }
+
+// slot_allocated, int>() not defined yet
+static_assert(next(0) == 0, "");
+// now it's defined, need to make existing spec point to defn or else ICE
+static_assert(next(0) == 1, "");
diff --git a/gcc/testsuite/g++.dg/template/friend81.C 
b/gcc/testsuite/g++.dg/template/friend81.C
new file 

[gcc r15-2118] c++: missing -Wunused-value for ! [PR114104]

2024-07-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:144b6099cdaa9ac1b298687c0cfdb06a970e338b

commit r15-2118-g144b6099cdaa9ac1b298687c0cfdb06a970e338b
Author: Patrick Palka 
Date:   Wed Jul 17 20:57:54 2024 -0400

c++: missing -Wunused-value for ! [PR114104]

Here we're neglecting to issue a -Wunused-value warning for suitable !
operator expressions, and in turn for != operator expressions that are
rewritten as !(x == y), only because we don't call warn_if_unused_value
on TRUTH_NOT_EXPR since its class is tcc_expression.  This patch makes
us also consider warning for TRUTH_NOT_EXPR and also for ADDR_EXPR.

PR c++/114104

gcc/cp/ChangeLog:

* cvt.cc (convert_to_void): Call warn_if_unused_value for
TRUTH_NOT_EXPR and ADDR_EXPR as well.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wunused-20.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cvt.cc  |  2 ++
 gcc/testsuite/g++.dg/warn/Wunused-20.C | 19 +++
 2 files changed, 21 insertions(+)

diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index db086c017e89..d95e01c118c4 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1664,6 +1664,8 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
  if (tclass == tcc_comparison
  || tclass == tcc_unary
  || tclass == tcc_binary
+ || code == TRUTH_NOT_EXPR
+ || code == ADDR_EXPR
  || code == VEC_PERM_EXPR
  || code == VEC_COND_EXPR)
warn_if_unused_value (e, loc);
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-20.C 
b/gcc/testsuite/g++.dg/warn/Wunused-20.C
new file mode 100644
index ..31b1920adcdd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-20.C
@@ -0,0 +1,19 @@
+// PR c++/114104
+// { dg-additional-options "-Wunused-value" }
+
+bool f();
+struct A { int i; };
+A& g();
+
+void h() {
+  !f(); // { dg-warning "value computed is not used" }
+  &g().i; // { dg-warning "value computed is not used" }
+}
+
+#if  __cplusplus >= 202002L
+[[nodiscard]] bool operator==(A&, int);
+
+void h(A a) {
+  a != 0; // { dg-warning "value computed is not used" "" { target c++20 } }
+}
+#endif


[gcc r14-10450] c++: alias template with dependent attributes [PR115897]

2024-07-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:2249c6348835c817f43c9fc55eac66e54ac1efeb

commit r14-10450-g2249c6348835c817f43c9fc55eac66e54ac1efeb
Author: Patrick Palka 
Date:   Mon Jul 15 18:07:55 2024 -0400

c++: alias template with dependent attributes [PR115897]

Here we're prematurely stripping the dependent alias template-id A to
its defining-type-id T when used as a template argument, which in turn
causes us to essentially ignore A's vector_size attribute in the outer
template-id.

This has always been a problem for class template-ids it seems, and after
r14-2170 variable template-ids are affected as well.

This patch marks alias templates that have a dependent attribute as
complex (as with e.g. constrained alias templates) so that we don't look
through them prematurely.

PR c++/115897

gcc/cp/ChangeLog:

* pt.cc (complex_alias_template_p): Return true for an alias
template with attributes.
(get_underlying_template): Don't look through an alias template
with attributes.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alias-decl-77.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 7954bb4fcb6fa80f6bb840133314885011821188)

Diff:
---
 gcc/cp/pt.cc   | 10 ++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C | 32 ++
 2 files changed, 42 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 580c3fc2cb2b..83638fd74b4d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6655,6 +6655,11 @@ complex_alias_template_p (const_tree tmpl, tree 
*seen_out)
   if (get_constraints (tmpl))
 return true;
 
+  /* An alias with dependent type attributes is complex.  */
+  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+  (DECL_TEMPLATE_RESULT (tmpl
+return true;
+
   if (!complex_alias_tmpl_info)
 complex_alias_tmpl_info = hash_map::create_ggc (13);
 
@@ -6807,6 +6812,11 @@ get_underlying_template (tree tmpl)
   if (!at_least_as_constrained (underlying, tmpl))
break;
 
+  /* If TMPL adds dependent type attributes, it isn't equivalent.  */
+  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+  (DECL_TEMPLATE_RESULT (tmpl
+   break;
+
   /* Alias is equivalent.  Strip it and repeat.  */
   tmpl = underlying;
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
new file mode 100644
index ..f72e4cc26538
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
@@ -0,0 +1,32 @@
+// PR c++/115897
+// { dg-do compile { target c++11 } }
+
+template
+struct is_same { static constexpr bool value = __is_same(T, U); };
+
+#if __cpp_variable_templates
+template
+constexpr bool is_same_v = __is_same(T, U);
+#endif
+
+template
+using A [[gnu::vector_size(16)]] = T;
+
+template
+using B = T;
+
+template
+using C [[gnu::vector_size(16)]] = B;
+
+template
+void f() {
+  static_assert(!is_same>::value, "");
+  static_assert(is_same, A>::value, "");
+
+#if __cpp_variable_templates
+  static_assert(!is_same_v>, "");
+  static_assert(is_same_v, A>, "");
+#endif
+};
+
+template void f();


[gcc r14-10451] c++: constrained partial spec type context [PR111890]

2024-07-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:1bbfe788d1a76979e5be14169248bc34106e9c03

commit r14-10451-g1bbfe788d1a76979e5be14169248bc34106e9c03
Author: Patrick Palka 
Date:   Wed Jul 17 11:08:35 2024 -0400

c++: constrained partial spec type context [PR111890]

maybe_new_partial_specialization wasn't propagating TYPE_CONTEXT when
creating a new class type corresponding to a constrained partial spec,
which do_friend relies on via template_class_depth to distinguish a
template friend from a non-template friend, and so in the below testcase
we were incorrectly instantiating the non-template operator+ as if it
were a template leading to an ICE.

PR c++/111890

gcc/cp/ChangeLog:

* pt.cc (maybe_new_partial_specialization): Propagate TYPE_CONTEXT
to the newly created partial specialization.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-partial-spec15.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 247335823f420eb1dd56f4bf32ac78d441f5ccc2)

Diff:
---
 gcc/cp/pt.cc |  1 +
 gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C | 20 
 2 files changed, 21 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 83638fd74b4d..80d0ca6d0dde 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -994,6 +994,7 @@ maybe_new_partial_specialization (tree& type)
   tree t = make_class_type (TREE_CODE (type));
   CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type);
   SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args));
+  TYPE_CONTEXT (t) = TYPE_CONTEXT (type);
 
   /* We only need a separate type node for storing the definition of this
 partial specialization; uses of S are unconstrained, so all are
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
new file mode 100644
index ..ad01a390fefd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
@@ -0,0 +1,20 @@
+// PR c++/111890
+// { dg-do compile { target c++20 } }
+
+template
+struct A {
+  template
+  struct B { };
+
+  template requires T::value
+  struct B { };
+
+  template requires (sizeof(T) == sizeof(int))
+  struct B {
+friend void operator+(B&, int) { }
+  };
+};
+
+void f(A::B b) {
+  b + 0;
+}


[gcc r14-10449] c++: bad 'this' conversion for nullary memfn [PR106760]

2024-07-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:79c5a09f959dc63824bd005522a072424f16d89d

commit r14-10449-g79c5a09f959dc63824bd005522a072424f16d89d
Author: Patrick Palka 
Date:   Fri Jun 28 19:45:21 2024 -0400

c++: bad 'this' conversion for nullary memfn [PR106760]

Here we notice the 'this' conversion for the call f() is bad, so
we correctly defer deduction for the template candidate, but we end up
never adding it to 'bad_cands' since missing_conversion_p for it returns
false (its only argument is 'this' which has already been determined to
be bad).  This is not a huge deal, but it causes us to longer accept the
call with -fpermissive in release builds, and a tree check ICE in checking
builds.

So if we have a non-strictly viable template candidate that has not been
instantiated, then we need to add it to 'bad_cands' even if no argument
conversion is missing.

PR c++/106760

gcc/cp/ChangeLog:

* call.cc (add_candidates): Relax test for adding a candidate
to 'bad_cands' to also accept an uninstantiated template candidate
that has no missing conversions.

gcc/testsuite/ChangeLog:

* g++.dg/ext/conv3.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 50073ffae0a9b8feb9b36fdafdebd9885f6d7dc8)

Diff:
---
 gcc/cp/call.cc   |  3 ++-
 gcc/testsuite/g++.dg/ext/conv3.C | 13 +
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index f5584c92efb8..844a7e2b35d7 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -6742,7 +6742,8 @@ add_candidates (tree fns, tree first_arg, const vec *args,
 
   if (cand->viable == -1
  && shortcut_bad_convs
- && missing_conversion_p (cand))
+ && (missing_conversion_p (cand)
+ || TREE_CODE (cand->fn) == TEMPLATE_DECL))
{
  /* This candidate has been tentatively marked non-strictly viable,
 and we didn't compute all argument conversions for it (having
diff --git a/gcc/testsuite/g++.dg/ext/conv3.C b/gcc/testsuite/g++.dg/ext/conv3.C
new file mode 100644
index ..7324d5600561
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/conv3.C
@@ -0,0 +1,13 @@
+// PR c++/106760
+// { dg-additional-options "-fpermissive" }
+
+struct S {
+  template int f();
+  template int g(...);
+};
+
+int main() {
+  const S s;
+  s.f(); // { dg-warning "discards qualifiers" }
+  s.g(); // { dg-warning "discards qualifiers" }
+}


[gcc r15-2098] c++: constrained partial spec type context [PR111890]

2024-07-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:247335823f420eb1dd56f4bf32ac78d441f5ccc2

commit r15-2098-g247335823f420eb1dd56f4bf32ac78d441f5ccc2
Author: Patrick Palka 
Date:   Wed Jul 17 11:08:35 2024 -0400

c++: constrained partial spec type context [PR111890]

maybe_new_partial_specialization wasn't propagating TYPE_CONTEXT when
creating a new class type corresponding to a constrained partial spec,
which do_friend relies on via template_class_depth to distinguish a
template friend from a non-template friend, and so in the below testcase
we were incorrectly instantiating the non-template operator+ as if it
were a template leading to an ICE.

PR c++/111890

gcc/cp/ChangeLog:

* pt.cc (maybe_new_partial_specialization): Propagate TYPE_CONTEXT
to the newly created partial specialization.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-partial-spec15.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc |  1 +
 gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C | 20 
 2 files changed, 21 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 4d72ff60cb8e..0620c8c023a2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -992,6 +992,7 @@ maybe_new_partial_specialization (tree& type)
   tree t = make_class_type (TREE_CODE (type));
   CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type);
   SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args));
+  TYPE_CONTEXT (t) = TYPE_CONTEXT (type);
 
   /* We only need a separate type node for storing the definition of this
 partial specialization; uses of S are unconstrained, so all are
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
new file mode 100644
index ..ad01a390fefd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec15.C
@@ -0,0 +1,20 @@
+// PR c++/111890
+// { dg-do compile { target c++20 } }
+
+template
+struct A {
+  template
+  struct B { };
+
+  template requires T::value
+  struct B { };
+
+  template requires (sizeof(T) == sizeof(int))
+  struct B {
+friend void operator+(B&, int) { }
+  };
+};
+
+void f(A::B b) {
+  b + 0;
+}


[gcc r15-2047] c++: alias template with dependent attributes [PR115897]

2024-07-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:7954bb4fcb6fa80f6bb840133314885011821188

commit r15-2047-g7954bb4fcb6fa80f6bb840133314885011821188
Author: Patrick Palka 
Date:   Mon Jul 15 18:07:55 2024 -0400

c++: alias template with dependent attributes [PR115897]

Here we're prematurely stripping the dependent alias template-id A to
its defining-type-id T when used as a template argument, which in turn
causes us to essentially ignore A's vector_size attribute in the outer
template-id.

This has always been a problem for class template-ids it seems, and after
r14-2170 variable template-ids are affected as well.

This patch marks alias templates that have a dependent attribute as
complex (as with e.g. constrained alias templates) so that we don't look
through them prematurely.

PR c++/115897

gcc/cp/ChangeLog:

* pt.cc (complex_alias_template_p): Return true for an alias
template with attributes.
(get_underlying_template): Don't look through an alias template
with attributes.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alias-decl-77.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc   | 10 ++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C | 32 ++
 2 files changed, 42 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e38e02488be1..4d72ff60cb8e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6628,6 +6628,11 @@ complex_alias_template_p (const_tree tmpl, tree 
*seen_out)
   if (get_constraints (tmpl))
 return true;
 
+  /* An alias with dependent type attributes is complex.  */
+  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+  (DECL_TEMPLATE_RESULT (tmpl
+return true;
+
   if (!complex_alias_tmpl_info)
 complex_alias_tmpl_info = hash_map::create_ggc (13);
 
@@ -6780,6 +6785,11 @@ get_underlying_template (tree tmpl)
   if (!at_least_as_constrained (underlying, tmpl))
break;
 
+  /* If TMPL adds dependent type attributes, it isn't equivalent.  */
+  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+  (DECL_TEMPLATE_RESULT (tmpl
+   break;
+
   /* Alias is equivalent.  Strip it and repeat.  */
   tmpl = underlying;
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
new file mode 100644
index ..f72e4cc26538
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
@@ -0,0 +1,32 @@
+// PR c++/115897
+// { dg-do compile { target c++11 } }
+
+template
+struct is_same { static constexpr bool value = __is_same(T, U); };
+
+#if __cpp_variable_templates
+template
+constexpr bool is_same_v = __is_same(T, U);
+#endif
+
+template
+using A [[gnu::vector_size(16)]] = T;
+
+template
+using B = T;
+
+template
+using C [[gnu::vector_size(16)]] = B;
+
+template
+void f() {
+  static_assert(!is_same>::value, "");
+  static_assert(is_same, A>::value, "");
+
+#if __cpp_variable_templates
+  static_assert(!is_same_v>, "");
+  static_assert(is_same_v, A>, "");
+#endif
+};
+
+template void f();


[gcc r15-1717] c++: bad 'this' conversion for nullary memfn [PR106760]

2024-06-28 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:50073ffae0a9b8feb9b36fdafdebd9885f6d7dc8

commit r15-1717-g50073ffae0a9b8feb9b36fdafdebd9885f6d7dc8
Author: Patrick Palka 
Date:   Fri Jun 28 19:45:21 2024 -0400

c++: bad 'this' conversion for nullary memfn [PR106760]

Here we notice the 'this' conversion for the call f() is bad, so
we correctly defer deduction for the template candidate, but we end up
never adding it to 'bad_cands' since missing_conversion_p for it returns
false (its only argument is 'this' which has already been determined to
be bad).  This is not a huge deal, but it causes us to longer accept the
call with -fpermissive in release builds, and a tree check ICE in checking
builds.

So if we have a non-strictly viable template candidate that has not been
instantiated, then we need to add it to 'bad_cands' even if no argument
conversion is missing.

PR c++/106760

gcc/cp/ChangeLog:

* call.cc (add_candidates): Relax test for adding a candidate
to 'bad_cands' to also accept an uninstantiated template candidate
that has no missing conversions.

gcc/testsuite/ChangeLog:

* g++.dg/ext/conv3.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc   |  3 ++-
 gcc/testsuite/g++.dg/ext/conv3.C | 13 +
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 7bbc1fb0c78..83070b2f633 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -6742,7 +6742,8 @@ add_candidates (tree fns, tree first_arg, const vec *args,
 
   if (cand->viable == -1
  && shortcut_bad_convs
- && missing_conversion_p (cand))
+ && (missing_conversion_p (cand)
+ || TREE_CODE (cand->fn) == TEMPLATE_DECL))
{
  /* This candidate has been tentatively marked non-strictly viable,
 and we didn't compute all argument conversions for it (having
diff --git a/gcc/testsuite/g++.dg/ext/conv3.C b/gcc/testsuite/g++.dg/ext/conv3.C
new file mode 100644
index 000..7324d560056
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/conv3.C
@@ -0,0 +1,13 @@
+// PR c++/106760
+// { dg-additional-options "-fpermissive" }
+
+struct S {
+  template int f();
+  template int g(...);
+};
+
+int main() {
+  const S s;
+  s.f(); // { dg-warning "discards qualifiers" }
+  s.g(); // { dg-warning "discards qualifiers" }
+}


[gcc r14-10359] c++: decltype of capture proxy of ref [PR115504]

2024-06-28 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:e6b115be1c392de415925282a38f28cd78cb6c35

commit r14-10359-ge6b115be1c392de415925282a38f28cd78cb6c35
Author: Patrick Palka 
Date:   Tue Jun 25 20:07:15 2024 -0400

c++: decltype of capture proxy of ref [PR115504]

The finish_decltype_type capture proxy handling added in r14-5330 was
incorrectly stripping references in the type of the captured variable.

PR c++/115504

gcc/cp/ChangeLog:

* semantics.cc (finish_decltype_type): Don't strip the reference
type (if any) of a capture proxy's captured variable.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/decltype-auto8.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 737449e5f233feb682b5dd2cc153892ad90a79bd)

Diff:
---
 gcc/cp/semantics.cc |  1 -
 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 22 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index d944decd329..b18fc7c61be 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11904,7 +11904,6 @@ finish_decltype_type (tree expr, bool 
id_expression_or_member_access_p,
{
  expr = DECL_CAPTURED_VARIABLE (expr);
  type = TREE_TYPE (expr);
- type = non_reference (type);
}
  else
{
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C 
b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C
new file mode 100644
index 000..55135cecf72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C
@@ -0,0 +1,22 @@
+// PR c++/115504
+// { dg-do compile { target c++14 } }
+
+void f(int& x, const int& y) {
+  [&x]() {
+decltype(auto) a = x;
+using type = decltype(x);
+using type = decltype(a);
+using type = int&; // not 'int'
+  };
+
+  [x]() {
+decltype(auto) a = x; // { dg-error "discards qualifiers" }
+  };
+
+  [x]() mutable {
+decltype(auto) a = x;
+using type = decltype(x);
+using type = decltype(a);
+using type = int&;
+  };
+}


[gcc r14-10357] c++: using non-dep array var of unknown bound [PR115358]

2024-06-28 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:33a9c4dd5fcac7e3f5d835b35fe787126339dd2b

commit r14-10357-g33a9c4dd5fcac7e3f5d835b35fe787126339dd2b
Author: Patrick Palka 
Date:   Tue Jun 25 10:42:21 2024 -0400

c++: using non-dep array var of unknown bound [PR115358]

For a non-dependent array variable of unknown bound, it seems we need to
try instantiating its definition upon use in a template context for sake
of proper checking and typing of the overall expression, like we do for
function specializations with deduced return type.

PR c++/115358

gcc/cp/ChangeLog:

* decl2.cc (mark_used): Call maybe_instantiate_decl for an array
variable with unknown bound.
* semantics.cc (finish_decltype_type): Remove now redundant
handling of array variables with unknown bound.
* typeck.cc (cxx_sizeof_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/template/array37.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit e3915c1ad56591cbd68229a64c941c38330abd69)

Diff:
---
 gcc/cp/decl2.cc |  2 ++
 gcc/cp/semantics.cc |  7 ---
 gcc/cp/typeck.cc|  7 ---
 gcc/testsuite/g++.dg/template/array37.C | 14 ++
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 88933be732d..af2e08c8a63 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -5952,6 +5952,8 @@ mark_used (tree decl, tsubst_flags_t complain /* = 
tf_warning_or_error */)
  find out its type.  For OpenMP user defined reductions, we need them
  instantiated for reduction clauses which inline them by hand directly.  */
   if (undeduced_auto_decl (decl)
+  || (VAR_P (decl)
+ && VAR_HAD_UNKNOWN_BOUND (decl))
   || (TREE_CODE (decl) == FUNCTION_DECL
  && DECL_OMP_DECLARE_REDUCTION_P (decl)))
 maybe_instantiate_decl (decl);
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 4513066d2ed..d944decd329 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11835,13 +11835,6 @@ finish_decltype_type (tree expr, bool 
id_expression_or_member_access_p,
   return error_mark_node;
 }
 
-  /* To get the size of a static data member declared as an array of
- unknown bound, we need to instantiate it.  */
-  if (VAR_P (expr)
-  && VAR_HAD_UNKNOWN_BOUND (expr)
-  && DECL_TEMPLATE_INSTANTIATION (expr))
-instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false);
-
   if (id_expression_or_member_access_p)
 {
   /* If e is an id-expression or a class member access (5.2.5
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 42578beb85b..21436f836fa 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -2128,13 +2128,6 @@ cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t 
complain)
   location_t e_loc = cp_expr_loc_or_loc (e, loc);
   STRIP_ANY_LOCATION_WRAPPER (e);
 
-  /* To get the size of a static data member declared as an array of
- unknown bound, we need to instantiate it.  */
-  if (VAR_P (e)
-  && VAR_HAD_UNKNOWN_BOUND (e)
-  && DECL_TEMPLATE_INSTANTIATION (e))
-instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
-
   if (TREE_CODE (e) == PARM_DECL
   && DECL_ARRAY_PARAMETER_P (e)
   && (complain & tf_warning))
diff --git a/gcc/testsuite/g++.dg/template/array37.C 
b/gcc/testsuite/g++.dg/template/array37.C
new file mode 100644
index 000..c5c11663a4d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/array37.C
@@ -0,0 +1,14 @@
+// PR c++/115358
+
+template
+struct A { static int STR[]; };
+
+template
+int A::STR[] = {1,2,3};
+
+void f(int(&)[3]);
+
+template
+void g() {
+  f(A::STR); // { dg-bogus "int []" }
+}


[gcc r14-10358] c++: alias CTAD and copy deduction guide [PR115198]

2024-06-28 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:a00a8d46ea6ff7130e2493e7bd9824e28e2509b7

commit r14-10358-ga00a8d46ea6ff7130e2493e7bd9824e28e2509b7
Author: Patrick Palka 
Date:   Tue Jun 25 12:59:24 2024 -0400

c++: alias CTAD and copy deduction guide [PR115198]

Here we're neglecting to update DECL_NAME during the alias CTAD guide
transformation, which causes copy_guide_p to return false for the
transformed copy deduction guide since DECL_NAME is still __dguide_C
with TREE_TYPE C but it should be __dguide_A with TREE_TYPE A
(i.e. C).  This ultimately results in ambiguity during
overload resolution between the copy deduction guide vs copy ctor guide.

This patch makes us update DECL_NAME of a transformed guide accordingly
during alias/inherited CTAD.

PR c++/115198

gcc/cp/ChangeLog:

* pt.cc (alias_ctad_tweaks): Update DECL_NAME of the transformed
guides.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias22.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 06ebb7c6f31fe42ffdea6f51ac1ba1f6b058c090)

Diff:
---
 gcc/cp/pt.cc |  6 +-
 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C | 14 ++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c7aee66f068..580c3fc2cb2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30338,13 +30338,14 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  any).  */
 
   enum { alias, inherited } ctad_kind;
-  tree atype, fullatparms, utype;
+  tree atype, fullatparms, utype, name;
   if (TREE_CODE (tmpl) == TEMPLATE_DECL)
 {
   ctad_kind = alias;
   atype = TREE_TYPE (tmpl);
   fullatparms = DECL_TEMPLATE_PARMS (tmpl);
   utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+  name = dguide_name (tmpl);
 }
   else
 {
@@ -30352,6 +30353,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
   atype = NULL_TREE;
   fullatparms = TREE_PURPOSE (tmpl);
   utype = TREE_VALUE (tmpl);
+  name = dguide_name (TPARMS_PRIMARY_TEMPLATE
+ (INNERMOST_TEMPLATE_PARMS (fullatparms)));
 }
 
   tsubst_flags_t complain = tf_warning_or_error;
@@ -30447,6 +30450,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
}
  if (g == error_mark_node)
continue;
+ DECL_NAME (g) = name;
  if (nfparms == 0)
{
  /* The targs are all non-dependent, so g isn't a template.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
new file mode 100644
index 000..9c6c841166a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
@@ -0,0 +1,14 @@
+// PR c++/115198
+// { dg-do compile { target c++20 } }
+
+template
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+template
+using A = C;
+
+C c;
+A a = c; // { dg-bogus "ambiguous" }


[gcc r15-1631] c++: decltype of capture proxy of ref [PR115504]

2024-06-25 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:737449e5f233feb682b5dd2cc153892ad90a79bd

commit r15-1631-g737449e5f233feb682b5dd2cc153892ad90a79bd
Author: Patrick Palka 
Date:   Tue Jun 25 20:07:15 2024 -0400

c++: decltype of capture proxy of ref [PR115504]

The finish_decltype_type capture proxy handling added in r14-5330 was
incorrectly stripping references in the type of the captured variable.

PR c++/115504

gcc/cp/ChangeLog:

* semantics.cc (finish_decltype_type): Don't strip the reference
type (if any) of a capture proxy's captured variable.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/decltype-auto8.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/semantics.cc |  1 -
 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 22 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8e3e4e23b72..44de4c9a529 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12071,7 +12071,6 @@ finish_decltype_type (tree expr, bool 
id_expression_or_member_access_p,
{
  expr = DECL_CAPTURED_VARIABLE (expr);
  type = TREE_TYPE (expr);
- type = non_reference (type);
}
  else
{
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C 
b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C
new file mode 100644
index 000..55135cecf72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C
@@ -0,0 +1,22 @@
+// PR c++/115504
+// { dg-do compile { target c++14 } }
+
+void f(int& x, const int& y) {
+  [&x]() {
+decltype(auto) a = x;
+using type = decltype(x);
+using type = decltype(a);
+using type = int&; // not 'int'
+  };
+
+  [x]() {
+decltype(auto) a = x; // { dg-error "discards qualifiers" }
+  };
+
+  [x]() mutable {
+decltype(auto) a = x;
+using type = decltype(x);
+using type = decltype(a);
+using type = int&;
+  };
+}


[gcc r15-1615] c++: alias CTAD and copy deduction guide [PR115198]

2024-06-25 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:06ebb7c6f31fe42ffdea6f51ac1ba1f6b058c090

commit r15-1615-g06ebb7c6f31fe42ffdea6f51ac1ba1f6b058c090
Author: Patrick Palka 
Date:   Tue Jun 25 12:59:24 2024 -0400

c++: alias CTAD and copy deduction guide [PR115198]

Here we're neglecting to update DECL_NAME during the alias CTAD guide
transformation, which causes copy_guide_p to return false for the
transformed copy deduction guide since DECL_NAME is still __dguide_C
with TREE_TYPE C but it should be __dguide_A with TREE_TYPE A
(i.e. C).  This ultimately results in ambiguity during
overload resolution between the copy deduction guide vs copy ctor guide.

This patch makes us update DECL_NAME of a transformed guide accordingly
during alias/inherited CTAD.

PR c++/115198

gcc/cp/ChangeLog:

* pt.cc (alias_ctad_tweaks): Update DECL_NAME of the transformed
guides.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias22.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc |  6 +-
 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C | 14 ++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 607753ae6b7..daa8ac386dc 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30342,13 +30342,14 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  any).  */
 
   enum { alias, inherited } ctad_kind;
-  tree atype, fullatparms, utype;
+  tree atype, fullatparms, utype, name;
   if (TREE_CODE (tmpl) == TEMPLATE_DECL)
 {
   ctad_kind = alias;
   atype = TREE_TYPE (tmpl);
   fullatparms = DECL_TEMPLATE_PARMS (tmpl);
   utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+  name = dguide_name (tmpl);
 }
   else
 {
@@ -30356,6 +30357,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
   atype = NULL_TREE;
   fullatparms = TREE_PURPOSE (tmpl);
   utype = TREE_VALUE (tmpl);
+  name = dguide_name (TPARMS_PRIMARY_TEMPLATE
+ (INNERMOST_TEMPLATE_PARMS (fullatparms)));
 }
 
   tsubst_flags_t complain = tf_warning_or_error;
@@ -30451,6 +30454,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
}
  if (g == error_mark_node)
continue;
+ DECL_NAME (g) = name;
  if (nfparms == 0)
{
  /* The targs are all non-dependent, so g isn't a template.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
new file mode 100644
index 000..9c6c841166a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
@@ -0,0 +1,14 @@
+// PR c++/115198
+// { dg-do compile { target c++20 } }
+
+template
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+template
+using A = C;
+
+C c;
+A a = c; // { dg-bogus "ambiguous" }


[gcc r15-1614] c++: using non-dep array var of unknown bound [PR115358]

2024-06-25 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:e3915c1ad56591cbd68229a64c941c38330abd69

commit r15-1614-ge3915c1ad56591cbd68229a64c941c38330abd69
Author: Patrick Palka 
Date:   Tue Jun 25 10:42:21 2024 -0400

c++: using non-dep array var of unknown bound [PR115358]

For a non-dependent array variable of unknown bound, it seems we need to
try instantiating its definition upon use in a template context for sake
of proper checking and typing of the overall expression, like we do for
function specializations with deduced return type.

PR c++/115358

gcc/cp/ChangeLog:

* decl2.cc (mark_used): Call maybe_instantiate_decl for an array
variable with unknown bound.
* semantics.cc (finish_decltype_type): Remove now redundant
handling of array variables with unknown bound.
* typeck.cc (cxx_sizeof_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/template/array37.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/decl2.cc |  2 ++
 gcc/cp/semantics.cc |  7 ---
 gcc/cp/typeck.cc|  7 ---
 gcc/testsuite/g++.dg/template/array37.C | 14 ++
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 6c3ef60d51f..cdd2b8aada2 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -6001,6 +6001,8 @@ mark_used (tree decl, tsubst_flags_t complain /* = 
tf_warning_or_error */)
  find out its type.  For OpenMP user defined reductions, we need them
  instantiated for reduction clauses which inline them by hand directly.  */
   if (undeduced_auto_decl (decl)
+  || (VAR_P (decl)
+ && VAR_HAD_UNKNOWN_BOUND (decl))
   || (TREE_CODE (decl) == FUNCTION_DECL
  && DECL_OMP_DECLARE_REDUCTION_P (decl)))
 maybe_instantiate_decl (decl);
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 08f5f245e7d..6c1813d37c6 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12002,13 +12002,6 @@ finish_decltype_type (tree expr, bool 
id_expression_or_member_access_p,
   return error_mark_node;
 }
 
-  /* To get the size of a static data member declared as an array of
- unknown bound, we need to instantiate it.  */
-  if (VAR_P (expr)
-  && VAR_HAD_UNKNOWN_BOUND (expr)
-  && DECL_TEMPLATE_INSTANTIATION (expr))
-instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false);
-
   if (id_expression_or_member_access_p)
 {
   /* If e is an id-expression or a class member access (5.2.5
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 717eb63eb98..50f48768a95 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -2130,13 +2130,6 @@ cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t 
complain)
   location_t e_loc = cp_expr_loc_or_loc (e, loc);
   STRIP_ANY_LOCATION_WRAPPER (e);
 
-  /* To get the size of a static data member declared as an array of
- unknown bound, we need to instantiate it.  */
-  if (VAR_P (e)
-  && VAR_HAD_UNKNOWN_BOUND (e)
-  && DECL_TEMPLATE_INSTANTIATION (e))
-instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
-
   if (TREE_CODE (e) == PARM_DECL
   && DECL_ARRAY_PARAMETER_P (e)
   && (complain & tf_warning))
diff --git a/gcc/testsuite/g++.dg/template/array37.C 
b/gcc/testsuite/g++.dg/template/array37.C
new file mode 100644
index 000..c5c11663a4d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/array37.C
@@ -0,0 +1,14 @@
+// PR c++/115358
+
+template
+struct A { static int STR[]; };
+
+template
+int A::STR[] = {1,2,3};
+
+void f(int(&)[3]);
+
+template
+void g() {
+  f(A::STR); // { dg-bogus "int []" }
+}


[gcc r14-10320] c++: undeclared identifier in requires-clause [PR99678]

2024-06-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:20cda2e85c307096a3856f7f27215b8a28982fb6

commit r14-10320-g20cda2e85c307096a3856f7f27215b8a28982fb6
Author: Patrick Palka 
Date:   Thu Jun 13 10:16:10 2024 -0400

c++: undeclared identifier in requires-clause [PR99678]

Since the terms of a requires-clause are grammatically primary-expressions
and not e.g. postfix-expressions, it seems we need to explicitly handle
and diagnose the case where a term parses to a bare unresolved identifier,
like cp_parser_postfix_expression does, since cp_parser_primary_expression
leaves that up to its callers.  Otherwise we incorrectly accept the first
three requires-clauses below.

Note that the only occurrences of primary-expression in the grammar are
postfix-expression and constraint-logical-and-expression, so it's not too
surprising that we need this special handling here.

PR c++/99678

gcc/cp/ChangeLog:

* parser.cc (cp_parser_constraint_primary_expression): Diagnose
a bare unresolved unqualified-id.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-requires38.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit d387ecb2b2f44f33fd6a7c5ec7eadaf6dd70efc9)

Diff:
---
 gcc/cp/parser.cc |  2 ++
 gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 598380dda089..6b786ed8266f 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -31225,6 +31225,8 @@ cp_parser_constraint_primary_expression (cp_parser 
*parser, bool lambda_p)
 }
   if (pce == pce_ok)
 {
+  if (idk == CP_ID_KIND_UNQUALIFIED && identifier_p (expr))
+   expr = unqualified_name_lookup_error (expr);
   cp_lexer_commit_tokens (parser->lexer);
   return finish_constraint_primary_expr (expr);
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C
new file mode 100644
index ..663195b79cc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C
@@ -0,0 +1,14 @@
+// PR c++/99678
+// { dg-do compile { target c++20 } }
+
+template
+void f1() requires undeclared_identifier; // { dg-error "not declared" }
+
+template
+void f2() requires true && undeclared_identifier; // { dg-error "not declared" 
}
+
+template
+void f3() requires false || undeclared_identifier; // { dg-error "not 
declared" }
+
+template
+void f4() requires undeclared_identifier(T{}); // { dg-error "must be enclosed 
in parentheses" }


[gcc r14-10319] c++: ICE w/ ambig and non-strictly-viable cands [PR115239]

2024-06-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:4df86402990e2f45e02a367f1734a22ebc041e98

commit r14-10319-g4df86402990e2f45e02a367f1734a22ebc041e98
Author: Patrick Palka 
Date:   Thu Jun 13 10:02:43 2024 -0400

c++: ICE w/ ambig and non-strictly-viable cands [PR115239]

Here during overload resolution we have two strictly viable ambiguous
candidates #1 and #2, and two non-strictly viable candidates #3 and #4
which we hold on to ever since r14-6522.  These latter candidates have
an empty second arg conversion since the first arg conversion was deemed
bad, and this trips up joust when called on #3 and #4 which assumes all
arg conversions are there.

We can fix this by making joust robust to empty arg conversions, but in
this situation we shouldn't need to compare #3 and #4 at all given that
we have a strictly viable candidate.  To that end, this patch makes
tourney shortcut considering non-strictly viable candidates upon
encountering ambiguity between two strictly viable candidates (taking
advantage of the fact that the candidates list is sorted according to
viability via splice_viable).

PR c++/115239

gcc/cp/ChangeLog:

* call.cc (tourney): Don't consider a non-strictly viable
candidate as the champ if there was ambiguity between two
strictly viable candidates.

gcc/testsuite/ChangeLog:

* g++.dg/overload/error7.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 7fed7e9bbc57d502e141e079a6be2706bdbd4560)

Diff:
---
 gcc/cp/call.cc |  3 ++-
 gcc/testsuite/g++.dg/overload/error7.C | 10 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 38b9c4f08601..f5584c92efb8 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13488,7 +13488,8 @@ tourney (struct z_candidate *candidates, tsubst_flags_t 
complain)
{
  previous_worse_champ = nullptr;
  champ = &(*challenger)->next;
- if (!*champ || !(*champ)->viable)
+ if (!*champ || !(*champ)->viable
+ || (*champ)->viable < (*challenger)->viable)
{
  champ = nullptr;
  break;
diff --git a/gcc/testsuite/g++.dg/overload/error7.C 
b/gcc/testsuite/g++.dg/overload/error7.C
new file mode 100644
index ..de50ce5f66e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/error7.C
@@ -0,0 +1,10 @@
+// PR c++/115239
+
+bool foo(char *, long); // #1, strictly viable, ambig with #2
+bool foo(char *, unsigned); // #2, strictly viable, ambig with #1
+bool foo(char, long);   // #3, non-strictly viable
+bool foo(char, unsigned);   // #4, non-strictly viable
+
+int main() {
+  foo((char *)0, 0); // { dg-error "ambiguous" }
+}


[gcc r14-10318] c++: visibility wrt concept-id as targ [PR115283]

2024-06-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:9583f781e17d4da881ee64db43af939402331413

commit r14-10318-g9583f781e17d4da881ee64db43af939402331413
Author: Patrick Palka 
Date:   Wed Jun 12 20:05:05 2024 -0400

c++: visibility wrt concept-id as targ [PR115283]

Like with alias templates, it seems we don't maintain visibility flags
for concepts either, so min_vis_expr_r should ignore them for now.
Otherwise after r14-6789 we may incorrectly give a function template that
uses a concept-id in its signature internal linkage.

PR c++/115283

gcc/cp/ChangeLog:

* decl2.cc (min_vis_expr_r) : Ignore
concepts.

gcc/testsuite/ChangeLog:

* g++.dg/template/linkage5.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit b1fe718cbe0c8883af89f52e0aad3ebf913683de)

Diff:
---
 gcc/cp/decl2.cc  |  5 +++--
 gcc/testsuite/g++.dg/template/linkage5.C | 14 ++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 806a2a4bc69d..88933be732db 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2710,9 +2710,10 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
   break;
 
 case TEMPLATE_DECL:
-  if (DECL_ALIAS_TEMPLATE_P (t))
+  if (DECL_ALIAS_TEMPLATE_P (t) || standard_concept_p (t))
/* FIXME: We don't maintain TREE_PUBLIC / DECL_VISIBILITY for
-  alias templates so we can't trust it here (PR107906).  */
+  alias templates so we can't trust it here (PR107906).  Ditto
+  for concepts.  */
break;
   t = DECL_TEMPLATE_RESULT (t);
   /* Fall through.  */
diff --git a/gcc/testsuite/g++.dg/template/linkage5.C 
b/gcc/testsuite/g++.dg/template/linkage5.C
new file mode 100644
index ..7e8f93f546f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/linkage5.C
@@ -0,0 +1,14 @@
+// PR c++/115283
+// { dg-final { scan-assembler "(weak|glob)\[^\n\]*_Z1fIiEv1AIX1CIT_EEE" } }
+// { dg-do compile { target c++20 } }
+
+template
+concept C = true;
+
+template
+struct A { };
+
+template
+void f(A>) { }
+
+template void f(A);


[gcc r15-1294] c++: undeclared identifier in requires-clause [PR99678]

2024-06-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:d387ecb2b2f44f33fd6a7c5ec7eadaf6dd70efc9

commit r15-1294-gd387ecb2b2f44f33fd6a7c5ec7eadaf6dd70efc9
Author: Patrick Palka 
Date:   Thu Jun 13 10:16:10 2024 -0400

c++: undeclared identifier in requires-clause [PR99678]

Since the terms of a requires-clause are grammatically primary-expressions
and not e.g. postfix-expressions, it seems we need to explicitly handle
and diagnose the case where a term parses to a bare unresolved identifier,
like cp_parser_postfix_expression does, since cp_parser_primary_expression
leaves that up to its callers.  Otherwise we incorrectly accept the first
three requires-clauses below.

Note that the only occurrences of primary-expression in the grammar are
postfix-expression and constraint-logical-and-expression, so it's not too
surprising that we need this special handling here.

PR c++/99678

gcc/cp/ChangeLog:

* parser.cc (cp_parser_constraint_primary_expression): Diagnose
a bare unresolved unqualified-id.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-requires38.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/parser.cc |  2 ++
 gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 01a19080d6c7..e7409b856f11 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -31525,6 +31525,8 @@ cp_parser_constraint_primary_expression (cp_parser 
*parser, bool lambda_p)
 }
   if (pce == pce_ok)
 {
+  if (idk == CP_ID_KIND_UNQUALIFIED && identifier_p (expr))
+   expr = unqualified_name_lookup_error (expr);
   cp_lexer_commit_tokens (parser->lexer);
   return finish_constraint_primary_expr (expr);
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C
new file mode 100644
index ..663195b79cc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires38.C
@@ -0,0 +1,14 @@
+// PR c++/99678
+// { dg-do compile { target c++20 } }
+
+template
+void f1() requires undeclared_identifier; // { dg-error "not declared" }
+
+template
+void f2() requires true && undeclared_identifier; // { dg-error "not declared" 
}
+
+template
+void f3() requires false || undeclared_identifier; // { dg-error "not 
declared" }
+
+template
+void f4() requires undeclared_identifier(T{}); // { dg-error "must be enclosed 
in parentheses" }


[gcc r15-1292] c++: ICE w/ ambig and non-strictly-viable cands [PR115239]

2024-06-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:7fed7e9bbc57d502e141e079a6be2706bdbd4560

commit r15-1292-g7fed7e9bbc57d502e141e079a6be2706bdbd4560
Author: Patrick Palka 
Date:   Thu Jun 13 10:02:43 2024 -0400

c++: ICE w/ ambig and non-strictly-viable cands [PR115239]

Here during overload resolution we have two strictly viable ambiguous
candidates #1 and #2, and two non-strictly viable candidates #3 and #4
which we hold on to ever since r14-6522.  These latter candidates have
an empty second arg conversion since the first arg conversion was deemed
bad, and this trips up joust when called on #3 and #4 which assumes all
arg conversions are there.

We can fix this by making joust robust to empty arg conversions, but in
this situation we shouldn't need to compare #3 and #4 at all given that
we have a strictly viable candidate.  To that end, this patch makes
tourney shortcut considering non-strictly viable candidates upon
encountering ambiguity between two strictly viable candidates (taking
advantage of the fact that the candidates list is sorted according to
viability via splice_viable).

PR c++/115239

gcc/cp/ChangeLog:

* call.cc (tourney): Don't consider a non-strictly viable
candidate as the champ if there was ambiguity between two
strictly viable candidates.

gcc/testsuite/ChangeLog:

* g++.dg/overload/error7.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/call.cc |  3 ++-
 gcc/testsuite/g++.dg/overload/error7.C | 10 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 85536fc25ff2..7bbc1fb0c789 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13490,7 +13490,8 @@ tourney (struct z_candidate *candidates, tsubst_flags_t 
complain)
{
  previous_worse_champ = nullptr;
  champ = &(*challenger)->next;
- if (!*champ || !(*champ)->viable)
+ if (!*champ || !(*champ)->viable
+ || (*champ)->viable < (*challenger)->viable)
{
  champ = nullptr;
  break;
diff --git a/gcc/testsuite/g++.dg/overload/error7.C 
b/gcc/testsuite/g++.dg/overload/error7.C
new file mode 100644
index ..de50ce5f66e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/error7.C
@@ -0,0 +1,10 @@
+// PR c++/115239
+
+bool foo(char *, long); // #1, strictly viable, ambig with #2
+bool foo(char *, unsigned); // #2, strictly viable, ambig with #1
+bool foo(char, long);   // #3, non-strictly viable
+bool foo(char, unsigned);   // #4, non-strictly viable
+
+int main() {
+  foo((char *)0, 0); // { dg-error "ambiguous" }
+}


[gcc r15-1227] c++: visibility wrt concept-id as targ [PR115283]

2024-06-12 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:b1fe718cbe0c8883af89f52e0aad3ebf913683de

commit r15-1227-gb1fe718cbe0c8883af89f52e0aad3ebf913683de
Author: Patrick Palka 
Date:   Wed Jun 12 20:05:05 2024 -0400

c++: visibility wrt concept-id as targ [PR115283]

Like with alias templates, it seems we don't maintain visibility flags
for concepts either, so min_vis_expr_r should ignore them for now.
Otherwise after r14-6789 we may incorrectly give a function template that
uses a concept-id in its signature internal linkage.

PR c++/115283

gcc/cp/ChangeLog:

* decl2.cc (min_vis_expr_r) : Ignore
concepts.

gcc/testsuite/ChangeLog:

* g++.dg/template/linkage5.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/decl2.cc  |  5 +++--
 gcc/testsuite/g++.dg/template/linkage5.C | 14 ++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 7baff46a1921..6c3ef60d51f8 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2723,9 +2723,10 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
   break;
 
 case TEMPLATE_DECL:
-  if (DECL_ALIAS_TEMPLATE_P (t))
+  if (DECL_ALIAS_TEMPLATE_P (t) || standard_concept_p (t))
/* FIXME: We don't maintain TREE_PUBLIC / DECL_VISIBILITY for
-  alias templates so we can't trust it here (PR107906).  */
+  alias templates so we can't trust it here (PR107906).  Ditto
+  for concepts.  */
break;
   t = DECL_TEMPLATE_RESULT (t);
   /* Fall through.  */
diff --git a/gcc/testsuite/g++.dg/template/linkage5.C 
b/gcc/testsuite/g++.dg/template/linkage5.C
new file mode 100644
index ..7e8f93f546f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/linkage5.C
@@ -0,0 +1,14 @@
+// PR c++/115283
+// { dg-final { scan-assembler "(weak|glob)\[^\n\]*_Z1fIiEv1AIX1CIT_EEE" } }
+// { dg-do compile { target c++20 } }
+
+template
+concept C = true;
+
+template
+struct A { };
+
+template
+void f(A>) { }
+
+template void f(A);


[gcc r14-10301] c++: lambda in pack expansion [PR115378]

2024-06-10 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:ff8105b4910f7dbee326cb36b01c16ac9bf10c4b

commit r14-10301-gff8105b4910f7dbee326cb36b01c16ac9bf10c4b
Author: Patrick Palka 
Date:   Fri Jun 7 12:12:30 2024 -0400

c++: lambda in pack expansion [PR115378]

Here find_parameter_packs_r is incorrectly treating the 'auto' return
type of a lambda as a parameter pack due to Concepts-TS specific logic
added in r6-4517, leading to confusion later when expanding the pattern.

Since we intend on removing Concepts TS support soon anyway, this patch
fixes this by restricting the problematic logic with flag_concepts_ts.
Doing so revealed that add_capture was relying on this logic to set
TEMPLATE_TYPE_PARAMETER_PACK for the 'auto' type of an pack expansion
init-capture, which we now need to do explicitly.

PR c++/115378

gcc/cp/ChangeLog:

* lambda.cc (lambda_capture_field_type): Set
TEMPLATE_TYPE_PARAMETER_PACK on the auto type of an init-capture
pack expansion.
* pt.cc (find_parameter_packs_r) :
Restrict TEMPLATE_TYPE_PARAMETER_PACK promotion with
flag_concepts_ts.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/decltype-auto-103497.C: Adjust expected diagnostic.
* g++.dg/template/pr95672.C: Likewise.
* g++.dg/cpp2a/lambda-targ5.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 5c761395402a730535983a5e49ef1775561ebc61)

Diff:
---
 gcc/cp/lambda.cc  |  3 ++-
 gcc/cp/pt.cc  |  2 +-
 gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C |  2 +-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C | 15 +++
 gcc/testsuite/g++.dg/template/pr95672.C   |  2 +-
 5 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 4b1f9391fee..5b5e31c141e 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -223,7 +223,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
   outermost CV qualifiers of EXPR.  */
type = build_reference_type (type);
   if (uses_parameter_packs (expr))
-   /* Stick with 'auto' even if the type could be deduced.  */;
+   /* Stick with 'auto' even if the type could be deduced.  */
+   TEMPLATE_TYPE_PARAMETER_PACK (auto_node) = true;
   else
type = do_auto_deduction (type, expr, auto_node);
 }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d3f61e90422..c7aee66f068 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -3942,7 +3942,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, 
void* data)
 parameter pack (14.6.3), or the type-specifier-seq of a type-id that
 is a pack expansion, the invented template parameter is a template
 parameter pack.  */
-  if (ppd->type_pack_expansion_p && is_auto (t)
+  if (flag_concepts_ts && ppd->type_pack_expansion_p && is_auto (t)
  && TEMPLATE_TYPE_LEVEL (t) != 0)
TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
   if (TEMPLATE_TYPE_PARAMETER_PACK (t))
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C 
b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
index cedd661710c..4162361d14f 100644
--- a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
@@ -1,7 +1,7 @@
 // PR c++/103497
 // { dg-do compile { target c++14 } }
 
-void foo(decltype(auto)... args);  // { dg-error "cannot declare a parameter 
with .decltype.auto.." }
+void foo(decltype(auto)... args);  // { dg-error "contains no parameter packs" 
}
 
 int main() {
   foo();
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C
new file mode 100644
index 000..efd4bb45d58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C
@@ -0,0 +1,15 @@
+// PR c++/115378
+// { dg-do compile { target c++20 } }
+
+struct tt {};
+
+template
+constexpr auto __counter = 1;
+
+template 
+using _as_base = tt;
+
+template 
+struct env : _as_base>... {};
+
+env t;
diff --git a/gcc/testsuite/g++.dg/template/pr95672.C 
b/gcc/testsuite/g++.dg/template/pr95672.C
index c752b4a2c08..d97b8db2e97 100644
--- a/gcc/testsuite/g++.dg/template/pr95672.C
+++ b/gcc/testsuite/g++.dg/template/pr95672.C
@@ -1,3 +1,3 @@
 // PR c++/95672
 // { dg-do compile { target c++14 } }
-struct g_class : decltype  (auto) ... {  }; // { dg-error "invalid use of pack 
expansion" }
+struct g_class : decltype  (auto) ... {  }; // { dg-error "contains no 
parameter packs" }


[gcc r15-1103] c++: lambda in pack expansion [PR115378]

2024-06-07 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:5c761395402a730535983a5e49ef1775561ebc61

commit r15-1103-g5c761395402a730535983a5e49ef1775561ebc61
Author: Patrick Palka 
Date:   Fri Jun 7 12:12:30 2024 -0400

c++: lambda in pack expansion [PR115378]

Here find_parameter_packs_r is incorrectly treating the 'auto' return
type of a lambda as a parameter pack due to Concepts-TS specific logic
added in r6-4517, leading to confusion later when expanding the pattern.

Since we intend on removing Concepts TS support soon anyway, this patch
fixes this by restricting the problematic logic with flag_concepts_ts.
Doing so revealed that add_capture was relying on this logic to set
TEMPLATE_TYPE_PARAMETER_PACK for the 'auto' type of an pack expansion
init-capture, which we now need to do explicitly.

PR c++/115378

gcc/cp/ChangeLog:

* lambda.cc (lambda_capture_field_type): Set
TEMPLATE_TYPE_PARAMETER_PACK on the auto type of an init-capture
pack expansion.
* pt.cc (find_parameter_packs_r) :
Restrict TEMPLATE_TYPE_PARAMETER_PACK promotion with
flag_concepts_ts.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/decltype-auto-103497.C: Adjust expected diagnostic.
* g++.dg/template/pr95672.C: Likewise.
* g++.dg/cpp2a/lambda-targ5.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/lambda.cc  |  3 ++-
 gcc/cp/pt.cc  |  2 +-
 gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C |  2 +-
 gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C | 15 +++
 gcc/testsuite/g++.dg/template/pr95672.C   |  2 +-
 5 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 630cc4eade1..0770417810e 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -223,7 +223,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
   outermost CV qualifiers of EXPR.  */
type = build_reference_type (type);
   if (uses_parameter_packs (expr))
-   /* Stick with 'auto' even if the type could be deduced.  */;
+   /* Stick with 'auto' even if the type could be deduced.  */
+   TEMPLATE_TYPE_PARAMETER_PACK (auto_node) = true;
   else
type = do_auto_deduction (type, expr, auto_node);
 }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index abbba7c6746..607753ae6b7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -3940,7 +3940,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, 
void* data)
 parameter pack (14.6.3), or the type-specifier-seq of a type-id that
 is a pack expansion, the invented template parameter is a template
 parameter pack.  */
-  if (ppd->type_pack_expansion_p && is_auto (t)
+  if (flag_concepts_ts && ppd->type_pack_expansion_p && is_auto (t)
  && TEMPLATE_TYPE_LEVEL (t) != 0)
TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
   if (TEMPLATE_TYPE_PARAMETER_PACK (t))
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C 
b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
index cedd661710c..4162361d14f 100644
--- a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
@@ -1,7 +1,7 @@
 // PR c++/103497
 // { dg-do compile { target c++14 } }
 
-void foo(decltype(auto)... args);  // { dg-error "cannot declare a parameter 
with .decltype.auto.." }
+void foo(decltype(auto)... args);  // { dg-error "contains no parameter packs" 
}
 
 int main() {
   foo();
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C
new file mode 100644
index 000..efd4bb45d58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C
@@ -0,0 +1,15 @@
+// PR c++/115378
+// { dg-do compile { target c++20 } }
+
+struct tt {};
+
+template
+constexpr auto __counter = 1;
+
+template 
+using _as_base = tt;
+
+template 
+struct env : _as_base>... {};
+
+env t;
diff --git a/gcc/testsuite/g++.dg/template/pr95672.C 
b/gcc/testsuite/g++.dg/template/pr95672.C
index c752b4a2c08..d97b8db2e97 100644
--- a/gcc/testsuite/g++.dg/template/pr95672.C
+++ b/gcc/testsuite/g++.dg/template/pr95672.C
@@ -1,3 +1,3 @@
 // PR c++/95672
 // { dg-do compile { target c++14 } }
-struct g_class : decltype  (auto) ... {  }; // { dg-error "invalid use of pack 
expansion" }
+struct g_class : decltype  (auto) ... {  }; // { dg-error "contains no 
parameter packs" }


[gcc r15-892] c++: canonicity of fn types w/ instantiated eh specs [PR115223]

2024-05-29 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:58b8c87b7fb281e35a6817cc91a292096fdc02dc

commit r15-892-g58b8c87b7fb281e35a6817cc91a292096fdc02dc
Author: Patrick Palka 
Date:   Wed May 29 04:49:37 2024 -0400

c++: canonicity of fn types w/ instantiated eh specs [PR115223]

When propagating structural equality in build_cp_fntype_variant, we
should consider structural equality of the exception-less variant, not
of the given type which might use structural equality only because it
has a (complex) noexcept-spec that we're intending to replace, as in
maybe_instantiate_noexcept which calls build_exception_variant using
the deferred-noexcept function type.  Otherwise we might pessimistically
use structural equality for a function type with a simple instantiated
noexcept-spec, leading to a LTO-triggered type verification failure if we
later use that (structural-equality) type as the canonical version of
some other variant.

PR c++/115223

gcc/cp/ChangeLog:

* tree.cc (build_cp_fntype_variant): Propagate structural
equality of the exception-less variant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept87.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/tree.cc  |  4 
 gcc/testsuite/g++.dg/cpp0x/noexcept87.C | 11 +++
 2 files changed, 15 insertions(+)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index fe3f034d000..72dd46e1bd1 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2796,6 +2796,10 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier 
rqual,
   bool complex_eh_spec_p = (cr && cr != noexcept_true_spec
&& !UNPARSED_NOEXCEPT_SPEC_P (cr));
 
+  if (!complex_eh_spec_p && TYPE_RAISES_EXCEPTIONS (type))
+/* We want to consider structural equality of the exception-less
+   variant since we'll be replacing the exception specification.  */
+type = build_cp_fntype_variant (type, rqual, /*raises=*/NULL_TREE, late);
   if (TYPE_STRUCTURAL_EQUALITY_P (type) || complex_eh_spec_p)
 /* Propagate structural equality.  And always use structural equality
for function types with a complex noexcept-spec since their identity
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept87.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept87.C
new file mode 100644
index 000..339569d15ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept87.C
@@ -0,0 +1,11 @@
+// PR c++/115223
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -flto }
+
+template
+void f() noexcept(bool(T() || true));
+
+void g() { f(); }
+
+using type = void;
+type callDestructorIfNecessary() noexcept {}


[gcc r15-779] c++: canonicity of fn types w/ complex eh specs [PR115159]

2024-05-22 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:3c98d06a9016a0fa3a806879bd168f13b8a606f8

commit r15-779-g3c98d06a9016a0fa3a806879bd168f13b8a606f8
Author: Patrick Palka 
Date:   Wed May 22 17:45:04 2024 -0400

c++: canonicity of fn types w/ complex eh specs [PR115159]

Here the member functions QList::g and QList::h are given the same
function type by build_cp_fntype_variant since their noexcept-specs are
equivalent according to cp_tree_equal.  In doing so however this means
that the function type of QList::h refers to a function parameter from
QList::g, which ends up confusing modules streaming.

I'm not sure if modules can be fixed to handle this situation, but
regardless it seems weird in principle that a function parameter can
escape in such a way.  The analogous situation with a trailing return
type and decltype

  auto g(QList &other) -> decltype(f(other));
  auto h(QList &other) -> decltype(f(other));

behaves better because we don't canonicalize decltype, and so the
function types of g and h are non-canonical and therefore not shared.

In light of this, it seems natural to treat function types with complex
noexcept-specs as non-canonical as well so that each such function
declaration is given a unique function type node.  (The main benefit of
type canonicalization is to speed up repeated type comparisons, but it
should be rare to repeatedly compare two otherwise compatible function
types with complex noexcept-specs.)

To that end, this patch strengthens the ce_exact case of comp_except_specs
to require identity instead of equivalence of the noexcept-spec so that
build_cp_fntype_variant doesn't reuse a variant when it shouldn't.  In
turn we need to use structural equality for types with a complex eh spec.
This lets us get rid of the tricky handling of canonical types when updating
unparsed noexcept-spec variants.

PR c++/115159

gcc/cp/ChangeLog:

* tree.cc (build_cp_fntype_variant): Always use structural
equality for types with a complex exception specification.
(fixup_deferred_exception_variants): Use structural equality
for adjusted variants.
* typeck.cc (comp_except_specs): Require == instead of
cp_tree_equal for ce_exact noexcept-spec comparison.

gcc/testsuite/ChangeLog:

* g++.dg/modules/noexcept-2_a.H: New test.
* g++.dg/modules/noexcept-2_b.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/tree.cc  | 48 ++---
 gcc/cp/typeck.cc|  4 ++-
 gcc/testsuite/g++.dg/modules/noexcept-2_a.H | 24 +++
 gcc/testsuite/g++.dg/modules/noexcept-2_b.C |  4 +++
 4 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 9d37d255d8d..4d87661b4ad 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2793,9 +2793,13 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier 
rqual,
 
   /* Canonicalize the exception specification.  */
   tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE;
+  bool complex_eh_spec_p = (cr && cr != noexcept_true_spec
+   && !UNPARSED_NOEXCEPT_SPEC_P (cr));
 
-  if (TYPE_STRUCTURAL_EQUALITY_P (type))
-/* Propagate structural equality. */
+  if (TYPE_STRUCTURAL_EQUALITY_P (type) || complex_eh_spec_p)
+/* Propagate structural equality.  And always use structural equality
+   for function types with a complex noexcept-spec since their identity
+   may depend on e.g. whether comparing_specializations is set.  */
 SET_TYPE_STRUCTURAL_EQUALITY (v);
   else if (TYPE_CANONICAL (type) != type || cr != raises || late)
 /* Build the underlying canonical type, since it is different
@@ -2812,55 +2816,23 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier 
rqual,
 /* TYPE is a function or method type with a deferred exception
specification that has been parsed to RAISES.  Fixup all the type
variants that are affected in place.  Via decltype &| noexcept
-   tricks, the unparsed spec could have escaped into the type system.
-   The general case is hard to fixup canonical types for.  */
+   tricks, the unparsed spec could have escaped into the type system.  */
 
 void
 fixup_deferred_exception_variants (tree type, tree raises)
 {
   tree original = TYPE_RAISES_EXCEPTIONS (type);
-  tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE;
 
   gcc_checking_assert (UNPARSED_NOEXCEPT_SPEC_P (original));
 
-  /* Though sucky, this walk will process the canonical variants
- first.  */
-  tree prev = NULL_TREE;
   for (tree variant = TYPE_MAIN_VARIANT (type);
-   variant; prev = variant, variant = TYPE_NEXT_VARIANT (variant))
+   variant; variant = TYPE_NEXT_VARIANT (variant))
 if (TYPE_RAISES_EXCEPTIONS (variant) == o

[gcc r14-10226] c++: folding non-dep enumerator from current inst [PR115139]

2024-05-21 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:caf43cc9e5c0b3265b55e5a0dc77fc55e9618c77

commit r14-10226-gcaf43cc9e5c0b3265b55e5a0dc77fc55e9618c77
Author: Patrick Palka 
Date:   Tue May 21 15:54:10 2024 -0400

c++: folding non-dep enumerator from current inst [PR115139]

After the tsubst_copy removal r14-4796-g3e3d73ed5e85e7 GCC 14 ICEs during
fold_non_dependent_expr for 'e1 | e2' below ultimately because we no
longer exit early when substituting the CONST_DECLs for e1 and e2 with
args=NULL_TREE and instead proceed to substitute the class context A
(also with args=NULL_TREE) which ends up ICEing from tsubst_pack_expansion
(due to processing_template_decl being cleared).

Incidentally, the ICE went away on trunk ever since the tsubst_aggr_type
removal r15-123-gf04dc89a991ddc since it changed the CONST_DECL case of
tsubst_expr to use tsubst to substitute the context, which short circuits
for empty args and so avoids the ICE.

This patch fixes this ICE for GCC 14 by narrowly restoring the early exit
for empty args that would've happened in tsubst_copy when substituting an
enumerator CONST_DECL.  We might as well apply this to trunk too, as a
small optimization.

PR c++/115139

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr) : Exit early if args
is empty.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent33.C: New test.

Reviewed-by: Marek Polacek 
Reviewed-by: Jason Merrill 
(cherry picked from commit f0c0bced62b9c728ed1e672747aa234d918da22c)

Diff:
---
 gcc/cp/pt.cc|  2 +-
 gcc/testsuite/g++.dg/template/non-dependent33.C | 13 +
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e9882f2a3e0..ba47620ec59 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21524,7 +21524,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
 
if (DECL_TEMPLATE_PARM_P (t))
  RETURN (RECUR (DECL_INITIAL (t)));
-   if (!uses_template_parms (DECL_CONTEXT (t)))
+   if (!args || !uses_template_parms (DECL_CONTEXT (t)))
  RETURN (t);
 
/* Unfortunately, we cannot just call lookup_name here.
diff --git a/gcc/testsuite/g++.dg/template/non-dependent33.C 
b/gcc/testsuite/g++.dg/template/non-dependent33.C
new file mode 100644
index 000..ea5b41fba93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent33.C
@@ -0,0 +1,13 @@
+// PR c++/115139
+// { dg-do compile { target c++11 } }
+
+template
+class A {
+  enum E {
+e1 = 1,
+e2 = 2,
+e3 = e1 | e2,
+  };
+};
+
+template class A;


[gcc r15-759] c++: folding non-dep enumerator from current inst [PR115139]

2024-05-21 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:f0c0bced62b9c728ed1e672747aa234d918da22c

commit r15-759-gf0c0bced62b9c728ed1e672747aa234d918da22c
Author: Patrick Palka 
Date:   Tue May 21 15:54:10 2024 -0400

c++: folding non-dep enumerator from current inst [PR115139]

After the tsubst_copy removal r14-4796-g3e3d73ed5e85e7 GCC 14 ICEs during
fold_non_dependent_expr for 'e1 | e2' below ultimately because we no
longer exit early when substituting the CONST_DECLs for e1 and e2 with
args=NULL_TREE and instead proceed to substitute the class context A
(also with args=NULL_TREE) which ends up ICEing from tsubst_pack_expansion
(due to processing_template_decl being cleared).

Incidentally, the ICE went away on trunk ever since the tsubst_aggr_type
removal r15-123-gf04dc89a991ddc since it changed the CONST_DECL case of
tsubst_expr to use tsubst to substitute the context, which short circuits
for empty args and so avoids the ICE.

This patch fixes this ICE for GCC 14 by narrowly restoring the early exit
for empty args that would've happened in tsubst_copy when substituting an
enumerator CONST_DECL.  We might as well apply this to trunk too, as a
small optimization.

PR c++/115139

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr) : Exit early if args
is empty.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent33.C: New test.

Reviewed-by: Marek Polacek 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc|  2 +-
 gcc/testsuite/g++.dg/template/non-dependent33.C | 13 +
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e77c48e463e..a95ce6eb3da 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21519,7 +21519,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
 
if (DECL_TEMPLATE_PARM_P (t))
  RETURN (RECUR (DECL_INITIAL (t)));
-   if (!uses_template_parms (DECL_CONTEXT (t)))
+   if (!args || !uses_template_parms (DECL_CONTEXT (t)))
  RETURN (t);
 
/* Unfortunately, we cannot just call lookup_name here.
diff --git a/gcc/testsuite/g++.dg/template/non-dependent33.C 
b/gcc/testsuite/g++.dg/template/non-dependent33.C
new file mode 100644
index 000..ea5b41fba93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent33.C
@@ -0,0 +1,13 @@
+// PR c++/115139
+// { dg-do compile { target c++11 } }
+
+template
+class A {
+  enum E {
+e1 = 1,
+e2 = 2,
+e3 = e1 | e2,
+  };
+};
+
+template class A;


[gcc r14-10221] c++: aggregate CTAD w/ paren init and bases [PR115114]

2024-05-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:a9837934203d41c96b5cf05e34f68c0d3311c973

commit r14-10221-ga9837934203d41c96b5cf05e34f68c0d3311c973
Author: Patrick Palka 
Date:   Fri May 17 09:02:52 2024 -0400

c++: aggregate CTAD w/ paren init and bases [PR115114]

During aggregate CTAD with paren init, we're accidentally overlooking
base classes since TYPE_FIELDS of a template type doesn't contain
corresponding base fields.  So we need to consider them separately.

PR c++/115114

gcc/cp/ChangeLog:

* pt.cc (maybe_aggr_guide): Consider bases in the paren init case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-aggr15.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 5aaf47cb1987bbc5508c4b9b7dad5ea7d69af2c2)

Diff:
---
 gcc/cp/pt.cc   |  7 +++
 .../g++.dg/cpp2a/class-deduction-aggr15.C  | 23 ++
 2 files changed, 30 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b5c494e8d15e..e9882f2a3e0a 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30205,6 +30205,13 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
   else if (TREE_CODE (init) == TREE_LIST)
 {
   int len = list_length (init);
+  for (tree binfo : BINFO_BASE_BINFOS (TYPE_BINFO (template_type)))
+   {
+ if (!len)
+   break;
+ parms = tree_cons (NULL_TREE, BINFO_TYPE (binfo), parms);
+ --len;
+   }
   for (tree field = TYPE_FIELDS (template_type);
   len;
   --len, field = DECL_CHAIN (field))
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C
new file mode 100644
index ..16dc0f52b64c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C
@@ -0,0 +1,23 @@
+// PR c++/115114
+// { dg-do compile { target c++20 } }
+
+struct X {} x;
+struct Y {} y;
+
+template
+struct A : T {
+  U m;
+};
+
+using ty1 = decltype(A{x, 42}); // OK
+using ty1 = decltype(A(x, 42)); // OK, used to fail
+using ty1 = A;
+
+template
+struct B : T, V {
+  U m = 42;
+};
+
+using ty2 = decltype(B{x, y}); // OK
+using ty2 = decltype(B(x, y)); // OK, used to fail
+using ty2 = B;


[gcc r14-10220] c++: lvalueness of non-dependent assignment expr [PR114994]

2024-05-20 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:b3399b445ba7495b0479d43f2389e64d48de870e

commit r14-10220-gb3399b445ba7495b0479d43f2389e64d48de870e
Author: Patrick Palka 
Date:   Tue May 14 22:55:16 2024 -0400

c++: lvalueness of non-dependent assignment expr [PR114994]

r14-4111-g6e92a6a2a72d3b made us check non-dependent simple assignment
expressions ahead of time and give them a type, as was already done for
compound assignments.  Unlike for compound assignments however, if a
simple assignment resolves to an operator overload we represent it as a
(typed) MODOP_EXPR instead of a CALL_EXPR to the selected overload.
(I reckoned this was at worst a pessimization -- we'll just have to repeat
overload resolution at instantiatiation time.)

But this turns out to break the below testcase ultimately because
MODOP_EXPR (of non-reference type) is always treated as an lvalue
according to lvalue_kind, which is incorrect for the MODOP_EXPR
representing x=42.

We can fix this by representing such class assignment expressions as
CALL_EXPRs as well, but this turns out to require some tweaking of our
-Wparentheses warning logic and may introduce other fallout making it
unsuitable for backporting.

So this patch instead fixes lvalue_kind to consider the type of a
MODOP_EXPR representing a class assignment.

PR c++/114994

gcc/cp/ChangeLog:

* tree.cc (lvalue_kind) : For a class
assignment, consider the result type.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent32.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit c6cc6d4741a880109c4e0e64d5a189687fb526f6)

Diff:
---
 gcc/cp/tree.cc  |  5 -
 gcc/testsuite/g++.dg/template/non-dependent32.C | 18 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe8179..9d37d255d8d5 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,7 +275,10 @@ lvalue_kind (const_tree ref)
   /* We expect to see unlowered MODOP_EXPRs only during
 template processing.  */
   gcc_assert (processing_template_decl);
-  return clk_ordinary;
+  if (CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0
+   goto default_;
+  else
+   return clk_ordinary;
 
 case MODIFY_EXPR:
 case TYPEID_EXPR:
diff --git a/gcc/testsuite/g++.dg/template/non-dependent32.C 
b/gcc/testsuite/g++.dg/template/non-dependent32.C
new file mode 100644
index ..54252c7dfaf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent32.C
@@ -0,0 +1,18 @@
+// PR c++/114994
+// { dg-do compile { target c++11 } }
+
+struct udl_arg {
+  udl_arg operator=(int);
+};
+
+void f(udl_arg&&);
+
+template
+void g() {
+  udl_arg x;
+  f(x=42); // { dg-bogus "cannot bind" }
+}
+
+int main() {
+  g();
+}


[gcc r15-630] c++: aggregate CTAD w/ paren init and bases [PR115114]

2024-05-17 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:5aaf47cb1987bbc5508c4b9b7dad5ea7d69af2c2

commit r15-630-g5aaf47cb1987bbc5508c4b9b7dad5ea7d69af2c2
Author: Patrick Palka 
Date:   Fri May 17 09:02:52 2024 -0400

c++: aggregate CTAD w/ paren init and bases [PR115114]

During aggregate CTAD with paren init, we're accidentally overlooking
base classes since TYPE_FIELDS of a template type doesn't contain
corresponding base fields.  So we need to consider them separately.

PR c++/115114

gcc/cp/ChangeLog:

* pt.cc (maybe_aggr_guide): Consider bases in the paren init case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-aggr15.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc   |  7 +++
 .../g++.dg/cpp2a/class-deduction-aggr15.C  | 23 ++
 2 files changed, 30 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 32640f8e946d..e77c48e463e2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30200,6 +30200,13 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
   else if (TREE_CODE (init) == TREE_LIST)
 {
   int len = list_length (init);
+  for (tree binfo : BINFO_BASE_BINFOS (TYPE_BINFO (template_type)))
+   {
+ if (!len)
+   break;
+ parms = tree_cons (NULL_TREE, BINFO_TYPE (binfo), parms);
+ --len;
+   }
   for (tree field = TYPE_FIELDS (template_type);
   len;
   --len, field = DECL_CHAIN (field))
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C
new file mode 100644
index ..16dc0f52b64c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C
@@ -0,0 +1,23 @@
+// PR c++/115114
+// { dg-do compile { target c++20 } }
+
+struct X {} x;
+struct Y {} y;
+
+template
+struct A : T {
+  U m;
+};
+
+using ty1 = decltype(A{x, 42}); // OK
+using ty1 = decltype(A(x, 42)); // OK, used to fail
+using ty1 = A;
+
+template
+struct B : T, V {
+  U m = 42;
+};
+
+using ty2 = decltype(B{x, y}); // OK
+using ty2 = decltype(B(x, y)); // OK, used to fail
+using ty2 = B;


[gcc r15-498] c++: lvalueness of non-dependent assignment expr [PR114994]

2024-05-14 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:c6cc6d4741a880109c4e0e64d5a189687fb526f6

commit r15-498-gc6cc6d4741a880109c4e0e64d5a189687fb526f6
Author: Patrick Palka 
Date:   Tue May 14 22:55:16 2024 -0400

c++: lvalueness of non-dependent assignment expr [PR114994]

r14-4111-g6e92a6a2a72d3b made us check non-dependent simple assignment
expressions ahead of time and give them a type, as was already done for
compound assignments.  Unlike for compound assignments however, if a
simple assignment resolves to an operator overload we represent it as a
(typed) MODOP_EXPR instead of a CALL_EXPR to the selected overload.
(I reckoned this was at worst a pessimization -- we'll just have to repeat
overload resolution at instantiatiation time.)

But this turns out to break the below testcase ultimately because
MODOP_EXPR (of non-reference type) is always treated as an lvalue
according to lvalue_kind, which is incorrect for the MODOP_EXPR
representing x=42.

We can fix this by representing such class assignment expressions as
CALL_EXPRs as well, but this turns out to require some tweaking of our
-Wparentheses warning logic and may introduce other fallout making it
unsuitable for backporting.

So this patch instead fixes lvalue_kind to consider the type of a
MODOP_EXPR representing a class assignment.

PR c++/114994

gcc/cp/ChangeLog:

* tree.cc (lvalue_kind) : For a class
assignment, consider the result type.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent32.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/tree.cc  |  5 -
 gcc/testsuite/g++.dg/template/non-dependent32.C | 18 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe8179..9d37d255d8d5 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,7 +275,10 @@ lvalue_kind (const_tree ref)
   /* We expect to see unlowered MODOP_EXPRs only during
 template processing.  */
   gcc_assert (processing_template_decl);
-  return clk_ordinary;
+  if (CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0
+   goto default_;
+  else
+   return clk_ordinary;
 
 case MODIFY_EXPR:
 case TYPEID_EXPR:
diff --git a/gcc/testsuite/g++.dg/template/non-dependent32.C 
b/gcc/testsuite/g++.dg/template/non-dependent32.C
new file mode 100644
index ..54252c7dfaf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent32.C
@@ -0,0 +1,18 @@
+// PR c++/114994
+// { dg-do compile { target c++11 } }
+
+struct udl_arg {
+  udl_arg operator=(int);
+};
+
+void f(udl_arg&&);
+
+template
+void g() {
+  udl_arg x;
+  f(x=42); // { dg-bogus "cannot bind" }
+}
+
+int main() {
+  g();
+}


[gcc r13-8767] c++: build_extra_args recapturing local specs [PR114303]

2024-05-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:47cac09307874ff1d640392e3d986453f34f7bcb

commit r13-8767-g47cac09307874ff1d640392e3d986453f34f7bcb
Author: Patrick Palka 
Date:   Thu Apr 11 10:16:41 2024 -0400

c++: build_extra_args recapturing local specs [PR114303]

r13-6452-g341e6cd8d603a3 made build_extra_args walk evaluated contexts
first so that we prefer processing a local specialization in an evaluated
context even if its first use is in an unevaluated context.  But this
means we need to avoid walking a tree that already has extra args/specs
saved because the list of saved specs appears to be an evaluated
context which we'll now walk first.  It seems then that we should be
calculating the saved specs from scratch each time, rather than
potentially walking the saved specs list from an earlier partial
instantiation when calling build_extra_args a second time around.

PR c++/114303

gcc/cp/ChangeLog:

* constraint.cc (tsubst_requires_expr): Clear
REQUIRES_EXPR_EXTRA_ARGS before calling build_extra_args.
* pt.cc (tree_extra_args): Define.
(extract_locals_r): Assert *_EXTRA_ARGS is empty.
(tsubst_stmt) : Clear IF_SCOPE on the new
IF_STMT.  Call build_extra_args on the new IF_STMT instead
of t which might already have IF_STMT_EXTRA_ARGS.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/constexpr-if-lambda6.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit b262b17636e47ae969a74f16e86ccb00678d5e88)

Diff:
---
 gcc/cp/constraint.cc  |  1 +
 gcc/cp/pt.cc  | 31 ++-
 gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda6.C | 16 
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 83df57dc6fd7..67fe2ae17cd8 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2370,6 +2370,7 @@ tsubst_requires_expr (tree t, tree args, sat_info info)
 matching or dguide constraint rewriting), in which case we need
 to partially substitute.  */
   t = copy_node (t);
+  REQUIRES_EXPR_EXTRA_ARGS (t) = NULL_TREE;
   REQUIRES_EXPR_EXTRA_ARGS (t) = build_extra_args (t, args, info.complain);
   return t;
 }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index fa660fcf49ee..3af705c647a0 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -3861,6 +3861,24 @@ has_extra_args_mechanism_p (const_tree t)
  && IF_STMT_CONSTEXPR_P (t))); /* IF_STMT_EXTRA_ARGS  */
 }
 
+/* Return *_EXTRA_ARGS of the given supported tree T.  */
+
+static tree&
+tree_extra_args (tree t)
+{
+  gcc_checking_assert (has_extra_args_mechanism_p (t));
+
+  if (PACK_EXPANSION_P (t))
+return PACK_EXPANSION_EXTRA_ARGS (t);
+  else if (TREE_CODE (t) == REQUIRES_EXPR)
+return REQUIRES_EXPR_EXTRA_ARGS (t);
+  else if (TREE_CODE (t) == IF_STMT
+  && IF_STMT_CONSTEXPR_P (t))
+return IF_STMT_EXTRA_ARGS (t);
+
+  gcc_unreachable ();
+}
+
 /* Structure used to track the progress of find_parameter_packs_r.  */
 struct find_parameter_pack_data
 {
@@ -13185,6 +13203,16 @@ extract_locals_r (tree *tp, int *walk_subtrees, void 
*data_)
 /* Remember local typedefs (85214).  */
 tp = &TYPE_NAME (*tp);
 
+  if (has_extra_args_mechanism_p (*tp))
+/* Assert *_EXTRA_ARGS is empty, because we don't want to walk it and
+   potentially see a previously captured local in an evaluated context
+   that's really only used in an unevaluated context (PR114303).  This
+   means callers of build_extra_args need to clear *_EXTRA_ARGS of the
+   outermost tree.  Nested *_EXTRA_ARGS should naturally be empty since
+   the outermost (extra-args) tree will intercept any substitution before
+   a nested tree can.  */
+gcc_checking_assert (tree_extra_args (*tp) == NULL_TREE);
+
   if (TREE_CODE (*tp) == DECL_EXPR)
 {
   tree decl = DECL_EXPR_DECL (*tp);
@@ -19189,10 +19217,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
 of the constexpr if is still dependent.  Don't substitute into the
 branches now, just remember the template arguments.  */
  do_poplevel (IF_SCOPE (stmt));
+ IF_SCOPE (stmt) = NULL_TREE;
  IF_COND (stmt) = IF_COND (t);
  THEN_CLAUSE (stmt) = THEN_CLAUSE (t);
  ELSE_CLAUSE (stmt) = ELSE_CLAUSE (t);
- IF_STMT_EXTRA_ARGS (stmt) = build_extra_args (t, args, complain);
+ IF_STMT_EXTRA_ARGS (stmt) = build_extra_args (stmt, args, complain);
  add_stmt (stmt);
  break;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda6.C 
b/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda6.C
new file mode 100644
index ..038c2a41210f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda6.C
@@ -0,0 +1,16 @@
+// PR c

[gcc r15-438] c++: replace tf_norm with a local flag

2024-05-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:67476ba8adb432033993f429b1aa4ee5689fa046

commit r15-438-g67476ba8adb432033993f429b1aa4ee5689fa046
Author: Patrick Palka 
Date:   Mon May 13 15:46:55 2024 -0400

c++: replace tf_norm with a local flag

The tf_norm flag controlling whether to build diagnostic information
during constraint normalization doesn't need to be a global tsubst flag,
and is confusingly named.  This patch replaces it with a boolean flag
local to normalization.

gcc/cp/ChangeLog:

* constraint.cc (norm_info::norm_info): Take a bool instead of
tsubst_flags_t.
(norm_info::generate_diagnostics): Turn this predicate function
into a bool data member.
(normalize_logical_operation): Adjust after norm_info changes.
(normalize_concept_check): Likewise.
(normalize_atom): Likewise.
(get_normalized_constraints_from_info): Likewise.
(normalize_concept_definition): Likewise.
(normalize_constraint_expression): Likewise.
(normalize_placeholder_type_constraints): Likewise.
(satisfy_nondeclaration_constraints): Likewise.
* cp-tree.h (enum tsubst_flags): Remove tf_norm.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constraint.cc | 40 
 gcc/cp/cp-tree.h |  3 +--
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8679d3ce658d..ebf4255e546e 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -622,33 +622,29 @@ parameter_mapping_equivalent_p (tree t1, tree t2)
 
 struct norm_info : subst_info
 {
-  explicit norm_info (tsubst_flags_t cmp)
-: norm_info (NULL_TREE, cmp)
+  explicit norm_info (bool diag)
+: norm_info (NULL_TREE, diag)
   {}
 
   /* Construct a top-level context for DECL.  */
 
-  norm_info (tree in_decl, tsubst_flags_t complain)
-: subst_info (tf_warning_or_error | complain, in_decl)
+  norm_info (tree in_decl, bool diag)
+: subst_info (tf_warning_or_error, in_decl),
+  generate_diagnostics (diag)
   {
 if (in_decl)
   {
initial_parms = DECL_TEMPLATE_PARMS (in_decl);
-   if (generate_diagnostics ())
+   if (generate_diagnostics)
  context = build_tree_list (NULL_TREE, in_decl);
   }
 else
   initial_parms = current_template_parms;
   }
 
-  bool generate_diagnostics() const
-  {
-return complain & tf_norm;
-  }
-
   void update_context(tree expr, tree args)
   {
-if (generate_diagnostics ())
+if (generate_diagnostics)
   {
tree map = build_parameter_mapping (expr, args, ctx_parms ());
context = tree_cons (map, expr, context);
@@ -679,6 +675,10 @@ struct norm_info : subst_info
  template parameters of ORIG_DECL.  */
 
   tree initial_parms = NULL_TREE;
+
+  /* Whether to build diagnostic information during normalization.  */
+
+  bool generate_diagnostics;
 };
 
 static tree normalize_expression (tree, tree, norm_info);
@@ -693,7 +693,7 @@ normalize_logical_operation (tree t, tree args, tree_code 
c, norm_info info)
   tree t1 = normalize_expression (TREE_OPERAND (t, 1), args, info);
 
   /* Build a new info object for the constraint.  */
-  tree ci = info.generate_diagnostics()
+  tree ci = info.generate_diagnostics
 ? build_tree_list (t, info.context)
 : NULL_TREE;
 
@@ -777,7 +777,7 @@ normalize_concept_check (tree check, tree args, norm_info 
info)
   if (!norm_cache)
 norm_cache = hash_table::create_ggc (31);
   norm_entry *entry = nullptr;
-  if (!info.generate_diagnostics ())
+  if (!info.generate_diagnostics)
 {
   /* Cache the normal form of the substituted concept-id (when not
 diagnosing).  */
@@ -831,7 +831,7 @@ normalize_atom (tree t, tree args, norm_info info)
   if (info.in_decl && concept_definition_p (info.in_decl))
 ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P (atom) = true;
 
-  if (!info.generate_diagnostics ())
+  if (!info.generate_diagnostics)
 {
   /* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal
 later can cheaply compare two atoms using just pointer equality.  */
@@ -910,7 +910,7 @@ get_normalized_constraints_from_info (tree ci, tree 
in_decl, bool diag = false)
 
   /* Substitution errors during normalization are fatal.  */
   ++processing_template_decl;
-  norm_info info (in_decl, diag ? tf_norm : tf_none);
+  norm_info info (in_decl, diag);
   tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci), info);
   --processing_template_decl;
 
@@ -1012,7 +1012,7 @@ normalize_concept_definition (tree tmpl, bool diag)
   gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
   tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl));
   ++processing_template_decl;
-  norm_info info (tmpl, diag ? tf_norm : tf_none);
+  norm_info info (tmpl, diag);
   tree norm = get_normalized_constraints (def, info);
   --processing_

[gcc r13-8765] c++: constexpr union member access folding [PR114709]

2024-05-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:d3659e2dfcc6db83391cd2c6d70097cba35eb4b9

commit r13-8765-gd3659e2dfcc6db83391cd2c6d70097cba35eb4b9
Author: Patrick Palka 
Date:   Wed Apr 24 17:49:56 2024 -0400

c++: constexpr union member access folding [PR114709]

The object/offset canonicalization performed in cxx_fold_indirect_ref
is undesirable for union member accesses because it loses information
about the member being accessed which we may later need to diagnose an
inactive-member access.  So this patch restricts the canonicalization
accordingly.

PR c++/114709

gcc/cp/ChangeLog:

* constexpr.cc (cxx_fold_indirect_ref): Restrict object/offset
canonicalization to RECORD_TYPE member accesses.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-union8.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 0844170e9ef60a8b2f6fba6786672f30ce1c2749)

Diff:
---
 gcc/cp/constexpr.cc   | 3 +++
 gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C | 8 
 2 files changed, 11 insertions(+)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index acb5496085bb..12dd9010148e 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -5547,6 +5547,9 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, 
location_t loc, tree type,
  more folding opportunities.  */
   auto canonicalize_obj_off = [] (tree& obj, tree& off) {
 while (TREE_CODE (obj) == COMPONENT_REF
+  /* We need to preserve union member accesses so that we can
+ later properly diagnose accessing the wrong member.  */
+  && TREE_CODE (TREE_TYPE (TREE_OPERAND (obj, 0))) == RECORD_TYPE
   && (tree_int_cst_sign_bit (off) || integer_zerop (off)))
   {
tree field = TREE_OPERAND (obj, 1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C
new file mode 100644
index ..34c264944b68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C
@@ -0,0 +1,8 @@
+// PR c++/114709
+// { dg-do compile { target c++11 } }
+
+struct T1 { int a, b; };
+struct T2 { int c; double d; };
+union U { T1 t1; T2 t2; };
+
+constexpr int v = U{{1,2}}.t2.*&T2::c; // { dg-error "accessing 'U::t2'" }


[gcc r14-10201] c++: nested aggregate/alias CTAD fixes [PR114974, PR114901, PR114903]

2024-05-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:57cd8665fea4c339369a43be017583621aa82fed

commit r14-10201-g57cd8665fea4c339369a43be017583621aa82fed
Author: Patrick Palka 
Date:   Mon May 13 09:53:40 2024 -0400

c++: nested aggregate/alias CTAD fixes [PR114974, PR114901, PR114903]

During maybe_aggr_guide with a nested class template and paren init,
like with list init we need to consider the generic template type rather
than the partially instantiated type since partial instantiations don't
have (partially instantiated) TYPE_FIELDS.  In turn we need to partially
substitute PARMs in the paren init case as well.  As a drive-by improvement
it seems better to use outer_template_args instead of DECL_TI_ARGS during
this partial substitution so that we lower instead of substitute the
innermost template parameters, which is generally more robust.

And during alias_ctad_tweaks with a nested class template, even though
the guides may be already partially instantiated we still need to
substitute the outermost arguments into its constraints.

PR c++/114974
PR c++/114901
PR c++/114903

gcc/cp/ChangeLog:

* pt.cc (maybe_aggr_guide): Fix obtaining TYPE_FIELDS in
the paren init case.  Hoist out partial substitution logic
to apply to the paren init case as well.
(alias_ctad_tweaks): Substitute outer template arguments into
a guide's constraints.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-aggr14.C: New test.
* g++.dg/cpp2a/class-deduction-alias20.C: New test.
* g++.dg/cpp2a/class-deduction-alias21.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 6d31a370e26eeb950c326332633b3e8e84b6630b)

Diff:
---
 gcc/cp/pt.cc   | 39 --
 .../g++.dg/cpp2a/class-deduction-aggr14.C  | 11 ++
 .../g++.dg/cpp2a/class-deduction-alias20.C | 22 
 .../g++.dg/cpp2a/class-deduction-alias21.C | 38 +
 4 files changed, 93 insertions(+), 17 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3b2106dd3f65..b5c494e8d15e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30201,26 +30201,11 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
   if (init == error_mark_node)
return NULL_TREE;
   parms = collect_ctor_idx_types (init, parms);
-  /* If we're creating a deduction guide for a member class template,
-we've used the original template pattern type for the reshape_init
-above; this is done because we want PARMS to be a template parameter
-type, something that can be deduced when used as a function template
-parameter.  At this point the outer class template has already been
-partially instantiated (we deferred the deduction until the enclosing
-scope is non-dependent).  Therefore we have to partially instantiate
-PARMS, so that its template level is properly reduced and we don't get
-mismatches when deducing types using the guide with PARMS.  */
-  if (member_template_p)
-   {
- ++processing_template_decl;
- parms = tsubst (parms, DECL_TI_ARGS (tmpl), complain, init);
- --processing_template_decl;
-   }
 }
   else if (TREE_CODE (init) == TREE_LIST)
 {
   int len = list_length (init);
-  for (tree field = TYPE_FIELDS (type);
+  for (tree field = TYPE_FIELDS (template_type);
   len;
   --len, field = DECL_CHAIN (field))
{
@@ -30235,6 +30220,22 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
 /* Aggregate initialization doesn't apply to an initializer expression.  */
 return NULL_TREE;
 
+  /* If we're creating a deduction guide for a member class template,
+ we've used the original template pattern type for the reshape_init
+ above; this is done because we want PARMS to be a template parameter
+ type, something that can be deduced when used as a function template
+ parameter.  At this point the outer class template has already been
+ partially instantiated (we deferred the deduction until the enclosing
+ scope is non-dependent).  Therefore we have to partially instantiate
+ PARMS, so that its template level is properly reduced and we don't get
+ mismatches when deducing types using the guide with PARMS.  */
+  if (member_template_p)
+{
+  ++processing_template_decl;
+  parms = tsubst (parms, outer_template_args (tmpl), complain, init);
+  --processing_template_decl;
+}
+
   if (parms)
 {
   tree last = parms;
@@ -30426,7 +30427,11 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  /* Substitute the associated constraints.  */
  tree ci = get_constraints (f);
  if (ci)
-   ci = tsubst_constraint_info (ci, targs, complain, in_decl);
+  

[gcc r15-434] c++: nested aggregate/alias CTAD fixes [PR114974, PR114901, PR114903]

2024-05-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:6d31a370e26eeb950c326332633b3e8e84b6630b

commit r15-434-g6d31a370e26eeb950c326332633b3e8e84b6630b
Author: Patrick Palka 
Date:   Mon May 13 09:53:40 2024 -0400

c++: nested aggregate/alias CTAD fixes [PR114974, PR114901, PR114903]

During maybe_aggr_guide with a nested class template and paren init,
like with list init we need to consider the generic template type rather
than the partially instantiated type since partial instantiations don't
have (partially instantiated) TYPE_FIELDS.  In turn we need to partially
substitute PARMs in the paren init case as well.  As a drive-by improvement
it seems better to use outer_template_args instead of DECL_TI_ARGS during
this partial substitution so that we lower instead of substitute the
innermost template parameters, which is generally more robust.

And during alias_ctad_tweaks with a nested class template, even though
the guides may be already partially instantiated we still need to
substitute the outermost arguments into its constraints.

PR c++/114974
PR c++/114901
PR c++/114903

gcc/cp/ChangeLog:

* pt.cc (maybe_aggr_guide): Fix obtaining TYPE_FIELDS in
the paren init case.  Hoist out partial substitution logic
to apply to the paren init case as well.
(alias_ctad_tweaks): Substitute outer template arguments into
a guide's constraints.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-aggr14.C: New test.
* g++.dg/cpp2a/class-deduction-alias20.C: New test.
* g++.dg/cpp2a/class-deduction-alias21.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc   | 39 --
 .../g++.dg/cpp2a/class-deduction-aggr14.C  | 11 ++
 .../g++.dg/cpp2a/class-deduction-alias20.C | 22 
 .../g++.dg/cpp2a/class-deduction-alias21.C | 38 +
 4 files changed, 93 insertions(+), 17 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a7d9fcf930e2..4b71e199d27f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30194,26 +30194,11 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
   if (init == error_mark_node)
return NULL_TREE;
   parms = collect_ctor_idx_types (init, parms);
-  /* If we're creating a deduction guide for a member class template,
-we've used the original template pattern type for the reshape_init
-above; this is done because we want PARMS to be a template parameter
-type, something that can be deduced when used as a function template
-parameter.  At this point the outer class template has already been
-partially instantiated (we deferred the deduction until the enclosing
-scope is non-dependent).  Therefore we have to partially instantiate
-PARMS, so that its template level is properly reduced and we don't get
-mismatches when deducing types using the guide with PARMS.  */
-  if (member_template_p)
-   {
- ++processing_template_decl;
- parms = tsubst (parms, DECL_TI_ARGS (tmpl), complain, init);
- --processing_template_decl;
-   }
 }
   else if (TREE_CODE (init) == TREE_LIST)
 {
   int len = list_length (init);
-  for (tree field = TYPE_FIELDS (type);
+  for (tree field = TYPE_FIELDS (template_type);
   len;
   --len, field = DECL_CHAIN (field))
{
@@ -30228,6 +30213,22 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
 /* Aggregate initialization doesn't apply to an initializer expression.  */
 return NULL_TREE;
 
+  /* If we're creating a deduction guide for a member class template,
+ we've used the original template pattern type for the reshape_init
+ above; this is done because we want PARMS to be a template parameter
+ type, something that can be deduced when used as a function template
+ parameter.  At this point the outer class template has already been
+ partially instantiated (we deferred the deduction until the enclosing
+ scope is non-dependent).  Therefore we have to partially instantiate
+ PARMS, so that its template level is properly reduced and we don't get
+ mismatches when deducing types using the guide with PARMS.  */
+  if (member_template_p)
+{
+  ++processing_template_decl;
+  parms = tsubst (parms, outer_template_args (tmpl), complain, init);
+  --processing_template_decl;
+}
+
   if (parms)
 {
   tree last = parms;
@@ -30419,7 +30420,11 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  /* Substitute the associated constraints.  */
  tree ci = get_constraints (f);
  if (ci)
-   ci = tsubst_constraint_info (ci, targs, complain, in_decl);
+   {
+ if (tree outer_targs = outer_template_args (f))
+ 

[gcc r14-10176] c++/modules: imported spec befriending class tmpl [PR114889]

2024-05-07 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:390bd23fd9c98dc40856beef05364f5d1c7b9d04

commit r14-10176-g390bd23fd9c98dc40856beef05364f5d1c7b9d04
Author: Patrick Palka 
Date:   Mon Apr 29 21:27:59 2024 -0400

c++/modules: imported spec befriending class tmpl [PR114889]

When adding to CLASSTYPE_BEFRIENDING_CLASSES as part of installing an
imported class definition, we need to look through TEMPLATE_DECL like
make_friend_class does.

Otherwise in the below testcase we won't add _Hashtable to
CLASSTYPE_BEFRIENDING_CLASSES of _Map_base, which leads to a bogus
access check failure for _M_hash_code.

PR c++/114889

gcc/cp/ChangeLog:

* module.cc (trees_in::read_class_def): Look through
TEMPLATE_DECL when adding to CLASSTYPE_BEFRIENDING_CLASSES.

gcc/testsuite/ChangeLog:

* g++.dg/modules/friend-8_a.H: New test.
* g++.dg/modules/friend-8_b.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 22b20ac6c6aead2d3f36c413a77dd0b80adfec39)

Diff:
---
 gcc/cp/module.cc  |  2 ++
 gcc/testsuite/g++.dg/modules/friend-8_a.H | 23 +++
 gcc/testsuite/g++.dg/modules/friend-8_b.C |  9 +
 3 files changed, 34 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c35e70b8cb8..3bf863e15d4 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12498,6 +12498,8 @@ trees_in::read_class_def (tree defn, tree 
maybe_template)
  for (; friend_classes; friend_classes = TREE_CHAIN (friend_classes))
{
  tree f = TREE_VALUE (friend_classes);
+ if (TREE_CODE (f) == TEMPLATE_DECL)
+   f = TREE_TYPE (f);
 
  if (CLASS_TYPE_P (f))
{
diff --git a/gcc/testsuite/g++.dg/modules/friend-8_a.H 
b/gcc/testsuite/g++.dg/modules/friend-8_a.H
new file mode 100644
index 000..b07ea25adfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-8_a.H
@@ -0,0 +1,23 @@
+// PR c++/114889
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template
+struct _Hashtable;
+
+template
+struct _Map_base {
+  void f() {
+_Hashtable<_Key, _Val> __h;
+__h._M_hash_code(0);
+  }
+};
+
+template
+struct _Hashtable {
+  template friend struct _Map_base;
+protected:
+  void _M_hash_code(int);
+};
+
+inline _Hashtable m;
diff --git a/gcc/testsuite/g++.dg/modules/friend-8_b.C 
b/gcc/testsuite/g++.dg/modules/friend-8_b.C
new file mode 100644
index 000..b04280bc91a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-8_b.C
@@ -0,0 +1,9 @@
+// PR c++/114889
+// { dg-additional-options "-fmodules-ts" }
+
+import "friend-8_a.H";
+
+int main() {
+  _Map_base m;
+  m.f();
+}


[gcc r15-123] c++: remove lookup_template_class's entering_scope flag

2024-05-02 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:f04dc89a991ddc6c08ac92c8ad29c6915c4ecafa

commit r15-123-gf04dc89a991ddc6c08ac92c8ad29c6915c4ecafa
Author: Patrick Palka 
Date:   Thu May 2 21:14:30 2024 -0400

c++: remove lookup_template_class's entering_scope flag

lookup_template_class's entering_scope flag controls whether to prefer
returning the primary template type A instead of the corresponding
implicit instantiation A.  When we want to set this flag as part of
substitution, we need to use tsubst_aggr_type which also takes this flag
as a parameter.  But having this separate entry point to type substitution
turned out to be subtly problematic because it doesn't reuse typedefs
like tsubst does, which r13-4729-gbe124477b38a71 fixed in a way that
respects the flag after the fact, by adjusting the entering_scope=false
result of lookup_template_class as if entering_scope=true was passed.

But if that's possible then it means lookup_template_class's
entering_scope flag is not necessary after all -- we can just do the
after-the-fact adjustment everywhere that we currently pass
entering_scope=true to it and tsubst_aggr_type.

To that end, this patch replaces this flag with an adjustment function
adjust_type_for_entering_scope, to be used whereever we currently need
the entering_scope=true behavior.  In turn we can get rid of
tsubst_aggr_type since the only reason we needed this entry point
was to be able to pass entering_scope=true to lookup_template_class.

gcc/cp/ChangeLog:

* coroutines.cc (instantiate_coro_traits): Adjust call to
lookup_template_class.
(instantiate_coro_handle_for_promise_type): Likewise.
* cp-tree.h (adjust_type_for_entering_scope): Declare.
(lookup_template_class): Adjust declaration.
* decl.cc (make_typename_type): Adjust call to
lookup_template_class. Likewise.
(get_tuple_size): Likewise.
(get_tuple_element_type): Likewise.
* pt.cc (adjust_type_for_entering_scope): Define.
(tsubst_entering_scope): Define.
(lookup_template_class): Remove entering_scope parameter.
Replace tsubst_aggr_type call with tsubst_entering_scope.
(tsubst_aggr_type): Remove.
(tsubst_aggr_type_1): Inline into tsubst.
(tsubst_function_decl): Replace tsubst_aggr_type call
with tsubst_entering_scope.
(tsubst_template_decl): Likewise.
(tsubst_decl): Likewise.
(tsubst) :
Inlined from tsubst_aggr_type_1.
: Adjust calls to
lookup_template_class.
: Replace tsubst_aggr_type call with
tsubst_entering_scope.
: Likewise.
Increment processing_template_decl when substituting the
context.
(tsubst_expr) : Replace tsubst_aggr_type
call with tsubst_entering_scope.
: Likewise.
(instantiate_template): Likewise.
(resolve_typename_type): Adjust lookup_template_class call
and call adjust_type_for_entering_scope afterward.
(listify): Adjust lookup_template_class call.
(alias_ctad_tweaks): Likewise.
* semantics.cc (finish_template_type): Adjust lookup_template_class
call and maybe call adjust_type_for_entering_scope afterward.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/coroutines.cc |   4 +-
 gcc/cp/cp-tree.h |   3 +-
 gcc/cp/decl.cc   |   4 +-
 gcc/cp/pt.cc | 207 ---
 gcc/cp/semantics.cc  |   4 +-
 5 files changed, 88 insertions(+), 134 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index b05cb9eb330..97bc211ff67 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -353,7 +353,7 @@ instantiate_coro_traits (tree fndecl, location_t kw)
   tree traits_class
 = lookup_template_class (coro_traits_templ, targ,
 /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
-/*entering scope=*/false, tf_warning_or_error);
+tf_warning_or_error);
 
   if (traits_class == error_mark_node)
 {
@@ -400,7 +400,7 @@ instantiate_coro_handle_for_promise_type (location_t kw, 
tree promise_type)
 = lookup_template_class (coro_handle_identifier, targ,
 /* in_decl=*/NULL_TREE,
 /* context=*/std_node,
-/* entering scope=*/false, tf_warning_or_error);
+tf_warning_or_error);
 
   if (handle_type == error_mark_node)
 {
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 933504b4821..1ba7054f8bc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7524,8 +7524,9 @@ extern tree push_template_decl(tree, 
bool is_frien

[gcc r13-8670] c++: problematic assert in reference_binding [PR113141]

2024-05-01 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:c70abea054fe0021b7b2c2e07996afaadc17a07b

commit r13-8670-gc70abea054fe0021b7b2c2e07996afaadc17a07b
Author: Patrick Palka 
Date:   Wed May 1 18:16:08 2024 -0400

c++: problematic assert in reference_binding [PR113141]

r14-9946 / r14-9947 fixed this PR properly for GCC 14.

For GCC 13, let's just remove the problematic assert.

PR c++/113141

gcc/cp/ChangeLog:

* call.cc (reference_binding): Remove badness criteria sanity
check in the recursive case.

gcc/testsuite/ChangeLog:

* g++.dg/conversion/ref12.C: New test.
* g++.dg/cpp0x/initlist-ref1.C: new test.

Diff:
---
 gcc/cp/call.cc |  1 -
 gcc/testsuite/g++.dg/conversion/ref12.C| 13 +
 gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C | 16 
 3 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index b10bdc62d38..70c7f6178b8 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -2017,7 +2017,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool 
c_cast_p, int flags,
if (!new_second)
  return NULL;
conv = merge_conversion_sequences (t, new_second);
-   gcc_assert (maybe_valid_p || conv->bad_p);
return conv;
  }
 }
diff --git a/gcc/testsuite/g++.dg/conversion/ref12.C 
b/gcc/testsuite/g++.dg/conversion/ref12.C
new file mode 100644
index 000..633b7e48e47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref12.C
@@ -0,0 +1,13 @@
+// PR c++/113141
+
+struct Matrix { };
+
+struct TPoint3 { operator const Matrix(); };
+
+void f(Matrix&);
+
+int main() {
+  TPoint3 X;
+  Matrix& m = (Matrix &)X;
+  f((Matrix &)X);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C
new file mode 100644
index 000..f893f12dafa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C
@@ -0,0 +1,16 @@
+// PR c++/113141
+// { dg-do compile { target c++11 } }
+
+struct ConvToRef {
+  operator int&();
+};
+
+struct A { int& r; };
+
+void f(A);
+
+int main() {
+  ConvToRef c;
+  A a{{c}};
+  f({{c}});
+}


[gcc r15-57] c++/modules: imported spec befriending class tmpl [PR114889]

2024-04-29 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:22b20ac6c6aead2d3f36c413a77dd0b80adfec39

commit r15-57-g22b20ac6c6aead2d3f36c413a77dd0b80adfec39
Author: Patrick Palka 
Date:   Mon Apr 29 21:27:59 2024 -0400

c++/modules: imported spec befriending class tmpl [PR114889]

When adding to CLASSTYPE_BEFRIENDING_CLASSES as part of installing an
imported class definition, we need to look through TEMPLATE_DECL like
make_friend_class does.

Otherwise in the below testcase we won't add _Hashtable to
CLASSTYPE_BEFRIENDING_CLASSES of _Map_base, which leads to a bogus
access check failure for _M_hash_code.

PR c++/114889

gcc/cp/ChangeLog:

* module.cc (trees_in::read_class_def): Look through
TEMPLATE_DECL when adding to CLASSTYPE_BEFRIENDING_CLASSES.

gcc/testsuite/ChangeLog:

* g++.dg/modules/friend-8_a.H: New test.
* g++.dg/modules/friend-8_b.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/module.cc  |  2 ++
 gcc/testsuite/g++.dg/modules/friend-8_a.H | 23 +++
 gcc/testsuite/g++.dg/modules/friend-8_b.C |  9 +
 3 files changed, 34 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c35e70b8cb8..3bf863e15d4 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12498,6 +12498,8 @@ trees_in::read_class_def (tree defn, tree 
maybe_template)
  for (; friend_classes; friend_classes = TREE_CHAIN (friend_classes))
{
  tree f = TREE_VALUE (friend_classes);
+ if (TREE_CODE (f) == TEMPLATE_DECL)
+   f = TREE_TYPE (f);
 
  if (CLASS_TYPE_P (f))
{
diff --git a/gcc/testsuite/g++.dg/modules/friend-8_a.H 
b/gcc/testsuite/g++.dg/modules/friend-8_a.H
new file mode 100644
index 000..b07ea25adfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-8_a.H
@@ -0,0 +1,23 @@
+// PR c++/114889
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template
+struct _Hashtable;
+
+template
+struct _Map_base {
+  void f() {
+_Hashtable<_Key, _Val> __h;
+__h._M_hash_code(0);
+  }
+};
+
+template
+struct _Hashtable {
+  template friend struct _Map_base;
+protected:
+  void _M_hash_code(int);
+};
+
+inline _Hashtable m;
diff --git a/gcc/testsuite/g++.dg/modules/friend-8_b.C 
b/gcc/testsuite/g++.dg/modules/friend-8_b.C
new file mode 100644
index 000..b04280bc91a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-8_b.C
@@ -0,0 +1,9 @@
+// PR c++/114889
+// { dg-additional-options "-fmodules-ts" }
+
+import "friend-8_a.H";
+
+int main() {
+  _Map_base m;
+  m.f();
+}


[gcc r14-10149] c++: ICE with templated sizeof(E1) / sizeof(E2) [PR114888]

2024-04-29 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:3c925ac349b03ae9439c632fb1c042cdc8d78f40

commit r14-10149-g3c925ac349b03ae9439c632fb1c042cdc8d78f40
Author: Patrick Palka 
Date:   Mon Apr 29 21:14:18 2024 -0400

c++: ICE with templated sizeof(E1) / sizeof(E2) [PR114888]

In the sizeof / sizeof operator expression handling we're missing
a dependence check for the second operand.

PR c++/114888

gcc/cp/ChangeLog:

* typeck.cc (cp_build_binary_op) : Add missing
dependence check for the second sizeof operand.

gcc/testsuite/ChangeLog:

* g++.dg/template/sizeof19.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 3900e944b0ac9db77380c5bb8635977dfd3b0691)

Diff:
---
 gcc/cp/typeck.cc | 1 +
 gcc/testsuite/g++.dg/template/sizeof19.C | 8 
 2 files changed, 9 insertions(+)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index e5a52dc2b39..a25f8622651 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -5501,6 +5501,7 @@ cp_build_binary_op (const op_location_t &location,
  if (!TYPE_P (type1))
type1 = TREE_TYPE (type1);
  if (type0
+ && type1
  && INDIRECT_TYPE_P (type0)
  && same_type_p (TREE_TYPE (type0), type1))
{
diff --git a/gcc/testsuite/g++.dg/template/sizeof19.C 
b/gcc/testsuite/g++.dg/template/sizeof19.C
new file mode 100644
index 000..a1467995a9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sizeof19.C
@@ -0,0 +1,8 @@
+// PR c++/114888
+
+template
+struct A {
+  struct B {} *b;
+  static const int c = sizeof (b) / sizeof (b[0]);
+};
+const int d = A::c;


[gcc r15-56] c++: ICE with templated sizeof(E1) / sizeof(E2) [PR114888]

2024-04-29 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:3900e944b0ac9db77380c5bb8635977dfd3b0691

commit r15-56-g3900e944b0ac9db77380c5bb8635977dfd3b0691
Author: Patrick Palka 
Date:   Mon Apr 29 21:14:18 2024 -0400

c++: ICE with templated sizeof(E1) / sizeof(E2) [PR114888]

In the sizeof / sizeof operator expression handling we're missing
a dependence check for the second operand.

PR c++/114888

gcc/cp/ChangeLog:

* typeck.cc (cp_build_binary_op) : Add missing
dependence check for the second sizeof operand.

gcc/testsuite/ChangeLog:

* g++.dg/template/sizeof19.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/typeck.cc | 1 +
 gcc/testsuite/g++.dg/template/sizeof19.C | 8 
 2 files changed, 9 insertions(+)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index e5a52dc2b39..a25f8622651 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -5501,6 +5501,7 @@ cp_build_binary_op (const op_location_t &location,
  if (!TYPE_P (type1))
type1 = TREE_TYPE (type1);
  if (type0
+ && type1
  && INDIRECT_TYPE_P (type0)
  && same_type_p (TREE_TYPE (type0), type1))
{
diff --git a/gcc/testsuite/g++.dg/template/sizeof19.C 
b/gcc/testsuite/g++.dg/template/sizeof19.C
new file mode 100644
index 000..a1467995a9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sizeof19.C
@@ -0,0 +1,8 @@
+// PR c++/114888
+
+template
+struct A {
+  struct B {} *b;
+  static const int c = sizeof (b) / sizeof (b[0]);
+};
+const int d = A::c;


[gcc r14-10140] c++: fix source printing for "required from here" message

2024-04-26 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:c014cfd8853240827feb3a4cef92403e83cd4265

commit r14-10140-gc014cfd8853240827feb3a4cef92403e83cd4265
Author: Patrick Palka 
Date:   Fri Apr 26 07:44:25 2024 -0400

c++: fix source printing for "required from here" message

It seems the diagnostic machinery's source line printing respects
the pretty printer prefix, but this is undesirable for the call to
diagnostic_show_locus in print_instantiation_partial_context_line
(added in r14-4388-g1c45319b66edc9) since the prefix may have been
set when issuing an earlier, unrelated diagnostic and we just want
to print an unprefixed source line.

This patch naively fixes this by clearing the prefix before calling
diagnostic_show_locus.

Before this patch, for error60a.C below we'd print

gcc/testsuite/g++.dg/template/error60a.C: In function ‘void usage()’:
gcc/testsuite/g++.dg/template/error60a.C:24:3: error: ‘unrelated_error’ was 
not declared in this scope
   24 |   unrelated_error; // { dg-error "not declared" }
  |   ^~~
gcc/testsuite/g++.dg/template/error60a.C: In instantiation of ‘void 
test(Foo) [with Foo = int]’:
gcc/testsuite/g++.dg/template/error60a.C:25:13:   required from here
gcc/testsuite/g++.dg/template/error60a.C:24:3: error:25 |   test 
(42); // { dg-message " required from here" }
gcc/testsuite/g++.dg/template/error60a.C:24:3: error:   |   
~~^~~~
gcc/testsuite/g++.dg/template/error60a.C:19:24: error: invalid conversion 
from ‘int’ to ‘int*’ [-fpermissive]
   19 |   my_pointer ptr (val); // { dg-error "invalid conversion from 
'int' to 'int\\*'" }
  |^~~
  ||
  |int
gcc/testsuite/g++.dg/template/error60a.C:9:20: note:   initializing 
argument 1 of ‘my_pointer::my_pointer(Foo*) [with Foo = int]’
9 |   my_pointer (Foo *ptr) // { dg-message " initializing argument 1" }
  |   ~^~~

and afterward we print

gcc/testsuite/g++.dg/template/error60a.C: In function ‘void usage()’:
gcc/testsuite/g++.dg/template/error60a.C:24:3: error: ‘unrelated_error’ was 
not declared in this scope
   24 |   unrelated_error; // { dg-error "not declared" }
  |   ^~~
gcc/testsuite/g++.dg/template/error60a.C: In instantiation of ‘void 
test(Foo) [with Foo = int]’:
gcc/testsuite/g++.dg/template/error60a.C:25:13:   required from here
   25 |   test (42); // { dg-message " required from here" }
  |   ~~^~~~
gcc/testsuite/g++.dg/template/error60a.C:19:24: error: invalid conversion 
from ‘int’ to ‘int*’ [-fpermissive]
   19 |   my_pointer ptr (val); // { dg-error "invalid conversion from 
'int' to 'int\\*'" }
  |^~~
  ||
  |int
gcc/testsuite/g++.dg/template/error60a.C:9:20: note:   initializing 
argument 1 of ‘my_pointer::my_pointer(Foo*) [with Foo = int]’
9 |   my_pointer (Foo *ptr) // { dg-message " initializing argument 1" }
  |   ~^~~

gcc/cp/ChangeLog:

* error.cc (print_instantiation_partial_context_line): Clear the
pretty printer prefix around the call to diagnostic_show_locus.

gcc/testsuite/ChangeLog:

* g++.dg/concepts/diagnostic2.C: Expect source line printed
for the "required from here" message.
* g++.dg/template/error60a.C: New test.

(cherry picked from commit 7d5479a2ecf6309281de10b747a7423169a2ff95)

Diff:
---
 gcc/cp/error.cc |  2 ++
 gcc/testsuite/g++.dg/concepts/diagnostic2.C |  6 +++-
 gcc/testsuite/g++.dg/template/error60a.C| 46 +
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 7074845154e..37987ccb570 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -3793,7 +3793,9 @@ print_instantiation_partial_context_line 
(diagnostic_context *context,
   : _("required from here\n"));
 }
   gcc_rich_location rich_loc (loc);
+  char *saved_prefix = pp_take_prefix (context->printer);
   diagnostic_show_locus (context, &rich_loc, DK_NOTE);
+  pp_set_prefix (context->printer, saved_prefix);
 }
 
 /* Same as print_instantiation_full_context but less verbose.  */
diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic2.C 
b/gcc/testsuite/g++.dg/concepts/diagnostic2.C
index 6550ed6b3bd..d6f5872de2c 100644
--- a/gcc/testsuite/g++.dg/concepts/diagnostic2.C
+++ b/gcc/testsuite/g++.dg/concepts/diagnostic2.C
@@ -23,7 +23,11 @@ void
 baz()
 {
   bar(); // { dg-error "no match" }
-/* { dg-begin-multiline-output "" }
+/* { dg-begin-multiline-output "for no match error" }
+   bar();
+   ^~
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "for required 

[gcc r15-4] c++: fix source printing for "required from here" message

2024-04-26 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:7d5479a2ecf6309281de10b747a7423169a2ff95

commit r15-4-g7d5479a2ecf6309281de10b747a7423169a2ff95
Author: Patrick Palka 
Date:   Fri Apr 26 07:44:25 2024 -0400

c++: fix source printing for "required from here" message

It seems the diagnostic machinery's source line printing respects
the pretty printer prefix, but this is undesirable for the call to
diagnostic_show_locus in print_instantiation_partial_context_line
(added in r14-4388-g1c45319b66edc9) since the prefix may have been
set when issuing an earlier, unrelated diagnostic and we just want
to print an unprefixed source line.

This patch naively fixes this by clearing the prefix before calling
diagnostic_show_locus.

Before this patch, for error60a.C below we'd print

gcc/testsuite/g++.dg/template/error60a.C: In function ‘void usage()’:
gcc/testsuite/g++.dg/template/error60a.C:24:3: error: ‘unrelated_error’ was 
not declared in this scope
   24 |   unrelated_error; // { dg-error "not declared" }
  |   ^~~
gcc/testsuite/g++.dg/template/error60a.C: In instantiation of ‘void 
test(Foo) [with Foo = int]’:
gcc/testsuite/g++.dg/template/error60a.C:25:13:   required from here
gcc/testsuite/g++.dg/template/error60a.C:24:3: error:25 |   test 
(42); // { dg-message " required from here" }
gcc/testsuite/g++.dg/template/error60a.C:24:3: error:   |   
~~^~~~
gcc/testsuite/g++.dg/template/error60a.C:19:24: error: invalid conversion 
from ‘int’ to ‘int*’ [-fpermissive]
   19 |   my_pointer ptr (val); // { dg-error "invalid conversion from 
'int' to 'int\\*'" }
  |^~~
  ||
  |int
gcc/testsuite/g++.dg/template/error60a.C:9:20: note:   initializing 
argument 1 of ‘my_pointer::my_pointer(Foo*) [with Foo = int]’
9 |   my_pointer (Foo *ptr) // { dg-message " initializing argument 1" }
  |   ~^~~

and afterward we print

gcc/testsuite/g++.dg/template/error60a.C: In function ‘void usage()’:
gcc/testsuite/g++.dg/template/error60a.C:24:3: error: ‘unrelated_error’ was 
not declared in this scope
   24 |   unrelated_error; // { dg-error "not declared" }
  |   ^~~
gcc/testsuite/g++.dg/template/error60a.C: In instantiation of ‘void 
test(Foo) [with Foo = int]’:
gcc/testsuite/g++.dg/template/error60a.C:25:13:   required from here
   25 |   test (42); // { dg-message " required from here" }
  |   ~~^~~~
gcc/testsuite/g++.dg/template/error60a.C:19:24: error: invalid conversion 
from ‘int’ to ‘int*’ [-fpermissive]
   19 |   my_pointer ptr (val); // { dg-error "invalid conversion from 
'int' to 'int\\*'" }
  |^~~
  ||
  |int
gcc/testsuite/g++.dg/template/error60a.C:9:20: note:   initializing 
argument 1 of ‘my_pointer::my_pointer(Foo*) [with Foo = int]’
9 |   my_pointer (Foo *ptr) // { dg-message " initializing argument 1" }
  |   ~^~~

gcc/cp/ChangeLog:

* error.cc (print_instantiation_partial_context_line): Clear the
pretty printer prefix around the call to diagnostic_show_locus.

gcc/testsuite/ChangeLog:

* g++.dg/concepts/diagnostic2.C: Expect source line printed
for the "required from here" message.
* g++.dg/template/error60a.C: New test.

Diff:
---
 gcc/cp/error.cc |  2 ++
 gcc/testsuite/g++.dg/concepts/diagnostic2.C |  6 +++-
 gcc/testsuite/g++.dg/template/error60a.C| 46 +
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 7074845154e..37987ccb570 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -3793,7 +3793,9 @@ print_instantiation_partial_context_line 
(diagnostic_context *context,
   : _("required from here\n"));
 }
   gcc_rich_location rich_loc (loc);
+  char *saved_prefix = pp_take_prefix (context->printer);
   diagnostic_show_locus (context, &rich_loc, DK_NOTE);
+  pp_set_prefix (context->printer, saved_prefix);
 }
 
 /* Same as print_instantiation_full_context but less verbose.  */
diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic2.C 
b/gcc/testsuite/g++.dg/concepts/diagnostic2.C
index 6550ed6b3bd..d6f5872de2c 100644
--- a/gcc/testsuite/g++.dg/concepts/diagnostic2.C
+++ b/gcc/testsuite/g++.dg/concepts/diagnostic2.C
@@ -23,7 +23,11 @@ void
 baz()
 {
   bar(); // { dg-error "no match" }
-/* { dg-begin-multiline-output "" }
+/* { dg-begin-multiline-output "for no match error" }
+   bar();
+   ^~
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "for required from here message" }
bar();
^~
{ dg-end-multiline-output "" } 

[gcc r14-10111] c++/modules testsuite: restrict expensive pr99023 test

2024-04-24 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:26a3edbe2357cf975f345ad1b59b9f9a3444316e

commit r14-10111-g26a3edbe2357cf975f345ad1b59b9f9a3444316e
Author: Patrick Palka 
Date:   Wed Apr 24 17:51:54 2024 -0400

c++/modules testsuite: restrict expensive pr99023 test

The pr99023 testcase uses --param=ggc-min-expand=0 which forces a GC
during every collection point and consequently is very slow to run,
and ends up being the main bottleneck of the modules.exp testsuite.

So this patch restricts this test to run once, in C++20 mode, instead of
multiple times (C++17, C++20 and C++23 mode by default).  After this
patch the modules.exp testsuite finishes in 3m instead of 3m40s with -j8
on my machine.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99023_a.X: Run only in C++20 mode.
* g++.dg/modules/pr99023_b.X: Likewise.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/testsuite/g++.dg/modules/pr99023_a.X | 1 +
 gcc/testsuite/g++.dg/modules/pr99023_b.X | 1 +
 2 files changed, 2 insertions(+)

diff --git a/gcc/testsuite/g++.dg/modules/pr99023_a.X 
b/gcc/testsuite/g++.dg/modules/pr99023_a.X
index c872d15f792..507e9569535 100644
--- a/gcc/testsuite/g++.dg/modules/pr99023_a.X
+++ b/gcc/testsuite/g++.dg/modules/pr99023_a.X
@@ -1,4 +1,5 @@
 // PR c++/99023, ICE
+// { dg-require-effective-target c++20_only }
 // { dg-additional-options {-x c++-system-header initializer_list -fmodules-ts 
--param ggc-min-expand=0} }
 
 // { dg-prune-output {linker input file unused} }
diff --git a/gcc/testsuite/g++.dg/modules/pr99023_b.X 
b/gcc/testsuite/g++.dg/modules/pr99023_b.X
index ca5f32e5bcc..59d32bee8d5 100644
--- a/gcc/testsuite/g++.dg/modules/pr99023_b.X
+++ b/gcc/testsuite/g++.dg/modules/pr99023_b.X
@@ -1,4 +1,5 @@
 // PR c++/99023, ICE
+// { dg-require-effective-target c++20_only }
 // { dg-additional-options {-x c++-system-header iostream -fmodules-ts 
-flang-info-include-translate= --param ggc-min-expand=0} }
 
 // { dg-prune-output {linker input file unused} }


[gcc r14-10110] c++: constexpr union member access folding [PR114709]

2024-04-24 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:0844170e9ef60a8b2f6fba6786672f30ce1c2749

commit r14-10110-g0844170e9ef60a8b2f6fba6786672f30ce1c2749
Author: Patrick Palka 
Date:   Wed Apr 24 17:49:56 2024 -0400

c++: constexpr union member access folding [PR114709]

The object/offset canonicalization performed in cxx_fold_indirect_ref
is undesirable for union member accesses because it loses information
about the member being accessed which we may later need to diagnose an
inactive-member access.  So this patch restricts the canonicalization
accordingly.

PR c++/114709

gcc/cp/ChangeLog:

* constexpr.cc (cxx_fold_indirect_ref): Restrict object/offset
canonicalization to RECORD_TYPE member accesses.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-union8.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constexpr.cc   | 3 +++
 gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C | 8 
 2 files changed, 11 insertions(+)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 302b266809f..2e83d24dfda 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -5799,6 +5799,9 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, 
location_t loc, tree type,
  more folding opportunities.  */
   auto canonicalize_obj_off = [] (tree& obj, tree& off) {
 while (TREE_CODE (obj) == COMPONENT_REF
+  /* We need to preserve union member accesses so that we can
+ later properly diagnose accessing the wrong member.  */
+  && TREE_CODE (TREE_TYPE (TREE_OPERAND (obj, 0))) == RECORD_TYPE
   && (tree_int_cst_sign_bit (off) || integer_zerop (off)))
   {
tree field = TREE_OPERAND (obj, 1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C
new file mode 100644
index 000..34c264944b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union8.C
@@ -0,0 +1,8 @@
+// PR c++/114709
+// { dg-do compile { target c++11 } }
+
+struct T1 { int a, b; };
+struct T2 { int c; double d; };
+union U { T1 t1; T2 t2; };
+
+constexpr int v = U{{1,2}}.t2.*&T2::c; // { dg-error "accessing 'U::t2'" }


[gcc r14-10096] c++/modules: deduced return type merging [PR114795]

2024-04-23 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:4f9401d1a802325e5dfa2db841945e1a9c59a980

commit r14-10096-g4f9401d1a802325e5dfa2db841945e1a9c59a980
Author: Patrick Palka 
Date:   Tue Apr 23 14:01:22 2024 -0400

c++/modules: deduced return type merging [PR114795]

When merging an imported function template specialization with an
existing one, if the existing one has an undeduced return type and the
imported one's is already deduced, we need to propagate the deduced type
since once we install the imported definition we won't get a chance to
deduce it by normal means.

So this patch makes is_matching_decl propagate the deduced return
type alongside our propagation of the exception specification.
Another option would be to propagate it later when installing the
imported definition from read_function_def, but it seems preferable
to do it sooner rather than later.

PR c++/114795

gcc/cp/ChangeLog:

* module.cc (trees_in::is_matching_decl): Propagate deduced
function return type.

gcc/testsuite/ChangeLog:

* g++.dg/modules/auto-4_a.H: New test.
* g++.dg/modules/auto-4_b.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/module.cc|  9 +
 gcc/testsuite/g++.dg/modules/auto-4_a.H | 14 ++
 gcc/testsuite/g++.dg/modules/auto-4_b.C | 15 +++
 3 files changed, 38 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index d94d8ff4df9..c35e70b8cb8 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -11537,6 +11537,15 @@ trees_in::is_matching_decl (tree existing, tree decl, 
bool is_typedef)
   else if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
   && !comp_except_specs (d_spec, e_spec, ce_type))
goto mismatch;
+
+  /* Similarly if EXISTING has an undeduced return type, but DECL's
+is already deduced.  */
+  if (undeduced_auto_decl (existing) && !undeduced_auto_decl (decl))
+   {
+ dump (dumper::MERGE)
+   && dump ("Propagating deduced return type to %N", existing);
+ TREE_TYPE (existing) = change_return_type (TREE_TYPE (d_type), 
e_type);
+   }
 }
   else if (is_typedef)
 {
diff --git a/gcc/testsuite/g++.dg/modules/auto-4_a.H 
b/gcc/testsuite/g++.dg/modules/auto-4_a.H
new file mode 100644
index 000..0f7cd262dfa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-4_a.H
@@ -0,0 +1,14 @@
+// PR c++/114795
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template
+struct A {
+  auto f() { return T(); }
+};
+
+template
+void g() {
+  A a;
+  a.f();
+}
diff --git a/gcc/testsuite/g++.dg/modules/auto-4_b.C 
b/gcc/testsuite/g++.dg/modules/auto-4_b.C
new file mode 100644
index 000..378684ef6d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-4_b.C
@@ -0,0 +1,15 @@
+// PR c++/114795
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+template
+struct A {
+  auto f() { return T(); }
+};
+
+A a;
+
+import "auto-4_a.H";
+
+int main() {
+  g(); // { dg-bogus "before deduction of 'auto'" "" { target *-*-* } 0 }
+}


[gcc r13-8608] c++: requires-exprs and partial constraint subst [PR110006]

2024-04-15 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:38c2679ff9330d3ac1d5d86459294446733a435a

commit r13-8608-g38c2679ff9330d3ac1d5d86459294446733a435a
Author: Patrick Palka 
Date:   Fri Feb 2 19:07:08 2024 -0500

c++: requires-exprs and partial constraint subst [PR110006]

In r11-3261-gb28b621ac67bee we made tsubst_requires_expr never partially
substitute into a requires-expression so as to avoid checking its
requirements out of order during e.g. generic lambda regeneration.

These PRs however illustrate that we still sometimes do need to
partially substitute into a requires-expression, in particular when it
appears in associated constraints that we're directly substituting for
sake of declaration matching or dguide constraint rewriting.  In these
cases we're being called from tsubst_constraint during which
processing_constraint_expression_p is true, so this patch checks this
predicate to control whether we defer substitution or partially
substitute.

In turn, we now need to propagate semantic tsubst flags through
tsubst_requires_expr rather than just using tf_none, notably for sake of
dguide constraint rewriting which sets tf_dguide.

PR c++/110006
PR c++/112769

gcc/cp/ChangeLog:

* constraint.cc (subst_info::quiet): Accomodate non-diagnostic
tsubst flags.
(tsubst_valid_expression_requirement): Likewise.
(tsubst_simple_requirement): Return a substituted _REQ node when
processing_template_decl.
(tsubst_type_requirement_1): Accomodate non-diagnostic tsubst
flags.
(tsubst_type_requirement): Return a substituted _REQ node when
processing_template_decl.
(tsubst_compound_requirement): Likewise.  Accomodate non-diagnostic
tsubst flags.
(tsubst_nested_requirement): Likewise.
(tsubst_requires_expr): Don't defer partial substitution when
processing_constraint_expression_p is true, in which case return
a substituted REQUIRES_EXPR.
* pt.cc (tsubst_expr) : Accomodate
non-diagnostic tsubst flags.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias18.C: New test.
* g++.dg/cpp2a/concepts-friend16.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 686b5eb9c9ee623a604dde5c49fa11c23f384c62)

Diff:
---
 gcc/cp/constraint.cc   | 56 +-
 gcc/cp/pt.cc   |  3 +-
 .../g++.dg/cpp2a/class-deduction-alias18.C | 13 +
 gcc/testsuite/g++.dg/cpp2a/concepts-friend16.C | 25 ++
 4 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 273d15ab097..971619eabea 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -85,7 +85,7 @@ struct subst_info
   /* True if we should not diagnose errors.  */
   bool quiet() const
   {
-return complain == tf_none;
+return !(complain & tf_warning_or_error);
   }
 
   /* True if we should diagnose errors.  */
@@ -1999,8 +1999,9 @@ hash_placeholder_constraint (tree c)
 static tree
 tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
 {
-  tree r = tsubst_expr (t, args, tf_none, info.in_decl);
-  if (convert_to_void (r, ICV_STATEMENT, tf_none) != error_mark_node)
+  tsubst_flags_t quiet = info.complain & ~tf_warning_or_error;
+  tree r = tsubst_expr (t, args, quiet, info.in_decl);
+  if (convert_to_void (r, ICV_STATEMENT, quiet) != error_mark_node)
 return r;
 
   if (info.diagnose_unsatisfaction_p ())
@@ -2036,6 +2037,8 @@ tsubst_simple_requirement (tree t, tree args, sat_info 
info)
   tree expr = tsubst_valid_expression_requirement (t0, args, info);
   if (expr == error_mark_node)
 return error_mark_node;
+  if (processing_template_decl)
+return finish_simple_requirement (EXPR_LOCATION (t), expr);
   return boolean_true_node;
 }
 
@@ -2045,7 +2048,8 @@ tsubst_simple_requirement (tree t, tree args, sat_info 
info)
 static tree
 tsubst_type_requirement_1 (tree t, tree args, sat_info info, location_t loc)
 {
-  tree r = tsubst (t, args, tf_none, info.in_decl);
+  tsubst_flags_t quiet = info.complain & ~tf_warning_or_error;
+  tree r = tsubst (t, args, quiet, info.in_decl);
   if (r != error_mark_node)
 return r;
 
@@ -2076,6 +2080,8 @@ tsubst_type_requirement (tree t, tree args, sat_info info)
   tree type = tsubst_type_requirement_1 (t0, args, info, EXPR_LOCATION (t));
   if (type == error_mark_node)
 return error_mark_node;
+  if (processing_template_decl)
+return finish_type_requirement (EXPR_LOCATION (t), type);
   return boolean_true_node;
 }
 
@@ -2132,9 +2138,11 @@ tsubst_compound_requirement (tree t, tree args, sat_info 
info)
 
   location_t loc = cp_expr_loc_or_input_loc (expr);
 
+  subst_info quiet (info.complain & ~t

[gcc r14-9956] c++/modules: make bits_in/out move-constructible

2024-04-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:da375baf54944298303f13c375a5756c6131d672

commit r14-9956-gda375baf54944298303f13c375a5756c6131d672
Author: Patrick Palka 
Date:   Sat Apr 13 16:06:28 2024 -0400

c++/modules: make bits_in/out move-constructible

gcc/cp/ChangeLog:

* module.cc (struct bytes_in::bits_in): Define defaulted
move ctor.
(struct bytes_out::bits_out): Likewise.

Diff:
---
 gcc/cp/module.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index bbed82652d4..c6f71e11515 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -706,6 +706,7 @@ struct bytes_in::bits_in {
 bflush ();
   }
 
+  bits_in(bits_in&&) = default;
   bits_in(const bits_in&) = delete;
   bits_in& operator=(const bits_in&) = delete;
 
@@ -752,6 +753,7 @@ struct bytes_out::bits_out {
 bflush ();
   }
 
+  bits_out(bits_out&&) = default;
   bits_out(const bits_out&) = delete;
   bits_out& operator=(const bits_out&) = delete;


[gcc r14-9955] c++/modules: optimize tree flag streaming

2024-04-13 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:436ab7e8e8b16866d8a807af242560ad4fdff0d6

commit r14-9955-g436ab7e8e8b16866d8a807af242560ad4fdff0d6
Author: Patrick Palka 
Date:   Sat Apr 13 10:52:32 2024 -0400

c++/modules: optimize tree flag streaming

One would expect consecutive calls to bytes_in/out::b for streaming
adjacent bits, as is done for tree flag streaming, to at least be
optimized by the compiler into individual bit operations using
statically known bit positions (and ideally combined into larger sized
reads/writes).

Unfortunately this doesn't happen because the compiler has trouble
tracking the values of this->bit_pos and this->bit_val across the
calls, likely because the compiler doesn't know the value of 'this'.
Thus for each consecutive bit stream operation, bit_pos and bit_val are
loaded from 'this', checked if buffering is needed, and finally the bit
is extracted from bit_val according to the (unknown) bit_pos, even
though relative to the previous operation (if we didn't need to buffer)
bit_val is unchanged and bit_pos is just 1 larger.  This ends up being
quite slow, with tree_node_bools taking 10% of time when streaming in
the std module.

This patch improves this by making tracking of bit_pos and bit_val
easier for the compiler.  Rather than bit_pos and bit_val being members
of the (effectively global) bytes_in/out objects, this patch factors out
the bit streaming code/state into separate classes bits_in/out that get
constructed locally as needed for bit streaming.  Since these objects
are now clearly local, the compiler can more easily track their values
and optimize away redundant buffering checks.

And since bit streaming is intended to be batched it's natural for these
new classes to be RAII-enabled such that the bit stream is flushed upon
destruction.

In order to make the most of this improved tracking of bit position,
this patch changes parts where we conditionally stream a tree flag
to unconditionally stream (the flag or a dummy value).  That way
the number of bits streamed and the respective bit positions are as
statically known as reasonably possible.  In lang_decl_bools and
lang_type_bools this patch makes us flush the current bit buffer at the
start so that subsequent bit positions are in turn statically known.
And in core_bools, we can add explicit early exits utilizing invariants
that the compiler can't figure out itself (e.g. a tree code can't have
both TS_TYPE_COMMON and TS_DECL_COMMON, and if a tree code doesn't have
TS_DECL_COMMON then it doesn't have TS_DECL_WITH_VIS).

This patch also moves the definitions of the relevant streaming classes
into anonymous namespaces so that the compiler can make more informed
decisions about inlining their member functions.

After this patch, compile time for a simple Hello World using the std
module is reduced by 7% with a release compiler.  The on-disk size of
the std module increases by 0.4% (presumably due to the extra flushing
done in lang_decl_bools and lang_type_bools).

The bit stream out performance isn't improved as much as the stream in
due to the spans/lengths instrumentation performed on stream out (which
maybe should be disabled for release builds?)

gcc/cp/ChangeLog:

* module.cc: Update comment about classes defined within.
(class data): Enclose in an anonymous namespace.
(data::calc_crc): Moved from bytes::calc_crc.
(class bytes): Remove.  Move bit_flush to namespace scope.
(class bytes_in): Enclose in an anonymous namespace.  Inherit
directly from data and adjust accordingly.  Move b and bflush
members to bits_in.
(class bytes_out): As above.  Remove is_set static data member.
(bit_flush): Moved from class bytes.
(struct bytes_in::bits_in): Define.
(struct bytes_out::bits_out): Define.
(bytes_in::stream_bits): Define.
(bytes_out::stream_bits): Define.
(bytes_out::bflush): Moved to bits_out/in.
(bytes_in::bflush): Likewise
(bytes_in::bfill): Removed.
(bytes_out::b): Moved to bits_out/in.
(bytes_in::b): Likewise.
(class trees_in): Enclose in an anonymous namespace.
(class trees_out): Enclose in an anonymous namespace.
(trees_out::core_bools): Add bits_out/in parameter and use it.
Unconditionally stream a bit for public_flag.  Add early exits
as appropriate.
(trees_out::core_bools): Likewise.
(trees_out::lang_decl_bools): Add bits_out/in parameter and use
it.  Flush the current bit buffer at the start.  Unconditionally
stream a bit for module_keyed_decls_p.
(trees_in::lang_decl_bools)

  1   2   >