Re: [PATCH] c++: Allow translations of check_postcondition_result messages [PR109309]

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

On 3/28/23 11:44, Jakub Jelinek wrote:

Hi!

As mentioned in the PR, constructing a message from two parts by
concatenating them prevents translations, unless one of the parts
is a keyword which should be never translated.

The following patch fixes that, ok for trunk?


OK.


2023-03-28  Jakub Jelinek  

PR c++/109309
* contracts.cc: Include intl.h.
(check_postcondition_result): Don't form diagnostics from two halves
of an english message to allow translations.

--- gcc/cp/contracts.cc.jj  2023-01-16 11:52:16.063734359 +0100
+++ gcc/cp/contracts.cc 2023-03-28 17:33:42.165326812 +0200
@@ -161,6 +161,7 @@ along with GCC; see the file COPYING3.
  #include "tree-iterator.h"
  #include "print-tree.h"
  #include "stor-layout.h"
+#include "intl.h"
  
  const int max_custom_roles = 32;

  static contract_role contract_build_roles[max_custom_roles] = {
@@ -636,17 +637,15 @@ bool
  check_postcondition_result (tree decl, tree type, location_t loc)
  {
if (VOID_TYPE_P (type))
-  {
-const char* what;
-if (DECL_CONSTRUCTOR_P (decl))
-  what = "constructor";
-else if (DECL_DESTRUCTOR_P (decl))
-  what  = "destructor";
-else
-  what = "function";
-error_at (loc, "%s does not return a value to test", what);
-return false;
-  }
+{
+  error_at (loc,
+   DECL_CONSTRUCTOR_P (decl)
+   ? G_("constructor does not return a value to test")
+   : DECL_DESTRUCTOR_P (decl)
+   ? G_("destructor does not return a value to test")
+   : G_("function does not return a value to test"));
+  return false;
+}
  
return true;

  }

Jakub





PING^2 Re: [PATCH RFC] c++: lambda mangling alias issues [PR107897]

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

On 3/14/23 11:16, Jason Merrill wrote:

On 3/8/23 11:54, Jason Merrill wrote:

On 3/8/23 11:15, Jason Merrill wrote:

On 3/8/23 10:53, Jan Hubicka wrote:
Tested x86_64-pc-linux-gnu.  Does this look good, or do we want to 
factor the

flag clearing into a symtab_node counterpart to cgraph_node::reset?

-- 8< --

In 107897, by the time we are looking at the mangling clash, the
alias has already been removed from the symbol table by 
analyze_functions,
so we can't look at n->cpp_implicit_alias.  So just assume that 
it's an

alias if it's internal.

In 108887 the problem is that removing the mangling alias from the 
symbol
table confuses analyze_functions, because it ended up as 
first_analyzed
somehow, so it becomes a dangling pointer.  Fixed by clearing 
various flags

to neutralize the alias.

PR c++/107897
PR c++/108887

gcc/cp/ChangeLog:

* decl2.cc (record_mangling): Improve symbol table handling.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Use -flto if supported.
* g++.dg/cpp0x/lambda/lambda-mangle7.C: New test.
---
  gcc/cp/decl2.cc   | 25 +--
  .../g++.dg/cpp0x/lambda/lambda-mangle7.C  | 70 
+++

  gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C |  1 +
  3 files changed, 91 insertions(+), 5 deletions(-)
  create mode 100644 
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C


diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 387e24542cd..e6e58b08de4 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4742,15 +4742,30 @@ record_mangling (tree decl, bool need_warning)
  = mangled_decls->find_slot_with_hash (id, 
IDENTIFIER_HASH_VALUE (id),

    INSERT);
-  /* If this is already an alias, remove the alias, because the real
+  /* If this is already an alias, cancel the alias, because the real
   decl takes precedence.  */
    if (*slot && DECL_ARTIFICIAL (*slot) && DECL_IGNORED_P (*slot))
-    if (symtab_node *n = symtab_node::get (*slot))
-  if (n->cpp_implicit_alias)
+    {
+  if (symtab_node *n = symtab_node::get (*slot))
  {
-  n->remove ();
-  *slot = NULL_TREE;
+  if (n->cpp_implicit_alias)
+    {
+  /* Actually removing the node isn't safe if other code 
is already

+ holding a pointer to it, so just neutralize it.  */
+  n->remove_from_same_comdat_group ();
+  n->analyzed = false;
+  n->definition = false;
+  n->alias = false;
+  n->cpp_implicit_alias = false;

We have n->reset () for that which is used in similar situation when
frontends overwrites extern inline function by its different offline
implementation.


The problem there is that reset() is a member of cgraph_node, not 
symtab_node, and I need something that works for variables as well.


reset doesn't call remove_from_same_comdat_group probably because it 
was

never used on anything in comdat group.  So I think it would make sense
to call n->reset() here and add remove_from_same_comdat_group into 
that.


How about moving it to symtab_node and using dyn_cast for the cgraph 
bits, like this:


Ping? (Patch in attachment in earlier message)





Re: [PATCH RFC] c-family: -Wsequence-point and COMPONENT_REF [PR107163]

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

On 3/24/23 18:25, Jakub Jelinek wrote:

On Fri, Mar 24, 2023 at 06:11:44PM -0400, Jason Merrill wrote:

When we touch this for COMPONENT_REF, shouldn't we then handle it as
unary given that the second operand is FIELD_DECL and third/fourth
will likely be NULL and even if not, aren't user expressions that should be
inspected?
So, instead of doing this do:
  case COMPONENT_REF:
x = TREE_OPERAND (x, 0);
writer = 0;
goto restart;
?


Is clearing 'writer' what we want, since an access to COMPONENT_REF is an
access to (a subobject of) its op0?


I've just mindlessly copied the unary op case.
writer is set for pre/post increments and lhs of MODIFY_EXPR, and it is
true that VIEW_CONVERT_EXPR doesn't clear it, but e.g. ARRAY_REF clears it
for all operands.


For whatever reason leaving writer set led to lots of false positives, 
so I've gone with your suggestion.



Currently with the fix it takes <1s while gcc12 takes ~80s.


Perfect.


PR c++/107163

gcc/c-family/ChangeLog:

* c-common.cc (verify_tree): Don't use sequenced handling
for COMPONENT_REF.

gcc/testsuite/ChangeLog:

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


LGTM, thanks.  Maybe the testcase would be better as
warn/Wsequence-point-5.C, dunno.


Done.

Jason



Re: [PATCH RFC] c-family: -Wsequence-point and COMPONENT_REF [PR107163]

2023-03-24 Thread Jason Merrill via Gcc-patches

On 3/23/23 17:03, Jakub Jelinek wrote:

On Thu, Mar 23, 2023 at 04:35:07PM -0400, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu.  Jakub, does this make sense to you?  Do we have a
way of testing for compile-hog regressions?

-- 8< --

The patch for PR91415 fixed -Wsequence-point to treat shifts and ARRAY_REF
as sequenced in C++17, and COMPONENT_REF as well.  But this is unnecessary
for COMPONENT_REF, since the RHS is just a FIELD_DECL with no actual
evaluation, and in this testcase handling COMPONENT_REF as sequenced blows
up fast in a deep inheritance tree.

PR c++/107163

gcc/c-family/ChangeLog:

* c-common.cc (verify_tree): Don't use sequenced handling
for COMPONENT_REF.


When we touch this for COMPONENT_REF, shouldn't we then handle it as
unary given that the second operand is FIELD_DECL and third/fourth
will likely be NULL and even if not, aren't user expressions that should be
inspected?
So, instead of doing this do:
 case COMPONENT_REF:
   x = TREE_OPERAND (x, 0);
   writer = 0;
   goto restart;
?


Is clearing 'writer' what we want, since an access to COMPONENT_REF is 
an access to (a subobject of) its op0?



As for compile-hog, depends on how long it will take it to compile before
fix/after fix.  If before fix can be above the normal timeout on reasonably
fast matchines and after fix can take a few seconds, great


Currently with the fix it takes <1s while gcc12 takes ~80s.


if after fix
would take longer but still not horribly long, one way to do it is
guard the test with run_expensive_tests effective target.  Or another way
is have the test smaller in complexity normally and
// { dg-additional-options "-DEXPENSIVE" { target run_expensive_tests } }
and #ifdef EXPENSIVE make it more complex.


Curiously, making the recursion much deeper doesn't work for that; I 
guess at some point the -Wsequence-point code decides the expression is 
too complex and gives up?


But repeating the assignment brings it up over the timeout.

How about this?From bb302f97929df9b854f7f929093441da60305254 Mon Sep 17 00:00:00 2001
From: Jason Merrill 
Date: Thu, 23 Mar 2023 15:57:39 -0400
Subject: [PATCH] c-family: -Wsequence-point and COMPONENT_REF [PR107163]
To: gcc-patches@gcc.gnu.org

The patch for PR91415 fixed -Wsequence-point to treat shifts and ARRAY_REF
as sequenced in C++17, and COMPONENT_REF as well.  But this is unnecessary
for COMPONENT_REF, since the RHS is just a FIELD_DECL with no actual
evaluation, and in this testcase handling COMPONENT_REF as sequenced blows
up fast in a deep inheritance tree.  Instead, look through it.

	PR c++/107163

gcc/c-family/ChangeLog:

	* c-common.cc (verify_tree): Don't use sequenced handling
	for COMPONENT_REF.

gcc/testsuite/ChangeLog:

	* g++.dg/template/recurse5.C: New test.
---
 gcc/c-family/c-common.cc |  5 +++-
 gcc/testsuite/g++.dg/template/recurse5.C | 37 
 2 files changed, 41 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/template/recurse5.C

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index bfb950e56db..07f7beac8fd 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -2154,12 +2154,15 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
 
 case LSHIFT_EXPR:
 case RSHIFT_EXPR:
-case COMPONENT_REF:
 case ARRAY_REF:
   if (cxx_dialect >= cxx17)
 	goto sequenced_binary;
   goto do_default;
 
+case COMPONENT_REF:
+  x = TREE_OPERAND (x, 0);
+  goto restart;
+
 default:
 do_default:
   /* For other expressions, simply recurse on their operands.
diff --git a/gcc/testsuite/g++.dg/template/recurse5.C b/gcc/testsuite/g++.dg/template/recurse5.C
new file mode 100644
index 000..0354ab09f53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/recurse5.C
@@ -0,0 +1,37 @@
+// PR c++/107163
+// { dg-additional-options "-Wsequence-point" }
+
+struct BaseType  {
+  int i;
+};
+
+template< int Seq >
+class DerivedType : public DerivedType< Seq - 1 > { };
+
+template<>
+class DerivedType< -1 > : public BaseType { };
+
+int main() {
+  DerivedType< 400 > d;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  d.i = 42;
+  return d.i;
+}
-- 
2.31.1



[pushed] c++: default template arg, partial ordering [PR105481]

2023-03-24 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

The default argument code in type_unification_real was assuming that all
targs we've deduced by that point are non-dependent, but that's not the case
for partial ordering.

PR c++/105481

gcc/cp/ChangeLog:

* pt.cc (type_unification_real): Adjust for partial ordering.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/fntmpdefarg-partial1.C: New test.
---
 gcc/cp/pt.cc   | 18 ++
 .../g++.dg/cpp0x/fntmpdefarg-partial1.C|  8 
 2 files changed, 22 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/fntmpdefarg-partial1.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 40deedc9ba9..3bb98ebeac1 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23304,14 +23304,24 @@ type_unification_real (tree tparms,
  return unify_parameter_deduction_failure (explain_p, tparm);
}
 
+  /* During partial ordering, we deduce dependent template args.  */
+  bool any_dependent_targs = false;
+
   /* Now substitute into the default template arguments.  */
   for (i = 0; i < ntparms; i++)
{
  tree targ = TREE_VEC_ELT (targs, i);
  tree tparm = TREE_VEC_ELT (tparms, i);
 
- if (targ || tparm == error_mark_node)
+ if (targ)
+   {
+ if (!any_dependent_targs && dependent_template_arg_p (targ))
+   any_dependent_targs = true;
+ continue;
+   }
+ if (tparm == error_mark_node)
continue;
+
  tree parm = TREE_VALUE (tparm);
  tree arg = TREE_PURPOSE (tparm);
  reopen_deferring_access_checks (*checks);
@@ -23347,9 +23357,9 @@ type_unification_real (tree tparms,
 do this substitution without processing_template_decl.  This
 is important if the default argument contains something that
 might be instantiation-dependent like access (87480).  */
- processing_template_decl_sentinel s;
+ processing_template_decl_sentinel s (!any_dependent_targs);
  tree substed = NULL_TREE;
- if (saw_undeduced == 1)
+ if (saw_undeduced == 1 && !any_dependent_targs)
{
  /* First instatiate in template context, in case we still
 depend on undeduced template parameters.  */
@@ -23372,7 +23382,7 @@ type_unification_real (tree tparms,
 complain, i, NULL_TREE);
  else if (saw_undeduced == 1)
arg = NULL_TREE;
- else
+ else if (!any_dependent_targs)
arg = error_mark_node;
}
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg-partial1.C 
b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg-partial1.C
new file mode 100644
index 000..2a6783e566b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg-partial1.C
@@ -0,0 +1,8 @@
+// PR c++/105481
+// { dg-do compile { target c++11 } }
+
+template struct uint;
+template uint f(const uint &);
+template> uint f(T);
+using X = uint<1>;
+X (*fp)(X const &) = f;

base-commit: c4792bd1de0621932a47fb86aca09fafafdb2972
-- 
2.31.1



Re: [PATCH] c++: outer 'this' leaking into local class [PR106969]

2023-03-24 Thread Jason Merrill via Gcc-patches

On 3/23/23 11:00, Patrick Palka wrote:

Here when resolving the implicit object for '&wrapped' within the
local class Foo, we expect to obtain a dummy object of type Foo& since
there's no 'this' available in this context.  And yet at this point
current_class_ref still corresponds to the outer class Context (and is
const), which confuses maybe_dummy_object into propagating the cv-quals
of current_class_ref and returning an object of type const Foo&.  Thus
decltype(&wrapped) wrongly yields const int* instead of int*.

The problem ultimately seems to be that the 'this' from the enclosing
class appears available for use when parsing the local class, but 'this'
shouldn't leak across classes like that.  This patch fixes this by
clearing current_class_ptr/ref when parsing a class definition.

After this change, for name-clash11.C in C++98 mode we would now
complain about an invalid use of 'this' for e.g.

   ASSERT (sizeof (this->A) == 16);

due to the way the ASSERT macro is defined using a local class.  This
patch redefines it using a local typedef instead.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?


OK.


PR c++/106969

gcc/cp/ChangeLog:

* parser.cc (cp_parser_class_specifier): Clear current_class_ptr
and current_class_ref when parsing a class definition.

gcc/testsuite/ChangeLog:

* g++.dg/lookup/name-clash11.C: New test.
* g++.dg/lookup/this2.C: New test.
---
  gcc/cp/parser.cc   | 13 +
  gcc/testsuite/g++.dg/lookup/name-clash11.C |  2 +-
  gcc/testsuite/g++.dg/lookup/this2.C| 22 ++
  3 files changed, 32 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/lookup/this2.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a277003ea58..be9c77b415e 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -26151,6 +26151,11 @@ cp_parser_class_specifier (cp_parser* parser)
saved_in_unbraced_linkage_specification_p
  = parser->in_unbraced_linkage_specification_p;
parser->in_unbraced_linkage_specification_p = false;
+  /* 'this' from an enclosing non-static member function is unvailable.  */
+  tree saved_ccp = current_class_ptr;
+  tree saved_ccr = current_class_ref;
+  current_class_ptr = NULL_TREE;
+  current_class_ref = NULL_TREE;
  
/* Start the class.  */

if (nested_name_specifier_p)
@@ -26369,8 +26374,6 @@ cp_parser_class_specifier (cp_parser* parser)
/* If there are noexcept-specifiers that have not yet been processed,
 take care of them now.  Do this before processing NSDMIs as they
 may depend on noexcept-specifiers already having been processed.  */
-  tree save_ccp = current_class_ptr;
-  tree save_ccr = current_class_ref;
FOR_EACH_VEC_SAFE_ELT (unparsed_noexcepts, ix, decl)
{
  tree ctx = DECL_CONTEXT (decl);
@@ -26496,8 +26499,8 @@ cp_parser_class_specifier (cp_parser* parser)
}
vec_safe_truncate (unparsed_contracts, 0);
  
-  current_class_ptr = save_ccp;

-  current_class_ref = save_ccr;
+  current_class_ptr = NULL_TREE;
+  current_class_ref = NULL_TREE;
if (pushed_scope)
pop_scope (pushed_scope);
  
@@ -26529,6 +26532,8 @@ cp_parser_class_specifier (cp_parser* parser)

  = saved_num_template_parameter_lists;
parser->in_unbraced_linkage_specification_p
  = saved_in_unbraced_linkage_specification_p;
+  current_class_ptr = saved_ccp;
+  current_class_ref = saved_ccr;
  
return type;

  }
diff --git a/gcc/testsuite/g++.dg/lookup/name-clash11.C 
b/gcc/testsuite/g++.dg/lookup/name-clash11.C
index bc63645e8d3..2ae9a65264d 100644
--- a/gcc/testsuite/g++.dg/lookup/name-clash11.C
+++ b/gcc/testsuite/g++.dg/lookup/name-clash11.C
@@ -7,7 +7,7 @@
  #  define ASSERT(e) static_assert (e, #e)
  #else
  #  define ASSERT(e) \
-  do { struct S { bool: !!(e); } asrt; (void)&asrt; } while (0)
+  do { typedef int asrt[bool(e) ? 1 : -1]; } while (0)
  #endif
  
  
diff --git a/gcc/testsuite/g++.dg/lookup/this2.C b/gcc/testsuite/g++.dg/lookup/this2.C

new file mode 100644
index 000..1450c563d92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/this2.C
@@ -0,0 +1,22 @@
+// PR c++/106969
+// { dg-do compile { target c++11 } }
+
+struct Context
+{
+void
+action() const
+{
+struct Foo
+{
+int wrapped;
+decltype( &wrapped ) get() { return &wrapped; }
+} t;
+
+*t.get()= 42; // OK, get() returns int* not const int*
+
+struct Bar
+{
+using type = decltype(this); // { dg-error "invalid use of 'this'" 
}
+};
+}
+};




[pushed] c++: constexpr PMF conversion [PR105996]

2023-03-23 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Here, we were calling build_reinterpret_cast regardless of whether there was
actually a cast, and that now sets REINTERPRET_CAST_P.  But that
optimization seems dodgy anyway, as it involves NOP_EXPR from one
RECORD_TYPE to another and we try to reserve NOP_EXPR for fundamental types.
And the generated code seems the same, so let's drop it.  And also strip
location wrappers.

PR c++/105996

gcc/cp/ChangeLog:

* typeck.cc (build_ptrmemfunc): Drop 0-offset optimization
and location wrappers.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-pmf3.C: New test.
---
 gcc/cp/typeck.cc| 13 +
 gcc/testsuite/g++.dg/cpp0x/constexpr-pmf3.C | 13 +
 2 files changed, 18 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-pmf3.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index afb956087ce..8b60cbbc167 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9960,18 +9960,15 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool 
c_cast_p,
   if (n == error_mark_node)
return error_mark_node;
 
+  STRIP_ANY_LOCATION_WRAPPER (pfn);
+
   /* We don't have to do any conversion to convert a
 pointer-to-member to its own type.  But, we don't want to
 just return a PTRMEM_CST if there's an explicit cast; that
 cast should make the expression an invalid template argument.  */
-  if (TREE_CODE (pfn) != PTRMEM_CST)
-   {
- if (same_type_p (to_type, pfn_type))
-   return pfn;
- else if (integer_zerop (n) && TREE_CODE (pfn) != CONSTRUCTOR)
-   return build_reinterpret_cast (input_location, to_type, pfn, 
-   complain);
-   }
+  if (TREE_CODE (pfn) != PTRMEM_CST
+ && same_type_p (to_type, pfn_type))
+   return pfn;
 
   if (TREE_SIDE_EFFECTS (pfn))
pfn = save_expr (pfn);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pmf3.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-pmf3.C
new file mode 100644
index 000..14daea312b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pmf3.C
@@ -0,0 +1,13 @@
+// PR c++/105996
+// { dg-do compile { target c++11 } }
+
+struct A {
+  void CB() {}
+};
+struct B : public A { };
+
+using APMF = void (A::*)();
+using BPMF = void (B::*)();
+
+constexpr APMF foo () { return &A::CB; };
+static constexpr BPMF b = foo();

base-commit: 3fbeff66684d95417646aaa22d0a8f1ec9786299
-- 
2.31.1



[PATCH RFC] c-family: -Wsequence-point and COMPONENT_REF [PR107163]

2023-03-23 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu.  Jakub, does this make sense to you?  Do we have a
way of testing for compile-hog regressions?

-- 8< --

The patch for PR91415 fixed -Wsequence-point to treat shifts and ARRAY_REF
as sequenced in C++17, and COMPONENT_REF as well.  But this is unnecessary
for COMPONENT_REF, since the RHS is just a FIELD_DECL with no actual
evaluation, and in this testcase handling COMPONENT_REF as sequenced blows
up fast in a deep inheritance tree.

PR c++/107163

gcc/c-family/ChangeLog:

* c-common.cc (verify_tree): Don't use sequenced handling
for COMPONENT_REF.
---
 gcc/c-family/c-common.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index bfb950e56db..a803cf94c68 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -2154,7 +2154,6 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct 
tlist **pno_sp,
 
 case LSHIFT_EXPR:
 case RSHIFT_EXPR:
-case COMPONENT_REF:
 case ARRAY_REF:
   if (cxx_dialect >= cxx17)
goto sequenced_binary;

base-commit: 4872e46e080c6695dfe1f9dc9db26b4703bc348c
-- 
2.31.1



[pushed] c++: local class in nested generic lambda [PR109241]

2023-03-22 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

In this testcase, the tree walk to look for bare parameter packs was
confused by finding a type with no TREE_BINFO.  But it should be fine that
it's unset; we already checked for unexpanded packs at parse time.

I also tried doing the partial instantiation of the local class, which is
probably the long-term direction we want to go, but for stage 4 let's go
with this safer change.

PR c++/109241

gcc/cp/ChangeLog:

* pt.cc (find_parameter_packs_r): Handle null TREE_BINFO.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/lambda-generic-local-class2.C: New test.
---
 gcc/cp/pt.cc| 12 
 .../g++.dg/cpp1y/lambda-generic-local-class2.C  | 13 +
 2 files changed, 21 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class2.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 90bcaa78701..40deedc9ba9 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4069,10 +4069,14 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, 
void* data)
 case TAG_DEFN:
   t = TREE_TYPE (t);
   if (CLASS_TYPE_P (t))
-   /* Local class, need to look through the whole definition.  */
-   for (tree bb : BINFO_BASE_BINFOS (TYPE_BINFO (t)))
- cp_walk_tree (&BINFO_TYPE (bb), &find_parameter_packs_r,
-   ppd, ppd->visited);
+   {
+ /* Local class, need to look through the whole definition.
+TYPE_BINFO might be unset for a partial instantiation.  */
+ if (TYPE_BINFO (t))
+   for (tree bb : BINFO_BASE_BINFOS (TYPE_BINFO (t)))
+ cp_walk_tree (&BINFO_TYPE (bb), &find_parameter_packs_r,
+   ppd, ppd->visited);
+   }
   else
/* Enum, look at the values.  */
for (tree l = TYPE_VALUES (t); l; l = TREE_CHAIN (l))
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class2.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class2.C
new file mode 100644
index 000..83856de1f41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-class2.C
@@ -0,0 +1,13 @@
+// PR c++/109241
+// { dg-do compile { target c++14 } }
+// { dg-options "" } no pedantic
+
+void g() {
+  [](auto) {
+[](auto) {
+  ({
+struct A {};
+  });
+};
+  }(1);
+}

base-commit: cd0c433e5faba9a18f64881cd761a53a530aa798
-- 
2.31.1



[pushed] c++: array bound partial ordering [PR108390]

2023-03-22 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

fold_convert doesn't work with a dependent argument, and problematically
differed from the corresponding fold+build_nop further down in the
function.  So change it to match.

PR c++/108390

gcc/cp/ChangeLog:

* pt.cc (unify): Use fold of build_nop instead of fold_convert.

gcc/testsuite/ChangeLog:

* g++.dg/template/partial-order3.C: New test.
---
 gcc/cp/pt.cc   | 8 +---
 gcc/testsuite/g++.dg/template/partial-order3.C | 6 ++
 2 files changed, 11 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/partial-order3.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 056b8c7abad..90bcaa78701 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24635,8 +24635,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
  if ((strict & UNIFY_ALLOW_INTEGER)
  && TREE_TYPE (targ) && TREE_TYPE (arg)
  && CP_INTEGRAL_TYPE_P (TREE_TYPE (targ)))
-   /* We're deducing from an array bound, the type doesn't matter.  */
-   arg = fold_convert (TREE_TYPE (targ), arg);
+   /* We're deducing from an array bound, the type doesn't matter.
+  This conversion should match the one below.  */
+   arg = fold (build_nop (TREE_TYPE (targ), arg));
  int x = !cp_tree_equal (targ, arg);
  if (x)
unify_inconsistency (explain_p, parm, targ, arg);
@@ -24684,7 +24685,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
   && CP_INTEGRAL_TYPE_P (tparm))
/* Convert the ARG to the type of PARM; the deduced non-type
   template argument must exactly match the types of the
-  corresponding parameter.  */
+  corresponding parameter.  This conversion should match the
+  one above.  */
arg = fold (build_nop (tparm, arg));
   else if (uses_template_parms (tparm))
{
diff --git a/gcc/testsuite/g++.dg/template/partial-order3.C 
b/gcc/testsuite/g++.dg/template/partial-order3.C
new file mode 100644
index 000..154505321bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial-order3.C
@@ -0,0 +1,6 @@
+// PR c++/108390
+// { dg-do compile { target c++11 } }
+
+template  long f(int(*)[t], T(*)[t]);
+template int f(int(*)[i], T(*)[i]) = delete;
+int n = f(0, 0);

base-commit: 3e791f45ded89626bc1f9f8013728f6e035801b2
-- 
2.31.1



[pushed] c++: attribute on dtor in template [PR108795]

2023-03-22 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Since r7-2549 we were throwing away the explicit C:: when we found that ~C
has an attribute that we treat as making its type dependent.

PR c++/108795

gcc/cp/ChangeLog:

* semantics.cc (finish_id_expression_1): Check scope before
returning id_expression.

gcc/testsuite/ChangeLog:

* g++.dg/ext/attr-tsafe1.C: New test.
---
 gcc/cp/semantics.cc|  1 +
 gcc/testsuite/g++.dg/ext/attr-tsafe1.C | 14 ++
 2 files changed, 15 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-tsafe1.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 87c2e8a7111..99a76e3ed65 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4238,6 +4238,7 @@ finish_id_expression_1 (tree id_expression,
: CP_ID_KIND_UNQUALIFIED)));
 
   if (dependent_p
+ && !scope
  && DECL_P (decl)
  && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
/* Dependent type attributes on the decl mean that the TREE_TYPE is
diff --git a/gcc/testsuite/g++.dg/ext/attr-tsafe1.C 
b/gcc/testsuite/g++.dg/ext/attr-tsafe1.C
new file mode 100644
index 000..20c319f154d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-tsafe1.C
@@ -0,0 +1,14 @@
+// PR c++/108795
+
+template  void g (T x)
+{
+  struct C
+  {
+__attribute__((transaction_safe)) ~C();
+  };
+  C::~C(); // { dg-error "" }
+}
+void f ()
+{
+  g (5);
+}

base-commit: d3a6f174543816600b1f472997d492088e4e396a
-- 
2.31.1



Re: [PATCH] c++: Avoid duplicate diagnostic calling unavailable function [PR109177]

2023-03-22 Thread Jason Merrill via Gcc-patches

On 3/22/23 07:32, Alex Coplan wrote:

Hi,

As the PR shows, we currently emit duplicate diagnostics for calls to
functions marked with __attribute__((unavailable)). This patch fixes
that.

I'm not sure whether it's considered acceptable to add the include of
decl.h to call.cc (in order to get at deprecated_state). It would be
useful to get some feedback on that.


That's fine.


Bootstrapped/regtested on aarch64-linux-gnu, OK for trunk?


OK.


gcc/cp/ChangeLog:

PR c++/109177
* call.cc (build_over_call): Use make_temp_override to suppress
both unavailable and deprecated warnings when calling
build_addr_func.

gcc/testsuite/ChangeLog:

PR c++/109177
* g++.dg/ext/pr109177.C: New test.




Re: [PATCH] wwwdocs: Clarify experimental status of C++17 prior to GCC 9

2023-03-22 Thread Jason Merrill via Gcc-patches

On 3/22/23 06:42, Jonathan Wakely wrote:

We don't currently have a single page where you can find out when
support for a given standard became non-experimental (you have to look
through all the gcc-X/changes.html pages to find it). I think we should
have that info on the cxx-status.html page. This adds it for C++17, and
we can do the same for C++20 when we declare that stable.

OK for wwwdocs?


OK.


-- >8 --

Also link to library docs for C++20 and add a cxx2a anchor which is used
by some old links.
---
  htdocs/projects/cxx-status.html | 20 
  1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/htdocs/projects/cxx-status.html b/htdocs/projects/cxx-status.html
index b5362bba..7f59e5a2 100644
--- a/htdocs/projects/cxx-status.html
+++ b/htdocs/projects/cxx-status.html
@@ -402,10 +402,12 @@
  -->

  
-  C++20 Support in GCC

+  C++20 Support in GCC
  
GCC has experimental support for the latest revision of the C++

-  standard, which was published in 2020.
+  standard, which was published in 2020.
+  The status of C++20 library features is described in
+  https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2020";>the library 
documentation.
  
C++20 features are available since GCC 8. To enable C++20

support, add the command-line parameter -std=c++20
@@ -988,14 +990,16 @@
  
GCC has almost full support for the previous revision of the C++

standard, which was published in 2017.
-  Some library features are missing or incomplete, as described in
+  The status of C++17 library features is described in
https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2017";>the 
library documentation.

  
-  C++17 features are available since GCC 5.  This mode is the default

-  in GCC 11; it can be explicitly selected with the -std=c++17
-  command-line flag, or -std=gnu++17 to enable GNU extensions
-  as well.
+  C++17 mode is the default since GCC 11; it can be explicitly selected
+  with the -std=c++17 command-line flag, or
+  -std=gnu++17 to enable GNU extensions as well.
+  Some C++17 features are available since GCC 5, but support was experimental
+  and the ABI of C++17 features was not stable until GCC 9.
+  
  
C++17 Language Features
  
@@ -1315,7 +1319,7 @@
  
GCC has full support for the of the 2014 C++ standard.
  
-  This mode is the default in GCC 6.1 up until GCC 10 (including); it can

+  This mode is the default in GCC 6.1 up until GCC 10 (inclusive); it can
be explicitly selected with the -std=c++14 command-line flag,
or -std=gnu++14 to enable GNU extensions as well.
  




[pushed] c++: DMI in template with virtual base [PR106890]

2023-03-21 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

When parsing a default member init we just build a CONVERT_EXPR for
converting to a virtual base, and then expand that into the more complex
form when we actually use the DMI in a constructor.  But that wasn't working
for the template case where we are considering the conversion at the point
that the constructor needs the DMI instantiation, so it seemed like we were
in a constructor already.  And then when the other constructor tries to
reuse the instantiation, it sees uses of the first constructor's parameters,
and dies.  So ensure that we get the CONVERT_EXPR in this case, too.

PR c++/106890

gcc/cp/ChangeLog:

* init.cc (maybe_instantiate_nsdmi_init): Don't leave
current_function_decl set to a constructor.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/nsdmi-template25.C: New test.
---
 gcc/cp/init.cc| 14 ++
 gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C | 18 ++
 2 files changed, 32 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 90302372340..c5a55dae563 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -613,6 +613,18 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t 
complain)
  pushed = true;
}
 
+ /* If we didn't push_to_top_level, still step out of constructor
+scope so build_base_path doesn't try to use its __in_chrg.  */
+ tree cfd = current_function_decl;
+ auto cbl = current_binding_level;
+ if (at_function_scope_p ())
+   {
+ current_function_decl
+   = decl_function_context (current_function_decl);
+ while (current_binding_level->kind != sk_class)
+   current_binding_level = current_binding_level->level_chain;
+   }
+
  inject_this_parameter (ctx, TYPE_UNQUALIFIED);
 
  start_lambda_scope (member);
@@ -629,6 +641,8 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t 
complain)
  if (init != error_mark_node)
hash_map_safe_put (nsdmi_inst, member, init);
 
+ current_function_decl = cfd;
+ current_binding_level = cbl;
  if (pushed)
{
  pop_deferring_access_checks ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C
new file mode 100644
index 000..368e745540e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C
@@ -0,0 +1,18 @@
+// PR c++/106890
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  int p;
+};
+
+template
+struct B : virtual public A
+{
+  B() { }
+  B(int) { }
+
+  int k = this->p;
+};
+
+template struct B;

base-commit: 0a846340b99675d57fc2f2923a0412134eed09d3
-- 
2.31.1



Re: [PATCH v2] c++: further -Wdangling-reference refinement [PR107532]

2023-03-21 Thread Jason Merrill via Gcc-patches

On 3/20/23 18:06, Marek Polacek wrote:

On Sat, Mar 18, 2023 at 08:35:36AM -0400, Jason Merrill wrote:

On 3/17/23 16:29, Marek Polacek wrote:

Based on ,
it seems like we should treat *any* class with a reference member
as a reference wrapper.  This simplifies the code so I'm happy to
make that change.

The patch, however, does not suppress the warning in

int i = 42;
auto const& v = std::get<0>(std::tuple(i));


Why not?  tuple has an int& member, doesn't it?  Do we need to look
into bases as well?


Indeed.  I don't know why I didn't do it right away; it's really not that
complicated:

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK.


-- >8 --
Based on ,
it seems like we should treat *any* class with a reference member
as a reference wrapper.  To suppress the warning in

   int i = 42;
   auto const& v = std::get<0>(std::tuple(i));

we have to look into base classes as well.  For std::tuple, this means
that we have to check the _Head_base subobject, which is a non-direct
base class of std::tuple.  So I've employed a DFS walk.

PR c++/107532

gcc/cp/ChangeLog:

* call.cc (class_has_reference_member_p): New.
(class_has_reference_member_p_r): New.
(reference_like_class_p): Don't look for a specific constructor.
Use a DFS walk with class_has_reference_member_p_r.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wdangling-reference11.C: New test.
* g++.dg/warn/Wdangling-reference12.C: New test.
---
  gcc/cp/call.cc| 63 +++
  .../g++.dg/warn/Wdangling-reference11.C   | 23 +++
  .../g++.dg/warn/Wdangling-reference12.C   | 12 
  3 files changed, 72 insertions(+), 26 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference12.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c52a09b9be2..429170e43ea 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13783,8 +13783,31 @@ std_pair_ref_ref_p (tree t)
  
  /* Return true if a class CTYPE is either std::reference_wrapper or

 std::ref_view, or a reference wrapper class.  We consider a class
-   a reference wrapper class if it has a reference member and a
-   constructor taking the same reference type.  */
+   a reference wrapper class if it has a reference member.  We no
+   longer check that it has a constructor taking the same reference type
+   since that approach still generated too many false positives.  */
+
+static bool
+class_has_reference_member_p (tree t)
+{
+  for (tree fields = TYPE_FIELDS (t);
+   fields;
+   fields = DECL_CHAIN (fields))
+if (TREE_CODE (fields) == FIELD_DECL
+   && !DECL_ARTIFICIAL (fields)
+   && TYPE_REF_P (TREE_TYPE (fields)))
+  return true;
+  return false;
+}
+
+/* A wrapper for the above suitable as a callback for dfs_walk_once.  */
+
+static tree
+class_has_reference_member_p_r (tree binfo, void *)
+{
+  return (class_has_reference_member_p (BINFO_TYPE (binfo))
+ ? integer_one_node : NULL_TREE);
+}
  
  static bool

  reference_like_class_p (tree ctype)
@@ -13800,31 +13823,19 @@ reference_like_class_p (tree ctype)
if (decl_in_std_namespace_p (tdecl))
  {
tree name = DECL_NAME (tdecl);
-  return (name
- && (id_equal (name, "reference_wrapper")
- || id_equal (name, "span")
- || id_equal (name, "ref_view")));
-}
-  for (tree fields = TYPE_FIELDS (ctype);
-   fields;
-   fields = DECL_CHAIN (fields))
-{
-  if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
-   continue;
-  tree type = TREE_TYPE (fields);
-  if (!TYPE_REF_P (type))
-   continue;
-  /* OK, the field is a reference member.  Do we have a constructor
-taking its type?  */
-  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype)))
-   {
- tree args = FUNCTION_FIRST_USER_PARMTYPE (fn);
- if (args
- && same_type_p (TREE_VALUE (args), type)
- && TREE_CHAIN (args) == void_list_node)
-   return true;
-   }
+  if (name
+ && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "span")
+ || id_equal (name, "ref_view")))
+   return true;
  }
+
+  /* Some classes, such as std::tuple, have the reference member in its
+ (non-direct) base class.  */
+  if (dfs_walk_once (TYPE_BINFO (ctype), class_has_reference_member_p_r,
+nullptr, nullptr))
+return true;
+
return false;
  }
  
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C

new file mode 100644
index 000..667618e7196
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
@@ -0,0 +1,23 @@
+// PR c

Re: [PATCH] c++, v2: Drop TREE_READONLY on vars (possibly) initialized by tls wrapper [PR109164]

2023-03-20 Thread Jason Merrill via Gcc-patches

On 3/20/23 15:26, Jakub Jelinek wrote:

On Mon, Mar 20, 2023 at 03:15:32PM -0400, Jason Merrill wrote:

+  else if (VAR_P (decl)
+  && CP_DECL_THREAD_LOCAL_P (decl)
+  && (!DECL_EXTERNAL (decl) || flag_extern_tls_init)


Hmm, I wonder why we don't check the above line in var_needs_tls_wrapper?


It is tested in get_tls_init_fn (one of the 2 previous callers of
var_needs_tls_wrapper).  No idea why it isn't in get_tls_wrapper_fn (the
other caller of it).


I suppose because we might see a definition of the variable later on, 
and we don't want to have previously decided to omit the wrapper because 
we hadn't seen it yet.


Jason



Re: [PATCH] c++, v2: Drop TREE_READONLY on vars (possibly) initialized by tls wrapper [PR109164]

2023-03-20 Thread Jason Merrill via Gcc-patches

On 3/18/23 11:09, Jakub Jelinek wrote:

On Sat, Mar 18, 2023 at 01:54:58PM +0100, Jakub Jelinek via Gcc-patches wrote:

The patch is mostly about DECL_EXTERNAL cases, the others are supposedly
handled by the var_definition_p code there (or at least I assumed;
testcases certainly test only DECL_EXTERNAL).
I guess it could be done in cp_finish_decl, maybe better next to the
   /* A reference will be modified here, as it is initialized.  */
   if (! DECL_EXTERNAL (decl)
   && TREE_READONLY (decl)
   && TYPE_REF_P (type))
 {
   was_readonly = 1;
   TREE_READONLY (decl) = 0;
 }
spot, but we'd need to export the decl2.cc helpers for it,
because not all DECL_THREAD_LOCAL_P vars need to be treated that way.
   if (VAR_P (decl)
   && CP_DECL_THREAD_LOCAL_P (decl)
   && var_needs_tls_wrapper (decl)
   && (!DECL_EXTERNAL (decl) || flag_extern_tls_init))
 TREE_READONLY (decl) = 0;
where var_needs_tls_wrapper would need to be exported from decl2.cc.
Though, var_needs_tls_wrapper -> var_defined_without_dynamic_init
needs
DECL_NONTRIVIALLY_INITIALIZED_P/DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P,
so perhaps that is accurate only closer to the end of cp_finish_decl?


Here it is in patch form, tested so far on tls.exp:

2023-03-18  Jakub Jelinek  

PR c++/109164
* cp-tree.h (var_needs_tls_wrapper): Declare.
* decl2.cc (var_needs_tls_wrapper): No longer static.
* decl.cc (cp_finish_decl): Clear TREE_READONLY on TLS variables
for which a TLS wrapper will be needed.

* g++.dg/tls/thread_local13.C: New test.
* g++.dg/tls/thread_local13-aux.cc: New file.
* g++.dg/tls/thread_local14.C: New test.
* g++.dg/tls/thread_local14-aux.cc: New file.

--- gcc/cp/cp-tree.h.jj 2023-03-17 08:37:07.542937058 +0100
+++ gcc/cp/cp-tree.h2023-03-18 16:02:46.771230806 +0100
@@ -6989,6 +6989,7 @@ extern void copy_linkage  (tree, tree);
  extern tree get_guard (tree);
  extern tree get_guard_cond(tree, bool);
  extern tree set_guard (tree);
+extern bool var_needs_tls_wrapper  (tree);
  extern tree maybe_get_tls_wrapper_call(tree);
  extern void mark_needed   (tree);
  extern bool decl_needed_p (tree);
--- gcc/cp/decl2.cc.jj  2023-03-17 16:09:01.749244271 +0100
+++ gcc/cp/decl2.cc 2023-03-18 15:48:31.340642324 +0100
@@ -3623,7 +3623,7 @@ var_defined_without_dynamic_init (tree v
  /* Returns true iff VAR is a variable that needs uses to be
 wrapped for possible dynamic initialization.  */
  
-static bool

+bool
  var_needs_tls_wrapper (tree var)
  {
return (!error_operand_p (var)
--- gcc/cp/decl.cc.jj   2023-03-18 15:47:32.198500421 +0100
+++ gcc/cp/decl.cc  2023-03-18 16:00:04.565584266 +0100
@@ -8706,6 +8706,18 @@ cp_finish_decl (tree decl, tree init, bo
  if (!decl_maybe_constant_destruction (decl, type))
TREE_READONLY (decl) = 0;
}
+  else if (VAR_P (decl)
+  && CP_DECL_THREAD_LOCAL_P (decl)
+  && (!DECL_EXTERNAL (decl) || flag_extern_tls_init)


Hmm, I wonder why we don't check the above line in var_needs_tls_wrapper?

But the patch is OK.


+  && (was_readonly || TREE_READONLY (decl))
+  && var_needs_tls_wrapper (decl))
+   {
+ /* TLS variables need dynamic initialization by the TLS wrapper
+function, we don't want to hoist accesses to it before the
+wrapper.  */
+ was_readonly = 0;
+ TREE_READONLY (decl) = 0;
+   }
  
make_rtl_for_nonlocal_decl (decl, init, asmspec);
  
--- gcc/testsuite/g++.dg/tls/thread_local13.C.jj	2023-03-18 15:47:50.934228583 +0100

+++ gcc/testsuite/g++.dg/tls/thread_local13.C   2023-03-18 15:47:50.934228583 
+0100
@@ -0,0 +1,21 @@
+// PR c++/109164
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+// { dg-add-options tls }
+// { dg-require-effective-target tls_runtime }
+// { dg-additional-sources "thread_local13-aux.cc" }
+
+struct S { virtual void foo (); int s; };
+extern thread_local S &t;
+bool bar ();
+
+bool
+baz ()
+{
+  while (1)
+{
+  t.foo ();
+  if (!bar ())
+return false;
+}
+}
--- gcc/testsuite/g++.dg/tls/thread_local13-aux.cc.jj   2023-03-18 
15:47:50.934228583 +0100
+++ gcc/testsuite/g++.dg/tls/thread_local13-aux.cc  2023-03-18 
15:47:50.934228583 +0100
@@ -0,0 +1,35 @@
+// PR c++/109164
+
+struct S { virtual void foo (); int s; };
+extern bool baz ();
+
+void
+S::foo ()
+{
+  if (s != 42)
+__builtin_abort ();
+}
+
+S s;
+
+S &
+qux ()
+{
+  s.s = 42;
+  return s;
+}
+
+thread_local S &t = qux ();
+
+bool
+bar ()
+{
+  return false;
+}
+
+int
+main ()
+{
+  if (baz ())
+__builtin_abort ();
+}
--- gcc/testsuite/g++.dg/tls/thread_local14.C.jj2023-03-18 
15:47:50.934228583 +0100
+++ gcc/testsuite/g++.dg/tls/thread_local14.C  

Re: [PATCH] c++: explicit ctor and list-initialization [PR109159]

2023-03-20 Thread Jason Merrill via Gcc-patches

On 3/20/23 11:55, Marek Polacek wrote:

When I implemented explicit(bool) in r9-3735, I added this code to
add_template_candidate_real:
+  /* Now the explicit specifier might have been deduced; check if this
+ declaration is explicit.  If it is and we're ignoring non-converting
+ constructors, don't add this function to the set of candidates.  */
+  if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn))
+return NULL;
but as this test demonstrates, that's incorrect when we're initializing
from a {}: for list-initialization we consider explicit constructors and
complain if one is chosen.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?


OK.


PR c++/109159

gcc/cp/ChangeLog:

* call.cc (add_template_candidate_real): Add explicit decls to the
set of candidates when the initializer is a braced-init-list.

libstdc++-v3/ChangeLog:

* testsuite/20_util/pair/cons/explicit_construct.cc: Adjust dg-error.
* testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise.
* testsuite/23_containers/span/explicit.cc: Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/explicit16.C: New test.
---
  gcc/cp/call.cc|  4 +-
  gcc/testsuite/g++.dg/cpp0x/explicit16.C   | 18 ++
  .../20_util/pair/cons/explicit_construct.cc   | 10 ++--
  .../20_util/tuple/cons/explicit_construct.cc  | 58 +--
  .../testsuite/23_containers/span/explicit.cc  |  4 +-
  5 files changed, 57 insertions(+), 37 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/explicit16.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c01e7b82457..c52a09b9be2 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -3612,7 +3612,9 @@ add_template_candidate_real (struct z_candidate 
**candidates, tree tmpl,
/* Now the explicit specifier might have been deduced; check if this
   declaration is explicit.  If it is and we're ignoring non-converting
   constructors, don't add this function to the set of candidates.  */
-  if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn))
+  if (((flags & (LOOKUP_ONLYCONVERTING|LOOKUP_LIST_INIT_CTOR))
+   == LOOKUP_ONLYCONVERTING)
+  && DECL_NONCONVERTING_P (fn))
  return NULL;
  
if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)

diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit16.C 
b/gcc/testsuite/g++.dg/cpp0x/explicit16.C
new file mode 100644
index 000..bb5a823aee6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit16.C
@@ -0,0 +1,18 @@
+// PR c++/109159
+// { dg-do compile { target c++11 } }
+
+struct A {
+  A(float) {}
+  template
+  explicit A(U) {}
+};
+
+void f(A t)
+{
+  t = {1}; // { dg-error "explicit constructor" }
+  t = 1;
+  A a1{1};
+  A a2 = {1}; // { dg-error "explicit constructor" }
+  A a3 = 1;
+  A a4(1);
+}
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc 
b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
index e875f0cbcd2..d550e9c604b 100644
--- a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -37,7 +37,7 @@ struct ExplicitDefaultDefault
  
  std::pair f1() {return {1,2};}
  
-std::pair f2() {return {1,2};} // { dg-error "could not convert" }

+std::pair f2() {return {1,2};} // { dg-error "explicit 
constructor" }
  
  std::pair f3() {return std::pair{1,2};}
  
@@ -52,7 +52,7 @@ std::pair v0{1,2};
  
  std::pair v1{1,2};
  
-std::pair v2 = {1,2}; // { dg-error "could not convert" }

+std::pair v2 = {1,2}; // { dg-error "explicit constructor" 
}
  
  std::pair v3{std::pair{1,2}};
  
@@ -99,7 +99,7 @@ void test_arg_passing()

  {
f6(v0); // { dg-error "could not convert" }
f6(v1);
-  f6({1,2}); // { dg-error "could not convert" }
+  f6({1,2}); // { dg-error "explicit constructor" }
f6(std::pair{});
f6(std::pair{}); // { dg-error "could not convert" }
f7(v0);
@@ -130,6 +130,6 @@ std::pair v14{nullptr, MoveOnly{}};
  std::pair v15{MoveOnly{}, nullptr};
  
  std::pair v16 =

-  {nullptr, MoveOnly{}}; // { dg-error "could not convert" }
+  {nullptr, MoveOnly{}}; // { dg-error "explicit constructor" }
  std::pair v17 =
-  {MoveOnly{}, nullptr}; // { dg-error "could not convert" }
+  {MoveOnly{}, nullptr}; // { dg-error "explicit constructor" }
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc 
b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
index 820ddef30b4..3352dd15f7d 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -45,11 +45,11 @@ std::tuple f1b() {return {1,2};}
  std::tuple f1c() {return {1,2,3};}
  
  std::tuple f2_a()

-{return {1};} // { dg-error "could not convert" }
+{return {1};} // { dg-error "explicit constructor" }
  std::tuple f2_b()
-{return {1,2};} // { dg-error "could not convert" }
+{return {1,2};} // { dg-err

Re: [PATCH] c++: Drop TREE_READONLY on vars (possibly) initialized by tls wrapper [PR109164]

2023-03-18 Thread Jason Merrill via Gcc-patches

On 3/17/23 13:51, Jakub Jelinek wrote:

Hi!

The following two testcases are miscompiled, because we keep TREE_READONLY
on the vars even when they are (possibly) dynamically initialized by a TLS
wrapper function.  Normally cp_finish_decl drops TREE_READONLY from vars
which need dynamic initialization, but for TLS we do this kind of
initialization upon every access to those variables.


Why not handle this case in cp_finish_decl, too?  That is, add 
DECL_THREAD_LOCAL_P to the TREE_STATIC check in



  if (var_definition_p
  /* With -fmerge-all-constants, gimplify_init_constructor  
 might add TREE_STATIC to aggregate variables.  */

  && (TREE_STATIC (decl)
  || (flag_merge_constants >= 2
  && AGGREGATE_TYPE_P (type
{
  /* If a TREE_READONLY variable needs initialization   
 at runtime, it is no longer readonly and we need to
 avoid MEM_READONLY_P being set on RTL created for it.  */


?


Keeping them
TREE_READONLY means e.g. PRE can hoist loads from those before loops
which contain the TLS wrapper calls, so we can access the TLS variables
before they are initialized.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-03-17  Jakub Jelinek  

PR c++/109164
* decl2.cc (get_tls_wrapper_fn): Clear TREE_READONLY on variables for
which a TLS wrapper is added.

* g++.dg/tls/thread_local13.C: New test.
* g++.dg/tls/thread_local13-aux.cc: New file.
* g++.dg/tls/thread_local14.C: New test.
* g++.dg/tls/thread_local14-aux.cc: New file.

--- gcc/cp/decl2.cc.jj  2023-03-07 21:20:31.800491531 +0100
+++ gcc/cp/decl2.cc 2023-03-17 12:20:11.960678291 +0100
@@ -3773,6 +3773,12 @@ get_tls_wrapper_fn (tree var)
DECL_BEFRIENDING_CLASSES (fn) = var;
  
set_global_binding (fn);

+
+  /* The variable now needs dynamic initialization by the wrapper
+function, we don't want to hoist accesses to it before the
+wrapper.  */
+  if (TREE_READONLY (var))
+   TREE_READONLY (var) = 0;
  }
return fn;
  }
--- gcc/testsuite/g++.dg/tls/thread_local13.C.jj2023-03-17 
12:28:24.692427351 +0100
+++ gcc/testsuite/g++.dg/tls/thread_local13.C   2023-03-17 12:30:34.505519746 
+0100
@@ -0,0 +1,21 @@
+// PR c++/109164
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+// { dg-add-options tls }
+// { dg-require-effective-target tls_runtime }
+// { dg-additional-sources "thread_local13-aux.cc" }
+
+struct S { virtual void foo (); int s; };
+extern thread_local S &t;
+bool bar ();
+
+bool
+baz ()
+{
+  while (1)
+{
+  t.foo ();
+  if (!bar ())
+return false;
+}
+}
--- gcc/testsuite/g++.dg/tls/thread_local13-aux.cc.jj   2023-03-17 
12:28:28.721368058 +0100
+++ gcc/testsuite/g++.dg/tls/thread_local13-aux.cc  2023-03-17 
12:37:53.952070861 +0100
@@ -0,0 +1,35 @@
+// PR c++/109164
+
+struct S { virtual void foo (); int s; };
+extern bool baz ();
+
+void
+S::foo ()
+{
+  if (s != 42)
+__builtin_abort ();
+}
+
+S s;
+
+S &
+qux ()
+{
+  s.s = 42;
+  return s;
+}
+
+thread_local S &t = qux ();
+
+bool
+bar ()
+{
+  return false;
+}
+
+int
+main ()
+{
+  if (baz ())
+__builtin_abort ();
+}
--- gcc/testsuite/g++.dg/tls/thread_local14.C.jj2023-03-17 
12:35:48.951905245 +0100
+++ gcc/testsuite/g++.dg/tls/thread_local14.C   2023-03-17 12:49:03.456249628 
+0100
@@ -0,0 +1,19 @@
+// PR c++/109164
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+// { dg-add-options tls }
+// { dg-require-effective-target tls_runtime }
+// { dg-additional-sources "thread_local14-aux.cc" }
+
+extern thread_local const int t;
+bool bar (int);
+
+bool
+baz ()
+{
+  while (1)
+{
+  if (!bar (t))
+return false;
+}
+}
--- gcc/testsuite/g++.dg/tls/thread_local14-aux.cc.jj   2023-03-17 
12:36:58.724881322 +0100
+++ gcc/testsuite/g++.dg/tls/thread_local14-aux.cc  2023-03-17 
12:48:53.914389421 +0100
@@ -0,0 +1,26 @@
+// PR c++/109164
+
+extern bool baz ();
+
+int
+qux ()
+{
+  return 42;
+}
+
+extern thread_local const int t = qux ();
+
+bool
+bar (int x)
+{
+  if (x != 42)
+__builtin_abort ();
+  return false;
+}
+
+int
+main ()
+{
+  if (baz ())
+__builtin_abort ();
+}

Jakub





Re: [PATCH] c++: further -Wdangling-reference refinement [PR107532]

2023-03-18 Thread Jason Merrill via Gcc-patches

On 3/17/23 16:29, Marek Polacek wrote:

Based on ,
it seems like we should treat *any* class with a reference member
as a reference wrapper.  This simplifies the code so I'm happy to
make that change.

The patch, however, does not suppress the warning in

   int i = 42;
   auto const& v = std::get<0>(std::tuple(i));


Why not?  tuple has an int& member, doesn't it?  Do we need to 
look into bases as well?



Since reference_like_class_p already checks for std::pair
maybe it could also check for std::tuple.  I don't know if we
want to make that change in GCC 13, or move -Wdangling-reference to
-Wextra for GCC 13 and perhaps move it back to -Wall in GCC 14.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/107532

gcc/cp/ChangeLog:

* call.cc (reference_like_class_p): Don't look for a constructor.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wdangling-reference11.C: New test.
---
  gcc/cp/call.cc| 35 +++
  .../g++.dg/warn/Wdangling-reference11.C   | 23 
  2 files changed, 35 insertions(+), 23 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference11.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c01e7b82457..00d56a157b6 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13781,8 +13781,9 @@ std_pair_ref_ref_p (tree t)
  
  /* Return true if a class CTYPE is either std::reference_wrapper or

 std::ref_view, or a reference wrapper class.  We consider a class
-   a reference wrapper class if it has a reference member and a
-   constructor taking the same reference type.  */
+   a reference wrapper class if it has a reference member.  We no
+   longer check that it has a constructor taking the same reference type
+   since that approach still generated too many false positives.  */
  
  static bool

  reference_like_class_p (tree ctype)
@@ -13798,31 +13799,19 @@ reference_like_class_p (tree ctype)
if (decl_in_std_namespace_p (tdecl))
  {
tree name = DECL_NAME (tdecl);
-  return (name
- && (id_equal (name, "reference_wrapper")
- || id_equal (name, "span")
- || id_equal (name, "ref_view")));
+  if (name
+ && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "span")
+ || id_equal (name, "ref_view")))
+   return true;
  }
for (tree fields = TYPE_FIELDS (ctype);
 fields;
 fields = DECL_CHAIN (fields))
-{
-  if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
-   continue;
-  tree type = TREE_TYPE (fields);
-  if (!TYPE_REF_P (type))
-   continue;
-  /* OK, the field is a reference member.  Do we have a constructor
-taking its type?  */
-  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype)))
-   {
- tree args = FUNCTION_FIRST_USER_PARMTYPE (fn);
- if (args
- && same_type_p (TREE_VALUE (args), type)
- && TREE_CHAIN (args) == void_list_node)
-   return true;
-   }
-}
+if (TREE_CODE (fields) == FIELD_DECL
+   && !DECL_ARTIFICIAL (fields)
+   && TYPE_REF_P (TREE_TYPE (fields)))
+  return true;
return false;
  }
  
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C

new file mode 100644
index 000..667618e7196
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
@@ -0,0 +1,23 @@
+// PR c++/107532
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wdangling-reference" }
+
+struct R
+{
+int& r;
+int& get() { return r; }
+int&& rget() { return static_cast(r); }
+};
+
+int main()
+{
+int i = 42;
+int& l = R{i}.get(); // { dg-bogus "dangling reference" }
+int const& cl = R{i}.get(); // { dg-bogus "dangling reference" }
+int&& r = R{i}.rget(); // { dg-bogus "dangling reference" }
+int const&& cr = R{i}.rget(); // { dg-bogus "dangling reference" }
+(void) l;
+(void) r;
+(void) cr;
+(void) cl;
+}

base-commit: ae7190e345a8d80310835cb83b3b41ef2aeb0d37




[pushed] c++: constant, array, lambda, template [PR108975]

2023-03-17 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

When a lambda refers to a constant local variable in the enclosing scope, we
tentatively capture it, but if we end up pulling out its constant value, we
go back at the end of the lambda and prune any unneeded captures.  Here
while parsing the template we decided that the dim capture was unneeded,
because we folded it away, but then we brought back the use in the template
trees that try to preserve the source representation with added type info.
So then when we tried to instantiate that use, we couldn't find what it was
trying to use, and crashed.

Fixed by not trying to prune when parsing a template; we'll prune at
instantiation time.

PR c++/108975

gcc/cp/ChangeLog:

* lambda.cc (prune_lambda_captures): Don't bother in a template.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/lambda/lambda-const11.C: New test.
---
 gcc/cp/lambda.cc   |  3 +++
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11.C | 14 ++
 2 files changed, 17 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11.C

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 212990a21bf..9925209b2ed 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1760,6 +1760,9 @@ prune_lambda_captures (tree body)
   if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_NONE)
 /* No default captures, and we don't prune explicit captures.  */
 return;
+  /* Don't bother pruning in a template, we'll prune at instantiation time.  */
+  if (dependent_type_p (TREE_TYPE (lam)))
+return;
 
   hash_map const_vars;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11.C 
b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11.C
new file mode 100644
index 000..26af75bf132
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11.C
@@ -0,0 +1,14 @@
+// PR c++/108975
+// { dg-do compile { target c++11 } }
+
+template
+void f() {
+  constexpr int dim = 1;
+  auto l = [&] {
+int n[dim * 1];
+  };
+  // In f, we shouldn't actually capture dim.
+  static_assert (sizeof(l) == 1, "");
+}
+
+template void f();

base-commit: 890043314a7f405081990ea9d0cb577dd44f883f
-- 
2.31.1



[pushed] c++: throw and private destructor [PR109172]

2023-03-17 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Since we aren't going through the normal call machinery, we need to check
the dtor access specifically.

PR c++/109172

gcc/cp/ChangeLog:

* except.cc (build_throw): Check dtor access.

gcc/testsuite/ChangeLog:

* g++.dg/eh/dtor4.C: New test.
---
 gcc/cp/except.cc| 10 --
 gcc/testsuite/g++.dg/eh/dtor4.C | 15 +++
 2 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/eh/dtor4.C

diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index 916e8189db6..91a5e049860 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -639,6 +639,8 @@ build_throw (location_t loc, tree exp)
   tree object, ptr;
   tree allocate_expr;
 
+  tsubst_flags_t complain = tf_warning_or_error;
+
   /* The CLEANUP_TYPE is the internal type of a destructor.  */
   if (!cleanup_type)
{
@@ -759,11 +761,15 @@ build_throw (location_t loc, tree exp)
   cleanup = NULL_TREE;
   if (type_build_dtor_call (TREE_TYPE (object)))
{
- tree dtor_fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
+ tree binfo = TYPE_BINFO (TREE_TYPE (object));
+ tree dtor_fn = lookup_fnfields (binfo,
  complete_dtor_identifier, 0,
  tf_warning_or_error);
  dtor_fn = BASELINK_FUNCTIONS (dtor_fn);
- mark_used (dtor_fn);
+ if (!mark_used (dtor_fn)
+ || !perform_or_defer_access_check (binfo, dtor_fn,
+dtor_fn, complain))
+   return error_mark_node;
  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
{
  cxx_mark_addressable (dtor_fn);
diff --git a/gcc/testsuite/g++.dg/eh/dtor4.C b/gcc/testsuite/g++.dg/eh/dtor4.C
new file mode 100644
index 000..6c0e804fe8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dtor4.C
@@ -0,0 +1,15 @@
+// PR c++/109172
+
+class Demo
+{
+  ~Demo();
+};
+
+int main()
+{
+  try
+{
+  throw *new Demo; // { dg-error private }
+}
+  catch(const Demo& e) { }
+}

base-commit: c48be8298c27143c1a684c0cb9689c88d16f4b49
-- 
2.31.1



[pushed] c++: namespace-scoped friend in local class [PR69410]

2023-03-17 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

do_friend was only considering class-qualified identifiers for the
qualified-id case, but we also need to skip local scope when there's an
explicit namespace scope.

PR c++/69410

gcc/cp/ChangeLog:

* friend.cc (do_friend): Handle namespace as scope argument.
* decl.cc (grokdeclarator): Pass down in_namespace.

gcc/testsuite/ChangeLog:

* g++.dg/lookup/friend24.C: New test.
---
 gcc/cp/decl.cc |  3 ++-
 gcc/cp/friend.cc   | 21 +
 gcc/testsuite/g++.dg/lookup/friend24.C |  9 +
 3 files changed, 28 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lookup/friend24.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 1d1ae022606..f5785339c5a 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -14393,7 +14393,8 @@ grokdeclarator (const cp_declarator *declarator,
cplus_decl_attributes (&decl, *attrlist, 0);
*attrlist = NULL_TREE;
 
-   decl = do_friend (ctype, unqualified_id, decl,
+   tree scope = ctype ? ctype : in_namespace;
+   decl = do_friend (scope, unqualified_id, decl,
  flags, funcdef_flag);
return decl;
  }
diff --git a/gcc/cp/friend.cc b/gcc/cp/friend.cc
index 2d9bd4bb4aa..b36de2b20bb 100644
--- a/gcc/cp/friend.cc
+++ b/gcc/cp/friend.cc
@@ -487,19 +487,32 @@ make_friend_class (tree type, tree friend_type, bool 
complain)
 }
 
 /* Record DECL (a FUNCTION_DECL) as a friend of the
-   CURRENT_CLASS_TYPE.  If DECL is a member function, CTYPE is the
+   CURRENT_CLASS_TYPE.  If DECL is a member function, SCOPE is the
class of which it is a member, as named in the friend declaration.
+   If the friend declaration was explicitly namespace-qualified, SCOPE
+   is that namespace.
DECLARATOR is the name of the friend.  FUNCDEF_FLAG is true if the
friend declaration is a definition of the function.  FLAGS is as
for grokclass fn.  */
 
 tree
-do_friend (tree ctype, tree declarator, tree decl,
+do_friend (tree scope, tree declarator, tree decl,
   enum overload_flags flags,
   bool funcdef_flag)
 {
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-  gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));
+
+  tree ctype = NULL_TREE;
+  tree in_namespace = NULL_TREE;
+  if (!scope)
+;
+  else if (MAYBE_CLASS_TYPE_P (scope))
+ctype = scope;
+  else
+{
+  gcc_checking_assert (TREE_CODE (scope) == NAMESPACE_DECL);
+  in_namespace = scope;
+}
 
   /* Friend functions are unique, until proved otherwise.  */
   DECL_UNIQUE_FRIEND_P (decl) = 1;
@@ -609,7 +622,7 @@ do_friend (tree ctype, tree declarator, tree decl,
   parameters.  Instead, we call pushdecl when the class
   is instantiated.  */
decl = push_template_decl (decl, /*is_friend=*/true);
- else if (current_function_decl)
+ else if (current_function_decl && !in_namespace)
/* pushdecl will check there's a local decl already.  */
decl = pushdecl (decl, /*hiding=*/true);
  else
diff --git a/gcc/testsuite/g++.dg/lookup/friend24.C 
b/gcc/testsuite/g++.dg/lookup/friend24.C
new file mode 100644
index 000..9a45410d2a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/friend24.C
@@ -0,0 +1,9 @@
+// PR c++/69410
+
+void a();
+void f() {
+class A {
+friend void ::a();
+friend class Z;
+};
+}

base-commit: 103d423f6ce72ccb03d55b7b1dfa2dabd5854371
-- 
2.31.1



[pushed] c++: __func__ and local class DMI [PR105809]

2023-03-16 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

As in 108242, we need to instantiate in the context of the enclosing
function, not after it's gone.

PR c++/105809

gcc/cp/ChangeLog:

* init.cc (get_nsdmi): Split out...
(maybe_instantiate_nsdmi_init): ...this function.
* cp-tree.h: Declare it.
* pt.cc (tsubst_expr): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-__func__3.C: New test.
---
 gcc/cp/cp-tree.h  |  1 +
 gcc/cp/init.cc| 27 ---
 gcc/cp/pt.cc  |  6 +
 .../g++.dg/cpp0x/constexpr-__func__3.C| 15 +++
 4 files changed, 40 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-__func__3.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index dfc1c845768..b74c18b03ad 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7086,6 +7086,7 @@ extern bool is_copy_initialization(tree);
 extern tree build_zero_init(tree, tree, bool);
 extern tree build_value_init   (tree, tsubst_flags_t);
 extern tree build_value_init_noctor(tree, tsubst_flags_t);
+extern tree maybe_instantiate_nsdmi_init   (tree, tsubst_flags_t);
 extern tree get_nsdmi  (tree, bool, tsubst_flags_t);
 extern tree build_offset_ref   (tree, tree, bool,
 tsubst_flags_t);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 1b7d3d8fe3e..90302372340 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -561,18 +561,16 @@ perform_target_ctor (tree init)
   return init;
 }
 
-/* Return the non-static data initializer for FIELD_DECL MEMBER.  */
+/* Instantiate the default member initializer of MEMBER, if needed.
+   Only get_nsdmi should use the return value of this function.  */
 
 static GTY((cache)) decl_tree_cache_map *nsdmi_inst;
 
 tree
-get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
+maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain)
 {
-  tree init;
-  tree save_ccp = current_class_ptr;
-  tree save_ccr = current_class_ref;
-  
-  if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
+  tree init = DECL_INITIAL (member);
+  if (init && DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
 {
   init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
   location_t expr_loc
@@ -642,8 +640,19 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t 
complain)
  input_location = sloc;
}
 }
-  else
-init = DECL_INITIAL (member);
+
+  return init;
+}
+
+/* Return the non-static data initializer for FIELD_DECL MEMBER.  */
+
+tree
+get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
+{
+  tree save_ccp = current_class_ptr;
+  tree save_ccr = current_class_ref;
+
+  tree init = maybe_instantiate_nsdmi_init (member, complain);
 
   if (init && TREE_CODE (init) == DEFERRED_PARSE)
 {
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1072882e1a8..056b8c7abad 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19353,6 +19353,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
  /* Closures are handled by the LAMBDA_EXPR.  */
  gcc_assert (!LAMBDA_TYPE_P (TREE_TYPE (t)));
  complete_type (tmp);
+ tree save_ccp = current_class_ptr;
+ tree save_ccr = current_class_ref;
  for (tree fld = TYPE_FIELDS (tmp); fld; fld = DECL_CHAIN (fld))
if ((VAR_P (fld)
 || (TREE_CODE (fld) == FUNCTION_DECL
@@ -19360,6 +19362,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
&& DECL_TEMPLATE_INSTANTIATION (fld))
  instantiate_decl (fld, /*defer_ok=*/false,
/*expl_inst_class=*/false);
+   else if (TREE_CODE (fld) == FIELD_DECL)
+ maybe_instantiate_nsdmi_init (fld, tf_warning_or_error);
+ current_class_ptr = save_ccp;
+ current_class_ref = save_ccr;
}
   break;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__3.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__3.C
new file mode 100644
index 000..365a4e00c5f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__3.C
@@ -0,0 +1,15 @@
+// PR c++/105809
+// { dg-do compile { target c++11 } }
+
+template void hh() {  ss t; }
+
+template
+int f(void)
+{
+constexpr char const* cc = __func__;
+struct j{  char const* kk=cc; };
+hh();
+return 0;
+}
+
+int t = f<1>();

base-commit: b323f52ccf966800297b0520b9e1d4b3951db525
-- 
2.31.1



[pushed] c++: generic lambda, local class, __func__ [PR108242]

2023-03-16 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Here we are trying to do name lookup in a deferred instantiation of t() and
failing to find __func__.  tsubst_expr already tries to instantiate members
of local classes, but was failing with the partial instantiation of generic
lambdas.

PR c++/108242

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr) [TAG_DEFN]: Handle partial instantiation.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/lambda-generic-func2.C: New test.
---
 gcc/cp/pt.cc   |  5 -
 .../g++.dg/cpp1y/lambda-generic-func2.C| 18 ++
 2 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-func2.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ddbd73371b9..1072882e1a8 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19341,7 +19341,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
 
 case TAG_DEFN:
   tmp = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
-  if (CLASS_TYPE_P (tmp))
+  if (dependent_type_p (tmp))
+   /* This is a partial instantiation, try again when full.  */
+   add_stmt (build_min (TAG_DEFN, tmp));
+  else if (CLASS_TYPE_P (tmp))
{
  /* Local classes are not independent templates; they are
 instantiated along with their containing function.  And this
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-func2.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-func2.C
new file mode 100644
index 000..ed541c7812f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-func2.C
@@ -0,0 +1,18 @@
+// PR c++/108242
+// { dg-do compile { target c++14 } }
+
+template
+void my_fun()
+{
+[&](auto) {
+static constexpr char const* fun_name = __func__;
+struct t
+{
+t() { fun_name; };
+} t1;
+}(12);
+}
+
+int main() {
+my_fun<1>();
+}

base-commit: 1cc8814098bb46f9fca58a0b831fbf9a8574bdc9
-- 
2.31.1



[pushed] c++: &enum::enumerator [PR101869]

2023-03-16 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

We don't want to call build_offset_ref with an enum.

PR c++/101869

gcc/cp/ChangeLog:

* semantics.cc (finish_qualified_id_expr): Don't try to build a
pointer-to-member if the scope is an enumeration.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/enum43.C: New test.
---
 gcc/cp/semantics.cc |  3 ++-
 gcc/testsuite/g++.dg/cpp0x/enum43.C | 11 +++
 2 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum43.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 57dd7b66da8..87c2e8a7111 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2386,7 +2386,8 @@ finish_qualified_id_expr (tree qualifying_class,
 
   /* If EXPR occurs as the operand of '&', use special handling that
  permits a pointer-to-member.  */
-  if (address_p && done)
+  if (address_p && done
+  && TREE_CODE (qualifying_class) != ENUMERAL_TYPE)
 {
   if (TREE_CODE (expr) == SCOPE_REF)
expr = TREE_OPERAND (expr, 1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum43.C 
b/gcc/testsuite/g++.dg/cpp0x/enum43.C
new file mode 100644
index 000..b2cd9797a06
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum43.C
@@ -0,0 +1,11 @@
+// PR c++/101869
+
+enum E { A };
+E operator & (E e)
+{
+  return e;
+}
+E f(void)
+{
+return &E::A;   // { dg-error "not a class" "" { target c++98_only } }
+}

base-commit: e6ccae0ac0d53cfa9099d62fada050ee87d4d0ad
-- 
2.31.1



Re: [PATCH] c++: ICE with diagnosed constraint recursion [PR100288]

2023-03-16 Thread Jason Merrill via Gcc-patches

On 3/16/23 12:48, Patrick Palka wrote:

When satisfaction_cache::get detects constraint recursion, it asserts
that entry->result is empty.  This makes sense when we're initially
detecting/diagnosing recursion from the inner recursive call, but
aftewards from the outer recursive call the recursion error is treated
like any other SFINAE error encountered during satisfaction, and we set
entry->result to whatever the satisfaction value ended up being.

Perhaps we should keep entry->result cleared in this case, but that'd
require the inner recursive call to communicate to the outer recursive
call that constraint recursion occurred, likely via setting entry->result
to some sentinel value, which doesn't seem to be worth the complexity.
So this patch just relaxes the problematic assert to accept non-empty
entry->result as long as we've already issued an error.

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?  Backports
seems unnecessary as the problematic assert is a checking assert.


OK.


PR c++/100288

gcc/cp/ChangeLog:

* constraint.cc (satisfaction_cache::get): Relax overly strict
checking assert in the constraint recursion case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-recursive-sat5.C: New test.
---
  gcc/cp/constraint.cc|  2 +-
  .../g++.dg/cpp2a/concepts-recursive-sat5.C  | 13 +
  2 files changed, 14 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index a28c85178fe..273d15ab097 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2705,7 +2705,7 @@ satisfaction_cache::get ()
if (entry->evaluating)
  {
/* If we get here, it means satisfaction is self-recursive.  */
-  gcc_checking_assert (!entry->result);
+  gcc_checking_assert (!entry->result || seen_error ());
if (info.noisy ())
error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom)),
  "satisfaction of atomic constraint %qE depends on itself",
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C
new file mode 100644
index 000..b7a02815db9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C
@@ -0,0 +1,13 @@
+// PR c++/100288
+// { dg-do compile { target c++20 } }
+
+class A { };
+
+template  concept pipeable = requires(A a, T t) { a | t; }; // { dg-error 
"depends on itself" }
+
+template  void operator|(A, T);
+
+void f(A tab) {
+  tab | 1; // { dg-error "no match" }
+  tab | 1; // { dg-error "no match" }
+}




Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-16 Thread Jason Merrill via Gcc-patches

On 3/16/23 11:48, Patrick Palka wrote:

On Thu, 16 Mar 2023, Jason Merrill wrote:


On 3/16/23 10:09, Patrick Palka wrote:

On Wed, 15 Mar 2023, Patrick Palka wrote:


On Thu, 9 Mar 2023, Jason Merrill wrote:


On 3/9/23 14:32, Patrick Palka wrote:

On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:


When processing a noexcept, constructors aren't elided:
build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
gcc/cp/constexpr.cc | 6 +-
gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx
*ctx,
tree t,
/* 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);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);


It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second
way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in
maybe_constant_value?


Sounds good.


Hmm, while working on this I noticed we currently don't reject a version
of
g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead
of
int (ever since r12-4425-g1595fe44e11a96):

struct A { int m; };
template constexpr int f() { return T::value; }
template void h(decltype(A{B ? f() : 0})); //
was int{...}
template void h(...);
void x() {
  h(0); // OK?
}

ISTM we should instantiate f here for the same reason we do in the
original version of the testcase, and for that to happen we need to
pass manifestly_const_eval=true in massage_init_elt.  Does that seem
reasonable?



FWIW the reason this came up is because I tried contriving a testcase
for the aforementioned maybe_constant_init change, and I came up with:

struct __as_receiver {
  int empty_env;
};

template
constexpr int f(T t) {
  return t.fail;
};

using type = decltype(__as_receiver{f(0)}); // OK, f no longer
instantiated

which we used to reject and afterwards accept.  But since the elements
of an initializer list are potentially constant evaluated, I wonder if
that that means f should be instantiated here after all despite the
unevaluated context?


The relevant section of the standard would seem to be
https://eel.is/c++draft/expr.const#20 ; an immediate subexpression of a
braced-init-list is potentially constant-evaluated even though it isn't
potentially-evaluated or manifestly constant-evaluated.

It seems like the call to fold_non_dependent_expr in check_narrowing ought to
cause instantiation in this case, why doesn't it?


Looks like check_narrowing isn't called at all in this aggr init case.
The call from e.g. convert_like_internal isn't reached because the
conversion for the initializer element is ck_identity, and don't ever
set conversion::check_narrowing for ck_identity conversions I think.


Ah, yes, that makes sense; an identity conversion can never be 
narrowing, so we don't care about the constant value.  So not 
instantiating seems correct, and the patch is OK.



Yet for using 'type = decltype(int{f(0)});' (similar to the example in
[temp.inst]/8) we do call check_narrowing directly from
finish_compound_literal, despite the conversion effectively being an
identity conversion.


Hmm, maybe check_narrowing should defer constant evaluation until after 
deciding that the target type is not a superset of the source type...



Here's the full patch for reference:

-- >8 --

Subject: [PATCH] c++: maybe_constant_init and unevaluated operands
[PR109030]

This testcase in this PR (already fixed by r13-6526-ge4692319fd5fc7)
illustrates that maybe_constant_init can be called on an unevaluated
operand (from massage_init_elt), so this entry point should limit
constant evaluation in that case, like maybe_constant_value does.

PR c++/10

Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-16 Thread Jason Merrill via Gcc-patches

On 3/16/23 10:09, Patrick Palka wrote:

On Wed, 15 Mar 2023, Patrick Palka wrote:


On Thu, 9 Mar 2023, Jason Merrill wrote:


On 3/9/23 14:32, Patrick Palka wrote:

On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:


When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
   gcc/cp/constexpr.cc | 6 +-
   gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
   2 files changed, 14 insertions(+), 1 deletion(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
tree t,
   /* 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);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);


It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in
maybe_constant_value?


Sounds good.


Hmm, while working on this I noticed we currently don't reject a version of
g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead of
int (ever since r12-4425-g1595fe44e11a96):

   struct A { int m; };
   template constexpr int f() { return T::value; }
   template void h(decltype(A{B ? f() : 0})); // was 
int{...}
   template void h(...);
   void x() {
 h(0); // OK?
   }

ISTM we should instantiate f here for the same reason we do in the
original version of the testcase, and for that to happen we need to
pass manifestly_const_eval=true in massage_init_elt.  Does that seem
reasonable?



FWIW the reason this came up is because I tried contriving a testcase
for the aforementioned maybe_constant_init change, and I came up with:

   struct __as_receiver {
 int empty_env;
   };

   template
   constexpr int f(T t) {
 return t.fail;
   };

   using type = decltype(__as_receiver{f(0)}); // OK, f no longer 
instantiated

which we used to reject and afterwards accept.  But since the elements
of an initializer list are potentially constant evaluated, I wonder if
that that means f should be instantiated here after all despite the
unevaluated context?


The relevant section of the standard would seem to be
https://eel.is/c++draft/expr.const#20 ; an immediate subexpression of a 
braced-init-list is potentially constant-evaluated even though it isn't 
potentially-evaluated or manifestly constant-evaluated.


It seems like the call to fold_non_dependent_expr in check_narrowing 
ought to cause instantiation in this case, why doesn't it?



Here's the full patch for reference:

-- >8 --

Subject: [PATCH] c++: maybe_constant_init and unevaluated operands [PR109030]

This testcase in this PR (already fixed by r13-6526-ge4692319fd5fc7)
illustrates that maybe_constant_init can be called on an unevaluated
operand (from massage_init_elt), so this entry point should limit
constant evaluation in that case, like maybe_constant_value does.

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_init_1): For an unevaluated
non-manifestly-constant operand, don't constant evaluate
and instead call fold_to_constant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/decltype83.C: New test.
---
  gcc/cp/constexpr.cc |  2 ++
  gcc/testsuite/g++.dg/cpp0x/decltype83.C | 14 ++
  2 files changed, 16 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype83.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8683c00596a..f325af375c8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8795,6 +8795,8 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (is_static)
manifestly_const_eval = true;
+  if (cp_unevaluated_operand && !manifestly_const_eval)
+  

[PATCH RFC] c++: co_await and move-only type [PR105406]

2023-03-15 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu.  As with the array issue, I know you have WIP to
deal with larger issues, but this seems like a reasonable local fix.  Does it
make sense to you?

-- 8< --

Here we were building a temporary MoveOnlyAwaitable to hold the result of
evaluating 'o', but since 'o' is an lvalue we should build a reference
instead.

PR c++/105406

gcc/cp/ChangeLog:

* coroutines.cc (build_co_await): Handle lvalue 'o'.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/co-await-moveonly1.C: New test.
---
 gcc/cp/coroutines.cc  |  9 ++-
 .../g++.dg/coroutines/co-await-moveonly1.C| 63 +++
 2 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 7f8cbc3d95e..a2189e43db8 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1024,9 +1024,13 @@ build_co_await (location_t loc, tree a, 
suspend_point_kind suspend_kind)
 }
   else
 {
-  e_proxy = get_awaitable_var (suspend_kind, o_type);
+  tree p_type = o_type;
+  if (glvalue_p (o))
+   p_type = cp_build_reference_type (p_type, !lvalue_p (o));
+  e_proxy = get_awaitable_var (suspend_kind, p_type);
   o = cp_build_modify_expr (loc, e_proxy, INIT_EXPR, o,
tf_warning_or_error);
+  e_proxy = convert_from_reference (e_proxy);
 }
 
   /* I suppose we could check that this is contextually convertible to bool.  
*/
@@ -1120,6 +1124,9 @@ build_co_await (location_t loc, tree a, 
suspend_point_kind suspend_kind)
 }
   TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume().  */
 
+  if (REFERENCE_REF_P (e_proxy))
+e_proxy = TREE_OPERAND (e_proxy, 0);
+
   tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
TREE_TYPE (TREE_TYPE (awrs_func)),
a, e_proxy, o, awaiter_calls,
diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C 
b/gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C
new file mode 100644
index 000..e2831c104bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C
@@ -0,0 +1,63 @@
+// PR c++/105406
+// { dg-do compile { target c++20 } }
+
+#include 
+#include 
+
+// A move-only awaitable
+class MoveOnlyAwaitable {
+public:
+MoveOnlyAwaitable() = default;
+MoveOnlyAwaitable(MoveOnlyAwaitable &&) = default;
+MoveOnlyAwaitable &operator=(MoveOnlyAwaitable &&) = default;
+
+MoveOnlyAwaitable(const MoveOnlyAwaitable &) = delete;
+MoveOnlyAwaitable &operator=(const MoveOnlyAwaitable &) = delete;
+
+bool await_ready() const noexcept { return false; }
+void await_suspend(std::coroutine_handle<>) noexcept {}
+void await_resume() {}
+};
+
+struct task {
+struct promise_type {
+auto initial_suspend() const { return std::suspend_never{}; }
+auto final_suspend() const noexcept { return std::suspend_never(); }
+auto get_return_object() { return task{}; }
+void return_void() {}
+void unhandled_exception() {}
+
+template
+T &&await_transform(T &&t) {
+return static_cast(t);
+}
+
+
+};
+
+bool await_ready() const { return false; }
+void await_suspend(std::coroutine_handle<> awaiter) {}
+void await_resume() {}
+};
+
+task myCoroutine() {
+// GCC: OK
+// clang: OK
+{
+co_await MoveOnlyAwaitable();
+}
+// GCC: OK
+// clang: OK
+{
+auto moveonly = MoveOnlyAwaitable();
+co_await std::move(moveonly);
+}
+
+// GCC <= 11.2: OK
+// GCC 11.3:ERROR:  error: use of deleted function 
'MoveOnlyAwaitable::MoveOnlyAwaitable(const MoveOnlyAwaitable&)
+// clang: OK
+{
+auto moveonly = MoveOnlyAwaitable();
+co_await moveonly;
+}
+}

base-commit: ea4dd8f512979db247c54d6b41377bb73699bcd7
-- 
2.31.1



[pushed] c++: co_await and initializer_list [PR103871]

2023-03-15 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

When flatten_await_stmt processes the backing array for an initializer_list,
we call cp_build_modify_expr to initialize the promoted variable from the
TARGET_EXPR; that needs to be accepted.

PR c++/103871
PR c++/98056

gcc/cp/ChangeLog:

* typeck.cc (cp_build_modify_expr): Allow array initialization of
DECL_ARTIFICIAL variable.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/co-await-initlist1.C: New test.
---
 gcc/cp/typeck.cc  |  2 ++
 .../g++.dg/coroutines/co-await-initlist1.C| 21 +++
 2 files changed, 23 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/co-await-initlist1.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index d5a3e501d8e..afb956087ce 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9630,6 +9630,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum 
tree_code modifycode,
}
 
   /* Allow array assignment in compiler-generated code.  */
+  else if (DECL_P (lhs) && DECL_ARTIFICIAL (lhs))
+   /* OK, used by coroutines (co-await-initlist1.C).  */;
   else if (!current_function_decl
   || !DECL_DEFAULTED_FN (current_function_decl))
{
diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-initlist1.C 
b/gcc/testsuite/g++.dg/coroutines/co-await-initlist1.C
new file mode 100644
index 000..b8e8923a9c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/co-await-initlist1.C
@@ -0,0 +1,21 @@
+// PR c++/103871
+// { dg-do compile { target c++20 } }
+
+#include 
+#include 
+
+struct my_coro {
+  struct promise_type {
+my_coro get_return_object();
+std::suspend_never initial_suspend();
+std::suspend_never final_suspend() noexcept;
+void unhandled_exception();
+  };
+};
+
+std::suspend_never inner(std::initializer_list);
+
+my_coro doesnt_work()
+{
+  co_await inner({ 1,2,3 });
+}

base-commit: 57052c6ed59c1a2ee4a67982f960e08593956955
-- 
2.31.1



Re: [PATCH v2] c++: ICE with constexpr lambda [PR107280]

2023-03-15 Thread Jason Merrill via Gcc-patches

On 3/15/23 10:37, Marek Polacek wrote:

On Fri, Mar 10, 2023 at 01:47:46PM -0500, Jason Merrill wrote:

On 3/10/23 11:17, Marek Polacek wrote:

We crash here since r10-3661, the store_init_value hunk in particular.
Before, we called cp_fully_fold_init, so e.g.

{.str=VIEW_CONVERT_EXPR("")}

was folded into

{.str=""}

but now we don't fold and keep the VCE around, and it causes trouble in
cxx_eval_store_expression: in the !refs->is_empty () loop we descend on
.str's initializer but since it's wrapped in a VCE, we skip the STRING_CST
check and then crash on the CONSTRUCTOR_NO_CLEARING.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?

PR c++/107280

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_store_expression): Strip location wrappers.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/constexpr-lambda28.C: New test.
---
   gcc/cp/constexpr.cc |  3 ++-
   gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C | 15 +++
   2 files changed, 17 insertions(+), 1 deletion(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8683c00596a..abf6ee560c5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6033,7 +6033,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
  *valp = build_constructor (type, NULL);
  CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
}
-  else if (TREE_CODE (*valp) == STRING_CST)
+  else if (STRIP_ANY_LOCATION_WRAPPER (*valp),
+  TREE_CODE (*valp) == STRING_CST)


Seems like this is stripping the location wrapper when we try to modify the
string; I think we want to strip it earlier, when we first initialize the
array member.


Hmm, I suppose we don't want to do the stripping too early.  I could
have put it in get_nsdmi, for instance, but maybe here is good as well?


I guess I was thinking more around the time when the value is imported 
into constant evaluation, i.e. this chunk of cxx_eval_constant_expression:



if (tree init = DECL_INITIAL (r))
  {
init = cxx_eval_constant_expression (ctx, init, vc_prvalue,
 non_constant_p, overflow_p);
/* Don't share a CONSTRUCTOR that might be changed.  */
init = unshare_constructor (init);
/* Remember that a constant object's constructor has already
   run.  */

if (CLASS_TYPE_P (TREE_TYPE (r))
&& CP_TYPE_CONST_P (TREE_TYPE (r)))
  TREE_READONLY (init) = true;
ctx->global->put_value (r, init);
  }


Feel free to pursue that approach or go ahead and push your first patch, 
whichever you prefer.


Jason



[PATCH 2/2] c++: passing one ttp to another [PR108179]

2023-03-15 Thread Jason Merrill via Gcc-patches
I kept trying to improve our choice of how many levels of outer_args to add,
when really the problem was that outer_args are for PARM and for this
reverse deduction we should be adding the outer arguments for ARG.

I spent quite a while trying to get DECL_CONTEXT set consistently on
template template parameters that have gone through
reduce_template_parm_level before I realized I could just use
current_scope().

PR c++/108179
PR c++/104107
PR c++/95036

gcc/cp/ChangeLog:

* pt.cc (coerce_template_template_parms): Use args from
DECL_CONTEXT (arg_tmpl) instead of outer_args.

gcc/testsuite/ChangeLog:

* g++.dg/template/ttp35.C: New test.
---
 gcc/cp/pt.cc  | 32 ++-
 gcc/testsuite/g++.dg/template/ttp35.C |  7 ++
 2 files changed, 24 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/ttp35.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c9cd9f6097d..1b2a250224e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8084,22 +8084,24 @@ coerce_template_template_parms (tree parm_tmpl,
 
   tree pargs = template_parms_level_to_args (parm_parms);
 
-  /* PARM, and thus the context in which we are passing ARG to it, may be
-at a deeper level than ARG; when trying to coerce to ARG_PARMS, we
-want to provide the right number of levels, so we reduce the number of
-levels in OUTER_ARGS before prepending them.  This is most important
-when ARG is a namespace-scope template, as in alias-decl-ttp2.C.
+  /* PARM and ARG might be at different template depths, and we want to
+pass the right additional levels of args when coercing PARGS to
+ARG_PARMS in case we need to do any substitution into non-type
+template parameter types.
 
-ARG might also be deeper than PARM (ttp23).  In that case, we include
-all of OUTER_ARGS.  The missing levels seem potentially problematic,
-but I can't come up with a testcase that breaks.  */
-  if (int arg_outer_levs = TMPL_PARMS_DEPTH (arg_parms_full) - 1)
-   {
- auto x = make_temp_override (TREE_VEC_LENGTH (outer_args));
- if (TMPL_ARGS_DEPTH (outer_args) > arg_outer_levs)
-   TREE_VEC_LENGTH (outer_args) = arg_outer_levs;
- pargs = add_to_template_args (outer_args, pargs);
-   }
+OUTER_ARGS are not the right outer levels in this case, as they are
+the args we're building up for PARM, and for the coercion we want the
+args for ARG.  If DECL_CONTEXT isn't set for a template template
+parameter, we can assume that it's in the current scope.  In that case
+we might end up adding more levels than needed, but that shouldn't be
+a problem; any args we need to refer to are at the right level.  */
+  tree ctx = DECL_CONTEXT (arg_tmpl);
+  if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
+   ctx = current_scope ();
+  tree scope_args = NULL_TREE;
+  if (tree tinfo = get_template_info (ctx))
+   scope_args = TI_ARGS (tinfo);
+  pargs = add_to_template_args (scope_args, pargs);
 
   pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none);
   if (pargs != error_mark_node)
diff --git a/gcc/testsuite/g++.dg/template/ttp35.C 
b/gcc/testsuite/g++.dg/template/ttp35.C
new file mode 100644
index 000..4847ea46ae1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp35.C
@@ -0,0 +1,7 @@
+// PR c++/108179
+
+template  class F>
+struct Foo {};
+
+template  class F>
+void f(Foo) {}
-- 
2.31.1



[pushed 1/2] c++: coerce_template_template_parms interface tweak

2023-03-15 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

This should have no semantic effect, but is a prerequisite for the PR108179
fix to follow.

PR c++/108179

gcc/cp/ChangeLog:

* pt.cc (coerce_template_template_parms): Take the arg and parm
templates directly.
(coerce_template_template_parm): Adjust.
(template_template_parm_bindings_ok_p): Adjust.
(convert_template_argument): Adjust.
---
 gcc/cp/pt.cc | 42 +++---
 1 file changed, 15 insertions(+), 27 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c53d8e279c6..c9cd9f6097d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7772,11 +7772,8 @@ coerce_template_template_parm (tree parm,
 template  class> class TT>
 class C;  */
   {
-   tree parmparm = DECL_TEMPLATE_PARMS (parm);
-   tree argparm = DECL_TEMPLATE_PARMS (arg);
-
if (!coerce_template_template_parms
-   (parmparm, argparm, complain, in_decl, outer_args))
+   (parm, arg, complain, in_decl, outer_args))
  return 0;
   }
   /* Fall through.  */
@@ -8024,21 +8021,19 @@ unify_bound_ttp_args (tree tparms, tree targs, tree 
parm, tree& arg,
   return 0;
 }
 
-/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
-   template template parameters.  Both PARM_PARMS and ARG_PARMS are
-   vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL
-   or PARM_DECL.
+/* Return 1 if PARM_TMPL and ARG_TMPL match using rule for
+   template template parameters.
 
Consider the example:
  template  class A;
  template class TT> class B;
 
-   For B, PARM_PARMS are the parameters to TT, while ARG_PARMS are
-   the parameters to A, and OUTER_ARGS contains A.  */
+   For B, PARM_TMPL is TT, while ARG_TMPL is A,
+   and OUTER_ARGS contains A.  */
 
 static int
-coerce_template_template_parms (tree parm_parms_full,
-   tree arg_parms_full,
+coerce_template_template_parms (tree parm_tmpl,
+   tree arg_tmpl,
tsubst_flags_t complain,
tree in_decl,
tree outer_args)
@@ -8047,7 +8042,8 @@ coerce_template_template_parms (tree parm_parms_full,
   tree parm, arg;
   int variadic_p = 0;
 
-  tree parm_parms = INNERMOST_TEMPLATE_PARMS (parm_parms_full);
+  tree parm_parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm_tmpl));
+  tree arg_parms_full = DECL_TEMPLATE_PARMS (arg_tmpl);
   tree arg_parms = INNERMOST_TEMPLATE_PARMS (arg_parms_full);
 
   gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
@@ -8228,8 +8224,6 @@ template_template_parm_bindings_ok_p (tree tparms, tree 
targs)
 
  for (idx = 0; idx < len; ++idx)
{
- tree targ_parms = NULL_TREE;
-
  if (packed_args)
/* Extract the next argument from the argument
   pack.  */
@@ -8241,18 +8235,16 @@ template_template_parm_bindings_ok_p (tree tparms, tree 
targs)
 
  /* Extract the template parameters from the template
 argument.  */
- if (TREE_CODE (targ) == TEMPLATE_DECL)
-   targ_parms = DECL_TEMPLATE_PARMS (targ);
- else if (TREE_CODE (targ) == TEMPLATE_TEMPLATE_PARM)
-   targ_parms = DECL_TEMPLATE_PARMS (TYPE_NAME (targ));
+ if (TREE_CODE (targ) == TEMPLATE_TEMPLATE_PARM)
+   targ = TYPE_NAME (targ);
 
  /* Verify that we can coerce the template template
 parameters from the template argument to the template
 parameter.  This requires an exact match.  */
- if (targ_parms
+ if (TREE_CODE (targ) == TEMPLATE_DECL
  && !coerce_template_template_parms
-  (DECL_TEMPLATE_PARMS (tparm),
-   targ_parms,
+  (tparm,
+   targ,
tf_none,
tparm,
targs))
@@ -8545,15 +8537,11 @@ convert_template_argument (tree parm,
val = orig_arg;
  else
{
- tree parmparm = DECL_TEMPLATE_PARMS (parm);
- tree argparm;
-
  /* Strip alias templates that are equivalent to another
 template.  */
  arg = get_underlying_template (arg);
- argparm = DECL_TEMPLATE_PARMS (arg);
 
- if (coerce_template_template_parms (parmparm, argparm,
+ if (coerce_template_template_parms (parm, arg,
  complain, in_decl,
  args))
{

base-commit: 9e44a9932c11f028269f3aa7e3031e703d151b0b
-- 
2.31.1



[pushed] c++: injected class name as default ttp arg [PR58538]

2023-03-15 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

This function needs to handle this case like convert_template_argument.

PR c++/58538

gcc/cp/ChangeLog:

* semantics.cc (check_template_template_default_arg): Check
maybe_get_template_decl_from_type_decl.

gcc/testsuite/ChangeLog:

* g++.dg/template/ttp7.C: Remove expected error.
---
 gcc/cp/semantics.cc  | 9 +++--
 gcc/testsuite/g++.dg/template/ttp7.C | 2 +-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index d67a9b26719..57dd7b66da8 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -3468,8 +3468,13 @@ check_template_template_default_arg (tree argument)
   && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
 {
   if (TREE_CODE (argument) == TYPE_DECL)
-   error ("invalid use of type %qT as a default value for a template "
-  "template-parameter", TREE_TYPE (argument));
+   {
+ if (tree t = maybe_get_template_decl_from_type_decl (argument))
+   if (TREE_CODE (t) == TEMPLATE_DECL)
+ return t;
+ error ("invalid use of type %qT as a default value for a template "
+"template-parameter", TREE_TYPE (argument));
+   }
   else
error ("invalid default argument for a template template parameter");
   return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/template/ttp7.C 
b/gcc/testsuite/g++.dg/template/ttp7.C
index 0bcaa8f7292..672077e7e7d 100644
--- a/gcc/testsuite/g++.dg/template/ttp7.C
+++ b/gcc/testsuite/g++.dg/template/ttp7.C
@@ -11,6 +11,6 @@ template class = A<0> > struct B2 {};  // { 
dg-error "as a default
 
 template 
 struct S {
-  template  class = S>   struct I1 {};  // { dg-error "as 
a default value" }
+  template  class = S>   struct I1 {}; // PR c++/58538
   template  class = ::S> struct I2 {};
 };

base-commit: 9e44a9932c11f028269f3aa7e3031e703d151b0b
prerequisite-patch-id: dc293188137e8f94cea3b5c135e62efad8fec595
prerequisite-patch-id: 30ba81cfc50ea4cae63d361169fda721504d06f5
-- 
2.31.1



[pushed] c++: variable tmpl partial specialization [PR108468]

2023-03-14 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Generally we expect TPARMS_PRIMARY_TEMPLATE to be set, but sometimes it
isn't for partial instantiations.  This ought to be improved, but it's
trivial to work around it in this case.

PR c++/108468

gcc/cp/ChangeLog:

* pt.cc (unify_pack_expansion): Check that TPARMS_PRIMARY_TEMPLATE
is non-null.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ78.C: New test.
---
 gcc/cp/pt.cc |  2 ++
 gcc/testsuite/g++.dg/cpp1y/var-templ78.C | 12 
 2 files changed, 14 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ78.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 65341c40f97..c53d8e279c6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24148,6 +24148,8 @@ unify_pack_expansion (tree tparms, tree targs, tree 
packed_parms,
 arguments if it is not otherwise deduced.  */
  if (cxx_dialect >= cxx20
  && TREE_VEC_LENGTH (new_args) < TREE_VEC_LENGTH (old_args)
+ /* FIXME This isn't set properly for partial instantiations.  */
+ && TPARMS_PRIMARY_TEMPLATE (tparms)
  && builtin_guide_p (TPARMS_PRIMARY_TEMPLATE (tparms)))
TREE_VEC_LENGTH (old_args) = TREE_VEC_LENGTH (new_args);
  if (!comp_template_args (old_args, new_args,
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ78.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ78.C
new file mode 100644
index 000..48366c92775
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ78.C
@@ -0,0 +1,12 @@
+// PR c++/108468
+// { dg-do compile { target c++14 } }
+
+template struct C {
+  template
+  static constexpr int x = 1;
+};
+
+template template
+int C::x = 2;
+
+int y = C<0>::x;

base-commit: 2b204accd07a3185b58b1edc6e9b019472857a5d
-- 
2.31.1



Re: [PATCH 2/2] c++: redeclaring member of constrained class template [PR96830]

2023-03-14 Thread Jason Merrill via Gcc-patches

On 3/14/23 12:41, Patrick Palka wrote:

When redeclaring a member of a constrained class template, we need to
repeat the class's constraints, but it turns out we don't verify
anywhere that the repeated constraints match the class's constraints.
A safe place to do so seems to be in push_template_decl, nearby a
similar consistency check for the template parameter list length of a
redeclaration.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?


Both patches are OK for trunk, but not 12; we tend not to backport fixes 
for accepts-invalid bugs, especially if they aren't regressions.  We 
don't want to add new diagnostics to an active release branch.



PR c++/96830

gcc/cp/ChangeLog:

* pt.cc (push_inline_template_parms_recursive): Set
TEMPLATE_PARMS_CONSTRAINTS.
(push_template_decl): For a redeclaration, verify constraints
for each enclosing template scope match those of the original
template declaratation.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-class5.C: New test.
* g++.dg/cpp2a/concepts-class5a.C: New test.
---
  gcc/cp/pt.cc  | 26 +
  gcc/testsuite/g++.dg/cpp2a/concepts-class5.C  | 37 ++
  gcc/testsuite/g++.dg/cpp2a/concepts-class5a.C | 38 +++
  3 files changed, 101 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-class5.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-class5a.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 053cc52b285..370a4f70f08 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -471,6 +471,8 @@ push_inline_template_parms_recursive (tree parmlist, int 
levels)
current_template_parms
  = tree_cons (size_int (current_template_depth + 1),
 parms, current_template_parms);
+  TEMPLATE_PARMS_CONSTRAINTS (current_template_parms)
+= TEMPLATE_PARMS_CONSTRAINTS (parmlist);
TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
  
begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,

@@ -6134,6 +6136,30 @@ push_template_decl (tree decl, bool is_friend)
  DECL_INTERFACE_KNOWN (decl) = 1;
  return error_mark_node;
}
+
+  /* Check that the constraints for each enclosing template scope are
+consistent with the original template declaration.  */
+  if (flag_concepts)
+   {
+ tree decl_parms = DECL_TEMPLATE_PARMS (tmpl);
+ tree scope_parms = current_template_parms;
+ if (PRIMARY_TEMPLATE_P (tmpl))
+   {
+ decl_parms = TREE_CHAIN (decl_parms);
+ scope_parms = TREE_CHAIN (scope_parms);
+   }
+ while (decl_parms)
+   {
+ if (!template_requirements_equivalent_p (decl_parms, scope_parms))
+   {
+ error ("redeclaration of %qD with different constraints",
+TPARMS_PRIMARY_TEMPLATE (TREE_VALUE (decl_parms)));
+ break;
+   }
+ decl_parms = TREE_CHAIN (decl_parms);
+ scope_parms = TREE_CHAIN (scope_parms);
+   }
+   }
  }
  
gcc_checking_assert (!tmpl || DECL_TEMPLATE_RESULT (tmpl) == decl);

diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-class5.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-class5.C
new file mode 100644
index 000..5d893d9f6a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-class5.C
@@ -0,0 +1,37 @@
+// PR c++/96830
+// { dg-do compile { target c++20 } }
+
+template concept C = true;
+
+template requires true
+struct A {
+  void f();
+  template void g();
+
+  struct B;
+  template struct C;
+
+  static int D;
+  template static int E;
+};
+
+template
+void A::f() { }  // { dg-error "different constraints" }
+
+template requires true
+template
+void A::g() { }  // { dg-error "different constraints" }
+
+template requires (!!true)
+struct A::B { }; // { dg-error "different constraints" }
+
+template requires true
+template
+struct A::C { }; // { dg-error "different constraints" }
+
+template
+int A::D = 0;// { dg-error "different constraints" }
+
+template requires true
+template
+int A::E = 0;// { dg-error "different constraints" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-class5a.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-class5a.C
new file mode 100644
index 000..a6a3684c258
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-class5a.C
@@ -0,0 +1,38 @@
+// PR c++/96830
+// A valid version of concepts-class5.C.
+// { dg-do compile { target c++20 } }
+
+template concept C = true;
+
+template requires true
+struct A {
+  void f();
+  template void g();
+
+  struct B;
+  template struct C;
+
+  static int D;
+  template static int E;
+};
+
+template requires true
+void A::f() { }
+
+template requires true
+template
+void A::g() { }
+
+template requires true
+struct A::B { };
+
+template requires true
+template
+struct A::C { };
+
+tem

[pushed] c++: -Wreturn-type with if (true) throw [PR107310]

2023-03-14 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

I removed this folding in GCC 12 because it was interfering with an
experiment of richi's, but that never went in and the change causes
regressions, so let's put it back.

This reverts commit r12-5638-ga3e75c1491cd2d.

PR c++/107310

gcc/cp/ChangeLog:

* cp-gimplify.cc (genericize_if_stmt): Restore folding
of constant conditions.

gcc/testsuite/ChangeLog:

* c-c++-common/Wimplicit-fallthrough-39.c: Adjust warning.
* g++.dg/warn/Wreturn-6.C: New test.
---
 gcc/cp/cp-gimplify.cc|  6 ++
 .../c-c++-common/Wimplicit-fallthrough-39.c  |  4 ++--
 gcc/testsuite/g++.dg/warn/Wreturn-6.C| 16 
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wreturn-6.C

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index b995b4f81a5..4fecd5616bd 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -190,6 +190,12 @@ genericize_if_stmt (tree *stmt_p)
 }
   else if (IF_STMT_CONSTEXPR_P (stmt))
 stmt = integer_nonzerop (cond) ? then_ : else_;
+  /* ??? This optimization doesn't seem to belong here, but removing it
+ causes -Wreturn-type regressions (e.g. 107310).  */
+  else if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
+stmt = then_;
+  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
+stmt = else_;
   else
 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
   protected_set_expr_location_if_unset (stmt, locus);
diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-39.c 
b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-39.c
index da4aef3a318..d06bc0db5ec 100644
--- a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-39.c
+++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-39.c
@@ -37,8 +37,8 @@ fn2 (int n)
   switch (n)
 {
 case 0:
-  if (1) /* { dg-warning "statement may fall through" "" { target c++ 
} } */
-   n++;  /* { dg-warning "statement may fall through" "" { 
target c } } */
+  if (1)
+   n++;  /* { dg-warning "statement may fall through" } */
 case 1:  /* { dg-message "here" } */
   return -1;
 }
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-6.C 
b/gcc/testsuite/g++.dg/warn/Wreturn-6.C
new file mode 100644
index 000..85fef0e16df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-6.C
@@ -0,0 +1,16 @@
+// PR c++/107310
+
+struct f
+{
+  ~f();
+};
+
+int foo(int t) {
+  f g;
+  switch (t) {
+  case 1:
+return 1;
+  }
+  if (true)
+throw 1;
+} // { dg-bogus "control reaches end" }

base-commit: 42630fadbe248717859d61c0244c821c32b4e52c
-- 
2.31.1



Re: [PATCH] gdbhooks: Update gdbhooks.py for recent tree_code_type changes [PR108634]

2023-03-14 Thread Jason Merrill via Gcc-patches

On 3/14/23 11:42, Jakub Jelinek wrote:

Hi!

On Mon, Mar 13, 2023 at 04:15:12PM -0400, Jason Merrill wrote:

The r13-6577 change to use tree_code_type_tmpl in earlier C++ dialects broke
gdbhooks, which expects tree_code_type to always be available.  I considered
trying to make gdbhooks more robust, but it seemed simpler to define
tree_code_type as a reference to the template.


As I said earlier, I think it is better to tweak gdbhooks.

The following patch does that, I've tested it now both with gcc 12 and
older gcc as system compiler and the patch fixed the latter while keeping
the former working as before.

Ok for trunk?


LGTM, OK on Friday if no other comments.


2023-03-14  Jakub Jelinek  

PR plugins/108634
* gdbhooks.py (TreePrinter.to_string): Wrap
gdb.parse_and_eval('tree_code_type') in a try block, parse
and eval 'tree_code_type_tmpl<0>::tree_code_type' instead if it
raises exception.  Update comments for the recent tree_code_type
changes.

--- gcc/gdbhooks.py.jj  2023-03-04 11:24:01.348791347 +0100
+++ gcc/gdbhooks.py 2023-03-14 16:35:48.445671242 +0100
@@ -220,13 +220,23 @@ class TreePrinter:
  
  val_TREE_CODE = self.node.TREE_CODE()
  
-# extern const enum tree_code_class tree_code_type[];

+# constexpr inline enum tree_code_class tree_code_type[] = { ... };
  # #define TREE_CODE_CLASS(CODE)   tree_code_type[(int) (CODE)]
+# or
+# template 
+# struct tree_code_type_tmpl {
+# static constexpr enum tree_code_class tree_code_type[] = { ... };
+# }; };
+# #define TREE_CODE_CLASS(CODE) \
+# tree_code_type_tmpl <0>::tree_code_type[(int) (CODE)]
  
  if val_TREE_CODE == 0xa5a5:

  return '' % intptr(self.gdbval)
  
-val_tree_code_type = gdb.parse_and_eval('tree_code_type')

+try:
+val_tree_code_type = gdb.parse_and_eval('tree_code_type')
+except:
+val_tree_code_type = 
gdb.parse_and_eval('tree_code_type_tmpl<0>::tree_code_type')
  val_tclass = val_tree_code_type[val_TREE_CODE]
  
  val_tree_code_name = gdb.parse_and_eval('tree_code_name')



Jakub





Ping Re: [PATCH RFC] c++: lambda mangling alias issues [PR107897]

2023-03-14 Thread Jason Merrill via Gcc-patches

On 3/8/23 11:54, Jason Merrill wrote:

On 3/8/23 11:15, Jason Merrill wrote:

On 3/8/23 10:53, Jan Hubicka wrote:
Tested x86_64-pc-linux-gnu.  Does this look good, or do we want to 
factor the

flag clearing into a symtab_node counterpart to cgraph_node::reset?

-- 8< --

In 107897, by the time we are looking at the mangling clash, the
alias has already been removed from the symbol table by 
analyze_functions,

so we can't look at n->cpp_implicit_alias.  So just assume that it's an
alias if it's internal.

In 108887 the problem is that removing the mangling alias from the 
symbol

table confuses analyze_functions, because it ended up as first_analyzed
somehow, so it becomes a dangling pointer.  Fixed by clearing 
various flags

to neutralize the alias.

PR c++/107897
PR c++/108887

gcc/cp/ChangeLog:

* decl2.cc (record_mangling): Improve symbol table handling.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Use -flto if supported.
* g++.dg/cpp0x/lambda/lambda-mangle7.C: New test.
---
  gcc/cp/decl2.cc   | 25 +--
  .../g++.dg/cpp0x/lambda/lambda-mangle7.C  | 70 
+++

  gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C |  1 +
  3 files changed, 91 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 387e24542cd..e6e58b08de4 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4742,15 +4742,30 @@ record_mangling (tree decl, bool need_warning)
  = mangled_decls->find_slot_with_hash (id, 
IDENTIFIER_HASH_VALUE (id),

    INSERT);
-  /* If this is already an alias, remove the alias, because the real
+  /* If this is already an alias, cancel the alias, because the real
   decl takes precedence.  */
    if (*slot && DECL_ARTIFICIAL (*slot) && DECL_IGNORED_P (*slot))
-    if (symtab_node *n = symtab_node::get (*slot))
-  if (n->cpp_implicit_alias)
+    {
+  if (symtab_node *n = symtab_node::get (*slot))
  {
-  n->remove ();
-  *slot = NULL_TREE;
+  if (n->cpp_implicit_alias)
+    {
+  /* Actually removing the node isn't safe if other code is 
already

+ holding a pointer to it, so just neutralize it.  */
+  n->remove_from_same_comdat_group ();
+  n->analyzed = false;
+  n->definition = false;
+  n->alias = false;
+  n->cpp_implicit_alias = false;

We have n->reset () for that which is used in similar situation when
frontends overwrites extern inline function by its different offline
implementation.


The problem there is that reset() is a member of cgraph_node, not 
symtab_node, and I need something that works for variables as well.



reset doesn't call remove_from_same_comdat_group probably because it was
never used on anything in comdat group.  So I think it would make sense
to call n->reset() here and add remove_from_same_comdat_group into that.


How about moving it to symtab_node and using dyn_cast for the cgraph 
bits, like this:


Ping? (Patch in attachment in earlier message)



Re: [PATCH] c++: Treat unnamed bitfields as padding for __has_unique_object_representations [PR109096]

2023-03-14 Thread Jason Merrill via Gcc-patches

On 3/14/23 03:58, Jakub Jelinek wrote:

Hi!

As reported in the PR, for __has_unique_object_representations we
were treating unnamed bitfields as named ones, which is wrong, they
are actually padding.

THe following patch fixes that.  Ok for trunk (and what about release
branches later?)?


OK.


2023-03-14  Jakub Jelinek  

PR c++/109096
* tree.cc (record_has_unique_obj_representations): Ignore unnamed
bitfields.

* g++.dg/cpp1z/has-unique-obj-representations3.C: New test.

--- gcc/cp/tree.cc.jj   2023-03-10 10:06:40.247560614 +0100
+++ gcc/cp/tree.cc  2023-03-13 10:38:03.394836926 +0100
@@ -4851,7 +4851,7 @@ record_has_unique_obj_representations (c
DECL_SIZE (field)))
  return false;
}
-else if (DECL_C_BIT_FIELD (field))
+else if (DECL_C_BIT_FIELD (field) && !DECL_UNNAMED_BIT_FIELD (field))
{
tree btype = DECL_BIT_FIELD_TYPE (field);
if (!type_has_unique_obj_representations (btype))
@@ -4862,7 +4862,7 @@ record_has_unique_obj_representations (c
  
offset_int cur = 0;

for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
-if (TREE_CODE (field) == FIELD_DECL)
+if (TREE_CODE (field) == FIELD_DECL && !DECL_UNNAMED_BIT_FIELD (field))
{
offset_int fld = wi::to_offset (DECL_FIELD_OFFSET (field));
offset_int bitpos = wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
--- gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations3.C.jj 
2023-03-13 10:50:21.705127719 +0100
+++ gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations3.C
2023-03-13 10:50:17.751185067 +0100
@@ -0,0 +1,10 @@
+// PR c++/109096
+// { dg-do compile { target c++11 } }
+
+#define INTB (__SIZEOF_INT__ * __CHAR_BIT__)
+struct U { int i : INTB * 3 / 4; int : INTB / 4; };
+struct V { int : INTB * 3 / 4; int j : INTB / 4; };
+struct W { int i; int : 0; int j; };
+static_assert (__has_unique_object_representations (U) == false, "");
+static_assert (__has_unique_object_representations (V) == false, "");
+static_assert (sizeof (W) != 2 * sizeof (int) || __has_unique_object_representations (W) 
== true, "");

Jakub





Re: [PATCH] testsuite: Fix up g++.dg/cpp2a/concepts-lambda3.C [PR108972]

2023-03-14 Thread Jason Merrill via Gcc-patches

On 3/14/23 03:54, Jakub Jelinek wrote:

Hi!

On Fri, Mar 10, 2023 at 01:49:38PM -0500, Jason Merrill via Gcc-patches wrote:

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Run at lower std levels,
but expect errors.


I'm seeing
+UNRESOLVED: g++.dg/cpp2a/concepts-lambda3.C  -std=c++11 compilation failed to 
produce executable
+UNRESOLVED: g++.dg/cpp2a/concepts-lambda3.C  -std=c++14 compilation failed to 
produce executable
+UNRESOLVED: g++.dg/cpp2a/concepts-lambda3.C  -std=c++17 compilation failed to 
produce executable
+UNRESOLVED: g++.dg/cpp2a/concepts-lambda3.C  -std=c++98 compilation failed to 
produce executable
with this change, and if I test with
GXX_TESTSUITE_STDS=98,11,14,17,20,2b make check-g++ -k 
RUNTESTFLAGS="--target_board=unix\{-m32,-m64,-m64/-fconcepts\} 
dg.exp=concepts-lambda3.C"
I see even FAILs for the -fconcepts case, so apparently even -std=c++17
-fconcepts isn't enough to make it compile without errors.

The following patch will expect errors for all of c++17_down and will
make the test dg-do compile for that case too, such that the UNRESOLVED
stuff is gone.

Ok for trunk?


OK.


2023-03-14  Jakub Jelinek  

PR c++/108972
* g++.dg/cpp2a/concepts-lambda3.C: Use dg-do run only for c++20,
for c++17_down dg-do compile.  Expect dg-excess-errors for c++17_down
rather than ! concepts.

--- gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C.jj2023-03-13 
23:01:42.082959131 +0100
+++ gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C   2023-03-14 
08:48:12.834128044 +0100
@@ -1,5 +1,6 @@
-// { dg-do run }
-// { dg-excess-errors "" { target { ! concepts } } } (PR108972)
+// { dg-do run { target c++20 } }
+// { dg-do compile { target c++17_down } }
+// { dg-excess-errors "" { target { c++17_down } } } (PR108972)
  
  template

  concept C1 = __is_same_as(T, int)


Jakub





Re: [PATCH RFA] tree: define tree_code_type in C++11/14 [PR108634]

2023-03-13 Thread Jason Merrill via Gcc-patches

On 3/13/23 16:15, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu, OK for trunk?

-- 8< --

The r13-6577 change to use tree_code_type_tmpl in earlier C++ dialects broke
gdbhooks, which expects tree_code_type to always be available.  I considered
trying to make gdbhooks more robust, but it seemed simpler to define
tree_code_type as a reference to the template.  This still ends up with a
definition of the reference in each translation unit, but that's allowed by the
ODR because it always refers to the same entity, and is much smaller than
having the whole table in each TU.


...or I could build with a newer bootstrap compiler, I suppose.


PR plugins/108634

gcc/ChangeLog:

* tree-core.h (tree_code_type, tree_code_length):
Define even without inline variable support.
* tree.h (TREE_CODE_CLASS, TREE_CODE_LENGTH):
Only one definition.
---
  gcc/tree-core.h |  3 +++
  gcc/tree.h  | 10 --
  2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index fd2be57b78c..545dfd30114 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -2298,6 +2298,7 @@ struct tree_code_type_tmpl {
  
  template 

  constexpr enum tree_code_class tree_code_type_tmpl::tree_code_type[];
+static constexpr auto &tree_code_type = tree_code_type_tmpl<0>::tree_code_type;
  #else
  constexpr inline enum tree_code_class tree_code_type[] = {
  #include "all-tree.def"
@@ -2326,6 +2327,8 @@ struct tree_code_length_tmpl {
  
  template 

  constexpr unsigned char tree_code_length_tmpl::tree_code_length[];
+static constexpr auto &tree_code_length
+= tree_code_length_tmpl<0>::tree_code_length;
  #else
  constexpr inline unsigned char tree_code_length[] = {
  #include "all-tree.def"
diff --git a/gcc/tree.h b/gcc/tree.h
index 91375f9652f..92ac0e6a214 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -177,12 +177,7 @@ code_helper::is_builtin_fn () const
  #define TREE_CODE_CLASS_STRING(CLASS)\
  tree_code_class_strings[(int) (CLASS)]
  
-#if __cpp_inline_variables < 201606L

-#define TREE_CODE_CLASS(CODE)  \
-  tree_code_type_tmpl <0>::tree_code_type[(int) (CODE)]
-#else
  #define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
-#endif
  
  /* Nonzero if NODE represents an exceptional code.  */
  
@@ -276,12 +271,7 @@ code_helper::is_builtin_fn () const
  
  #define EXPR_P(NODE) IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (NODE)))
  
-#if __cpp_inline_variables < 201606L

-#define TREE_CODE_LENGTH(CODE) \
-  tree_code_length_tmpl <0>::tree_code_length[(int) (CODE)]
-#else
  #define TREE_CODE_LENGTH(CODE)tree_code_length[(int) (CODE)]
-#endif
  
  
  /* Helper macros for math builtins.  */


base-commit: c227508d06a63f9b8fede3fd88813accb447060e




[pushed] c++: handle _FloatNN redeclaration like bool [PR107128]

2023-03-13 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

It's been inconvenient to compile testcases preprocessed with GCC 12 or
earlier because they break on

  typedef __float128 _Float128;

We already had code for handling this with bool and wchar_t, it just needs
to be extended to _FloatNN as well.

PR c++/107128

gcc/cp/ChangeLog:

* parser.cc (cp_parser_set_decl_spec_type): Use
redefined_builtin_type for extended_float_type_p.

gcc/testsuite/ChangeLog:

* g++.dg/warn/pragma-system_header6.h: New test.
* g++.dg/warn/pragma-system_header6.C: New test.
---
 gcc/testsuite/g++.dg/warn/pragma-system_header6.h | 3 +++
 gcc/cp/parser.cc  | 2 ++
 gcc/testsuite/g++.dg/warn/pragma-system_header6.C | 1 +
 3 files changed, 6 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/warn/pragma-system_header6.h
 create mode 100644 gcc/testsuite/g++.dg/warn/pragma-system_header6.C

diff --git a/gcc/testsuite/g++.dg/warn/pragma-system_header6.h 
b/gcc/testsuite/g++.dg/warn/pragma-system_header6.h
new file mode 100644
index 000..989ccd8795a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pragma-system_header6.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+typedef float _Float32;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 533041946c0..a277003ea58 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -33452,10 +33452,12 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq 
*decl_specs,
  C++-safe.  */
   if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
   && !type_definition_p
+  && TYPE_P (type_spec)
   && (type_spec == boolean_type_node
  || type_spec == char8_type_node
  || type_spec == char16_type_node
  || type_spec == char32_type_node
+ || extended_float_type_p (type_spec)
  || type_spec == wchar_type_node)
   && (decl_specs->type
  || decl_spec_seq_has_spec_p (decl_specs, ds_long)
diff --git a/gcc/testsuite/g++.dg/warn/pragma-system_header6.C 
b/gcc/testsuite/g++.dg/warn/pragma-system_header6.C
new file mode 100644
index 000..924e4522cf0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pragma-system_header6.C
@@ -0,0 +1 @@
+#include "pragma-system_header6.h"

base-commit: 8e9c65d34c799c9dadea1e2e60b4180f26262829
-- 
2.31.1



[PATCH RFA] tree: define tree_code_type in C++11/14 [PR108634]

2023-03-13 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, OK for trunk?

-- 8< --

The r13-6577 change to use tree_code_type_tmpl in earlier C++ dialects broke
gdbhooks, which expects tree_code_type to always be available.  I considered
trying to make gdbhooks more robust, but it seemed simpler to define
tree_code_type as a reference to the template.  This still ends up with a
definition of the reference in each translation unit, but that's allowed by the
ODR because it always refers to the same entity, and is much smaller than
having the whole table in each TU.

PR plugins/108634

gcc/ChangeLog:

* tree-core.h (tree_code_type, tree_code_length):
Define even without inline variable support.
* tree.h (TREE_CODE_CLASS, TREE_CODE_LENGTH):
Only one definition.
---
 gcc/tree-core.h |  3 +++
 gcc/tree.h  | 10 --
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index fd2be57b78c..545dfd30114 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -2298,6 +2298,7 @@ struct tree_code_type_tmpl {
 
 template 
 constexpr enum tree_code_class tree_code_type_tmpl::tree_code_type[];
+static constexpr auto &tree_code_type = tree_code_type_tmpl<0>::tree_code_type;
 #else
 constexpr inline enum tree_code_class tree_code_type[] = {
 #include "all-tree.def"
@@ -2326,6 +2327,8 @@ struct tree_code_length_tmpl {
 
 template 
 constexpr unsigned char tree_code_length_tmpl::tree_code_length[];
+static constexpr auto &tree_code_length
+= tree_code_length_tmpl<0>::tree_code_length;
 #else
 constexpr inline unsigned char tree_code_length[] = {
 #include "all-tree.def"
diff --git a/gcc/tree.h b/gcc/tree.h
index 91375f9652f..92ac0e6a214 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -177,12 +177,7 @@ code_helper::is_builtin_fn () const
 #define TREE_CODE_CLASS_STRING(CLASS)\
 tree_code_class_strings[(int) (CLASS)]
 
-#if __cpp_inline_variables < 201606L
-#define TREE_CODE_CLASS(CODE)  \
-  tree_code_type_tmpl <0>::tree_code_type[(int) (CODE)]
-#else
 #define TREE_CODE_CLASS(CODE)  tree_code_type[(int) (CODE)]
-#endif
 
 /* Nonzero if NODE represents an exceptional code.  */
 
@@ -276,12 +271,7 @@ code_helper::is_builtin_fn () const
 
 #define EXPR_P(NODE) IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (NODE)))
 
-#if __cpp_inline_variables < 201606L
-#define TREE_CODE_LENGTH(CODE) \
-  tree_code_length_tmpl <0>::tree_code_length[(int) (CODE)]
-#else
 #define TREE_CODE_LENGTH(CODE) tree_code_length[(int) (CODE)]
-#endif
 
 
 /* Helper macros for math builtins.  */

base-commit: c227508d06a63f9b8fede3fd88813accb447060e
-- 
2.31.1



Re: [PATCH] c++: suppress -Wdangling-reference for std::span [PR107532]

2023-03-13 Thread Jason Merrill via Gcc-patches

On 3/10/23 14:07, Marek Polacek wrote:

std::span is a view and therefore should be treated as a reference
wrapper class for the purposes of -Wdangling-reference.  I'm not sure
there's a pattern that we could check for.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK.


PR c++/107532

gcc/cp/ChangeLog:

* call.cc (reference_like_class_p): Check for std::span.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wdangling-reference10.C: New test.
---
  gcc/cp/call.cc|  1 +
  gcc/testsuite/g++.dg/warn/Wdangling-reference10.C | 12 
  2 files changed, 13 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference10.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 3dfa12a0733..c01e7b82457 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13800,6 +13800,7 @@ reference_like_class_p (tree ctype)
tree name = DECL_NAME (tdecl);
return (name
  && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "span")
  || id_equal (name, "ref_view")));
  }
for (tree fields = TYPE_FIELDS (ctype);
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference10.C 
b/gcc/testsuite/g++.dg/warn/Wdangling-reference10.C
new file mode 100644
index 000..733fb8cce63
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference10.C
@@ -0,0 +1,12 @@
+// PR c++/107532
+// { dg-do compile { target c++20 } }
+// { dg-options "-Wdangling-reference" }
+
+#include 
+#include 
+
+void f(const std::vector& v)
+{
+  const int& r = std::span(v)[0]; // { dg-bogus "dangling 
reference" }
+  (void) r;
+}

base-commit: 20d790aa3ea5b0d240032cab997b8e0938cac62c




Re: [PATCH gcc-{11, 12}] c++: top level bind when rewriting coroutines [PR106188]

2023-03-13 Thread Jason Merrill via Gcc-patches

On 3/13/23 02:57, Arsen Arsenović wrote:

In the edge case of a coroutine not containing any locals, the ifcd/switch
temporaries would get added to the coroutine frame, corrupting its
layout. To prevent this, we can make sure there is always a BIND_EXPR at
the top of the function body, and thus, always a place for our new
temporaries to go without interfering with the coroutine frame.

PR c++/106188 - Incorrect frame layout after transforming conditional statement 
without top-level bind expression
PR c++/106713 - if (co_await ...) crashes with a jump to ud2

PR c++/106188
PR c++/106713

gcc/cp/ChangeLog:

* coroutines.cc (coro_rewrite_function_body): Ensure we have a
BIND_EXPR wrapping the function body.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/pr106188.C: New test.
---
Morning,

A while back, we merged this patch into GCC 13 to fix PR106188, but
never backported it into GCC 11 and 12, which both still suffer from
this bug.

I've tested the same patch against releases/gcc-{11,12} and they apply
and fix the testcase (and the testcase fails without them, as expected)
on x86_64-pc-linux-gnu.

OK for backporting?


OK.


Thanks in advance.

  gcc/cp/coroutines.cc   |  9 ++
  gcc/testsuite/g++.dg/coroutines/pr106188.C | 34 ++
  2 files changed, 43 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/coroutines/pr106188.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index e982cdb89a7..ea3850082cf 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4067,6 +4067,15 @@ coro_rewrite_function_body (location_t fn_start, tree 
fnbody, tree orig,
BLOCK_SUPERCONTEXT (replace_blk) = top_block;
BLOCK_SUBBLOCKS (top_block) = replace_blk;
  }
+  else
+{
+  /* We are missing a top level BIND_EXPR. We need one to ensure that we
+don't shuffle around the coroutine frame and corrupt it.  */
+  tree bind_wrap = build3_loc (fn_start, BIND_EXPR, void_type_node,
+  NULL, NULL, NULL);
+  BIND_EXPR_BODY (bind_wrap) = fnbody;
+  fnbody = bind_wrap;
+}
  
/* Wrap the function body in a try {} catch (...) {} block, if exceptions

   are enabled.  */
diff --git a/gcc/testsuite/g++.dg/coroutines/pr106188.C 
b/gcc/testsuite/g++.dg/coroutines/pr106188.C
new file mode 100644
index 000..9db3778d079
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr106188.C
@@ -0,0 +1,34 @@
+// { dg-do run { target c++20 } }
+// test case from pr106188, w/o workaround
+#include 
+
+struct task {
+  struct promise_type {
+task get_return_object() { return task{}; }
+void return_void() {}
+void unhandled_exception() {}
+auto initial_suspend() noexcept { return std::suspend_never{}; }
+auto final_suspend() noexcept { return std::suspend_never{}; }
+  };
+};
+
+struct suspend_and_resume {
+  bool await_ready() const { return false; }
+  void await_suspend(std::coroutine_handle<> h) { h.resume(); }
+  void await_resume() {}
+};
+
+task f() {
+  if (co_await suspend_and_resume{}, false) {}
+}
+
+task g() {
+  switch (co_await suspend_and_resume{}, 0) {
+default: break;
+  }
+}
+
+int main() {
+  f();
+  g();
+}




[pushed] c++: constrained lambda error-recovery [PR108972]

2023-03-10 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Better not to ICE after various valid errors.

PR c++/108972

gcc/cp/ChangeLog:

* lambda.cc (compare_lambda_template_head): Check more
for error_mark_node.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Run at lower std levels,
but expect errors.
---
 gcc/cp/lambda.cc  | 4 
 gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index c752622816d..212990a21bf 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1537,6 +1537,8 @@ compare_lambda_template_head (tree tmpl_a, tree tmpl_b)
  if (parm_a == error_mark_node)
return false;
  parm_a = TREE_VALUE (parm_a);
+ if (parm_a == error_mark_node)
+   return false;
  if (DECL_VIRTUAL_P (parm_a))
parm_a = NULL_TREE;
}
@@ -1548,6 +1550,8 @@ compare_lambda_template_head (tree tmpl_a, tree tmpl_b)
  if (parm_b == error_mark_node)
return false;
  parm_b = TREE_VALUE (parm_b);
+ if (parm_b == error_mark_node)
+   return false;
  if (DECL_VIRTUAL_P (parm_b))
parm_b = NULL_TREE;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C
index 291e451ca1a..b18e6b62aa4 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C
@@ -1,4 +1,5 @@
-// { dg-do run { target c++20 } }
+// { dg-do run }
+// { dg-excess-errors "" { target { ! concepts } } } (PR108972)
 
 template
 concept C1 = __is_same_as(T, int)
@@ -61,4 +62,3 @@ int main(int, char**)
 
   return 0;
 }
-

base-commit: e1c8cf9006bd278e969ab7ed35178067ce128f32
-- 
2.31.1



Re: [PATCH] c++: ICE with constexpr lambda [PR107280]

2023-03-10 Thread Jason Merrill via Gcc-patches

On 3/10/23 11:17, Marek Polacek wrote:

We crash here since r10-3661, the store_init_value hunk in particular.
Before, we called cp_fully_fold_init, so e.g.

   {.str=VIEW_CONVERT_EXPR("")}

was folded into

   {.str=""}

but now we don't fold and keep the VCE around, and it causes trouble in
cxx_eval_store_expression: in the !refs->is_empty () loop we descend on
.str's initializer but since it's wrapped in a VCE, we skip the STRING_CST
check and then crash on the CONSTRUCTOR_NO_CLEARING.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?

PR c++/107280

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_store_expression): Strip location wrappers.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/constexpr-lambda28.C: New test.
---
  gcc/cp/constexpr.cc |  3 ++-
  gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C | 15 +++
  2 files changed, 17 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8683c00596a..abf6ee560c5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6033,7 +6033,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
  *valp = build_constructor (type, NULL);
  CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
}
-  else if (TREE_CODE (*valp) == STRING_CST)
+  else if (STRIP_ANY_LOCATION_WRAPPER (*valp),
+  TREE_CODE (*valp) == STRING_CST)


Seems like this is stripping the location wrapper when we try to modify 
the string; I think we want to strip it earlier, when we first 
initialize the array member.


Jason



Re: [PATCH] c++ testsuite: Add test for PR107703

2023-03-10 Thread Jason Merrill via Gcc-patches

On 3/10/23 10:43, Jakub Jelinek wrote:

Hi!

This is on top of the
https://gcc.gnu.org/pipermail/gcc-patches/2022-November/606398.html
and
https://gcc.gnu.org/pipermail/gcc-patches/2023-March/613724.html
patches (to be precise, the latter isn't essential for it), I've
realized that for the PR107703 bugfix in the first patch I haven't
added some test coverage that the extended floating vs. integral
or vice versa conversions work correctly.

This new testcase adds such checks.  And when writing it I've
found that in ext-floating.h header in the testsuite I forgot back
in November to remove #undef __STDCPP_BFLOAT16_T__ which was left
there because the bfloat16 support wasn't in yet.

The new testcase (and all older ext-floating*.C tests too) passes
on vanilla trunk without the ext-floating.h change (x86_64-linux
-m32/-m64) and with the PR107703 fix also with the ext-floating.h
change.

Ok for trunk?


OK.


2023-03-10  Jakub Jelinek  

PR target/107703
* g++.dg/cpp23/ext-floating.h (__STDCPP_BFLOAT16_T__): Don't undefine
it.
(std::bfloat16_t): Use decltype (0.0bf16) like libstdc++, rather than
__bf16.
* g++.dg/cpp23/ext-floating14.C: New test.

--- gcc/testsuite/g++.dg/cpp23/ext-floating.h.jj2022-09-27 
08:03:27.118982749 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating.h   2023-03-10 15:04:01.647824767 
+0100
@@ -14,9 +14,8 @@ namespace std
#ifdef __STDCPP_FLOAT128_T__
using float128_t = _Float128;
#endif
-  #undef __STDCPP_BFLOAT16_T__
#ifdef __STDCPP_BFLOAT16_T__
-  using bfloat16_t = __bf16; // ???
+  using bfloat16_t = decltype (0.0bf16);
#endif
template struct integral_constant {
  static constexpr T value = v;
--- gcc/testsuite/g++.dg/cpp23/ext-floating14.C.jj  2023-03-10 
14:12:17.658925358 +0100
+++ gcc/testsuite/g++.dg/cpp23/ext-floating14.C 2023-03-10 15:32:26.912057825 
+0100
@@ -0,0 +1,585 @@
+// P1467R9 - Extended floating-point types and standard names.
+// PR target/107703
+// { dg-do run { target c++23 } }
+// { dg-options "-fexcess-precision=standard" }
+
+#include "ext-floating.h"
+
+#ifdef __SIZEOF_INT128__
+#define INT128_MAX ((signed __int128) ((~(unsigned __int128) 0) >> 1))
+#endif
+
+template 
+[[gnu::noipa]] T cvt (F f)
+{
+  return T (F (f));
+}
+
+int
+main ()
+{
+  // __FLT32_MAX_EXP__ is 128, so make sure all unsigned long long and 
unsigned __int128
+  // values fit into it.  __FLT16_MAX__ is 65504.0f16, so we need to be
+  // careful for that.
+#if __SIZEOF_LONG_LONG__ * __CHAR_BIT__ <= 128
+#if !defined(__SIZEOF_INT128__) || __SIZEOF_INT128__ * __CHAR_BIT__ == 128
+#ifdef __STDCPP_FLOAT16_T__
+  if (cvt  (42) != (std::float16_t) 42
+  || cvt  (-42) != (std::float16_t) -42
+#if __SCHAR_MAX__ < 65504
+  || cvt  (__SCHAR_MAX__) != (std::float16_t) 
__SCHAR_MAX__
+  || cvt  (-__SCHAR_MAX__ - 1) != 
(std::float16_t) (-__SCHAR_MAX__ - 1)
+#endif
+ )
+__builtin_abort ();
+  if (cvt  (42) != (std::float16_t) 42
+#if __SCHAR_MAX__ * 2 + 1 < 65504
+  || cvt  ((unsigned char) ~0) != 
(std::float16_t) ((unsigned char) ~0)
+#endif
+ )
+__builtin_abort ();
+  if (cvt  (42) != (std::float16_t) 42
+  || cvt  (-42) != (std::float16_t) -42
+#if __SHRT_MAX__ < 65504
+  || cvt  (__SHRT_MAX__) != (std::float16_t) 
__SHRT_MAX__
+  || cvt  (-__SHRT_MAX__ - 1) != 
(std::float16_t) (-__SHRT_MAX__ - 1)
+#else
+  || cvt  (65504) != (std::float16_t) 65504
+  || cvt  (-65504) != (std::float16_t) -65504
+#endif
+ )
+__builtin_abort ();
+  if (cvt  (42) != (std::float16_t) 42
+  || cvt  (65504U) != (std::float16_t) 
65504U)
+__builtin_abort ();
+  if (cvt  (42) != (std::float16_t) 42
+  || cvt  (-42) != (std::float16_t) -42
+#if __INT_MAX__ < 65504
+  || cvt  (__INT_MAX__) != (std::float16_t) 
__INT_MAX__
+  || cvt  (-__INT_MAX__ - 1) != 
(std::float16_t) (-__INT_MAX__ - 1)
+#else
+  || cvt  (65504) != (std::float16_t) 65504
+  || cvt  (-65504) != (std::float16_t) -65504
+#endif
+ )
+__builtin_abort ();
+  if (cvt  (42) != (std::float16_t) 42U
+  || cvt  (65504U) != (std::float16_t) 
65504U)
+__builtin_abort ();
+  if (cvt  (42L) != (std::float16_t) 42L
+  || cvt  (-42L) != (std::float16_t) -42L
+  || cvt  (65504L) != (std::float16_t) 
65504L
+  || cvt  (-65504L) != (std::float16_t) 
-65504L)
+__builtin_abort ();
+  if (cvt  (42UL) != (std::float16_t) 42UL
+  || cvt  (65504UL) != (std::float16_t) 
65504UL)
+__builtin_abort ();
+  if (cvt  (42LL) != (std::float16_t) 
42LL
+  || cvt  (-42LL) != 
(std::float16_t) -42LL
+  || cvt  (65504LL) != 
(std::float16_t) 65504LL
+  || cvt  (-65504LL) != 
(std::float16_t) -65504LL)
+__builtin_abort ();
+  if (cvt  (42ULL) != (std::float16_t) 
42ULL
+  || cvt  (65504ULL) != 
(std::float16_t) 65504ULL)
+__builtin_abort ();
+#ifdef __SIZEOF_INT128__
+  if (cvt  (42LL) != (std::float16_t) (signed 
__int128) 42LL
+  || cvt  (-42LL) != 

Re: [PATCH] c++: Don't clear TREE_READONLY for -fmerge-all-constants for non-aggregates [PR107558]

2023-03-10 Thread Jason Merrill via Gcc-patches

On 11/24/22 04:13, Jakub Jelinek wrote:

Hi!

The following testcase ICEs, because OpenMP lowering for shared clause
on l variable with REFERENCE_TYPE creates POINTER_TYPE to REFERENCE_TYPE.
The reason is that the automatic variable has non-trivial construction
(reference to a lambda) and -fmerge-all-constants is on and so TREE_READONLY
isn't set - omp-low will handle automatic TREE_READONLY vars in shared
specially and only copy to the construct and not back, while !TREE_READONLY
are assumed to be changeable.
The PR91529 change rationale was that the gimplification can change
some non-addressable automatic variables to TREE_STATIC with
-fmerge-all-constants and therefore TREE_READONLY on them is undesirable.
But, the gimplifier does that only for aggregate variables:
   switch (TREE_CODE (type))
 {
 case RECORD_TYPE:
 case UNION_TYPE:
 case QUAL_UNION_TYPE:
 case ARRAY_TYPE:
and not for anything else.  So, I think clearing TREE_READONLY for
automatic integral or reference or pointer etc. vars for
-fmerge-all-constants only is unnecessary.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


OK.


2022-11-24  Jakub Jelinek  

PR c++/107558
* decl.cc (cp_finish_decl): Don't clear TREE_READONLY on
automatic non-aggregate variables just because of
-fmerge-all-constants.

* g++.dg/gomp/pr107558.C: New test.

--- gcc/cp/decl.cc.jj   2022-11-19 09:21:14.662439877 +0100
+++ gcc/cp/decl.cc  2022-11-23 13:12:31.866553152 +0100
@@ -8679,8 +8679,10 @@ cp_finish_decl (tree decl, tree init, bo
  
if (var_definition_p

  /* With -fmerge-all-constants, gimplify_init_constructor
-might add TREE_STATIC to the variable.  */
- && (TREE_STATIC (decl) || flag_merge_constants >= 2))
+might add TREE_STATIC to aggregate variables.  */
+ && (TREE_STATIC (decl)
+ || (flag_merge_constants >= 2
+ && AGGREGATE_TYPE_P (type
{
  /* If a TREE_READONLY variable needs initialization
 at runtime, it is no longer readonly and we need to
--- gcc/testsuite/g++.dg/gomp/pr107558.C.jj 2022-11-23 13:13:27.260736525 
+0100
+++ gcc/testsuite/g++.dg/gomp/pr107558.C2022-11-23 13:15:22.271041005 
+0100
@@ -0,0 +1,14 @@
+// PR c++/107558
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fmerge-all-constants" }
+// { dg-additional-options "-flto" { target lto } }
+
+int a = 15;
+
+void
+foo ()
+{
+  auto &&l = [&]() { return a; };
+#pragma omp target parallel
+  l ();
+}

Jakub





Re: [PATCH] c++, abi: Fix up class layout with bitfields [PR109039]

2023-03-10 Thread Jason Merrill via Gcc-patches

On 3/9/23 14:40, Jakub Jelinek wrote:

Hi!

The following testcase FAILs, because starting with r12-6028
the S class has only 2 bytes, not enough to hold one 7-bit bitfield, one 8-bit
bitfield and one 8-bit char field.

The reason is that when end_of_class attempts to compute dsize, it simply
adds byte_position of the field and DECL_SIZE_UNIT (and uses maximum from
those offsets).
The problematic bit-field in question has bit_position 7, byte_position 0,
DECL_SIZE 8 and DECL_SIZE_UNIT 1.  So, byte_position + DECL_SIZE_UNIT is
1, even when the bitfield only has a single bit in the first byte and 7
further bits in the second byte, so per the Itanium ABI it should be 2:
"In either case, update dsize(C) to include the last byte
containing (part of) the bit-field, and update sizeof(C) to
max(sizeof(C),dsize(C))."

The following patch fixes it by computing bitsize of the end and using
CEIL_DIV_EXPR division to round it to next byte boundary and convert
from bits to bytes.

While this is an ABI change, classes with such incorrect layout couldn't
have worked properly, so I doubt anybody is actually running it often
in the wild.  Thus I think adding some ABI warning for it is unnecessary.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
(and after a while for GCC 12)?


OK.


2023-03-09  Jakub Jelinek  

PR c++/109039
* class.cc (end_of_class): For bit-fields, instead of computing
offset as sum of byte_position (field) and DECL_SIZE_UNIT (field),
compute it as sum of bit_position (field) and DECL_SIZE (field)
divided by BITS_PER_UNIT rounded up.

* g++.dg/abi/no_unique_address7.C: New test.

--- gcc/cp/class.cc.jj  2023-02-04 06:22:17.053407477 +0100
+++ gcc/cp/class.cc 2023-03-09 18:02:43.967815721 +0100
@@ -6476,7 +6476,15 @@ end_of_class (tree t, eoc_mode mode)
 size of the type (usually 1) for computing nvsize.  */
  size = TYPE_SIZE_UNIT (TREE_TYPE (field));
  
-	offset = size_binop (PLUS_EXPR, byte_position (field), size);

+   if (DECL_BIT_FIELD_TYPE (field))
+ {
+   offset = size_binop (PLUS_EXPR, bit_position (field),
+DECL_SIZE (field));
+   offset = size_binop (CEIL_DIV_EXPR, offset, bitsize_unit_node);
+   offset = fold_convert (sizetype, offset);
+ }
+   else
+ offset = size_binop (PLUS_EXPR, byte_position (field), size);
if (tree_int_cst_lt (result, offset))
  result = offset;
}
--- gcc/testsuite/g++.dg/abi/no_unique_address7.C.jj2023-03-09 
18:09:08.397205087 +0100
+++ gcc/testsuite/g++.dg/abi/no_unique_address7.C   2023-03-09 
18:08:56.439379395 +0100
@@ -0,0 +1,33 @@
+// PR c++/109039
+// { dg-do run { target c++11 } }
+
+struct X {
+  signed short x0 : 7;
+  signed short x1 : 8;
+  X () : x0 (1), x1 (2) {}
+  int get () { return x0 + x1; }
+};
+
+struct S {
+  [[no_unique_address]] X x;
+  signed char c;
+  S () : c (0) {}
+};
+
+S s;
+
+int
+main ()
+{
+  if (s.x.x0 != 1 || s.x.x1 != 2 || s.c != 0)
+__builtin_abort ();
+  s.x.x0 = -1;
+  s.x.x1 = -1;
+  if (s.x.x0 != -1 || s.x.x1 != -1 || s.c != 0)
+__builtin_abort ();
+  s.c = -1;
+  s.x.x0 = 0;
+  s.x.x1 = 0;
+  if (s.x.x0 != 0 || s.x.x1 != 0 || s.c != -1)
+__builtin_abort ();
+}

Jakub





[pushed] c++: class NTTP and nested anon union [PR108566]

2023-03-10 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

We were failing to come up with the name for the anonymous union.  It seems
like unfortunate redundancy, but the ABI does say that the name of an
anonymous union is its first named member.

PR c++/108566

gcc/cp/ChangeLog:

* mangle.cc (anon_aggr_naming_decl): New.
(write_unqualified_name): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/abi/anon6.C: New test.
---
 gcc/cp/mangle.cc | 27 ++-
 gcc/testsuite/g++.dg/abi/anon6.C | 19 +++
 2 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/anon6.C

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 242b3f31cba..a235f23459d 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1389,6 +1389,28 @@ find_decomp_unqualified_name (tree decl, size_t *len)
   return p;
 }
 
+/* "For the purposes of mangling, the name of an anonymous union is considered
+   to be the name of the first named data member found by a pre-order,
+   depth-first, declaration-order walk of the data members of the anonymous
+   union. If there is no such data member (i.e., if all of the data members in
+   the union are unnamed), then there is no way for a program to refer to the
+   anonymous union, and there is therefore no need to mangle its name."  */
+
+static tree
+anon_aggr_naming_decl (tree type)
+{
+  tree field = next_aggregate_field (TYPE_FIELDS (type));
+  for (; field; field = next_aggregate_field (DECL_CHAIN (field)))
+{
+  if (DECL_NAME (field))
+   return field;
+  if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
+   if (tree sub = anon_aggr_naming_decl (TREE_TYPE (field)))
+ return sub;
+}
+  return NULL_TREE;
+}
+
 /* We don't need to handle thunks, vtables, or VTTs here.  Those are
mangled through special entry points.
 
@@ -1432,7 +1454,10 @@ write_unqualified_name (tree decl)
 
   bool found = false;
 
-  if (DECL_NAME (decl) == NULL_TREE)
+  if (DECL_NAME (decl) == NULL_TREE
+  && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+decl = anon_aggr_naming_decl (TREE_TYPE (decl));
+  else if (DECL_NAME (decl) == NULL_TREE)
 {
   found = true;
   gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
diff --git a/gcc/testsuite/g++.dg/abi/anon6.C b/gcc/testsuite/g++.dg/abi/anon6.C
new file mode 100644
index 000..7be0b0bbdb7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/anon6.C
@@ -0,0 +1,19 @@
+// PR c++/108566
+// { dg-do compile { target c++20 } }
+
+template
+struct wrapper1 {
+  union {
+union {
+  T RightName;
+};
+  };
+};
+
+template void dummy(){}
+
+void uses() {
+  dummy{123.0}>();
+}
+
+// { dg-final { scan-assembler 
"_Z5dummyIXtl8wrapper1IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Edi9RightNameLd405ec000EEvv"
 } }

base-commit: 2fc55f51f9953b451d6d6ddfae23379001e6ac95
-- 
2.31.1



[pushed] c++: signed __int128_t [PR108099]

2023-03-09 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

The code for handling signed + typedef was breaking on __int128_t, because
it isn't a proper typedef: it doesn't have DECL_ORIGINAL_TYPE.

PR c++/108099

gcc/cp/ChangeLog:

* decl.cc (grokdeclarator): Handle non-typedef typedef_decl.

gcc/testsuite/ChangeLog:

* g++.dg/ext/int128-7.C: New test.
---
 gcc/cp/decl.cc  | 11 ---
 gcc/testsuite/g++.dg/ext/int128-7.C |  4 
 2 files changed, 12 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/int128-7.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 30c7470974d..b1603859644 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -12440,10 +12440,15 @@ grokdeclarator (const cp_declarator *declarator,
{
  if (typedef_decl)
{
- pedwarn (loc, OPT_Wpedantic, "%qs specified with %qT",
-  key, type);
+ pedwarn (loc, OPT_Wpedantic, "%qs specified with %qD",
+  key, typedef_decl);
  ok = !flag_pedantic_errors;
- type = DECL_ORIGINAL_TYPE (typedef_decl);
+ if (is_typedef_decl (typedef_decl))
+   type = DECL_ORIGINAL_TYPE (typedef_decl);
+ else
+   /* PR108099: __int128_t comes from c_common_nodes_and_builtins,
+  and is not built as a typedef.  */
+   type = TREE_TYPE (typedef_decl);
  typedef_decl = NULL_TREE;
}
  else if (declspecs->decltype_p)
diff --git a/gcc/testsuite/g++.dg/ext/int128-7.C 
b/gcc/testsuite/g++.dg/ext/int128-7.C
new file mode 100644
index 000..bf5e8c40a4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/int128-7.C
@@ -0,0 +1,4 @@
+// PR c++/108099
+// { dg-do compile { target { c++11 && int128 } } }
+
+using i128 = signed __int128_t;// { dg-error "specified with" }

base-commit: 68c5d92a1390ecccb61d3600a95eeff6caf7ccdf
-- 
2.31.1



[pushed] c++: overloaded fn in contract [PR108542]

2023-03-09 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

PR c++/108542

gcc/cp/ChangeLog:

* class.cc (instantiate_type): Strip location wrapper.

gcc/testsuite/ChangeLog:

* g++.dg/contracts/contracts-err1.C: New test.
---
 gcc/cp/class.cc | 2 ++
 gcc/testsuite/g++.dg/contracts/contracts-err1.C | 7 +++
 2 files changed, 9 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/contracts/contracts-err1.C

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 27a79829737..d37e9d4d576 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -8728,6 +8728,8 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t 
complain)
 
   complain &= ~tf_ptrmem_ok;
 
+  STRIP_ANY_LOCATION_WRAPPER (rhs);
+
   if (lhstype == unknown_type_node)
 {
   if (complain & tf_error)
diff --git a/gcc/testsuite/g++.dg/contracts/contracts-err1.C 
b/gcc/testsuite/g++.dg/contracts/contracts-err1.C
new file mode 100644
index 000..8437d94e2ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/contracts/contracts-err1.C
@@ -0,0 +1,7 @@
+// PR c++/108542
+// { dg-additional-options -fcontracts }
+// { dg-do compile { target c++11 } }
+
+template
+void f (T n) {}
+void g() [[pre: f]];   // { dg-error "overloaded" }

base-commit: e0324e2629e25a90c13c68b4eef1e47b091970c3
-- 
2.31.1



Re: [PATCH] c++: noexcept and copy elision [PR109030]

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

On 3/9/23 14:32, Patrick Palka wrote:

On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:


When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
  gcc/cp/constexpr.cc | 6 +-
  gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
  2 files changed, 14 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  
/* 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);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);


It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in maybe_constant_value?


Sounds good.


IIUC since we could still have an evaluated subexpression withis
noexcept, the two fixes would be complementary.

  
bool non_constant_args = false;

new_call.bindings
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
new file mode 100644
index 000..16db8eb79ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
@@ -0,0 +1,9 @@
+// PR c++/109030
+// { dg-do compile { target c++11 } }
+
+struct foo { };
+
+struct __as_receiver {
+  foo empty_env;
+};
+void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }

base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902
--
2.39.2








[pushed] c++: allocator temps in list of arrays [PR108773]

2023-03-09 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

The optimization to reuse the same allocator temporary for all string
constructor calls was breaking on this testcase, because the temps were
already in the argument to build_vec_init, and replacing them with
references to one slot got confused with calls at multiple levels (for the
initializer_list backing array, and then again for the array member of the
std::array).  Fixed by reusing the whole TARGET_EXPR instead of pulling out
the slot; gimplification ensures that it's only initialized once.

I also moved the check for initializing a std:: class down into the tree
walk, and handle multiple temps within a single array element
initialization.

PR c++/108773

gcc/cp/ChangeLog:

* init.cc (find_allocator_temps_r): New.
(combine_allocator_temps): Replace find_allocator_temp.
(build_vec_init): Adjust.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-array18.C: New test.
* g++.dg/cpp0x/initlist-array19.C: New test.
---
 gcc/cp/init.cc| 78 ++-
 gcc/testsuite/g++.dg/cpp0x/initlist-array18.C | 30 +++
 gcc/testsuite/g++.dg/cpp0x/initlist-array19.C | 23 ++
 3 files changed, 110 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-array18.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-array19.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 52e96fbe590..1b7d3d8fe3e 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4330,8 +4330,54 @@ find_temps_r (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
+/* walk_tree callback to collect temporaries in an expression that
+   are allocator arguments to standard library classes.  */
+
+static tree
+find_allocator_temps_r (tree *tp, int *walk_subtrees, void *data)
+{
+  vec &temps = *static_cast *>(data);
+  tree t = *tp;
+  if (TYPE_P (t))
+{
+  *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+  /* If this is a call to a constructor for a std:: class, look for
+ a reference-to-allocator argument.  */
+  tree fn = cp_get_callee_fndecl_nofold (t);
+  if (fn && DECL_CONSTRUCTOR_P (fn)
+  && decl_in_std_namespace_p (TYPE_NAME (DECL_CONTEXT (fn
+{
+  int nargs = call_expr_nargs (t);
+  for (int i = 1; i < nargs; ++i)
+   {
+ tree arg = get_nth_callarg (t, i);
+ tree atype = TREE_TYPE (arg);
+ if (TREE_CODE (atype) == REFERENCE_TYPE
+ && is_std_allocator (TREE_TYPE (atype)))
+   {
+ STRIP_NOPS (arg);
+ if (TREE_CODE (arg) == ADDR_EXPR)
+   {
+ tree *ap = &TREE_OPERAND (arg, 0);
+ if (TREE_CODE (*ap) == TARGET_EXPR)
+   temps.safe_push (ap);
+   }
+   }
+   }
+}
+
+  return NULL_TREE;
+}
+
 /* If INIT initializes a standard library class, and involves a temporary
-   std::allocator, return a pointer to the temp.
+   std::allocator, use ALLOC_OBJ for all such temporaries.
+
+   Note that this can clobber the input to build_vec_init; no unsharing is
+   done.  To make this safe we use the TARGET_EXPR in all places rather than
+   pulling out the TARGET_EXPR_SLOT.
 
Used by build_vec_init when initializing an array of e.g. strings to reuse
the same temporary allocator for all of the strings.  We can do this because
@@ -4341,22 +4387,18 @@ find_temps_r (tree *tp, int *walk_subtrees, void *data)
??? Add an attribute to allow users to assert the same property for other
classes, i.e. one object of the type is interchangeable with any other?  */
 
-static tree*
-find_allocator_temp (tree init)
+static void
+combine_allocator_temps (tree &init, tree &alloc_obj)
 {
-  if (TREE_CODE (init) == EXPR_STMT)
-init = EXPR_STMT_EXPR (init);
-  if (TREE_CODE (init) == CONVERT_EXPR)
-init = TREE_OPERAND (init, 0);
-  tree type = TREE_TYPE (init);
-  if (!CLASS_TYPE_P (type) || !decl_in_std_namespace_p (TYPE_NAME (type)))
-return NULL;
   auto_vec temps;
-  cp_walk_tree_without_duplicates (&init, find_temps_r, &temps);
+  cp_walk_tree_without_duplicates (&init, find_allocator_temps_r, &temps);
   for (tree *p : temps)
-if (is_std_allocator (TREE_TYPE (*p)))
-  return p;
-  return NULL;
+{
+  if (!alloc_obj)
+   alloc_obj = *p;
+  else
+   *p = alloc_obj;
+}
 }
 
 /* `build_vec_init' returns tree structure that performs
@@ -4694,13 +4736,7 @@ build_vec_init (tree base, tree maxindex, tree init,
  if (one_init)
{
  /* Only create one std::allocator temporary.  */
- if (tree *this_alloc = find_allocator_temp (one_init))
-   {
- if (alloc_obj)
-   *this_alloc = alloc_obj;
- else
-   alloc_obj = TARGET_EXPR_SLOT (*this_alloc);
-   }
+ combine_allocator_temps (one_init, alloc_obj);
  

Re: [PATCH RFC 1/3] c++: add __is_deducible trait [PR105841]

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

On 2/20/23 11:58, Patrick Palka wrote:

On Sat, 18 Feb 2023, Jason Merrill via Gcc-patches wrote:


Tested x86_64-pc-linux-gnu.  Since this is fixing experimental (C++20)
functionality, I think it's reasonable to apply now; I'm interested in other
opinions, and thoughts about the user-facing functionality.  I'm thinking to
make it internal-only for GCC 13 at least by adding a space in the name, but
does this look useful to the library?


IIUC this looks like a generalization of an __is_specialization_of trait
that returns whether a type is a specialization of a given class template,
which seems potentially useful for the library to me.  We already define
some ad-hoc predicates for testing this, e.g. __is_reverse_view,
__is_span etc in  as well as a more general __is_specialization_of
in  for templates that take only type arguments.  Using a built-in
trait should be more efficient.

[...]

Since the first argument of a TRAIT_EXPR can now be a TEMPLATE_DECL, I
suppose cp_tree_equal needs to be changed too.


>[...]


For sake of the __is_specialization_of use case, I wonder if it'd
be possible to have a "fast path" that avoids deduction/coercion when
the given template is a class template?


Thanks, done.  I've also fixed array bounds type deduction and added 
more comments about the relationship of the implementation and the 
specification in terms of partial specialization.


The second patch makes it internal-only for GCC 13; you can revert that 
if you want to experiment with using it in the library.


Tested x86_64-pc-linux-gnu, applying to trunk.From 81f820cff3316cea454ba81dc38ddf55b1afa852 Mon Sep 17 00:00:00 2001
From: Jason Merrill 
Date: Thu, 9 Feb 2023 12:51:51 -0800
Subject: [PATCH] c++: add __is_deducible trait [PR105841]
To: gcc-patches@gcc.gnu.org

C++20 class template argument deduction for an alias template involves
adding a constraint that the template arguments for the alias template can
be deduced from the return type of the deduction guide for the underlying
class template.  In the standard, this is modeled as defining a class
template with a partial specialization, but it's much more efficient to
implement with a trait that directly tries to perform the deduction.

The first argument to the trait is a template rather than a type, so various
places needed to be adjusted to accommodate that.

	PR c++/105841

gcc/ChangeLog:

	* doc/extend.texi (Type Traits):: Document __is_deducible.

gcc/cp/ChangeLog:

	* cp-trait.def (IS_DEDUCIBLE): New.
	* cxx-pretty-print.cc (pp_cxx_trait): Handle non-type.
	* parser.cc (cp_parser_trait): Likewise.
	* tree.cc (cp_tree_equal): Likewise.
	* pt.cc (tsubst_copy_and_build): Likewise.
	(type_targs_deducible_from): New.
	(alias_ctad_tweaks): Use it.
	* semantics.cc (trait_expr_value): Handle CPTK_IS_DEDUCIBLE.
	(finish_trait_expr): Likewise.
	* constraint.cc (diagnose_trait_expr): Likewise.
	* cp-tree.h (type_targs_deducible_from): Declare.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/is_deducible1.C: New test.
---
 gcc/doc/extend.texi  |  4 ++
 gcc/cp/cp-tree.h |  1 +
 gcc/cp/constraint.cc |  3 ++
 gcc/cp/cxx-pretty-print.cc   |  5 +-
 gcc/cp/parser.cc | 20 +--
 gcc/cp/pt.cc | 69 
 gcc/cp/semantics.cc  | 11 
 gcc/cp/tree.cc   |  2 +-
 gcc/testsuite/g++.dg/ext/is_deducible1.C | 31 +++
 gcc/cp/cp-trait.def  |  1 +
 10 files changed, 131 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_deducible1.C

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index c1122916255..b64a85722db 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -25213,6 +25213,10 @@ type.  A diagnostic is produced if this requirement is not met.
 If @code{type} is a cv-qualified class type, and not a union type
 ([basic.compound]) the trait is @code{true}, else it is @code{false}.
 
+@item __is_deducible (template, type)
+If template arguments for @code{template} can be deduced from
+@code{type} or obtained from default template arguments.
+
 @item __is_empty (type)
 If @code{__is_class (type)} is @code{false} then the trait is @code{false}.
 Otherwise @code{type} is considered empty if and only if: @code{type}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fb21c064141..dfc1c845768 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7361,6 +7361,7 @@ extern tree fn_type_unification			(tree, tree, tree,
 		 bool, bool);
 extern void mark_decl_instantiated		(tree, int);
 extern int more_specialized_fn			(tree, tree, int);
+extern bool type_targs_deducible_from		(tree, tree);
 extern void do_decl_instantiation		(tree, tree);
 extern void do_type_instantiation		(tree, tree, tsubst_flags_t);
 extern bool always_instantiate_p		(tree);
diff --git a/gcc/cp/constraint.

Re: [PATCH RFC] c++: lambda mangling alias issues [PR107897]

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

On 3/8/23 11:15, Jason Merrill wrote:

On 3/8/23 10:53, Jan Hubicka wrote:
Tested x86_64-pc-linux-gnu.  Does this look good, or do we want to 
factor the

flag clearing into a symtab_node counterpart to cgraph_node::reset?

-- 8< --

In 107897, by the time we are looking at the mangling clash, the
alias has already been removed from the symbol table by 
analyze_functions,

so we can't look at n->cpp_implicit_alias.  So just assume that it's an
alias if it's internal.

In 108887 the problem is that removing the mangling alias from the 
symbol

table confuses analyze_functions, because it ended up as first_analyzed
somehow, so it becomes a dangling pointer.  Fixed by clearing various 
flags

to neutralize the alias.

PR c++/107897
PR c++/108887

gcc/cp/ChangeLog:

* decl2.cc (record_mangling): Improve symbol table handling.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Use -flto if supported.
* g++.dg/cpp0x/lambda/lambda-mangle7.C: New test.
---
  gcc/cp/decl2.cc   | 25 +--
  .../g++.dg/cpp0x/lambda/lambda-mangle7.C  | 70 +++
  gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C |  1 +
  3 files changed, 91 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 387e24542cd..e6e58b08de4 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4742,15 +4742,30 @@ record_mangling (tree decl, bool need_warning)
  = mangled_decls->find_slot_with_hash (id, IDENTIFIER_HASH_VALUE 
(id),

    INSERT);
-  /* If this is already an alias, remove the alias, because the real
+  /* If this is already an alias, cancel the alias, because the real
   decl takes precedence.  */
    if (*slot && DECL_ARTIFICIAL (*slot) && DECL_IGNORED_P (*slot))
-    if (symtab_node *n = symtab_node::get (*slot))
-  if (n->cpp_implicit_alias)
+    {
+  if (symtab_node *n = symtab_node::get (*slot))
  {
-  n->remove ();
-  *slot = NULL_TREE;
+  if (n->cpp_implicit_alias)
+    {
+  /* Actually removing the node isn't safe if other code is 
already

+ holding a pointer to it, so just neutralize it.  */
+  n->remove_from_same_comdat_group ();
+  n->analyzed = false;
+  n->definition = false;
+  n->alias = false;
+  n->cpp_implicit_alias = false;

We have n->reset () for that which is used in similar situation when
frontends overwrites extern inline function by its different offline
implementation.


The problem there is that reset() is a member of cgraph_node, not 
symtab_node, and I need something that works for variables as well.



reset doesn't call remove_from_same_comdat_group probably because it was
never used on anything in comdat group.  So I think it would make sense
to call n->reset() here and add remove_from_same_comdat_group into that.


How about moving it to symtab_node and using dyn_cast for the cgraph 
bits, like this:
From 1d869ceb04573727e59be6518903133c8654069a Mon Sep 17 00:00:00 2001
From: Jason Merrill 
Date: Mon, 6 Mar 2023 15:33:45 -0500
Subject: [PATCH] c++: lambda mangling alias issues [PR107897]
To: gcc-patches@gcc.gnu.org

In 107897, by the time we are looking at the mangling clash, the
alias has already been removed from the symbol table by analyze_functions,
so we can't look at n->cpp_implicit_alias.  So just assume that it's an
alias if it's internal.

In 108887 the problem is that removing the mangling alias from the symbol
table confuses analyze_functions, because it ended up as first_analyzed
somehow, so it becomes a dangling pointer.  Fixed by clearing various flags
to neutralize the alias.

	PR c++/107897
	PR c++/108887

gcc/ChangeLog:

	* cgraph.h: Move reset() from cgraph_node to symtab_node.
	* cgraphunit.cc (symtab_node::reset): Adjust.

gcc/cp/ChangeLog:

	* decl2.cc (record_mangling): Use symtab_node::reset.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/concepts-lambda3.C: Use -flto if supported.
	* g++.dg/cpp0x/lambda/lambda-mangle7.C: New test.
---
 gcc/cgraph.h  | 16 ++---
 gcc/cgraphunit.cc | 27 ---
 gcc/cp/decl2.cc   | 19 +++--
 .../g++.dg/cpp0x/lambda/lambda-mangle7.C  | 70 +++
 gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C |  1 +
 5 files changed, 109 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index b5fc739f1b0..fb938470be9 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -149,6 +149,14 @@ public:
  cgraph/varpool node creation routines.  */
   void register_symbol (void);
 
+  /* As an GCC extension we allow redefinition of the function.  The
+ semantics when both copies of bodies differ is not well defined.
+ We replace the old body with new body so in unit at a time mode
+ we always use 

Re: [PATCH RFC] c++: lambda mangling alias issues [PR107897]

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

On 3/8/23 10:53, Jan Hubicka wrote:

Tested x86_64-pc-linux-gnu.  Does this look good, or do we want to factor the
flag clearing into a symtab_node counterpart to cgraph_node::reset?

-- 8< --

In 107897, by the time we are looking at the mangling clash, the
alias has already been removed from the symbol table by analyze_functions,
so we can't look at n->cpp_implicit_alias.  So just assume that it's an
alias if it's internal.

In 108887 the problem is that removing the mangling alias from the symbol
table confuses analyze_functions, because it ended up as first_analyzed
somehow, so it becomes a dangling pointer.  Fixed by clearing various flags
to neutralize the alias.

PR c++/107897
PR c++/108887

gcc/cp/ChangeLog:

* decl2.cc (record_mangling): Improve symbol table handling.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Use -flto if supported.
* g++.dg/cpp0x/lambda/lambda-mangle7.C: New test.
---
  gcc/cp/decl2.cc   | 25 +--
  .../g++.dg/cpp0x/lambda/lambda-mangle7.C  | 70 +++
  gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C |  1 +
  3 files changed, 91 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 387e24542cd..e6e58b08de4 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4742,15 +4742,30 @@ record_mangling (tree decl, bool need_warning)
  = mangled_decls->find_slot_with_hash (id, IDENTIFIER_HASH_VALUE (id),
  INSERT);
  
-  /* If this is already an alias, remove the alias, because the real

+  /* If this is already an alias, cancel the alias, because the real
   decl takes precedence.  */
if (*slot && DECL_ARTIFICIAL (*slot) && DECL_IGNORED_P (*slot))
-if (symtab_node *n = symtab_node::get (*slot))
-  if (n->cpp_implicit_alias)
+{
+  if (symtab_node *n = symtab_node::get (*slot))
{
- n->remove ();
- *slot = NULL_TREE;
+ if (n->cpp_implicit_alias)
+   {
+ /* Actually removing the node isn't safe if other code is already
+holding a pointer to it, so just neutralize it.  */
+ n->remove_from_same_comdat_group ();
+ n->analyzed = false;
+ n->definition = false;
+ n->alias = false;
+ n->cpp_implicit_alias = false;

We have n->reset () for that which is used in similar situation when
frontends overwrites extern inline function by its different offline
implementation.


The problem there is that reset() is a member of cgraph_node, not 
symtab_node, and I need something that works for variables as well.



reset doesn't call remove_from_same_comdat_group probably because it was
never used on anything in comdat group.  So I think it would make sense
to call n->reset() here and add remove_from_same_comdat_group into that.

OK with that change.
Honza

+   }
}
+  else
+   /* analyze_functions might have already removed the alias from the
+  symbol table if it's internal.  */
+   gcc_checking_assert (!TREE_PUBLIC (*slot));
+
+  *slot = NULL_TREE;
+}
  
if (!*slot)

  *slot = decl;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C 
b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C
new file mode 100644
index 000..c7946a2be08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C
@@ -0,0 +1,70 @@
+// PR c++/108887
+// { dg-do compile { target c++11 } }
+
+template  struct integral_constant {
+  static constexpr int value = __v;
+};
+using false_type = integral_constant;
+template  struct __result_of_impl;
+template 
+struct __result_of_impl {
+  typedef decltype(0) type;
+};
+template 
+struct __invoke_result
+: __result_of_impl {};
+template 
+void __invoke_impl(_Fn __f, _Args... __args) {
+  __f(__args...);
+}
+template 
+void __invoke_r(_Callable __fn, _Args... __args) {
+  using __result = __invoke_result<_Args...>;
+  using __type = typename __result::type;
+  __invoke_impl<__type>(__fn, __args...);
+}
+struct QString {
+  QString(const char *);
+};
+template  class function;
+template  struct _Base_manager {
+  static _Functor _M_get_pointer(int) { __builtin_abort (); }
+};
+template  class _Function_handler;
+template 
+struct _Function_handler<_Res(_ArgTypes...), _Functor> {
+  using _Base = _Base_manager<_Functor>;
+  static _Res _M_invoke(const int &__functor, _ArgTypes &&...__args) {
+auto __trans_tmp_1 = _Base::_M_get_pointer(__functor);
+__invoke_r<_Res>(__trans_tmp_1, __args...);
+  }
+};
+template 
+struct function<_Res(_ArgTypes...)> {
+  template 
+  using _Handler = _Function_handler<_Res(_ArgTypes...), _Functor>;
+  template  function(_Functor) {
+using _My_handler = _Handler<_Functor>;
+_M_invoker = _My_handler::_M_invoke;
+  }
+  using _Invoker_type = _Res (*)(const int &, _Arg

[PATCH RFC] c++: lambda mangling alias issues [PR107897]

2023-03-07 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu.  Does this look good, or do we want to factor the
flag clearing into a symtab_node counterpart to cgraph_node::reset?

-- 8< --

In 107897, by the time we are looking at the mangling clash, the
alias has already been removed from the symbol table by analyze_functions,
so we can't look at n->cpp_implicit_alias.  So just assume that it's an
alias if it's internal.

In 108887 the problem is that removing the mangling alias from the symbol
table confuses analyze_functions, because it ended up as first_analyzed
somehow, so it becomes a dangling pointer.  Fixed by clearing various flags
to neutralize the alias.

PR c++/107897
PR c++/108887

gcc/cp/ChangeLog:

* decl2.cc (record_mangling): Improve symbol table handling.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda3.C: Use -flto if supported.
* g++.dg/cpp0x/lambda/lambda-mangle7.C: New test.
---
 gcc/cp/decl2.cc   | 25 +--
 .../g++.dg/cpp0x/lambda/lambda-mangle7.C  | 70 +++
 gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C |  1 +
 3 files changed, 91 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 387e24542cd..e6e58b08de4 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4742,15 +4742,30 @@ record_mangling (tree decl, bool need_warning)
 = mangled_decls->find_slot_with_hash (id, IDENTIFIER_HASH_VALUE (id),
  INSERT);
 
-  /* If this is already an alias, remove the alias, because the real
+  /* If this is already an alias, cancel the alias, because the real
  decl takes precedence.  */
   if (*slot && DECL_ARTIFICIAL (*slot) && DECL_IGNORED_P (*slot))
-if (symtab_node *n = symtab_node::get (*slot))
-  if (n->cpp_implicit_alias)
+{
+  if (symtab_node *n = symtab_node::get (*slot))
{
- n->remove ();
- *slot = NULL_TREE;
+ if (n->cpp_implicit_alias)
+   {
+ /* Actually removing the node isn't safe if other code is already
+holding a pointer to it, so just neutralize it.  */
+ n->remove_from_same_comdat_group ();
+ n->analyzed = false;
+ n->definition = false;
+ n->alias = false;
+ n->cpp_implicit_alias = false;
+   }
}
+  else
+   /* analyze_functions might have already removed the alias from the
+  symbol table if it's internal.  */
+   gcc_checking_assert (!TREE_PUBLIC (*slot));
+
+  *slot = NULL_TREE;
+}
 
   if (!*slot)
 *slot = decl;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C 
b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C
new file mode 100644
index 000..c7946a2be08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle7.C
@@ -0,0 +1,70 @@
+// PR c++/108887
+// { dg-do compile { target c++11 } }
+
+template  struct integral_constant {
+  static constexpr int value = __v;
+};
+using false_type = integral_constant;
+template  struct __result_of_impl;
+template 
+struct __result_of_impl {
+  typedef decltype(0) type;
+};
+template 
+struct __invoke_result
+: __result_of_impl {};
+template 
+void __invoke_impl(_Fn __f, _Args... __args) {
+  __f(__args...);
+}
+template 
+void __invoke_r(_Callable __fn, _Args... __args) {
+  using __result = __invoke_result<_Args...>;
+  using __type = typename __result::type;
+  __invoke_impl<__type>(__fn, __args...);
+}
+struct QString {
+  QString(const char *);
+};
+template  class function;
+template  struct _Base_manager {
+  static _Functor _M_get_pointer(int) { __builtin_abort (); }
+};
+template  class _Function_handler;
+template 
+struct _Function_handler<_Res(_ArgTypes...), _Functor> {
+  using _Base = _Base_manager<_Functor>;
+  static _Res _M_invoke(const int &__functor, _ArgTypes &&...__args) {
+auto __trans_tmp_1 = _Base::_M_get_pointer(__functor);
+__invoke_r<_Res>(__trans_tmp_1, __args...);
+  }
+};
+template 
+struct function<_Res(_ArgTypes...)> {
+  template 
+  using _Handler = _Function_handler<_Res(_ArgTypes...), _Functor>;
+  template  function(_Functor) {
+using _My_handler = _Handler<_Functor>;
+_M_invoker = _My_handler::_M_invoke;
+  }
+  using _Invoker_type = _Res (*)(const int &, _ArgTypes &&...);
+  _Invoker_type _M_invoker;
+};
+struct QRegularExpression {
+  QRegularExpression(QString);
+};
+struct AbstractAccount {
+  void get(function,
+   function);
+};
+struct AbstractTimelineModel {
+  AbstractAccount m_account;
+};
+struct LinkPaginationTimelineModel : AbstractTimelineModel {
+  void fillTimeline();
+};
+void LinkPaginationTimelineModel::fillTimeline() {
+  [] {};
+  m_account.get([](AbstractAccount *) { static QRegularExpression re(""); },
+[](AbstractAccount *) {});
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C 
b/gc

[PATCH] c++: static lambda tsubst [PR108526]

2023-03-07 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

A missed piece of the patch for static operator(): in tsubst_function_decl,
we don't want to replace the first parameter with a new closure pointer if
operator() is static.

PR c++/108526
PR c++/106651

gcc/cp/ChangeLog:

* pt.cc (tsubst_function_decl): Don't replace the closure
parameter if DECL_STATIC_FUNCTION_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/static-operator-call5.C: Pass -g.
---
 gcc/cp/pt.cc   | 4 ++--
 gcc/testsuite/g++.dg/cpp23/static-operator-call5.C | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 85136df1730..aafc99d12c3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -14393,12 +14393,12 @@ tsubst_function_decl (tree t, tree args, 
tsubst_flags_t complain,
 DECL_NAME (r) = make_conv_op_name (TREE_TYPE (type));
 
   tree parms = DECL_ARGUMENTS (t);
-  if (closure)
+  if (closure && !DECL_STATIC_FUNCTION_P (t))
 parms = DECL_CHAIN (parms);
   parms = tsubst (parms, args, complain, t);
   for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
 DECL_CONTEXT (parm) = r;
-  if (closure)
+  if (closure && !DECL_STATIC_FUNCTION_P (t))
 {
   tree tparm = build_this_parm (r, closure, type_memfn_quals (type));
   DECL_NAME (tparm) = closure_identifier;
diff --git a/gcc/testsuite/g++.dg/cpp23/static-operator-call5.C 
b/gcc/testsuite/g++.dg/cpp23/static-operator-call5.C
index ae022d0b971..f7ce8c03008 100644
--- a/gcc/testsuite/g++.dg/cpp23/static-operator-call5.C
+++ b/gcc/testsuite/g++.dg/cpp23/static-operator-call5.C
@@ -1,5 +1,6 @@
 // PR c++/108526
 // { dg-do compile { target c++23 } }
+// { dg-additional-options -g } PR108706
 
 template void f()
 {

base-commit: 247cacc9e381d666a492dfa4ed61b7b19e2d008f
-- 
2.31.1



Re: [PATCH] c++: Fix up ICE in emit_support_tinfo_1 [PR109042]

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

On 3/7/23 04:07, Jakub Jelinek wrote:

Hi!

In my recent rtti.cc change I assumed when emitting the support tinfos
that the tinfos for the fundamental types haven't been created yet.
Normally (in libsupc++.a (fundamental_type_info.o)) that is the case,
but as can be seen on the testcase, one can violate it by using typeid
etc. in the same TU and do it before ~__fundamental_type_info ()
definition.

The following patch fixes that by popping from unemitted_tinfo_decls
only in the normal case when it is there, and treating non-NULL
DECL_INITIAL on a tinfo node as indication that emit_tinfo_decl has
processed it already.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-03-07  Jakub Jelinek  

PR c++/109042
* rtti.cc (emit_support_tinfo_1): Don't assert that last
unemitted_tinfo_decls element is tinfo, instead pop from it only in
that case.
* decl2.cc (c_parse_final_cleanups): Don't call emit_tinfo_decl
for unemitted_tinfO_decls which have already non-NULL DECL_INITIAL.

* g++.dg/rtti/pr109042.C: New test.

--- gcc/cp/rtti.cc.jj   2023-03-03 00:34:52.028567946 +0100
+++ gcc/cp/rtti.cc  2023-03-06 19:06:27.433307136 +0100
@@ -1581,10 +1581,10 @@ emit_support_tinfo_1 (tree bltn)
/* Emit it right away if not emitted already.  */
if (DECL_INITIAL (tinfo) == NULL_TREE)
{
- gcc_assert (unemitted_tinfo_decls->last () == tinfo);
  bool ok = emit_tinfo_decl (tinfo);
  gcc_assert (ok);
- unemitted_tinfo_decls->pop ();
+ if (unemitted_tinfo_decls->last () == tinfo)
+   unemitted_tinfo_decls->pop ();


So if it's not last we'll leave it in the vec, even though it is no 
longer unemitted, and let c_parse_final_cleanups deal with removing it? 
 That could use a comment.  OK with that change.



}
  }
  }
--- gcc/cp/decl2.cc.jj  2023-01-18 16:11:47.053213397 +0100
+++ gcc/cp/decl2.cc 2023-03-06 19:07:16.830582984 +0100
@@ -4982,7 +4982,7 @@ c_parse_final_cleanups (void)
 get emitted.  */
for (i = unemitted_tinfo_decls->length ();
   unemitted_tinfo_decls->iterate (--i, &t);)
-   if (emit_tinfo_decl (t))
+   if (DECL_INITIAL (t) || emit_tinfo_decl (t))
  {
reconsider = true;
unemitted_tinfo_decls->unordered_remove (i);
--- gcc/testsuite/g++.dg/rtti/pr109042.C.jj 2023-03-06 19:11:06.995208812 
+0100
+++ gcc/testsuite/g++.dg/rtti/pr109042.C2023-03-06 19:10:59.117324298 
+0100
@@ -0,0 +1,20 @@
+// PR c++/109042
+// { dg-do compile }
+
+namespace std { class type_info {}; }
+
+std::type_info
+foo ()
+{
+  return typeid (void);
+}
+
+namespace __cxxabiv1 {
+  struct __fundamental_type_info {
+virtual ~__fundamental_type_info ();
+  };
+
+  __fundamental_type_info::~__fundamental_type_info ()
+  {
+  }
+}

Jakub





Re: [PATCH] c++: noexcept and copy elision [PR109030]

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

On 3/6/23 18:59, Marek Polacek wrote:

When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK.


PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
  gcc/cp/constexpr.cc | 6 +-
  gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
  2 files changed, 14 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  
/* 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);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);
  
bool non_constant_args = false;

new_call.bindings
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
new file mode 100644
index 000..16db8eb79ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
@@ -0,0 +1,9 @@
+// PR c++/109030
+// { dg-do compile { target c++11 } }
+
+struct foo { };
+
+struct __as_receiver {
+  foo empty_env;
+};
+void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }

base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902




Re: [PATCH v2] c++: error with constexpr operator() [PR107939]

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

On 3/6/23 17:01, Marek Polacek wrote:

On Mon, Mar 06, 2023 at 11:12:56AM -0500, Jason Merrill wrote:

On 3/3/23 12:51, Marek Polacek wrote:

Similarly to PR107938, this also started with r11-557, whereby cp_finish_decl
can call check_initializer even in a template for a constexpr initializer.

Here we are rejecting

extern const Q q;

template
constexpr auto p = q(0);

even though q has a constexpr operator().  It's deemed non-const by
decl_maybe_constant_var_p because even though 'q' is const it is not
of integral/enum type.  I think the fix is for p_c_e to treat q(0) as
potentially-constant, as below.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?

PR c++/107939

gcc/cp/ChangeLog:

* constexpr.cc (is_constexpr_function_object): New.
(potential_constant_expression_1): Treat an object with constexpr
operator() as potentially-constant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ74.C: Remove dg-error.
* g++.dg/cpp1y/var-templ77.C: New test.
---
   gcc/cp/constexpr.cc  | 23 ++-
   gcc/testsuite/g++.dg/cpp1y/var-templ74.C |  2 +-
   gcc/testsuite/g++.dg/cpp1y/var-templ77.C | 14 ++
   3 files changed, 37 insertions(+), 2 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index acf9847a4d1..7d786f332b4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8929,6 +8929,24 @@ check_for_return_continue (tree *tp, int *walk_subtrees, 
void *data)
 return NULL_TREE;
   }
+/* Return true iff TYPE is a class with constexpr operator().  */
+
+static bool
+is_constexpr_function_object (tree type)
+{
+  if (!CLASS_TYPE_P (type))
+return false;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+if (TREE_CODE (f) == FUNCTION_DECL
+   && DECL_OVERLOADED_OPERATOR_P (f)
+   && DECL_OVERLOADED_OPERATOR_IS (f, CALL_EXPR)
+   && DECL_DECLARED_CONSTEXPR_P (f))
+  return true;
+
+  return false;
+}
+
   /* Return true if T denotes a potentially constant expression.  Issue
  diagnostic as appropriate under control of FLAGS.  If WANT_RVAL is true,
  an lvalue-rvalue conversion is implied.  If NOW is true, we want to
@@ -9160,7 +9178,10 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
  }
else if (fun)
 {
-   if (RECUR (fun, rval))
+   if (VAR_P (fun)
+   && is_constexpr_function_object (TREE_TYPE (fun)))
+ /* Could be an object with constexpr operator().  */;


I guess if fun is not a function pointer, we don't know if we're using it as
an lvalue or rvalue


Presumably the operator function could return this, making it an lvalue?
I'm not sure I'm really clear on this.


I mean just calling the operator uses the variable as an lvalue, by 
passing its address as 'this'.



, so we want to pass 'any' for want_rval, which should
make this work;


Yes, want_rval==false means that p_c_e/VAR_DECL will not issue the
hard error.


I don't think we need to be specific about constexpr op(),
as a constexpr conversion operator to fn* could also do the trick.


Ah, those surrogate classes.  I couldn't reproduce the problem with
them, though I'm adding a test for it anyway.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK, thanks.


-- >8 --
Similarly to PR107938, this also started with r11-557, whereby cp_finish_decl
can call check_initializer even in a template for a constexpr initializer.

Here we are rejecting

   extern const Q q;

   template
   constexpr auto p = q(0);

even though q has a constexpr operator().  It's deemed non-const by
decl_maybe_constant_var_p because even though 'q' is const it is not
of integral/enum type.

If fun is not a function pointer, we don't know if we're using it as an
lvalue or rvalue, so with this patch we pass 'any' for want_rval.  With
that, p_c_e/VAR_DECL doesn't flat out reject the underlying VAR_DECL.

PR c++/107939

gcc/cp/ChangeLog:

* constexpr.cc (potential_constant_expression_1) : Pass
'any' when recursing on a VAR_DECL and not a pointer to function.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ74.C: Remove dg-error.
* g++.dg/cpp1y/var-templ77.C: New test.
---
  gcc/cp/constexpr.cc  |  8 --
  gcc/testsuite/g++.dg/cpp1y/var-templ74.C |  2 +-
  gcc/testsuite/g++.dg/cpp1y/var-templ77.C | 32 
  3 files changed, 39 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..3079561f2e8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9179,8 +9179,12 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
  }
else if (fun)
{
-   if (RECUR (f

Re: [PATCH v6] c++: -Wdangling-reference with reference wrapper [PR107532]

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

On 3/6/23 16:54, Marek Polacek wrote:

On Fri, Mar 03, 2023 at 09:30:38PM -0500, Jason Merrill wrote:

On 3/3/23 12:50, Marek Polacek wrote:

 switch (TREE_CODE (expr))
   {
   case CALL_EXPR:
@@ -13831,7 +13895,8 @@ do_warn_dangling_reference (tree expr)
 std::pair v = std::minmax(1, 2);
   which also creates a dangling reference, because std::minmax
   returns std::pair(b, a).  */
-   if (!(TYPE_REF_OBJ_P (rettype) || std_pair_ref_ref_p (rettype)))
+   if (!arg_p
+   && (!(TYPE_REF_OBJ_P (rettype) || std_pair_ref_ref_p (rettype


Instead of checking !arg_p maybe the std_pair_ref_ref_p call should change
to reference_like_class_p (which in turn should check std_pair_ref_ref_p)?


Could do.  I suppose the logic is that for std::pair
arguments we want to see through it to get at its arguments.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here, -Wdangling-reference triggers where it probably shouldn't, causing
some grief.  The code in question uses a reference wrapper with a member
function returning a reference to a subobject of a non-temporary object:

   const Plane & meta = fm.planes().inner();

I've tried a few approaches, e.g., checking that the member function's
return type is the same as the type of the enclosing class (which is
the case for member functions returning *this), but that then breaks
Wdangling-reference4.C with std::optional.

This patch adjusts do_warn_dangling_reference so that we look through
reference wrapper classes (meaning, has a reference member and a
constructor taking the same reference type, or is std::reference_wrapper
or std::ranges::ref_view) and don't warn for them, supposing that the
member function returns a reference to a non-temporary object.

PR c++/107532

gcc/cp/ChangeLog:

* call.cc (reference_like_class_p): New.
(do_warn_dangling_reference): Add new bool parameter.  See through
reference_like_class_p.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wdangling-reference8.C: New test.
* g++.dg/warn/Wdangling-reference9.C: New test.
---
  gcc/cp/call.cc| 97 ---
  .../g++.dg/warn/Wdangling-reference8.C| 77 +++
  .../g++.dg/warn/Wdangling-reference9.C| 21 
  3 files changed, 181 insertions(+), 14 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference8.C
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference9.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 048b2b052f8..a43980b6e15 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13779,6 +13779,52 @@ std_pair_ref_ref_p (tree t)
return true;
  }
  
+/* Return true if a class CTYPE is either std::reference_wrapper or

+   std::ref_view, or a reference wrapper class.  We consider a class
+   a reference wrapper class if it has a reference member and a
+   constructor taking the same reference type.  */
+
+static bool
+reference_like_class_p (tree ctype)
+{
+  if (!CLASS_TYPE_P (ctype))
+return false;
+
+  /* Also accept a std::pair.  */
+  if (std_pair_ref_ref_p (ctype))
+return true;
+
+  tree tdecl = TYPE_NAME (TYPE_MAIN_VARIANT (ctype));
+  if (decl_in_std_namespace_p (tdecl))
+{
+  tree name = DECL_NAME (tdecl);
+  return (name
+ && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "ref_view")));
+}
+  for (tree fields = TYPE_FIELDS (ctype);
+   fields;
+   fields = DECL_CHAIN (fields))
+{
+  if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
+   continue;
+  tree type = TREE_TYPE (fields);
+  if (!TYPE_REF_P (type))
+   continue;
+  /* OK, the field is a reference member.  Do we have a constructor
+taking its type?  */
+  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype)))
+   {
+ tree args = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ if (args
+ && same_type_p (TREE_VALUE (args), type)
+ && TREE_CHAIN (args) == void_list_node)
+   return true;
+   }
+}
+  return false;
+}
+
  /* Helper for maybe_warn_dangling_reference to find a problematic CALL_EXPR
 that initializes the LHS (and at least one of its arguments represents
 a temporary, as outlined in maybe_warn_dangling_reference), or NULL_TREE
@@ -13793,12 +13839,36 @@ std_pair_ref_ref_p (tree t)
   const int& y = (f(1), 42); // NULL_TREE
   const int& z = f(f(1)); // f(f(1))
  
-   EXPR is the initializer.  */

+   EXPR is the initializer.  If ARG_P is true, we're processing an argument
+   to a function; the point is to distinguish between, for example,
+
+ Ref::inner (&TARGET_EXPR )
+
+   where we shouldn't warn, and
+
+ Ref::inner (&TARGET_EXPR )>)
+
+   where we should warn (Ref is a reference_like_class_p so we see through
+   it.  */
  
  static tree

-do_warn_dangling_reference (tree expr)
+do_warn_dan

Re: [PATCH] c++: error with constexpr operator() [PR107939]

2023-03-06 Thread Jason Merrill via Gcc-patches

On 3/3/23 12:51, Marek Polacek wrote:

Similarly to PR107938, this also started with r11-557, whereby cp_finish_decl
can call check_initializer even in a template for a constexpr initializer.

Here we are rejecting

   extern const Q q;

   template
   constexpr auto p = q(0);

even though q has a constexpr operator().  It's deemed non-const by
decl_maybe_constant_var_p because even though 'q' is const it is not
of integral/enum type.  I think the fix is for p_c_e to treat q(0) as
potentially-constant, as below.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?

PR c++/107939

gcc/cp/ChangeLog:

* constexpr.cc (is_constexpr_function_object): New.
(potential_constant_expression_1): Treat an object with constexpr
operator() as potentially-constant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ74.C: Remove dg-error.
* g++.dg/cpp1y/var-templ77.C: New test.
---
  gcc/cp/constexpr.cc  | 23 ++-
  gcc/testsuite/g++.dg/cpp1y/var-templ74.C |  2 +-
  gcc/testsuite/g++.dg/cpp1y/var-templ77.C | 14 ++
  3 files changed, 37 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index acf9847a4d1..7d786f332b4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8929,6 +8929,24 @@ check_for_return_continue (tree *tp, int *walk_subtrees, 
void *data)
return NULL_TREE;
  }
  
+/* Return true iff TYPE is a class with constexpr operator().  */

+
+static bool
+is_constexpr_function_object (tree type)
+{
+  if (!CLASS_TYPE_P (type))
+return false;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+if (TREE_CODE (f) == FUNCTION_DECL
+   && DECL_OVERLOADED_OPERATOR_P (f)
+   && DECL_OVERLOADED_OPERATOR_IS (f, CALL_EXPR)
+   && DECL_DECLARED_CONSTEXPR_P (f))
+  return true;
+
+  return false;
+}
+
  /* Return true if T denotes a potentially constant expression.  Issue
 diagnostic as appropriate under control of FLAGS.  If WANT_RVAL is true,
 an lvalue-rvalue conversion is implied.  If NOW is true, we want to
@@ -9160,7 +9178,10 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
  }
else if (fun)
{
-   if (RECUR (fun, rval))
+   if (VAR_P (fun)
+   && is_constexpr_function_object (TREE_TYPE (fun)))
+ /* Could be an object with constexpr operator().  */;


I guess if fun is not a function pointer, we don't know if we're using 
it as an lvalue or rvalue, so we want to pass 'any' for want_rval, which 
should make this work; I don't think we need to be specific about 
constexpr op(), as a constexpr conversion operator to fn* could also do 
the trick.



+   else if (RECUR (fun, rval))
  /* Might end up being a constant function pointer.  */;
else
  return false;
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ74.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ74.C
index 4e2e800a6eb..c76a7d949ac 100644
--- a/gcc/testsuite/g++.dg/cpp1y/var-templ74.C
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ74.C
@@ -9,7 +9,7 @@ struct Q {
  extern const Q q;
  
  template

-constexpr const Q* p = q(0); // { dg-bogus "not usable" "PR107939" { xfail 
*-*-* } }
+constexpr const Q* p = q(0);
  
  void

  g ()
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ77.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ77.C
new file mode 100644
index 000..b480f54b001
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ77.C
@@ -0,0 +1,14 @@
+// PR c++/107939
+// { dg-do compile { target c++14 } }
+
+struct Q {
+  struct P {
+const Q* p;
+  };
+  int n;
+  constexpr P operator()(int) const { return {this}; }
+};
+
+extern const Q q;
+template
+constexpr auto p = q(0);

base-commit: 9056d0df830c5a295d7594d517d409d10476990d




Re: [PATCH v5] c++: -Wdangling-reference with reference wrapper [PR107532]

2023-03-03 Thread Jason Merrill via Gcc-patches

On 3/3/23 12:50, Marek Polacek wrote:

On Fri, Mar 03, 2023 at 11:25:06AM -0500, Jason Merrill wrote:

On 3/2/23 16:24, Marek Polacek wrote:

On Wed, Mar 01, 2023 at 04:53:23PM -0500, Jason Merrill wrote:

@@ -13791,12 +13830,39 @@ std_pair_ref_ref_p (tree t)
 const int& y = (f(1), 42); // NULL_TREE
 const int& z = f(f(1)); // f(f(1))
-   EXPR is the initializer.  */
+   EXPR is the initializer.  If ARG_P is true, we're processing an argument
+   to a function; the point is to distinguish between, for example,
+
+ Ref::inner (&TARGET_EXPR )
+
+   where we shouldn't warn, and
+
+ Ref::inner (&TARGET_EXPR )>)
+
+   where we should warn (Ref is a reference_like_class_p so we see through
+   it.  */
static tree
-do_warn_dangling_reference (tree expr)
+do_warn_dangling_reference (tree expr, bool arg_p)
{
  STRIP_NOPS (expr);
+  if (TREE_CODE (expr) == ADDR_EXPR)
+expr = TREE_OPERAND (expr, 0);


I think if we move this here, we also need to check that expr before
STRIP_NOPS had REFERENCE_TYPE.  OK with that change.


Sorry but I don't think I can do that.  There can be CONVERT_EXPRs
that need to be stripped, whether arg_p or !arg_p.  For example, we can get
(const int *) f ((const int &) &TARGET_EXPR >)
for
const int& r5 = (42, f(10));


I meant that we only want to strip ADDR_EXPR if 'expr' at the start of the
function had REFERENCE_TYPE, corresponding to


 /* Check that this argument initializes a reference, except
for
the argument initializing the object of a member function.  */
 if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
 && !TYPE_REF_P (TREE_TYPE (arg)))
   continue;


above the code for stripping an ADDR_EXPR from an argument that your patch
removes.


I see.


If the original expr is a pointer rather than a reference, we don't want to
complain about it pointing to a temporary.


Ug, I can't make it work.  When we recurse, I can no longer check
fndecl.  How about just moving the stripping back where it was?


Sure.


-- >8 --
Here, -Wdangling-reference triggers where it probably shouldn't, causing
some grief.  The code in question uses a reference wrapper with a member
function returning a reference to a subobject of a non-temporary object:

   const Plane & meta = fm.planes().inner();

I've tried a few approaches, e.g., checking that the member function's
return type is the same as the type of the enclosing class (which is
the case for member functions returning *this), but that then breaks
Wdangling-reference4.C with std::optional.

This patch adjusts do_warn_dangling_reference so that we look through
reference wrapper classes (meaning, has a reference member and a
constructor taking the same reference type, or is std::reference_wrapper
or std::ranges::ref_view) and don't warn for them, supposing that the
member function returns a reference to a non-temporary object.

PR c++/107532

gcc/cp/ChangeLog:

* call.cc (reference_like_class_p): New.
(do_warn_dangling_reference): Add new bool parameter.  See through
reference_like_class_p.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wdangling-reference8.C: New test.
* g++.dg/warn/Wdangling-reference9.C: New test.
---
  gcc/cp/call.cc| 92 ---
  .../g++.dg/warn/Wdangling-reference8.C| 77 
  .../g++.dg/warn/Wdangling-reference9.C| 21 +
  3 files changed, 176 insertions(+), 14 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference8.C
  create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference9.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 048b2b052f8..62536573633 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13779,6 +13779,45 @@ std_pair_ref_ref_p (tree t)
return true;
  }
  
+/* Return true if a class CTYPE is either std::reference_wrapper or

+   std::ref_view, or a reference wrapper class.  We consider a class
+   a reference wrapper class if it has a reference member and a
+   constructor taking the same reference type.  */
+
+static bool
+reference_like_class_p (tree ctype)
+{
+  tree tdecl = TYPE_NAME (TYPE_MAIN_VARIANT (ctype));
+  if (decl_in_std_namespace_p (tdecl))
+{
+  tree name = DECL_NAME (tdecl);
+  return (name
+ && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "ref_view")));
+}
+  for (tree fields = TYPE_FIELDS (ctype);
+   fields;
+   fields = DECL_CHAIN (fields))
+{
+  if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
+   continue;
+  tree type = TREE_TYPE (fields);
+  if (!TYPE_REF_P (type))
+   continue;
+  /* OK, the field is a reference member.  Do we have a constructor
+taking its type?  */
+  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype)))
+   {
+ tree args = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ if (args
+ 

Re: [PATCH v4] c++: -Wdangling-reference with reference wrapper [PR107532]

2023-03-03 Thread Jason Merrill via Gcc-patches

On 3/2/23 16:24, Marek Polacek wrote:

On Wed, Mar 01, 2023 at 04:53:23PM -0500, Jason Merrill wrote:

@@ -13791,12 +13830,39 @@ std_pair_ref_ref_p (tree t)
const int& y = (f(1), 42); // NULL_TREE
const int& z = f(f(1)); // f(f(1))
-   EXPR is the initializer.  */
+   EXPR is the initializer.  If ARG_P is true, we're processing an argument
+   to a function; the point is to distinguish between, for example,
+
+ Ref::inner (&TARGET_EXPR )
+
+   where we shouldn't warn, and
+
+ Ref::inner (&TARGET_EXPR )>)
+
+   where we should warn (Ref is a reference_like_class_p so we see through
+   it.  */
   static tree
-do_warn_dangling_reference (tree expr)
+do_warn_dangling_reference (tree expr, bool arg_p)
   {
 STRIP_NOPS (expr);
+  if (TREE_CODE (expr) == ADDR_EXPR)
+expr = TREE_OPERAND (expr, 0);


I think if we move this here, we also need to check that expr before
STRIP_NOPS had REFERENCE_TYPE.  OK with that change.


Sorry but I don't think I can do that.  There can be CONVERT_EXPRs
that need to be stripped, whether arg_p or !arg_p.  For example, we can get
(const int *) f ((const int &) &TARGET_EXPR >)
for
const int& r5 = (42, f(10));


I meant that we only want to strip ADDR_EXPR if 'expr' at the start of 
the function had REFERENCE_TYPE, corresponding to


/* Check that this argument initializes a reference, except for 
   the argument initializing the object of a member function.  */

if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
&& !TYPE_REF_P (TREE_TYPE (arg)))
  continue;


above the code for stripping an ADDR_EXPR from an argument that your 
patch removes.


If the original expr is a pointer rather than a reference, we don't want 
to complain about it pointing to a temporary.


Jason



Re: [PATCH] c++: thinko in extract_local_specs [PR108998]

2023-03-03 Thread Jason Merrill via Gcc-patches

On 3/3/23 09:58, Patrick Palka wrote:

In order to fix PR100295, r13-4730-g18499b9f848707 attempted to make
extract_local_specs walk the given pattern twice, ignoring unevaluated
operands the first time around so that we prefer to process a local
specialization in an evaluated context if it appears in one (we process
a local specialization once even if it appears multiple times in the
pattern).

But there's a thinko in the patch, namely that we don't actually walk
the pattern twice, because we reuse the visited set for the second walk
(to avoid processing a local specialization twice), and the root node
(and any nodes leading up to an unevaluated operand) is considered
visited already.  So the patch effectively made extract_local_specs
ignore unevaluated operands altogether, which this testcase demonstrates
isn't quite safe (extract_local_specs never sees 'aa' and we don't save
its local specialization, so we later try to specialize 'aa' on the spot
with the args {{int},{42}} which causes us to nonsensically substitute
its auto with 42.)

This patch fixes this by walking only the trees we skipped over during
the first walk the second time around.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?


OK.


PR c++/108998

gcc/cp/ChangeLog:

* pt.cc (el_data::skipped_trees): New data member.
(extract_locals_r): Push to skipped_trees any unevaluated
contexts that we skipped over.
(extract_local_specs): During the second walk, consider only
the trees in skipped_trees.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-generic11.C: New test.
---
  gcc/cp/pt.cc  | 10 +-
  gcc/testsuite/g++.dg/cpp2a/lambda-generic11.C | 13 +
  2 files changed, 22 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-generic11.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ba1b3027513..85136df1730 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13052,6 +13052,8 @@ public:
tsubst_flags_t complain;
/* True iff we don't want to walk into unevaluated contexts.  */
bool skip_unevaluated_operands = false;
+  /* The unevaluated contexts that we avoided walking.  */
+  auto_vec skipped_trees;
  
el_data (tsubst_flags_t c)

  : extra (NULL_TREE), complain (c) {}
@@ -13066,6 +13068,7 @@ extract_locals_r (tree *tp, int *walk_subtrees, void 
*data_)
if (data.skip_unevaluated_operands
&& unevaluated_p (TREE_CODE (*tp)))
  {
+  data.skipped_trees.safe_push (*tp);
*walk_subtrees = 0;
return NULL_TREE;
  }
@@ -13168,8 +13171,13 @@ extract_local_specs (tree pattern, tsubst_flags_t 
complain)
   context).  */
data.skip_unevaluated_operands = true;
cp_walk_tree (&pattern, extract_locals_r, &data, &data.visited);
+  /* Now walk the unevaluated contexts we skipped the first time around.  */
data.skip_unevaluated_operands = false;
-  cp_walk_tree (&pattern, extract_locals_r, &data, &data.visited);
+  for (tree t : data.skipped_trees)
+{
+  data.visited.remove (t);
+  cp_walk_tree (&t, extract_locals_r, &data, &data.visited);
+}
return data.extra;
  }
  
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic11.C b/gcc/testsuite/g++.dg/cpp2a/lambda-generic11.C

new file mode 100644
index 000..418650699e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic11.C
@@ -0,0 +1,13 @@
+// PR c++/108999
+// { dg-do compile { target c++20 } }
+
+template
+void ice(T a) {
+  auto aa = a;
+  auto lambda = []() {
+if constexpr (sizeof(aa) + I != 42) {}
+  };
+  lambda.template operator()<0>();
+}
+
+template void ice(int);




Re: [PATCH] c++, v2: Don't defer local statics initialized with constant expressions [PR108702]

2023-03-03 Thread Jason Merrill via Gcc-patches

On 3/3/23 10:18, Jakub Jelinek wrote:

On Thu, Mar 02, 2023 at 11:48:04AM -0500, Jason Merrill wrote:

The stmtexpr19.C testcase used to be rejected as it has a static
variable in statement expression in constexpr context, but as that
static variable is initialized by constant expression, when P2647R1
was implemented we agreed to make it valid.

Now, as reported, the testcase compiles fine, but doesn't actually link
because the static variable isn't defined anywhere, and with -flto ICEs
because of this problem.  This is because we never
varpool_node::finalize_decl those vars, the constant expression in which
the DECL_EXPR is present for the static VAR_DECL is folded (constant
evaluated) into just the address of the VAR_DECL.


Would it make sense to define it when we see the DECL_EXPR in constant
evaluation?


So like this?


OK, thanks.


Passes GXX_TESTSUITE_STDS=98,11,14,17,20,2b make check-g++ so far.

2023-03-03  Jakub Jelinek  

PR c++/108702
* constexpr.cc: Include toplev.h.
(cxx_eval_constant_expression) : When seeing a local
static initialized by constant expression outside of a constexpr
function which has been deferred by make_rtl_for_nonlocal_decl,
call rest_of_decl_compilation on it.

* g++.dg/ext/stmtexpr19.C: Use dg-do link rather than dg-do compile.

--- gcc/cp/constexpr.cc.jj  2023-03-03 00:34:44.113679918 +0100
+++ gcc/cp/constexpr.cc 2023-03-03 13:26:57.602871900 +0100
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.
  #include "attribs.h"
  #include "fold-const.h"
  #include "intl.h"
+#include "toplev.h"
  
  static bool verify_constant (tree, bool, bool *, bool *);

  #define VERIFY_CONSTANT(X)\
@@ -7127,6 +7128,24 @@ cxx_eval_constant_expression (const cons
break;
  }
  
+	/* make_rtl_for_nonlocal_decl could have deferred emission of

+  a local static var, but if it appears in a statement expression
+  which is constant expression evaluated to e.g. just the address
+  of the variable, its DECL_EXPR will never be seen during
+  gimple lowering's record_vars_into as the statement expression
+  will not be in the IL at all.  */
+   if (VAR_P (r)
+   && TREE_STATIC (r)
+   && !DECL_REALLY_EXTERN (r)
+   && DECL_FUNCTION_SCOPE_P (r)
+   && !var_in_maybe_constexpr_fn (r)
+   && decl_constant_var_p (r))
+ {
+   varpool_node *node = varpool_node::get (r);
+   if (node == NULL || !node->definition)
+ rest_of_decl_compilation (r, 0, at_eof);
+ }
+
if (AGGREGATE_TYPE_P (TREE_TYPE (r))
|| VECTOR_TYPE_P (TREE_TYPE (r)))
  {
--- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj2023-02-09 15:52:29.623359240 
+0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr19.C   2023-03-03 12:24:20.217186735 
+0100
@@ -1,6 +1,6 @@
  // PR c++/81073
  // { dg-options "" }
-// { dg-do compile { target c++11 } }
+// { dg-do link { target c++11 } }
  
  struct test { const int *addr; };
  



Jakub





Re: [PATCH] c++, debug: Fix up locus of DW_TAG_imported_module [PR108716]

2023-03-02 Thread Jason Merrill via Gcc-patches

On 2/9/23 03:41, Jakub Jelinek wrote:

Hi!

Before IMPORTED_DECL has been introduced in PR37410, we used to emit correct
DW_AT_decl_line on DW_TAG_imported_module on the testcase below, after that
change we haven't emitted it at all for a while and after some time
started emitting incorrect locus, in particular the location of } closing
the function.

The problem is that while we have correct EXPR_LOCATION on the USING_STMT,
when genericizing that USING_STMT into IMPORTED_DECL we don't copy the
location to DECL_SOURCE_LOCATION, so it gets whatever input_location happens
to be when it is created.

The following patch fixes that, bootstrapped/regtested on x86_64-linux and
i686-linux, ok for trunk?


OK.


2023-02-09  Jakub Jelinek  

PR debug/108716
* cp-gimplify.cc (cp_genericize_r) : Set
DECL_SOURCE_LOCATION on IMPORTED_DECL to expression location
of USING_STMT or input_location.

* g++.dg/debug/dwarf2/pr108716.C: New test.

--- gcc/cp/cp-gimplify.cc.jj2023-02-01 10:19:43.038140336 +0100
+++ gcc/cp/cp-gimplify.cc   2023-02-08 10:36:00.301501540 +0100
@@ -1514,6 +1514,8 @@ cp_genericize_r (tree *stmt_p, int *walk
tree using_directive = make_node (IMPORTED_DECL);
TREE_TYPE (using_directive) = void_type_node;
DECL_CONTEXT (using_directive) = current_function_decl;
+   DECL_SOURCE_LOCATION (using_directive)
+ = cp_expr_loc_or_input_loc (stmt);
  
  		IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;

DECL_CHAIN (using_directive) = BLOCK_VARS (block);
--- gcc/testsuite/g++.dg/debug/dwarf2/pr108716.C.jj 2023-02-08 
11:48:39.667385750 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/pr108716.C2023-02-08 
11:48:57.998115610 +0100
@@ -0,0 +1,14 @@
+// PR debug/108716
+// { dg-options "-O0 -gdwarf-5 -dA -fno-merge-debug-strings" }
+// { dg-final { scan-assembler "DIE \\(\[^\n\r\]*\\) 
DW_TAG_imported_module\[^\n\r\]*\[\n\r]*\[^\n\r\]* 
DW_AT_decl_file\[^\n\r\]*\[\n\r]*\[^\n\r\]*0xc\[^\n\r\]* 
DW_AT_decl_line\[^\n\r\]*\[\n\r]*(\[^\n\r\]*0x13\[^\n\r\]* 
DW_AT_decl_column\[^\n\r\]*\[\n\r]*)?" } }
+
+namespace M {
+  int x = 1;
+}
+
+int
+main ()
+{
+  using namespace M;
+  return 0;
+}

Jakub





Re: [PATCH] c++: Don't defer local statics initialized with constant expressions [PR108702]

2023-03-02 Thread Jason Merrill via Gcc-patches

On 2/9/23 11:14, Jakub Jelinek wrote:

Hi!

The stmtexpr19.C testcase used to be rejected as it has a static
variable in statement expression in constexpr context, but as that
static variable is initialized by constant expression, when P2647R1
was implemented we agreed to make it valid.

Now, as reported, the testcase compiles fine, but doesn't actually link
because the static variable isn't defined anywhere, and with -flto ICEs
because of this problem.  This is because we never
varpool_node::finalize_decl those vars, the constant expression in which
the DECL_EXPR is present for the static VAR_DECL is folded (constant
evaluated) into just the address of the VAR_DECL.


Would it make sense to define it when we see the DECL_EXPR in constant 
evaluation?



Now, similar testcase included below (do we want to include it in the
testsuite too?) works fine, because in
cp_finish_decl -> make_rtl_for_nonlocal_decl
we have since PR70353 fix:
   /* We defer emission of local statics until the corresponding
  DECL_EXPR is expanded.  But with constexpr its function might never
  be expanded, so go ahead and tell cgraph about the variable now.  */
   defer_p = ((DECL_FUNCTION_SCOPE_P (decl)
   && !var_in_maybe_constexpr_fn (decl))
  || DECL_VIRTUAL_P (decl));
and so don't defer them in constexpr/consteval functions.  The following
patch extends that and doesn't defer vars initialized by constant
expressions either, because otherwise there is nothing to finalize those.
It is true that e.g. with -O0
int foo (int x) {
   if (x) { static int y = 1; ++y; }
   if (0) { static int z = 1; ++z; }
   return sizeof (({ static int w = 1; w; }));
}
we used to emit just y and z and with the patch emit also w, but with
optimizations that is optimized away properly.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

The testcase I was talking above that works because of the
&& !var_in_maybe_constexpr_fn (decl) case is:

extern "C" void abort ();

constexpr const int *
foo ()
{
   static constexpr int a = 1;
   return &a;
}

consteval const int *
bar ()
{
   static constexpr int a = 1;
   return &a;
}

[[gnu::noipa]] void
baz (const int *x)
{
   if (*x != 1)
 abort ();
}

int
main ()
{
   constexpr const int *p = foo ();
   constexpr const int *q = bar ();
   baz (p);
   baz (q);
   if (p == q)
 abort ();
}

2023-02-09  Jakub Jelinek  

PR c++/108702
* decl.cc (make_rtl_for_nonlocal_decl): Don't defer local statics
initialized by constant expressions.

* g++.dg/ext/stmtexpr19.C: Use dg-do link rather than dg-do compile.

--- gcc/cp/decl.cc.jj   2023-01-24 11:10:13.151076134 +0100
+++ gcc/cp/decl.cc  2023-02-09 13:29:50.527083618 +0100
@@ -7731,9 +7731,12 @@ make_rtl_for_nonlocal_decl (tree decl, t
  
/* We defer emission of local statics until the corresponding

   DECL_EXPR is expanded.  But with constexpr its function might never
- be expanded, so go ahead and tell cgraph about the variable now.  */
+ be expanded, so go ahead and tell cgraph about the variable now.
+ Also don't defer local statics initialized by constant expressions,
+ see PR108702.  */
defer_p = ((DECL_FUNCTION_SCOPE_P (decl)
- && !var_in_maybe_constexpr_fn (decl))
+ && !var_in_maybe_constexpr_fn (decl)
+ && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
 || DECL_VIRTUAL_P (decl));
  
/* Defer template instantiations.  */

--- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj2022-11-19 09:26:30.168061316 
+0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr19.C   2023-02-09 13:32:48.887453520 
+0100
@@ -1,6 +1,6 @@
  // PR c++/81073
  // { dg-options "" }
-// { dg-do compile { target c++11 } }
+// { dg-do link { target c++11 } }
  
  struct test { const int *addr; };
  


Jakub





Re: [PATCH] c++: more mce_false folding from cp_fully_fold_init [PR108243]

2023-03-02 Thread Jason Merrill via Gcc-patches

On 2/21/23 14:10, Patrick Palka wrote:

We should also fold the overall initializer passed to cp_fully_fold_init
with mce_false, which enables folding of the copy-initialization of
'a1' in the below testcase (the initializer here is an AGGR_INIT_EXPR).

Unfortunately this doesn't help with direct- or default-initialization
because we don't call cp_fully_fold_init in that case, and even if we
did the initializer in that case is expressed as a bare CALL_EXPR
instead of an AGGR_INIT_EXPR, which cp_fully_fold_init can't really
fold.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


OK.


PR c++/108243

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_fully_fold): Add an internal overload that
additionally takes and propagate an mce_value parameter, and
define the existing public overload in terms of it.
(cp_fully_fold_init): Pass mce_false to cp_fully_fold.

gcc/testsuite/ChangeLog:

* g++.dg/opt/is_constant_evaluated3.C: New test.
---
  gcc/cp/cp-gimplify.cc | 14 +++
  .../g++.dg/opt/is_constant_evaluated3.C   | 23 +++
  2 files changed, 33 insertions(+), 4 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 32fe53521cc..5d5c6efb856 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -2447,8 +2447,8 @@ cp_fold_rvalue (tree x)
  
  /* Perform folding on expression X.  */
  
-tree

-cp_fully_fold (tree x)
+static tree
+cp_fully_fold (tree x, mce_value manifestly_const_eval)
  {
if (processing_template_decl)
  return x;
@@ -2456,7 +2456,7 @@ cp_fully_fold (tree x)
   have to call both.  */
if (cxx_dialect >= cxx11)
  {
-  x = maybe_constant_value (x);
+  x = maybe_constant_value (x, /*decl=*/NULL_TREE, manifestly_const_eval);
/* Sometimes we are given a CONSTRUCTOR but the call above wraps it into
 a TARGET_EXPR; undo that here.  */
if (TREE_CODE (x) == TARGET_EXPR)
@@ -2469,6 +2469,12 @@ cp_fully_fold (tree x)
return cp_fold_rvalue (x);
  }
  
+tree

+cp_fully_fold (tree x)
+{
+  return cp_fully_fold (x, mce_unknown);
+}
+
  /* Likewise, but also fold recursively, which cp_fully_fold doesn't perform
 in some cases.  */
  
@@ -2477,7 +2483,7 @@ cp_fully_fold_init (tree x)

  {
if (processing_template_decl)
  return x;
-  x = cp_fully_fold (x);
+  x = cp_fully_fold (x, mce_false);
cp_fold_data data (ff_mce_false);
cp_walk_tree (&x, cp_fold_r, &data, NULL);
return x;
diff --git a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C 
b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C
new file mode 100644
index 000..0a1e46e5638
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3.C
@@ -0,0 +1,23 @@
+// PR c++/108243
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-O -fdump-tree-original" }
+
+struct A {
+  constexpr A(int n) : n(n), m(__builtin_is_constant_evaluated()) { }
+  constexpr A() : A(42) { }
+  int n, m;
+};
+
+int main() {
+  A a1 = {42};
+  A a2{42};
+  A a3(42);
+  A a4;
+  A a5{};
+}
+
+// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" } }
+// { dg-final { scan-tree-dump "a2 = {\\.n=42, \\.m=0}" "original" { xfail 
*-*-* } } }
+// { dg-final { scan-tree-dump "a3 = {\\.n=42, \\.m=0}" "original" { xfail 
*-*-* } } }
+// { dg-final { scan-tree-dump "a4 = {\\.n=42, \\.m=0}" "original" { xfail 
*-*-* } } }
+// { dg-final { scan-tree-dump "a5 = {\\.n=42, \\.m=0}" "original" { xfail 
*-*-* } } }




Re: [PATCH] c++: constant non-copy-init is manifestly constant [PR108243]

2023-03-02 Thread Jason Merrill via Gcc-patches

On 2/21/23 15:18, Patrick Palka wrote:

On Mon, 20 Feb 2023, Patrick Palka wrote:


According to [basic.start.static]/2 and [expr.const]/2, a variable
with static storage duration initialized with a constant initializer
has constant initialization, and such an initializer is manifestly
constant-evaluated.

We're already getting this right with copy initialization because in
that case check_initializer would consistently call store_init_value
(which for TREE_STATIC variables calls fold_non_dependent_init with
m_c_e=true).

But for direct (or default) initialization, we don't always call
store_init_value.  We instead however always call maybe_constant_init
from expand_default_init[1], albeit with m_c_e=false which means we
don't always get the "manifestly constant-evaluated" part right for
copy-init.

This patch fixes this by simply passing m_c_e=true to this call to
maybe_constant_init for static storage duration variables, mirroring
what store_init_value basically does.

[1]: this maybe_constant_init call isn't reached in the copy-init
case because there init is a CONSTRUCTOR rather than a TREE_LIST so
expand_default_init exits early returning an INIT_EXPR.  This INIT_EXPR
is ultimately what causes us to consistently hit the store_init_value
code path from check_initializer in the copy-init case.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  Would it be suitable to backport this to the 12 branch since
it should only affect C++20 code?

PR c++/108243

gcc/cp/ChangeLog:

* init.cc (expand_default_init): Pass m_c_e=true instead of
=false to maybe_constant_init when initializing a variable
with static storage duration.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/is-constant-evaluated14.C: New test.
---
  gcc/cp/init.cc|   5 +-
  .../g++.dg/cpp2a/is-constant-evaluated14.C| 140 ++
  2 files changed, 144 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated14.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 52e96fbe590..705a5b3bdb6 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -2203,7 +2203,10 @@ expand_default_init (tree binfo, tree true_exp, tree 
exp, tree init, int flags,
tree fn = get_callee_fndecl (rval);
if (fn && DECL_DECLARED_CONSTEXPR_P (fn))
{
- tree e = maybe_constant_init (rval, exp);
+ bool manifestly_const_eval = false;
+ if (VAR_P (exp) && TREE_STATIC (exp))
+   manifestly_const_eval = true;
+ tree e = maybe_constant_init (rval, exp, manifestly_const_eval);
  if (TREE_CONSTANT (e))
rval = cp_build_init_expr (exp, e);
}


Hmm, alternatively we could just override manifestly_const_eval to true
from maybe_constant_init for static storage duration variables, like so.
I guess this approach much be preferable since it potentially benefits
all maybe_constant_init callers?


That does look better.

OK (perhaps with a local variable to hold the mce_value).


-- >8 --

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_init_1): Override
manifestly_const_eval to true if is_static.

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index aa2c14355f8..8ae83a6eadf 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8760,7 +8760,8 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
bool is_static = (decl && DECL_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,
-   mce_value (manifestly_const_eval),
+   (is_static ? mce_true
+: mce_value 
(manifestly_const_eval)),
false, decl);
  }
if (TREE_CODE (t) == TARGET_EXPR)


diff --git a/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated14.C 
b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated14.C
new file mode 100644
index 000..365bca3fd9a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated14.C
@@ -0,0 +1,140 @@
+// PR c++/108243
+// Verify a variable with static storage duration initialized with a
+// constant initializer has constant initialization, and the initializer
+// is manifestly constant-evaluated.
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-fdump-tree-original" }
+
+#include 
+
+struct A {
+  constexpr A(int n) : n(n), m(__builtin_is_constant_evaluated()) { }
+  constexpr A() : A(42) { }
+  void verify_mce() const {
+if (m != 1) __builtin_abort();
+  }
+  int n;
+  int m;
+};
+
+A a1 = {42};
+A a2{42};
+A a3(42);
+A a4;
+A a5{};
+
+void f() {
+  static A a1 = {42};
+  static A a2{42};
+  static A a3(42);
+  static A a4;
+  static A a5{};
+  for (auto& a : {a1, a2, a3, a4, a5})
+a.verify_mce();
+}

Re: [PATCH] c++, v3: Emit fundamental tinfos for _Float16/decltype(0.0bf16) types on ia32 with -mno-sse2 [PR108883]

2023-03-02 Thread Jason Merrill via Gcc-patches

On 3/2/23 06:20, Jakub Jelinek wrote:

Hi!

On Wed, Mar 01, 2023 at 05:50:47PM -0500, Jason Merrill wrote:

And then there is a question whether we want to emit rtti for
_Float{16,32,64,128}, _Float{32,64,128}x and decltype(0.0bf16) regardless
of whether the target supports them at all or not.
Emitting them always would have an advantage, if say bfloat16_t support
isn't added for aarch64 for GCC 13 (it is still pending review), we wouldn't
need to deal with symbol versioning for it in GCC 14 or later.
On the other side, on some arches some types are very unlikely to be
supported.  And e.g. _Float128x isn't supported on any arch right now.


A good point.  Incidentally, it seems problematic for embedded users that
all the fundamental type_infos are emitted in the same .o, making it hard to
link in only the ones you care about.  And new floating-point variants add
to that problem.  So perhaps until that is addressed, it's better to avoid
adding a bunch more on targets that don't support them.


Ok, so here is a variant of the patch which still drops the fallback_* stuff,
but for float*_type_node doesn't do the automatic fallback in generic code
and leaves those to a target hook.

So far lightly tested on x86_64-linux -m32/-m64:

2023-03-02  Jakub Jelinek  

PR target/108883
gcc/
* target.h (emit_support_tinfos_callback): New typedef.
* targhooks.h (default_emit_support_tinfos): Declare.
* targhooks.cc (default_emit_support_tinfos): New function.
* target.def (emit_support_tinfos): New target hook.
* doc/tm.texi.in (emit_support_tinfos): Document it.
* doc/tm.texi: Regenerated.
* config/i386/i386.cc (ix86_emit_support_tinfos): New function.
(TARGET_EMIT_SUPPORT_TINFOS): Redefine.
gcc/cp/
* cp-tree.h (enum cp_tree_index): Remove CPTI_FALLBACK_DFLOAT*_TYPE
enumerators.
(fallback_dfloat32_type, fallback_dfloat64_type,
fallback_dfloat128_type): Remove.
* rtti.cc (emit_support_tinfo_1): If not emitted already, call
emit_tinfo_decl and remove from unemitted_tinfo_decls right away.
(emit_support_tinfos): Move &dfloat*_type_node from fundamentals array
into new fundamentals_with_fallback array.  Call emit_support_tinfo_1
on elements of that array too, with the difference that if
the type is NULL, use a fallback REAL_TYPE for it temporarily.
Drop the !targetm.decimal_float_supported_p () handling.  Call
targetm.emit_support_tinfos at the end.
* mangle.cc (write_builtin_type): Remove references to
fallback_dfloat*_type.  Handle bfloat16_type_node mangling.

--- gcc/target.h.jj 2023-02-17 12:45:08.056638510 +0100
+++ gcc/target.h2023-03-02 12:06:59.248146213 +0100
@@ -260,6 +260,8 @@ enum poly_value_estimate_kind
POLY_VALUE_LIKELY
  };
  
+typedef void (*emit_support_tinfos_callback) (tree);

+
  extern bool verify_type_context (location_t, type_context_kind, const_tree,
 bool = false);
  
--- gcc/targhooks.h.jj	2023-01-02 09:32:50.422880177 +0100

+++ gcc/targhooks.h 2023-03-02 12:06:22.559686384 +0100
@@ -98,6 +98,8 @@ extern int default_builtin_vectorization
  
  extern tree default_builtin_reciprocal (tree);
  
+extern void default_emit_support_tinfos (emit_support_tinfos_callback);

+
  extern HOST_WIDE_INT default_static_rtx_alignment (machine_mode);
  extern HOST_WIDE_INT default_constant_alignment (const_tree, HOST_WIDE_INT);
  extern HOST_WIDE_INT constant_alignment_word_strings (const_tree,
--- gcc/targhooks.cc.jj 2023-01-02 09:32:52.591848839 +0100
+++ gcc/targhooks.cc2023-03-02 12:01:39.576868114 +0100
@@ -752,6 +752,11 @@ default_builtin_reciprocal (tree)
return NULL_TREE;
  }
  
+void

+default_emit_support_tinfos (emit_support_tinfos_callback)
+{
+}
+
  bool
  hook_bool_CUMULATIVE_ARGS_arg_info_false (cumulative_args_t,
  const function_arg_info &)
--- gcc/target.def.jj   2023-02-22 15:58:50.252996452 +0100
+++ gcc/target.def  2023-03-02 12:01:52.002684436 +0100
@@ -2606,6 +2606,19 @@ types.",
   const char *, (const_tree type),
   hook_constcharptr_const_tree_null)
  
+/* Temporarily add conditional target specific types for the purpose of

+   emitting C++ fundamental type tinfos.  */
+DEFHOOK
+(emit_support_tinfos,
+ "If your target defines any fundamental types which depend on ISA flags,\n\
+they might need C++ tinfo symbols in libsupc++/libstdc++ regardless of\n\
+ISA flags the library is compiled with.\n\
+This hook allows creating tinfo symbols even for those cases, by temporarily\n\
+creating corresponding fundamental type trees, calling the @var{callback}\n\


"each corresponding fundamental type tree"?

OK with that change.


+function on it and setting the type back to @code{nullptr}.",
+ void, (emit_support_tinfos_callback callback),
+ default_emit_support_tinfos)
+
  /* Make any adjustments to libfunc names n

Re: [PATCH] c++: ICE with -Wmismatched-tags and member template [PR106259]

2023-03-02 Thread Jason Merrill via Gcc-patches

On 3/1/23 17:33, Marek Polacek wrote:

On Wed, Mar 01, 2023 at 04:44:12PM -0500, Jason Merrill wrote:

On 3/1/23 16:40, Marek Polacek wrote:

On Wed, Mar 01, 2023 at 04:30:16PM -0500, Jason Merrill wrote:

On 3/1/23 15:33, Marek Polacek wrote:

-Wmismatched-tags warns about the (harmless) struct/class mismatch.
For, e.g.,

 template struct A { };
 class A a;

it works by adding A to the class2loc hash table while parsing the
class-head and then, while parsing the elaborate type-specifier, we
add A.  At the end of c_parse_file we go through the table and
warn about the class-key mismatches.  In this PR we crash though; we
have

 template struct A {
   template struct W { };
 };
 struct A::W w; // #1

where while parsing A and #1 we've stashed
  A
  A::W
  A::W
into class2loc.  Then in class_decl_loc_t::diag_mismatched_tags TYPE
is A::W, and specialization_of gets us A::W, which
is not in class2loc, so we crash on gcc_assert (cdlguide).  But it's
OK not to have found A::W, we should just look one "level" up,
that is, A::W.

It's important to handle class specializations, so e.g.

 template<>
 struct A {
   template
   class W { };
 };

where W's class-key is different than in the primary template above,
so we should warn depending on whether we're looking into A
or into a different instantiation.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/106259

gcc/cp/ChangeLog:

* parser.cc (class_decl_loc_t::diag_mismatched_tags): If the first
lookup of SPEC didn't find anything, try to look for
most_general_template.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wmismatched-tags-11.C: New test.
---
gcc/cp/parser.cc  | 30 +++
.../g++.dg/warn/Wmismatched-tags-11.C | 23 ++
2 files changed, 47 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-11.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 1a124f5395e..b528ee7b1d9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -34473,14 +34473,32 @@ class_decl_loc_t::diag_mismatched_tags (tree 
type_decl)
 be (and inevitably is) at index zero.  */
  tree spec = specialization_of (type);
  cdlguide = class2loc.get (spec);
+  /* It's possible that we didn't find SPEC.  Consider:
+
+  template struct A {
+template struct W { };
+  };
+  struct A::W w; // #1
+
+where while parsing A and #1 we've stashed
+  A
+  A::W
+  A::W
+into CLASS2LOC.  If TYPE is A::W, specialization_of
+will yield A::W which may be in CLASS2LOC if we had
+an A class specialization, but otherwise won't be in it.
+So try to look up A::W.  */
+  if (!cdlguide)
+   {
+ spec = DECL_TEMPLATE_RESULT (most_general_template (spec));


Would it make sense to only look at most_general_template, not A::W
at all?


I think that would break with class specialization, as in...


+template struct A {
+  template
+  struct W { };
+};
+
+template<>
+struct A {
+  template
+  class W { };
+};
+
+void
+g ()
+{
+  struct A::W w1; // { dg-warning "mismatched" }


...this, where we should first look into A, and only if not
found, go to A.


I'd expect the


   /* Stop if we run into an explicitly specialized class template.  */


code in most_general_template to avoid that problem.


Ah, I had no idea it does that.  The unconditional most_general_template
works fine for the new test, but some of the existing tests then fail.
Reduced:

templatestruct S2; // #1
template  class S2; // #2

extern class  S2 s2ci; // #3
extern struct S2 s2ci; // { dg-warning "\\\[-Wmismatched-tags" }

where the unconditional most_general_template changes spec from
"class S2" to "struct S2" (both of which are in class2loc).
So it regresses the diagnostic, complaining that #3 should have "struct"
since #1 has "struct".  I think we want to keep the current diagnostic,
saying that the last line should have "class" since the specialization
in line #2 has "class".


Makes sense, the patch is OK.

Jason



Re: [PATCH] debug/108772 - ICE with late debug generated with -flto

2023-03-02 Thread Jason Merrill via Gcc-patches

On 3/2/23 02:43, Richard Biener wrote:

On Wed, 1 Mar 2023, Jason Merrill wrote:


On 3/1/23 08:09, Jakub Jelinek wrote:

On Wed, Mar 01, 2023 at 01:07:02PM +, Richard Biener wrote:

When combining -g1 with -flto we run into the DIE location annotation
machinery for globals calling dwarf2out_late_global_decl but not
having any early generated DIE for function scope statics.  In
this process we'd generate a limbo DIE since also the function scope
doesn't have any early generated DIE.  The limbo handling then tries
to force a DIE for the context chain which ultimatively fails and
ICEs at the std namespace decl because at -g1 we don't represent that.

The following avoids this situation by making sure to never generate
any limbo DIEs from dwarf2out_late_global_decl in the in_lto_p path
but instead for function scope globals rely on DIE generation for
the function to output a DIE for the local static (which doesn't
happen for -g1).


So the issue is that we're trying to force out a DIE for a decl that we
wouldn't have generated without -flto?  How is it avoided in the non-LTO case?


When we go rest_of_decl_compilation for this decl we defer to the
containing function to generate an early DIE but that doesn't
(because of -g1).  The call to late_global_decl that's done by
assemble_decl then does nothing because there's no early DIE.  But with
-flto we cannot completely rely on early DIE presence (not even without,
in case of cloning - but we don't clone global variables), esp. because
there's still the "supported" non-early-LTO path for non-ELF targets.

So at this point it seems to be the best thing to mimic what
rest_of_decl_compilation does and defer to dwarf2out of the
containing function to generate the DIE (or not).  For the reason
of the least amount of changes at this point in stage4 I went for
querying the DECL_CONTEXT DIE instead of right-out not handling
local_function_static () decls in this path.

If you'd prefer that, so

   if (! die && in_lto_p
   /* Function scope variables are emitted when emitting the
  DIE for the function.  */
   && ! local_function_static (decl))
 dwarf2out_decl (decl);

then I can test that variant as well which feels a bit more
consistent.


That variant is OK, thanks.

Jason



Re: [PATCH] c++: Add target hook for emit_support_tinfos [PR108883]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 2/27/23 18:51, Jakub Jelinek wrote:

On Mon, Feb 27, 2023 at 06:26:04PM -0500, Jason Merrill wrote:

The following patch instead adds a target hook which allows the backend
to temporarily tweak registered types such that emit_support_tinfos
emits whatever is needed.


Why handle these types differently from the DFP handling at the end of
emit_support_tinfos?


One thing is that the fallback_* nodes look like a waste to me,
the tinfo decls are mangled right away, and the fallback_* nodes need to be
walked by GC, so I think we could get away even for the decimal tinfos
to just do:
   dfloat32_type_node = make_node (REAL_TYPE);
   emit_support_tinfo_1 (dfloat32_type_node);
   dfloat32_type_node = NULL_TREE;
etc. and drop the fallback stuff.


I think you're right.


If we wanted to do fallback_* even for the _Float*/decltype(0.0bf16)
nodes, which are at least sometimes mangled in target hooks it would
make stuff harder because fallback_* is C++ FE private.

And then there is a question whether we want to emit rtti for
_Float{16,32,64,128}, _Float{32,64,128}x and decltype(0.0bf16) regardless
of whether the target supports them at all or not.
Emitting them always would have an advantage, if say bfloat16_t support
isn't added for aarch64 for GCC 13 (it is still pending review), we wouldn't
need to deal with symbol versioning for it in GCC 14 or later.
On the other side, on some arches some types are very unlikely to be
supported.  And e.g. _Float128x isn't supported on any arch right now.


A good point.  Incidentally, it seems problematic for embedded users 
that all the fundamental type_infos are emitted in the same .o, making 
it hard to link in only the ones you care about.  And new floating-point 
variants add to that problem.  So perhaps until that is addressed, it's 
better to avoid adding a bunch more on targets that don't support them.


Hmm.


Though, if we can get rid of the fallback_* stuff and we wanted to emit
all _Float{16,32,64,128}, _Float{32,64,128}x and decltype(0.0bf16) tinfos
on all arches (or say for now all but _Float128x), we could do it simply
by splitting the fundamentals array in emit_support_tinfos into
one without fallback and one with fallback, put say
 &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
 &bfloat16_type_node, &float16_type_node, &float32_type_node,
 &float64_type_node, &float128_type_node, &float32x_type_node,
 &float64x_type_node, &float128x_type_node, 0
into the latter and simply handle the NULL case with a temporary fallback,
like:
   tree fallback = NULL_TREE;
   for (ix = 0; fundamentals_with_fallback[ix]; ix++)
 if (*fundamentals_with_fallback[ix])
   emit_support_tinfo_1 (*fundamentals_with_fallback[ix]);
 else
   {
if (fallback == NULL_TREE)
  fallback = make_node (REAL_TYPE);
*fundamentals_with_fallback[ix] = fallback;
emit_support_tinfo_1 (fallback);
*fundamentals_with_fallback[ix] = NULL_TREE;
   }

Jakub





Re: [PATCH v4] c++: -Wdangling-reference with reference wrapper [PR107532]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 2/7/23 11:46, Marek Polacek wrote:

On Sun, Feb 05, 2023 at 05:25:25PM -0800, Jason Merrill wrote:

On 1/24/23 17:49, Marek Polacek wrote:

On Fri, Jan 20, 2023 at 03:19:54PM -0500, Jason Merrill wrote:

On 1/19/23 21:03, Marek Polacek wrote:

On Thu, Jan 19, 2023 at 01:02:02PM -0500, Jason Merrill wrote:

On 1/18/23 20:13, Marek Polacek wrote:

On Wed, Jan 18, 2023 at 04:07:59PM -0500, Jason Merrill wrote:

On 1/18/23 12:52, Marek Polacek wrote:

Here, -Wdangling-reference triggers where it probably shouldn't, causing
some grief.  The code in question uses a reference wrapper with a member
function returning a reference to a subobject of a non-temporary object:

   const Plane & meta = fm.planes().inner();

I've tried a few approaches, e.g., checking that the member function's
return type is the same as the type of the enclosing class (which is
the case for member functions returning *this), but that then breaks
Wdangling-reference4.C with std::optional.

So I figured that perhaps we want to look at the object we're invoking
the member function(s) on and see if that is a temporary, as in, don't
warn about

   const Plane & meta = fm.planes().inner();

but do warn about

   const Plane & meta = FrameMetadata().planes().inner();

It's ugly, but better than asking users to add #pragmas into their code.


Hmm, that doesn't seem right; the former is only OK because Ref is in fact a
reference-like type.  If planes() returned a class that held data, we would
want to warn.


Sure, it's always some kind of tradeoff with warnings :/.

In this case, we might recognize the reference-like class because it has a
reference member and a constructor taking the same reference type.


That occurred to me too, but then I found out that std::reference_wrapper
actually uses T*, not T&, as you say.  But here's a patch to do that
(I hope).

That wouldn't help with std::reference_wrapper or std::ref_view because they
have pointer members instead of references, but perhaps loosening the check
to include that case would make sense?


Sorry, I don't understand what you mean by loosening the check.  I could
hardcode std::reference_wrapper and std::ref_view but I don't think that's
what you meant.


Indeed that's not what I meant, but as I was saying in our meeting I think
it's worth doing; the compiler has various tweaks to handle specific
standard-library classes better.

Okay, done in the patch below.  Except that I'm not including a test for
std::ranges::ref_view because I don't really know how that works.


Surely I cannot _not_ warn for any class that contains a T*.


I was thinking if a constructor takes a T& and the class has a T* that would
be close enough, though this also wouldn't handle the standard library
classes so the benefit is questionable.


Here's the patch so that we have some actual code to discuss...  Thanks.

-- >8 --
Here, -Wdangling-reference triggers where it probably shouldn't, causing
some grief.  The code in question uses a reference wrapper with a member
function returning a reference to a subobject of a non-temporary object:

  const Plane & meta = fm.planes().inner();

I've tried a few approaches, e.g., checking that the member function's
return type is the same as the type of the enclosing class (which is
the case for member functions returning *this), but that then breaks
Wdangling-reference4.C with std::optional.

Perhaps we want to look at the member function's enclosing class
to see if it's a reference wrapper class (meaning, has a reference
member and a constructor taking the same reference type) and don't
warn if so, supposing that the member function returns a reference
to a non-temporary object.

It's ugly, but better than asking users to add #pragmas into their code.

PR c++/107532

gcc/cp/ChangeLog:

* call.cc (do_warn_dangling_reference): Don't warn when the
member function comes from a reference wrapper class.


Let's factor the new code out into e.g. reference_like_class_p


Done.  Thanks,

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here, -Wdangling-reference triggers where it probably shouldn't, causing
some grief.  The code in question uses a reference wrapper with a member
function returning a reference to a subobject of a non-temporary object:

 const Plane & meta = fm.planes().inner();

I've tried a few approaches, e.g., checking that the member function's
return type is the same as the type of the enclosing class (which is
the case for member functions returning *this), but that then breaks
Wdangling-reference4.C with std::optional.

Perhaps we want to look at the member function's enclosing class
to see if it's a reference wrapper class (meaning, has a reference
member and a constructor taking the same reference type, or is
std::reference_wrapper or std::ranges::ref_view) and don't warn if so,
supposing that the member function returns a reference to a non-temporary
object.

It's ugly, but better than askin

Re: [PATCH] c++: ICE with -Wmismatched-tags and member template [PR106259]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/23 16:40, Marek Polacek wrote:

On Wed, Mar 01, 2023 at 04:30:16PM -0500, Jason Merrill wrote:

On 3/1/23 15:33, Marek Polacek wrote:

-Wmismatched-tags warns about the (harmless) struct/class mismatch.
For, e.g.,

template struct A { };
class A a;

it works by adding A to the class2loc hash table while parsing the
class-head and then, while parsing the elaborate type-specifier, we
add A.  At the end of c_parse_file we go through the table and
warn about the class-key mismatches.  In this PR we crash though; we
have

template struct A {
  template struct W { };
};
struct A::W w; // #1

where while parsing A and #1 we've stashed
 A
 A::W
 A::W
into class2loc.  Then in class_decl_loc_t::diag_mismatched_tags TYPE
is A::W, and specialization_of gets us A::W, which
is not in class2loc, so we crash on gcc_assert (cdlguide).  But it's
OK not to have found A::W, we should just look one "level" up,
that is, A::W.

It's important to handle class specializations, so e.g.

template<>
struct A {
  template
  class W { };
};

where W's class-key is different than in the primary template above,
so we should warn depending on whether we're looking into A
or into a different instantiation.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/106259

gcc/cp/ChangeLog:

* parser.cc (class_decl_loc_t::diag_mismatched_tags): If the first
lookup of SPEC didn't find anything, try to look for
most_general_template.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wmismatched-tags-11.C: New test.
---
   gcc/cp/parser.cc  | 30 +++
   .../g++.dg/warn/Wmismatched-tags-11.C | 23 ++
   2 files changed, 47 insertions(+), 6 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-11.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 1a124f5395e..b528ee7b1d9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -34473,14 +34473,32 @@ class_decl_loc_t::diag_mismatched_tags (tree 
type_decl)
 be (and inevitably is) at index zero.  */
 tree spec = specialization_of (type);
 cdlguide = class2loc.get (spec);
+  /* It's possible that we didn't find SPEC.  Consider:
+
+  template struct A {
+template struct W { };
+  };
+  struct A::W w; // #1
+
+where while parsing A and #1 we've stashed
+  A
+  A::W
+  A::W
+into CLASS2LOC.  If TYPE is A::W, specialization_of
+will yield A::W which may be in CLASS2LOC if we had
+an A class specialization, but otherwise won't be in it.
+So try to look up A::W.  */
+  if (!cdlguide)
+   {
+ spec = DECL_TEMPLATE_RESULT (most_general_template (spec));


Would it make sense to only look at most_general_template, not A::W
at all?


I think that would break with class specialization, as in...


+template struct A {
+  template
+  struct W { };
+};
+
+template<>
+struct A {
+  template
+  class W { };
+};
+
+void
+g ()
+{
+  struct A::W w1; // { dg-warning "mismatched" }


...this, where we should first look into A, and only if not
found, go to A.


I'd expect the


  /* Stop if we run into an explicitly specialized class template.  */


code in most_general_template to avoid that problem.

Jason



Re: [PATCH 1/2] c++: factor out TYPENAME_TYPE substitution

2023-03-01 Thread Jason Merrill via Gcc-patches

On 2/21/23 19:05, Patrick Palka wrote:

On Sun, 19 Feb 2023, Jason Merrill wrote:


On 2/15/23 12:11, Patrick Palka wrote:

On Wed, 15 Feb 2023, Jason Merrill wrote:


On 2/15/23 09:21, Patrick Palka wrote:

On Tue, 14 Feb 2023, Jason Merrill wrote:


On 2/13/23 09:23, Patrick Palka wrote:

[N.B. this is a corrected version of
https://gcc.gnu.org/pipermail/gcc-patches/2022-November/607443.html
]

This patch factors out the TYPENAME_TYPE case of tsubst into a
separate
function tsubst_typename_type.  It also factors out the two tsubst
flags
controlling TYPENAME_TYPE substitution, tf_keep_type_decl and
tf_tst_ok,
into distinct boolean parameters of this new function (and of
make_typename_type).  Consequently, callers which used to pass
tf_tst_ok
to tsubst now instead must directly call tsubst_typename_type when
appropriate.


Hmm, I don't love how that turns 4 lines into 8 more complex lines in
each
caller.  And the previous approach of saying "a CTAD placeholder is
OK"
seem
like better abstraction than repeating the specific TYPENAME_TYPE
handling
in
each place.


Ah yeah, I see what you mean.  I was thinking since tf_tst_ok is
specific to TYPENAME_TYPE handling and isn't propagated (i.e. it only
affects top-level TYPENAME_TYPEs), it seemed cleaner to encode the flag
as a bool parameter "template_ok" of tsubst_typename_type instead of as
a global tsubst_flag that gets propagated freely.




In a subsequent patch we'll add another flag to
tsubst_typename_type controlling whether we want to ignore non-types
during the qualified lookup.


As mentioned above, the second patch in this series would just add
another flag "type_only" alongside "template_ok", since this flag will
also only affects top-level TYPENAME_TYPEs and doesn't need to propagate
like tsubst_flags.

Except, it turns it, this new flag _does_ need to propagate, namely when
expanding a variadic using:

 using typename Ts::type::m...; // from typename25a.C below

Here we have a USING_DECL whose USING_DECL_SCOPE is a
TYPE_PACK_EXPANSION over TYPENAME_TYPE.  In order to correctly
substitute this TYPENAME_TYPE, the USING_DECL case of tsubst_decl needs
to pass an appropriate tsubst_flag to tsubst_pack_expansion to be
propagated to tsubst (to be propagated to make_typename_type).

So in light of this case it seems adding a new tsubst_flag is the
way to go, which means we can avoid this refactoring patch entirely.

Like so?  Bootstrapped and regtested on x86_64-pc-linux-gnu.


OK, though I still wonder about adding a tsubst_scope function that would
add
the tf_qualifying_scope.


Hmm, but we need to add tf_qualifying_scope to two tsubst_copy calls,
one tsubst call and one tsubst_aggr_type call (with entering_scope=true).
Would tsubst_scope call tsubst, tsubst_copy or tsubst_aggr_type?


In general it would call tsubst.

It's odd that anything is calling tsubst_copy with a type, that seems like a
copy/paste error.  But it just hands off to tsubst anyway, so the effect is
the same.


Ah, makes sense.  And if we make tsubst_copy hand off to tsubst
immediately for TYPE_P trees we can make tsubst_copy oblivious to the
tf_qualifying_scope flag.  I experimented with going a step further and
fixing callers that pass a type to tsubst_copy, but that sort of clean
up might be in vain given that we might be getting rid of tsubst_copy
in the next stage 1.



tsubst_aggr_type is needed when pushing into the scope of a declarator; I
don't know offhand why we would need that when substituting the scope of a
TYPENAME_TYPE.


Apparently if we don't do entering_scope=true here then it breaks

   g++.dg/template/friend61.C
   g++.dg/template/memfriend12.C
   g++.dg/template/memfriend17.C

I think it's because without entering_scope=true, dependent substitution
yields a dependent specialization A instead of the primary template
type A, but we need the latter to perform qualified name lookup from
such a substituted dependent scope.  I left that call alone for now.

How does this look?  Bootstrapped and regtested on x86_64-pc-linux-gnu.


OK.


-- >8 --

Subject: [PATCH] c++: clean up tf_qualifying_scope usage

This patch introduces a convenience wrapper tsubst_scope for tsubst'ing
into a type with tf_qualifying_scope set, and makes suitable callers use
it instead of explicitly setting tf_qualifying_scope.  This also makes
tsubst_copy immediately delegate to tsubst for all type trees, which
allows tsubst_copy to be oblivious to the tf_qualifying_scope flag.

gcc/cp/ChangeLog:

* pt.cc (tsubst_scope): Define.
(tsubst_decl) : Call tsubst_scope instead of
calling tsubst_scope with tf_qualifying_scope set.
(tsubst_qualified_id): Call tsubst_scope instead of
calling tsubst with tf_qualifying_scope set.
(tsubst_copy): Immediately delegate to tsubst for all TYPE_P
trees.  Remove tf_qualifying_scope manipulation.
: Call tsubst_scope instead of calling
tsubst with tf_qualifying_scope set.
---
  gcc/cp/pt.cc | 4

Re: [PATCH] c++: ICE with -Wmismatched-tags and member template [PR106259]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/23 15:33, Marek Polacek wrote:

-Wmismatched-tags warns about the (harmless) struct/class mismatch.
For, e.g.,

   template struct A { };
   class A a;

it works by adding A to the class2loc hash table while parsing the
class-head and then, while parsing the elaborate type-specifier, we
add A.  At the end of c_parse_file we go through the table and
warn about the class-key mismatches.  In this PR we crash though; we
have

   template struct A {
 template struct W { };
   };
   struct A::W w; // #1

where while parsing A and #1 we've stashed
A
A::W
A::W
into class2loc.  Then in class_decl_loc_t::diag_mismatched_tags TYPE
is A::W, and specialization_of gets us A::W, which
is not in class2loc, so we crash on gcc_assert (cdlguide).  But it's
OK not to have found A::W, we should just look one "level" up,
that is, A::W.

It's important to handle class specializations, so e.g.

   template<>
   struct A {
 template
 class W { };
   };

where W's class-key is different than in the primary template above,
so we should warn depending on whether we're looking into A
or into a different instantiation.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/106259

gcc/cp/ChangeLog:

* parser.cc (class_decl_loc_t::diag_mismatched_tags): If the first
lookup of SPEC didn't find anything, try to look for
most_general_template.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wmismatched-tags-11.C: New test.
---
  gcc/cp/parser.cc  | 30 +++
  .../g++.dg/warn/Wmismatched-tags-11.C | 23 ++
  2 files changed, 47 insertions(+), 6 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-11.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 1a124f5395e..b528ee7b1d9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -34473,14 +34473,32 @@ class_decl_loc_t::diag_mismatched_tags (tree 
type_decl)
 be (and inevitably is) at index zero.  */
tree spec = specialization_of (type);
cdlguide = class2loc.get (spec);
+  /* It's possible that we didn't find SPEC.  Consider:
+
+  template struct A {
+template struct W { };
+  };
+  struct A::W w; // #1
+
+where while parsing A and #1 we've stashed
+  A
+  A::W
+  A::W
+into CLASS2LOC.  If TYPE is A::W, specialization_of
+will yield A::W which may be in CLASS2LOC if we had
+an A class specialization, but otherwise won't be in it.
+So try to look up A::W.  */
+  if (!cdlguide)
+   {
+ spec = DECL_TEMPLATE_RESULT (most_general_template (spec));


Would it make sense to only look at most_general_template, not 
A::W at all?



+ cdlguide = class2loc.get (spec);
+   }
+  /* Now we really should have found something.  */
gcc_assert (cdlguide != NULL);
  }
-  else
-{
-  /* Skip declarations that consistently use the same class-key.  */
-  if (def_class_key != none_type)
-   return;
-}
+  /* Skip declarations that consistently use the same class-key.  */
+  else if (def_class_key != none_type)
+return;
  
/* Set if a definition for the class has been seen.  */

const bool def_p = cdlguide->def_p ();
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-11.C 
b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-11.C
new file mode 100644
index 000..6c4e571726a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-11.C
@@ -0,0 +1,23 @@
+// PR c++/106259
+// { dg-do compile }
+// { dg-options "-Wmismatched-tags" }
+
+template struct A {
+  template
+  struct W { };
+};
+
+template<>
+struct A {
+  template
+  class W { };
+};
+
+void
+g ()
+{
+  struct A::W w1; // { dg-warning "mismatched" }
+  struct A::W w2;
+  class A::W w3;
+  class A::W w4; // { dg-warning "mismatched" }
+}

base-commit: 096f034a8f5df41f610e62c1592fb90a3f551cd5




Re: [PATCH] c++: can't eval PTRMEM_CST in incomplete class [PR107574]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 2/2/23 19:28, Marek Polacek wrote:

Here we're attempting to evaluate a PTRMEM_CST in a class that hasn't
been completed yet, but that doesn't work:

 /* We can't lower this until the class is complete.  */
 if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
   return cst;

and then this unlowered PTRMEM_CST is used as EXPR in

 tree op1 = build_nop (ptrdiff_type_node, expr);

and we crash in a subsequent cp_fold_convert which gets type=ptrdiff_type_node,
expr=PTRMEM_CST and does

   else if (TREE_CODE (expr) == PTRMEM_CST
&& same_type_p (TYPE_PTRMEM_CLASS_TYPE (type),
PTRMEM_CST_CLASS (expr)))

where TYPE_PTRMEM_CLASS_TYPE (type) is going to crash since the type
is ptrdiff_type_node.  We could just add a TYPE_PTRMEM_P check before
accessing TYPE_PTRMEM_CLASS_TYPE but I think it's nicer to explain why
we couldn't evaluate the expression.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/107574

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_constant_expression): Emit an error when
a PTRMEM_CST cannot be evaluated.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/ptrmem-cst1.C: New test.
---
  gcc/cp/constexpr.cc  |  9 +
  gcc/testsuite/g++.dg/cpp0x/ptrmem-cst1.C | 11 +++
  2 files changed, 20 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/ptrmem-cst1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 5b31f9c27d1..2c03988b097 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -7691,6 +7691,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE 
(op))
&& !can_convert_qual (type, op))
  op = cplus_expand_constant (op);
+   if (TREE_CODE (op) == PTRMEM_CST && !TYPE_PTRMEM_P (type))
+ {
+   if (!ctx->quiet)
+ error_at (loc, "%qE is not a constant expression when the "
+   "class %qT is still incomplete", op,
+   PTRMEM_CST_CLASS (op));
+   *non_constant_p = true;
+   return t;
+ }


Hmm, maybe handle this a few lines higher, in this existing if:


if (TREE_CODE (op) == PTRMEM_CST && !TYPE_PTRMEM_P (type))
  op = cplus_expand_constant (op);


?  OK with that change.



Re: [PATCH] debug/108772 - ICE with late debug generated with -flto

2023-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/23 08:09, Jakub Jelinek wrote:

On Wed, Mar 01, 2023 at 01:07:02PM +, Richard Biener wrote:

When combining -g1 with -flto we run into the DIE location annotation
machinery for globals calling dwarf2out_late_global_decl but not
having any early generated DIE for function scope statics.  In
this process we'd generate a limbo DIE since also the function scope
doesn't have any early generated DIE.  The limbo handling then tries
to force a DIE for the context chain which ultimatively fails and
ICEs at the std namespace decl because at -g1 we don't represent that.

The following avoids this situation by making sure to never generate
any limbo DIEs from dwarf2out_late_global_decl in the in_lto_p path
but instead for function scope globals rely on DIE generation for
the function to output a DIE for the local static (which doesn't
happen for -g1).


So the issue is that we're trying to force out a DIE for a decl that we 
wouldn't have generated without -flto?  How is it avoided in the non-LTO 
case?



I explored a lot of other options to fix this but in the end this
seems to be the most spot-on fix with the least risk of unwanted
effects.

LTO bootstrapped on x86_64-unknown-linux-gnu (running into PR108984),
bootstrapped and tested on x86_64-unknown-linux-gnu.

OK?

Thanks,
Richard.

PR debug/108772
* dwarf2out.cc (dwarf2out_late_global_decl): Do not
generate a DIE for a function scope static when we do
not have a DIE for the function already.

* g++.dg/lto/pr108772_0.C: New testcase.


LGTM, but please give Jason a day to chime in if he disagrees.

Jakub





Re: [PATCH] c++: unevaluated array new-expr size constantness [PR108219]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/23 12:20, Patrick Palka wrote:

On Wed, 1 Mar 2023, Jason Merrill wrote:


On 3/1/23 10:32, Patrick Palka wrote:

On Mon, 27 Feb 2023, Jason Merrill wrote:


On 2/22/23 14:45, Patrick Palka wrote:

Here we're mishandling the unevaluated array new-expressions due to a
supposed non-constant array size ever since r12-5253-g4df7f8c79835d569,
made us no longer perform constant evaluation of non-manifestly-constant
expressions within unevaluated contexts.  This shouldn't make a
difference here since the array sizes are constant literals, except
they're actually NON_LVALUE_EXPR location wrappers wrapping INTEGER_CST,
wrappers which used to get stripped as part of constant evaluation and
now no longer do.  Moreover it means build_vec_init can't constant fold
the 'maxindex' passed from build_new_1 (since it uses
maybe_constant_value
with mce_unknown).


Hmm, now that you mention it I think the

if (manifestly_const_eval != mce_unknown)

change in maybe_constant_value isn't quite right, we don't want to force
evaluation in unevaluated mce_false context either.


Ah, makes sense.  Fixed in the below patch.




This patch fixes the first issue by making maybe_constant_value and
fold_non_dependent_expr_template shortcut handling location wrappers
around constant nodes, and the second issue by using fold_build2_loc
instead of cp_build_binary_op when computing the maxindex to pass to
build_vec_init.


Maybe in unevaluated mce_unknown/false context maybe_constant_value should
call fold?


That seems like a good compromise between proper constant evaluation
and not constant evaluating at all, though I wonder how 'fold' behaves
w.r.t. to undefined behavior such as division by zero and signed overflow?


'fold' doesn't fold division by zero, but I think we should only return the
result of 'fold' at this point if it is in fact constant, not if it's a
non-constant simplification.


Sounds good, I wasn't sure if 'fold' could return a non-constant
simplification.


Yep, it also folds e.g. x*1 to x.


I suppose we want to be pretty conservative with the
constantness test, so I went with CONSTANT_CLASS_P && !TREE_OVERFLOW.


Makes sense.


Like so?  Smoke tested so far, bootstrap and regtest on
x86_64-pc-linu-xgnu in progress.

-- >8 --

Subject: [PATCH] c++: unevaluated array new-expr size constantness [PR108219]

Here we're mishandling the unevaluated array new-expressions due to a
supposed non-constant array size ever since r12-5253-g4df7f8c79835d569
made us no longer perform constant evaluation of non-manifestly-constant
expressions within unevaluated contexts.  This shouldn't make a
difference here since the array sizes are constant literals, except
these sizes are expressed as NON_LVALUE_EXPR location wrappers around
INTEGER_CST, wrappers which used to get stripped as part of constant
evaluation and now no longer do.  Moreover it means build_vec_init can't
constant fold the 'maxindex' passed from build_new_1 (since it uses
maybe_constant_value with mce_unknown).

This patch fixes this by making maybe_constant_value and
fold_non_dependent_expr at least try folding simple unevaluated operands
via fold(), which will evaluate simple arithmetic, look through location
wrappers, perform integral conversions, etc.

Co-authored-by: Jason Merrill 

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?

PR c++/108219
PR c++/108218

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_value): Move up early exit
test for unevaluated operands.  Try reducing an unevaluated
operand to a constant via fold.
(fold_non_dependent_expr_template): Add early exit test for
CONSTANT_CLASS_P nodes.  Try reducing an unevaluated operand
to a constant via fold.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/new6.C: New test.
* g++.dg/cpp2a/concepts-new1.C: New test.
---
  gcc/cp/constexpr.cc| 23 +-
  gcc/testsuite/g++.dg/cpp0x/new6.C  | 13 
  gcc/testsuite/g++.dg/cpp2a/concepts-new1.C | 13 
  3 files changed, 44 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/new6.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-new1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index b4d3e95bbd5..324968050ba 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8523,6 +8523,14 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE 
*/,
  /* No caching or evaluation needed.  */
  return t;
  
+  /* Don't constant evaluate an unevaluated non-manifestly-constant operand,

+ but at least try folding simple expressions to a constant.  */
+  if (cp_unevaluated_operand && manifestly_const_eval != mce_true)
+{
+  tree r = fold (t);
+  return CONSTANT_CLASS_P (r) && !TREE_OVERFLOW (r) ? r : t;
+}
+
if (manifestly_const_eval != mce_unknown)
  return cxx_eval_outermost_constant_expr (t, true, true

Re: [PATCH] c++: unevaluated array new-expr size constantness [PR108219]

2023-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/23 10:32, Patrick Palka wrote:

On Mon, 27 Feb 2023, Jason Merrill wrote:


On 2/22/23 14:45, Patrick Palka wrote:

Here we're mishandling the unevaluated array new-expressions due to a
supposed non-constant array size ever since r12-5253-g4df7f8c79835d569,
made us no longer perform constant evaluation of non-manifestly-constant
expressions within unevaluated contexts.  This shouldn't make a
difference here since the array sizes are constant literals, except
they're actually NON_LVALUE_EXPR location wrappers wrapping INTEGER_CST,
wrappers which used to get stripped as part of constant evaluation and
now no longer do.  Moreover it means build_vec_init can't constant fold
the 'maxindex' passed from build_new_1 (since it uses maybe_constant_value
with mce_unknown).


Hmm, now that you mention it I think the

   if (manifestly_const_eval != mce_unknown)

change in maybe_constant_value isn't quite right, we don't want to force
evaluation in unevaluated mce_false context either.


Ah, makes sense.  Fixed in the below patch.




This patch fixes the first issue by making maybe_constant_value and
fold_non_dependent_expr_template shortcut handling location wrappers
around constant nodes, and the second issue by using fold_build2_loc
instead of cp_build_binary_op when computing the maxindex to pass to
build_vec_init.


Maybe in unevaluated mce_unknown/false context maybe_constant_value should
call fold?


That seems like a good compromise between proper constant evaluation
and not constant evaluating at all, though I wonder how 'fold' behaves
w.r.t. to undefined behavior such as division by zero and signed overflow?


'fold' doesn't fold division by zero, but I think we should only return 
the result of 'fold' at this point if it is in fact constant, not if 
it's a non-constant simplification.



IIUC proper constant evaluation treats UB as non-constant, so it might
be potentially problematic if 'fold' instea dtakes advantage of UB.  Or
maybe since we're in an unevaluated context it doesn't matter?

-- >8 --

Subject: [PATCH] c++: unevaluated array new-expr size constantness [PR108219]

Here we're mishandling the unevaluated array new-expressions due to a
supposed non-constant array size ever since r12-5253-g4df7f8c79835d569
made us no longer perform constant evaluation of non-manifestly-constant
expressions within unevaluated contexts.  This shouldn't make a
difference here since the array sizes are constant literals, except
these sizes are expressed as NON_LVALUE_EXPR location wrappers around
INTEGER_CST, wrappers which used to get stripped as part of constant
evaluation and now no longer do.  Moreover it means build_vec_init can't
constant fold the 'maxindex' passed from build_new_1 (since it uses
maybe_constant_value with mce_unknown).

This patch fixes this by making maybe_constant_value and
fold_non_dependent_expr at least try folding simple unevaluated operands
via fold(), which will evaluate simple arithmetic, look through location
wrappers, perform integral conversions, etc.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?

PR c++/108219
PR c++/108218

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_value): Move up early exit
test for unevaluated operands.  Call fold on unevaluated
operands.
(fold_non_dependent_expr_template): Add early exit test for
CONSTANT_CLASS_P nodes.  Call fold on unevaluated operands.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/new6.C: New test.
* g++.dg/cpp2a/concepts-new1.C: New test.
---
  gcc/cp/constexpr.cc| 17 -
  gcc/testsuite/g++.dg/cpp0x/new6.C  | 13 +
  gcc/testsuite/g++.dg/cpp2a/concepts-new1.C | 13 +
  3 files changed, 38 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/new6.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-new1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index b4d3e95bbd5..d71abe6beed 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8523,6 +8523,11 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE 
*/,
  /* No caching or evaluation needed.  */
  return t;
  
+  /* Don't constant evaluate an unevaluated non-manifestly-constant operand,

+ but at least try folding simple expressions.  */
+  if (cp_unevaluated_operand && manifestly_const_eval != mce_true)
+return fold (t);
+
if (manifestly_const_eval != mce_unknown)
  return cxx_eval_outermost_constant_expr (t, true, true,
 manifestly_const_eval, false, 
decl);
@@ -8544,10 +8549,6 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE 
*/,
return r;
  }
  
-  /* Don't evaluate an unevaluated operand.  */

-  if (cp_unevaluated_operand)
-return t;
-
uid_sensitive_constexpr_evaluation_checker c;
r = cxx_eval_outermost_constant_expr (t, true, true,
   

Re: [PATCH] c++: Don't recurse on DECL_INITIAL for DECL_EXPR on non-VAR_DECLs [PR108606]

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

On 2/22/23 04:06, Jakub Jelinek wrote:

Hi!

The r13-2965-g73d9b0e5947e16 change changed the line touched in this patch
from
   return RECUR (tmp, want_rval);
to
   return RECUR (DECL_INITIAL (tmp), want_rval);
This is on DECL_EXPR handling code, where tmp can be lots of different
trees and DECL_INITIAL unfortunately also means different things on
different trees.
It is the initializer on VAR_DECL, DECL_ARG_TYPE on PARM_DECLs (though
those are unlikely to have DECL_EXPRs), for FUNCTION_DECLs the body,
..., USING_DECL_DECLS on USING_DECLs and DECL_FRIENDLIST on TYPE_DECLs.

The testcase below ICEs because we have a DECL_EXPR for TYPE_DECL
which has non-NULL DECL_FRIENDLIST and we certainly can't recurse on
the friend list.

The following patch is a conditional partial reversion of r13-2965,
it will recurse on DECL_INITIAL only for VAR_DECLs and for anything
else keep previous behavior.


Hmm, we can probably just return true for non-VAR_DECLs.  OK either way.


Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-02-22  Jakub Jelinek  

PR c++/108606
* constexpr.cc (potential_constant_expression_1) :
Only recurse on DECL_INITIAL (tmp) if tmp is a VAR_DECL, otherwise
recurse on tmp.

* g++.dg/cpp1y/pr108606.C: New test.

--- gcc/cp/constexpr.cc.jj  2023-02-20 22:06:36.0 +0100
+++ gcc/cp/constexpr.cc 2023-02-21 14:40:39.366910531 +0100
@@ -9699,7 +9699,9 @@ potential_constant_expression_1 (tree t,
   (tmp, /*constexpr_context_p=*/true, flags))
return false;
}
-  return RECUR (DECL_INITIAL (tmp), want_rval);
+  if (VAR_P (tmp))
+   return RECUR (DECL_INITIAL (tmp), want_rval);
+  return RECUR (tmp, want_rval);
  
  case TRY_FINALLY_EXPR:

return (RECUR (TREE_OPERAND (t, 0), want_rval)
--- gcc/testsuite/g++.dg/cpp1y/pr108606.C.jj2023-02-21 14:44:41.292380973 
+0100
+++ gcc/testsuite/g++.dg/cpp1y/pr108606.C   2023-02-21 14:44:15.622755459 
+0100
@@ -0,0 +1,11 @@
+// PR c++/108606
+// { dg-do compile { target c++14 } }
+
+template 
+void bar (T) {}
+
+void
+foo ()
+{
+  bar ([&] (auto x) { class C { friend void baz (); }; });
+}

Jakub





Re: [PATCH] [vxworks] make wint_t and wchar_t the same distinct type

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

On 2/22/23 10:23, Alexandre Oliva wrote:

Hello, Jason,

On Feb 17, 2023, Jason Merrill  wrote:


On 2/17/23 23:04, Alexandre Oliva wrote:


We used to define WINT_TYPE to WCHAR_TYPE, so that both wint_t and
wchar_t mapped to the same underlying type, but this caused a glitch
in Wstringop-overflow-6.C: on vxworks, wint_t is typedef'ed to
wchar_t



And fixing that isn't an option?


Erhm, why do you say "fixing"?  That implies it's broken, but I don't
see anything in the C++ standards, or in the relevant bits that it
imports from the C standards, that rules out using wint_t = wchar_t in
C++.  wint_t is imported from the C standard as an integral type that
meets certain requirements, and AFAICT in C++ wchar_t is an integral
type that meets those requirements.  Am I missing something?


Now, could it be changed so that wint_t is wchar_t's underlying type
rather than wchar_t?  If the equivalence is a compliance error, we could
file a bug report with WRS and request them to fix it, but modifying
their system headers would require a copyright license they don't grant,
so we avoid doing that.  I imagine that breaking this equivalence would
have ABI implications, and even break legitimate (though unportable)
programs because of overload, specializations and whatnot, so there
would have to be very strong reasons to support a request for such a
change.


Do the integer builtins work properly if we force them to use wchar_t
instead of an integer type?


I haven't observed any regressions, I don't see any builtin functions
with wint in their signature that we even expand as builtins, and my
imagination is failing me on why an integral type such as wchar_t would
fail for wint_t, where other integral types, including wchar_t's
underlying type, would work.  Did you have any specific risks in mind
about what could go wrong?


Sorry, I think I was mostly confusing myself about how distinct wchar_t 
really is.


The patch is OK.

Jason



Re: [PATCH] Accept pmf-vbit-in-delta extra warning

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

On 2/22/23 11:03, Alexandre Oliva wrote:

On Feb 17, 2023, Jason Merrill  wrote:


On 2/17/23 23:02, Alexandre Oliva wrote:


cp_build_binary_op, that issues -Waddress warnings, issues an extra
warning on arm targets, that g++.dg/warn/Waddress-5.C does not expect
when comparing a pointer-to-member-function literal with null.

The reason for the extra warning is that, on arm targets,
TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta, which
causes a different path to be taken, that extracts the
pointer-to-function and the delta fields (minus the vbit) and compares
each one with zero.  It's when comparing this pointer-to-function with
zero, in a recursive cp_build_binary_op, that another warning is
issued.

I suppose there should be a way to skip the warning in this recursive
call, without disabling other warnings that might be issued there, but



warning_sentinel ws (warn_address)


Oh, yeah, that will suppress the expected warning for pfn0, but isn't
there any risk whatsoever that it could suppress other -Waddress
warnings for tree operands of pfn0?


There shouldn't be an issue; those operands would have been considered 
for warning when building their subexpressions.



I see the cp_save_expr for side effects, but what if e.g. the pmfn we're
testing is an array element, and the index expression tests another pmfn
against NULL that should be warned about?  Or something else that
wouldn't have TREE_SIDE_EFFECTS, and would thus not go through
cp_save_expr.  Would we then warn for uses of both pfn0 and delta0?


Here's what I'm going to test for these concerns.  Ok to install if it
bootstraps successfully, and my concerns are unfounded?


OK.


[c++] suppress redundant null-addr warn in pfn from pmfn

From: Alexandre Oliva 

When TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta, when
we warn about comparing a pointer-to-member-function with NULL, we
also warn about comparing the pointer-to-function extracted from it
with NULL, which is redundant.  Suppress the redundant warning.


for  gcc/cp/ChangeLog

* typeck.cc (cp_build_binary_op): Suppress redundant warning
for pfn null test in pmfn test with vbit-in-delta.
---
  gcc/cp/typeck.cc |   17 -
  1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 4afb5e4f0d420..d5a3e501d8e91 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -5780,11 +5780,18 @@ cp_build_binary_op (const op_location_t &location,
  
  	  pfn0 = pfn_from_ptrmemfunc (op0);

  delta0 = delta_from_ptrmemfunc (op0);
- e1 = cp_build_binary_op (location,
-  EQ_EXPR,
-  pfn0,
-  build_zero_cst (TREE_TYPE (pfn0)),
-  complain);
+ {
+   /* If we will warn below about a null-address compare
+  involving the orig_op0 ptrmemfunc, we'd likely also
+  warn about the pfn0's null-address compare, and
+  that would be redundant, so suppress it.  */
+   warning_sentinel ws (warn_address);
+   e1 = cp_build_binary_op (location,
+EQ_EXPR,
+pfn0,
+build_zero_cst (TREE_TYPE (pfn0)),
+complain);
+ }
  e2 = cp_build_binary_op (location,
   BIT_AND_EXPR,
   delta0,






Re: [PATCH] c++: unevaluated array new-expr size constantness [PR108219]

2023-02-27 Thread Jason Merrill via Gcc-patches

On 2/22/23 14:45, Patrick Palka wrote:

Here we're mishandling the unevaluated array new-expressions due to a
supposed non-constant array size ever since r12-5253-g4df7f8c79835d569,
made us no longer perform constant evaluation of non-manifestly-constant
expressions within unevaluated contexts.  This shouldn't make a
difference here since the array sizes are constant literals, except
they're actually NON_LVALUE_EXPR location wrappers wrapping INTEGER_CST,
wrappers which used to get stripped as part of constant evaluation and
now no longer do.  Moreover it means build_vec_init can't constant fold
the 'maxindex' passed from build_new_1 (since it uses maybe_constant_value
with mce_unknown).


Hmm, now that you mention it I think the

  if (manifestly_const_eval != mce_unknown)

change in maybe_constant_value isn't quite right, we don't want to force 
evaluation in unevaluated mce_false context either.



This patch fixes the first issue by making maybe_constant_value and
fold_non_dependent_expr_template shortcut handling location wrappers
around constant nodes, and the second issue by using fold_build2_loc
instead of cp_build_binary_op when computing the maxindex to pass to
build_vec_init.


Maybe in unevaluated mce_unknown/false context maybe_constant_value 
should call fold?



Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?

PR c++/108219
PR c++/108218

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_value): Extend the constant node
shortcut to look through location wrappers too.
(fold_non_dependent_expr_template): Mirror the constant node
shortcut from maybe_constant_value.
* init.cc (build_new_1): Use fold_build2_loc instead
of cp_build_binary_op to build a MINUS_EXPR representing the
maximum index.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/new6.C: New test.
* g++.dg/cpp2a/concepts-new1.C: New test.
---
  gcc/cp/constexpr.cc|  8 ++--
  gcc/cp/init.cc | 18 --
  gcc/testsuite/g++.dg/cpp0x/new6.C  |  9 +
  gcc/testsuite/g++.dg/cpp2a/concepts-new1.C | 13 +
  4 files changed, 36 insertions(+), 12 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/new6.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-new1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index aa2c14355f8..d38c4c80415 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8538,9 +8538,9 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
t = mark_non_constant (t);
return t;
  }
-  else if (CONSTANT_CLASS_P (t))
+  else if (CONSTANT_CLASS_OR_WRAPPER_P (t))
  /* No caching or evaluation needed.  */
-return t;
+return tree_strip_any_location_wrapper (t);
  
if (manifestly_const_eval != mce_unknown)

  return cxx_eval_outermost_constant_expr (t, true, true,
@@ -8631,6 +8631,10 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t 
complain,
  return t;
}
  
+  if (CONSTANT_CLASS_OR_WRAPPER_P (t))

+   /* No evaluation needed.  */
+   return tree_strip_any_location_wrapper (t);
+
if (cp_unevaluated_operand && !manifestly_const_eval)
return t;
  
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc

index 705a5b3bdb6..574d2e2586c 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3653,16 +3653,14 @@ build_new_1 (vec **placement, tree type, 
tree nelts,
  error ("parenthesized initializer in array new");
  return error_mark_node;
  }
- init_expr
-   = build_vec_init (data_addr,
- cp_build_binary_op (input_location,
- MINUS_EXPR, outer_nelts,
- integer_one_node,
- complain),
- vecinit,
- explicit_value_init_p,
- /*from_array=*/0,
-  complain);
+ tree maxindex = fold_build2_loc (input_location, MINUS_EXPR,
+  TREE_TYPE (outer_nelts),
+  outer_nelts,
+  build_one_cst (TREE_TYPE
+ (outer_nelts)));
+ init_expr = build_vec_init (data_addr, maxindex, vecinit,
+ explicit_value_init_p, /*from_array=*/0,
+ complain);
}
else
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/new6.C 
b/gcc/testsuite/g++.dg/cpp0x/new6.C
new file mode 100644
index 000..17a669b42d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/new6.C
@@ -0,0 +1,9 @@
+// PR c++/108218
+// { dg-do compile { target c++11 } }
+
+template

Re: [PATCH] c++: Add target hook for emit_support_tinfos [PR108883]

2023-02-27 Thread Jason Merrill via Gcc-patches

On 2/23/23 05:23, Jakub Jelinek wrote:

Hi!

_Float16 and decltype(0.0bf16) types are on x86 supported only with
-msse2.  On x86_64 that is the default, but on ia32 it is not.
We should still emit fundamental type tinfo for those types in
libsupc++.a/libstdc++.*, regardless of whether libsupc++/libstdc++
is compiled with -msse2 or not, as user programs can be compiled
with different ISA flags from libsupc++/libstdc++ and if they
are compiled with -msse2 and use std::float16_t or std::bfloat16_t
and need RTTI for it, it should work out of the box.  Furthermore,
libstdc++ ABI on ia32 shouldn't depend on whether the library
is compiled with -mno-sse or -msse2.

Unfortunately, just hacking up libsupc++ Makefile/configure so that
a single source is compiled with -msse2 isn't appropriate, because
that TU emits also code and the code should be able to run on CPUs
which libstdc++ supports.  We could add [[gnu::attribute ("no-sse2")]]
there perhaps conditionally, but it all gets quite ugly.

The following patch instead adds a target hook which allows the backend
to temporarily tweak registered types such that emit_support_tinfos
emits whatever is needed.


Why handle these types differently from the DFP handling at the end of 
emit_support_tinfos?



Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-02-23  Jakub Jelinek  

PR target/108883
* hooks.h (hook_void_bool): Declare.
* hooks.cc (hook_void_bool): New function.
* target.def (emit_support_tinfos): New target hook.
* doc/tm.texi.in (emit_support_tinfos): Document it.
* doc/tm.texi: Regenerated.
* config/i386/i386.cc (ix86_emit_support_tinfos): New function.
(TARGET_EMIT_SUPPORT_TINFOS): Redefine.

* rtti.cc (emit_support_tinfos): Call targetm.emit_support_tinfos
before and after emit_support_tinfo_1 calls.

--- gcc/hooks.h.jj  2023-01-02 09:32:29.418183667 +0100
+++ gcc/hooks.h 2023-02-22 12:34:32.144973558 +0100
@@ -77,6 +77,7 @@ extern bool hook_bool_wint_wint_uint_boo
unsigned int, bool);
  
  extern void hook_void_void (void);

+extern void hook_void_bool (bool);
  extern void hook_void_constcharptr (const char *);
  extern void hook_void_rtx_insn_int (rtx_insn *, int);
  extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
--- gcc/hooks.cc.jj 2023-01-02 09:32:49.675890970 +0100
+++ gcc/hooks.cc2023-02-22 12:36:46.241035355 +0100
@@ -271,6 +271,11 @@ hook_hwi_void_0 (void)
  }
  
  void

+hook_void_bool (bool)
+{
+}
+
+void
  hook_void_tree (tree)
  {
  }
--- gcc/target.def.jj   2023-01-04 10:45:50.117881714 +0100
+++ gcc/target.def  2023-02-22 12:33:39.715731356 +0100
@@ -2606,6 +2606,20 @@ types.",
   const char *, (const_tree type),
   hook_constcharptr_const_tree_null)
  
+/* Temporarily add conditional target specific types for the purpose of

+   emitting C++ fundamental type tinfos.  */
+DEFHOOK
+(emit_support_tinfos,
+ "If your target defines any fundamental types which depend on ISA flags,\n\
+they might need C++ tinfo symbols in libsupc++/libstdc++ regardless of\n\
+ISA flags the library is compiled with.\n\
+The hook is called with @var{add} @code{true} at the start of C++ FE\n\
+@code{emit_support_tinfos} and with @var{add} @code{false} at the end of it\n\
+and can temporarily create fundamental types that are not supposed to be\n\
+otherwise created due to the ISA options.",
+ void, (bool add),
+ hook_void_bool)
+
  /* Make any adjustments to libfunc names needed for this target.  */
  DEFHOOK
  (init_libfuncs,
--- gcc/doc/tm.texi.in.jj   2023-01-16 11:52:16.124733460 +0100
+++ gcc/doc/tm.texi.in  2023-02-22 12:46:37.951482849 +0100
@@ -1286,6 +1286,8 @@ pattern needs to support both a 32- and
  
  @hook TARGET_MANGLE_TYPE
  
+@hook TARGET_EMIT_SUPPORT_TINFOS

+
  @node Type Layout
  @section Layout of Source Language Data Types
  
--- gcc/doc/tm.texi.jj	2023-01-16 11:52:16.123733475 +0100

+++ gcc/doc/tm.texi 2023-02-22 12:46:41.741428081 +0100
@@ -1525,6 +1525,16 @@ appropriate for a target that does not d
  types.
  @end deftypefn
  
+@deftypefn {Target Hook} void TARGET_EMIT_SUPPORT_TINFOS (bool @var{add})

+If your target defines any fundamental types which depend on ISA flags,
+they might need C++ tinfo symbols in libsupc++/libstdc++ regardless of
+ISA flags the library is compiled with.
+The hook is called with @var{add} @code{true} at the start of C++ FE
+@code{emit_support_tinfos} and with @var{add} @code{false} at the end of it
+and can temporarily create fundamental types that are not supposed to be
+otherwise created due to the ISA options.
+@end deftypefn
+
  @node Type Layout
  @section Layout of Source Language Data Types
  
--- gcc/config/i386/i386.cc.jj	2023-02-16 10:13:23.701210667 +0100

+++ gcc/config/i386/i386.cc 2023-02-22 12:59:55.110960505 +0100
@@ -22775,6 +22775,30 @@ ix86_mangle_type (const_tree type)
  }
  }
  
+/* 

Re: [PATCH] c++: Fix up -fcontracts option description [PR108890]

2023-02-27 Thread Jason Merrill via Gcc-patches

On 2/23/23 05:26, Jakub Jelinek wrote:

Hi!

This translation PR mentioned the description is a little bit weird.

Ok for trunk?


OK.


2023-02-23  Jakub Jelinek  

PR translation/108890
* c.opt (fcontracts): Fix description.

--- gcc/c-family/c.opt.jj   2023-02-01 10:19:42.637146215 +0100
+++ gcc/c-family/c.opt  2023-02-23 10:25:06.084085718 +0100
@@ -1689,7 +1689,7 @@ C++ ObjC++ Joined RejectNegative Host_Wi
  
  fcontracts

  C++ ObjC++ Var(flag_contracts) Init(0)
-Enable certain features present drafts of C++ Contracts.
+Enable certain features present in drafts of C++ Contracts.
  
  Enum

  Name(on_off) Type(int) UnknownError(argument %qs must be either % or 
%)

Jakub





Re: [PATCH] c++: variable template and targ deduction [PR108550]

2023-02-27 Thread Jason Merrill via Gcc-patches

On 2/23/23 10:54, Marek Polacek wrote:

On Thu, Feb 23, 2023 at 10:17:22AM -0500, Patrick Palka wrote:

On Wed, 22 Feb 2023, Marek Polacek wrote:


In this test, we get a bogus error because we failed to deduce the auto in
constexpr auto is_pointer_v = is_pointer::value;
to bool.  Then ensure_literal_type_for_constexpr_object thinks the object
isn't literal and an error is reported.

This is another case of the interaction between tf_partial and 'auto',
where the auto was not reduced so the deduction failed.  In more detail:
we have

   Wrap1()

in the code and we need to perform OR -> fn_type_unification.  The targ
list is incomplete, so we do
   tsubst_flags_t ecomplain = complain | tf_partial | tf_fndecl_type;
   fntype = tsubst (TREE_TYPE (fn), explicit_targs, ecomplain, NULL_TREE);
where TREE_TYPE (fn) is struct integral_constant  (void).  Then
we substitute the return type, which results in tsubsting is_pointer_v.
is_pointer_v is a variable template with a placeholder type:

   template 
   constexpr auto is_pointer_v = is_pointer::value;

so we find ourselves in lookup_and_finish_template_variable.  tf_partial is
still set, so finish_template_variable -> instantiate_template -> tsubst
won't reduce the level of auto.  But then we do mark_used which eventually
calls do_auto_deduction which clears tf_partial, because we want to replace
the auto now.  But we hadn't reduced auto's level so this fails.  And
since we're not in an immediate context, we emit a hard error.

I suppose that when we reach lookup_and_finish_template_variable it's
probably time to clear tf_partial.  (I added an assert and our testsuite
doesn't have a test whereby we get to lookup_and_finish_template_variable
while tf_partial is still active.)

Does this make *any* sense to you?

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/108550

gcc/cp/ChangeLog:

* pt.cc (lookup_and_finish_template_variable): Clear tf_partial.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ70.C: New test.
* g++.dg/cpp1y/var-templ71.C: New test.
---
  gcc/cp/pt.cc |  6 ++
  gcc/testsuite/g++.dg/cpp1y/var-templ70.C | 25 +++
  gcc/testsuite/g++.dg/cpp1y/var-templ71.C | 26 
  3 files changed, 57 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ70.C
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ71.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1a071e95004..f636bac5413 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10355,6 +10355,12 @@ lookup_and_finish_template_variable (tree templ, tree 
targs,
if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (templ)) == 1
&& !any_dependent_template_arguments_p (targs))
  {
+  /* We may be called while doing a partial substitution, but the
+type of the variable template may be auto, in which case we
+will call do_auto_deduction in mark_used (which clears tf_partial)
+and the auto must be properly reduced at that time for the
+deduction to work.  */
+  complain &= ~tf_partial;


LGTM.  I can't think of a reason to keep tf_partial set at this point
since we know there's only a single level of template arguments left to
substitute and the args we have are non-dependent, so the substitution
is in no way partial.


Right, once we get to finish_template_variable I suppose we're really
committed to the var tmpl.  So the fix should be safe, albeit it feels
a bit ad hoc.  FWIW, I'd tested adding alias templates to the mix and
it still worked.
  

Though I wonder if ideally we should clear tf_partial more generally
from instantiate_template?  Modulo diagnostics, the result of
instantiate_template shouldn't depend on complain, in particular because
we cache the result in the specializations table is which keyed off of
only the given tmpl and args.  Not sure if that'd be a suitable change
for stage4/backports though...


This makes sense; I guess anytime you have the full set of targs and are
going to instantiate, tf_partial should be cleared otherwise it can
wreak havoc.  I'd be nervous about applying such a patch now but maybe
we could experiment with that in GCC 14.


This sounds right to me; it would never make sense to have tf_partial 
set in instantiate_template, so we should be able to clear it there.  We 
might even do


 complain = complain & tf_warning_or_error

since none of the other flags are relevant at that level either.

But this patch is OK for GCC 13.


Thanks for taking a look!
  

var = finish_template_variable (var, complain);
mark_used (var);
  }
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ70.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ70.C
new file mode 100644
index 000..1d35c38c7cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ70.C
@@ -0,0 +1,25 @@
+// PR c++/108550
+// { dg-do compile { target c++14 } }
+
+template
+struct is_pointer
+{
+  static const

Re: [PATCH] c++: non-dependent variable template-id [PR108848]

2023-02-27 Thread Jason Merrill via Gcc-patches

On 2/23/23 16:52, Patrick Palka wrote:

Here we're incorrectly treating the non-dependent variable template-id
tag as dependent ever since r226642 gave variable TEMPLATE_ID_EXPR
an empty type which causes the call to finish_template_variable from
finish_id_expression_1 to be dead code at template parse time.  Thus
we're led into treating tag.var as a dependent name at parse
time.

This patch fixes this by making finish_id_expression_1 instantiate a
variable template-id as long as the template and args are non-dependent
according to the dependence test in lookup_and_finish_template_variable
and not according to type_dependent_expression_p.  This patch also moves
said dependence test into finish_template_variable.

bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

PR c++/108848

gcc/cp/ChangeLog:

* pt.cc (finish_template_variable): Move dependence check
to here from ...
(lookup_and_finish_template_variable): ... here.
* semantics.cc (finish_id_expression_1): Call
finish_template_variable sooner and regardless of
type_dependent_expression_p.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/noexcept1.C: Don't expect bogus "different
exception specifier" error.  Expect a separate "not usable
in a constant expression" error.
* g++.dg/cpp1y/var-templ70.C: New test.
* g++.dg/cpp1y/var-templ71.C: New test.
---
  gcc/cp/pt.cc | 18 ++
  gcc/cp/semantics.cc  | 14 +-
  gcc/testsuite/g++.dg/cpp1y/noexcept1.C   |  4 ++--
  gcc/testsuite/g++.dg/cpp1y/var-templ70.C | 20 
  gcc/testsuite/g++.dg/cpp1y/var-templ71.C | 10 ++
  5 files changed, 47 insertions(+), 19 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ70.C
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ71.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b1ac7d4beb4..11c0baa0119 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10317,7 +10317,8 @@ lookup_template_variable (tree templ, tree arglist)
return build2 (TEMPLATE_ID_EXPR, NULL_TREE, templ, arglist);
  }
  
-/* Instantiate a variable declaration from a TEMPLATE_ID_EXPR for use. */

+/* Instantiate a variable declaration from a TEMPLATE_ID_EXPR if it's
+   not dependent.  */
  
  tree

  finish_template_variable (tree var, tsubst_flags_t complain)
@@ -10325,6 +10326,12 @@ finish_template_variable (tree var, tsubst_flags_t 
complain)
tree templ = TREE_OPERAND (var, 0);
tree arglist = TREE_OPERAND (var, 1);
  
+  /* If the template or arguments are dependent, then we

+ can't instantiate yet.  */
+  if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (templ)) != 1
+  || any_dependent_template_arguments_p (arglist))
+return var;
+
tree parms = DECL_TEMPLATE_PARMS (templ);
arglist = coerce_template_parms (parms, arglist, templ, complain);
if (arglist == error_mark_node)
@@ -10352,13 +10359,8 @@ lookup_and_finish_template_variable (tree templ, tree 
targs,
 tsubst_flags_t complain)
  {
tree var = lookup_template_variable (templ, targs);
-  if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (templ)) == 1
-  && !any_dependent_template_arguments_p (targs))
-{
-  var = finish_template_variable (var, complain);
-  mark_used (var);
-}
-
+  var = finish_template_variable (var, complain);
+  mark_used (var);
return convert_from_reference (var);
  }
  
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc

index c2df0b69b30..a18364dda4f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4208,6 +4208,11 @@ finish_id_expression_1 (tree id_expression,
  }
else
  {


We could use a comment here about why this needs to come before checking 
type_dep*.  OK with that change.



+  if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
+ && variable_template_p (TREE_OPERAND (decl, 0))
+ && !concept_check_p (decl))
+   decl = finish_template_variable (decl);
+
bool dependent_p = type_dependent_expression_p (decl);
  
/* If the declaration was explicitly qualified indicate

@@ -4275,15 +4280,6 @@ finish_id_expression_1 (tree id_expression,
/* Replace an evaluated use of the thread_local variable with
   a call to its wrapper.  */
decl = wrap;
-  else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
-  && !dependent_p
-  && variable_template_p (TREE_OPERAND (decl, 0))
-  && !concept_check_p (decl))
-   {
- decl = finish_template_variable (decl);
- mark_used (decl);
- decl = convert_from_reference (decl);
-   }
else if (concept_check_p (decl))
{
  /* Nothing more to do. All of the analysis for concept checks
diff --git a/gcc/testsuite/g++.dg/cpp1y/noexcept1.C 
b/gcc/testsuite/g++.dg/cpp1y/noexcept1.C
index 86e46c96148..caa4a056a2e 100644
--- a/

Re: [PATCH] c++: ICE with constexpr variable template [PR107938]

2023-02-27 Thread Jason Merrill via Gcc-patches

On 2/23/23 18:51, Marek Polacek wrote:

Since r11-557, cp_finish_decl can call check_initializer even in
a template for a constexpr initializer.  That ultimately leads to
convert_for_assignment and check_address_or_pointer_of_packed_member,
where we crash, because it doesn't expect that the CALL_EXPR is
a function object.  Q has a constexpr operator(), but since we're
in a template, q(0) is a CALL_EXPR whose CALL_EXPR_FN is just
a VAR_DECL; it hasn't been converted to Q::operator(&q, 0) yet.
I propose to robustify check_address_or_pointer_of_packed_member.

var-templ74.C has an XFAIL, subject to 107939.

I noticed that our -Waddress-of-packed-member tests weren't testing
member functions, added thus.  (I was tempted to check
FUNCTION_POINTER_TYPE_P but that doesn't include METHOD_TYPE.)

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?


OK.


PR c++/107938

gcc/c-family/ChangeLog:

* c-warn.cc (check_address_or_pointer_of_packed_member): Check
POINTER_TYPE_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ73.C: New test.
* g++.dg/cpp1y/var-templ74.C: New test.
* g++.dg/warn/Waddress-of-packed-member3.C: New test.
---
  gcc/c-family/c-warn.cc|  4 
  gcc/testsuite/g++.dg/cpp1y/var-templ73.C  | 12 ++
  gcc/testsuite/g++.dg/cpp1y/var-templ74.C  | 19 +++
  .../g++.dg/warn/Waddress-of-packed-member3.C  | 23 +++
  4 files changed, 58 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ73.C
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ74.C
  create mode 100644 gcc/testsuite/g++.dg/warn/Waddress-of-packed-member3.C

diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index a6fb95b1e80..29ae1ea1dc8 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -3000,6 +3000,10 @@ check_address_or_pointer_of_packed_member (tree type, 
tree rhs)
  if (rhs == NULL_TREE)
return NULL_TREE;
  rhs = TREE_TYPE (rhs);/* Pointer type.  */
+ /* We could be called while processing a template and RHS could be
+a functor.  In that case it's a class, not a pointer.  */
+ if (!POINTER_TYPE_P (rhs))
+   return NULL_TREE;
  rhs = TREE_TYPE (rhs);/* Function type.  */
  rhstype = TREE_TYPE (rhs);
  if (!rhstype || !POINTER_TYPE_P (rhstype))
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ73.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ73.C
new file mode 100644
index 000..b76babcfa81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ73.C
@@ -0,0 +1,12 @@
+// PR c++/107938
+// { dg-do compile { target c++14 } }
+
+struct Q {
+  int n;
+  constexpr const Q* operator()(int) const { return this; }
+};
+
+constexpr Q q{};
+
+template
+constexpr const Q* p = q(0);
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ74.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ74.C
new file mode 100644
index 000..4e2e800a6eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ74.C
@@ -0,0 +1,19 @@
+// PR c++/107938
+// { dg-do compile { target c++14 } }
+
+struct Q {
+  int n;
+  constexpr const Q* operator()(int) const { return this; }
+};
+
+extern const Q q;
+
+template
+constexpr const Q* p = q(0); // { dg-bogus "not usable" "PR107939" { xfail 
*-*-* } }
+
+void
+g ()
+{
+  constexpr const Q* p2 = q(0);
+  constexpr auto x = p<0>;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member3.C 
b/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member3.C
new file mode 100644
index 000..aeffb969c01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-of-packed-member3.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target { ! default_packed } } }
+// Test that -Waddress-of-packed-member works with member functions.
+
+struct S {
+  char c;
+} __attribute__((packed));
+
+struct X {
+  S* memfn ();
+  static S* smemfn ();
+} x;
+
+S *foo ();
+
+S**
+f ()
+{
+  S **s;
+  s = reinterpret_cast(foo ()); // { dg-warning "converting a packed" }
+  s = reinterpret_cast(x.memfn ()); // { dg-warning "converting a packed" 
}
+  s = reinterpret_cast(X::smemfn ()); // { dg-warning "converting a 
packed" }
+  return s;
+}

base-commit: f33d7a88d069d169bbe76da8e5c52de17f68ca05




Re: [PATCH] Skip module_cmi_p and related unsupported module test

2023-02-20 Thread Jason Merrill via Gcc-patches

On 2/17/23 22:55, Alexandre Oliva wrote:


When a multi-source module is found to be unsupported, we fail
module_cmi_p and subsequent sources.  Override proc unsupported to
mark the result in module_do, and test it to skip module_cmp_p and
subsequent related tests.


Hmm, I guess the problem that the modules tests are trying to use 
dg-test as a subroutine, and can't get at the result of the test to skip 
later processing?  Seems like LTO deals with the same issue by not using 
dg-test at all.


This seems like an ugly kludge around that problem, but I don't have any 
clever ideas of a better approach short of rewriting everything.  So, OK 
with a comment explaining the rationale above your overridden "unsupported".


Also, your commit subject line needs a subsystem tag, I guess 
"testsuite:" in this case.



Regstrapped on x86_64-linux-gnu.
Tested on arm-vxworks7 (gcc-12) and arm-eabi (trunk).  Ok to install?

for  gcc/testsuite/ChangeLog

* g++.dg/modules/modules.exp: Override unsupported to update
module_do, and test it after dg-test.
---
  gcc/testsuite/g++.dg/modules/modules.exp |   14 ++
  1 file changed, 14 insertions(+)

diff --git a/gcc/testsuite/g++.dg/modules/modules.exp 
b/gcc/testsuite/g++.dg/modules/modules.exp
index 61994b059457b..ba1287427bf05 100644
--- a/gcc/testsuite/g++.dg/modules/modules.exp
+++ b/gcc/testsuite/g++.dg/modules/modules.exp
@@ -315,6 +315,14 @@ proc module-check-requirements { tests } {
  # cleanup any detritus from previous run
  cleanup_module_files [find $DEFAULT_REPO *.gcm]
  
+set module_do {"compile" "P"}

+rename unsupported saved-unsupported
+proc unsupported { args } {
+global module_do
+lset module_do 1 "N"
+return [saved-unsupported $args]
+}
+
  # not grouped tests, sadly tcl doesn't have negated glob
  foreach test [prune [lsort [find $srcdir/$subdir {*.[CH]}]] \
  "$srcdir/$subdir/*_?.\[CH\]"] {
@@ -327,6 +335,9 @@ foreach test [prune [lsort [find $srcdir/$subdir {*.[CH]}]] 
\
set module_cmis {}
verbose "Testing $nshort $std" 1
dg-test $test "$std" $DEFAULT_MODFLAGS
+   if { [lindex $module_do 1] == "N" } {
+   continue
+   }
set testcase [string range $test [string length "$srcdir/"] end]
cleanup_module_files [module_cmi_p $testcase $module_cmis]
}
@@ -372,6 +383,9 @@ foreach src [lsort [find $srcdir/$subdir {*_a.[CHX}]] {
}
}
dg-test -keep-output $test "$std" $DEFAULT_MODFLAGS
+   if { [lindex $module_do 1] == "N" } {
+   break
+   }
set testcase [string range $test [string length "$srcdir/"] 
end]
lappend mod_files [module_cmi_p $testcase $module_cmis]
}





Re: [PATCH 1/2] c++: factor out TYPENAME_TYPE substitution

2023-02-20 Thread Jason Merrill via Gcc-patches

On 2/15/23 12:11, Patrick Palka wrote:

On Wed, 15 Feb 2023, Jason Merrill wrote:


On 2/15/23 09:21, Patrick Palka wrote:

On Tue, 14 Feb 2023, Jason Merrill wrote:


On 2/13/23 09:23, Patrick Palka wrote:

[N.B. this is a corrected version of
https://gcc.gnu.org/pipermail/gcc-patches/2022-November/607443.html ]

This patch factors out the TYPENAME_TYPE case of tsubst into a separate
function tsubst_typename_type.  It also factors out the two tsubst flags
controlling TYPENAME_TYPE substitution, tf_keep_type_decl and tf_tst_ok,
into distinct boolean parameters of this new function (and of
make_typename_type).  Consequently, callers which used to pass tf_tst_ok
to tsubst now instead must directly call tsubst_typename_type when
appropriate.


Hmm, I don't love how that turns 4 lines into 8 more complex lines in each
caller.  And the previous approach of saying "a CTAD placeholder is OK"
seem
like better abstraction than repeating the specific TYPENAME_TYPE handling
in
each place.


Ah yeah, I see what you mean.  I was thinking since tf_tst_ok is
specific to TYPENAME_TYPE handling and isn't propagated (i.e. it only
affects top-level TYPENAME_TYPEs), it seemed cleaner to encode the flag
as a bool parameter "template_ok" of tsubst_typename_type instead of as
a global tsubst_flag that gets propagated freely.




In a subsequent patch we'll add another flag to
tsubst_typename_type controlling whether we want to ignore non-types
during the qualified lookup.


As mentioned above, the second patch in this series would just add
another flag "type_only" alongside "template_ok", since this flag will
also only affects top-level TYPENAME_TYPEs and doesn't need to propagate
like tsubst_flags.

Except, it turns it, this new flag _does_ need to propagate, namely when
expanding a variadic using:

using typename Ts::type::m...; // from typename25a.C below

Here we have a USING_DECL whose USING_DECL_SCOPE is a
TYPE_PACK_EXPANSION over TYPENAME_TYPE.  In order to correctly
substitute this TYPENAME_TYPE, the USING_DECL case of tsubst_decl needs
to pass an appropriate tsubst_flag to tsubst_pack_expansion to be
propagated to tsubst (to be propagated to make_typename_type).

So in light of this case it seems adding a new tsubst_flag is the
way to go, which means we can avoid this refactoring patch entirely.

Like so?  Bootstrapped and regtested on x86_64-pc-linux-gnu.


OK, though I still wonder about adding a tsubst_scope function that would add
the tf_qualifying_scope.


Hmm, but we need to add tf_qualifying_scope to two tsubst_copy calls,
one tsubst call and one tsubst_aggr_type call (with entering_scope=true).
Would tsubst_scope call tsubst, tsubst_copy or tsubst_aggr_type?


In general it would call tsubst.

It's odd that anything is calling tsubst_copy with a type, that seems 
like a copy/paste error.  But it just hands off to tsubst anyway, so the 
effect is the same.


tsubst_aggr_type is needed when pushing into the scope of a declarator; 
I don't know offhand why we would need that when substituting the scope 
of a TYPENAME_TYPE.


I'd call tsubst, and leave the tsubst_aggr_type call alone for GCC 13.


-- >8 --

Subject: [PATCH] c++: TYPENAME_TYPE lookup ignoring non-types [PR107773]

Currently when resolving a TYPENAME_TYPE for 'typename T::m' via
make_typename_type, we consider only type bindings of 'm' and ignore
non-type ones.  But [temp.res.general]/3 says, in a note, "the usual
qualified name lookup ([basic.lookup.qual]) applies even in the presence
of 'typename'", and qualified name lookup doesn't discriminate between
type and non-type bindings.  So when resolving such a TYPENAME_TYPE
we want the lookup to consider all bindings.

An exception is when we have a TYPENAME_TYPE corresponding to the
qualifying scope of the :: scope resolution operator, such as
'T::type' in 'typename T::type::m'.  In that case, [basic.lookup.qual]/1
applies, and lookup for such a TYPENAME_TYPE must ignore non-type bindings.
So in order to correctly handle all cases, make_typename_type needs an
additional flag controlling whether lookup should ignore non-types or not.

To that end this patch adds a new tsubst flag tf_qualifying_scope to
communicate to make_typename_type whether we want to ignore non-type
bindings during the lookup (by default we don't want to ignore them).
In contexts where we do want to ignore non-types (when substituting
into the scope of TYPENAME_TYPE, SCOPE_REF or USING_DECL) we simply
pass tf_qualifying_scope to the relevant tsubst / tsubst_copy call.
This flag is intended to apply only to top-level TYPENAME_TYPEs so
we must be careful to clear the flag to avoid propagating it during
substitution of sub-trees.

PR c++/107773

gcc/cp/ChangeLog:

* cp-tree.h (enum tsubst_flags): New flag tf_qualifying_scope.
* decl.cc (make_typename_type): Use lookup_member instead of
lookup_field.  If tf_qualifying_scope is set, pass want_type=true
instead of =false to lookup_member.  Gene

Re: [PATCH] c++: ICE with -fno-elide-constructors and trivial fn [PR101073]

2023-02-20 Thread Jason Merrill via Gcc-patches

On 2/15/23 13:37, Marek Polacek wrote:

On Wed, Feb 15, 2023 at 02:39:16PM -0500, Jason Merrill wrote:

On 2/9/23 09:39, Marek Polacek wrote:

In constexpr-nsdmi3.C, with -fno-elide-constructors, we don't elide
the Y::Y(const Y&) call used to initialize o.c.  So store_init_value
-> cxx_constant_init must constexpr-evaluate the call to Y::Y(const Y&)
in cxx_eval_call_expression.  It's a trivial function, so we do the
"Shortcut trivial constructor/op=" code and rather than evaluating
the function, we just create an assignment

o.c = *(const struct Y &) (const struct Y *) &(&)->b

which is a MODIFY_EXPR, so the preeval code in cxx_eval_store_expression
clears .ctor and .object, therefore we can't replace the PLACEHOLDER_EXPR
whereupon we crash at

/* A placeholder without a referent.  We can get here when
   checking whether NSDMIs are noexcept, or in massage_init_elt;
   just say it's non-constant for now.  */
gcc_assert (ctx->quiet);

The PLACEHOLDER_EXPR can also be on the LHS as in constexpr-nsdmi10.C.
I don't think we can do much here, but I noticed that the whole
trivial_fn_p (fun) block is only entered when -fno-elide-constructors.
This is true since GCC 9; it wasn't easy to bisect what changes made it
so, but r240845 is probably one of them.  -fno-elide-constructors is an
option for experiments only so it's not clear to me why we'd still want
to shortcut trivial constructor/op=.  I propose to remove the code and
add a checking assert to make sure we're not getting a trivial_fn_p
unless -fno-elide-constructors.


Hmm, trivial op= doesn't ever hit this code?


With -fno-elide-constructors we hit the trivial_fn_p block twice in
constexpr-nsdmi9.C, once for "constexpr Y::Y(const Y&)" and then for
"constexpr Y& Y::operator=(Y&&)".  So it does hit the code, but only
with -fno-elide-constructors.


Odd, I'm not sure why that would make a difference for assignment.


Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  I don't
think I want to backport this.

PR c++/101073

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Replace shortcutting trivial
constructor/op= with a checking assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-nsdmi3.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi10.C: New test.
---
   gcc/cp/constexpr.cc   | 25 +++
   gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi3.C | 17 +
   .../g++.dg/cpp1y/constexpr-nsdmi10.C  | 18 +
   3 files changed, 38 insertions(+), 22 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi3.C
   create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-nsdmi10.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 564766c8a00..1d53dcf0f20 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2865,28 +2865,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
 ctx = &new_ctx;
   }
-  /* Shortcut trivial constructor/op=.  */
-  if (trivial_fn_p (fun))
-{
-  tree init = NULL_TREE;
-  if (call_expr_nargs (t) == 2)
-   init = convert_from_reference (get_nth_callarg (t, 1));
-  else if (TREE_CODE (t) == AGGR_INIT_EXPR
-  && AGGR_INIT_ZERO_FIRST (t))
-   init = build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false);
-  if (init)
-   {
- tree op = get_nth_callarg (t, 0);
- if (is_dummy_object (op))
-   op = ctx->object;
- else
-   op = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (op)), op);
- tree set = build2 (MODIFY_EXPR, TREE_TYPE (op), op, init);


I think the problem is using MODIFY_EXPR instead of INIT_EXPR to represent a
constructor; that's why cxx_eval_store_expression thinks it's OK to
preevaluate.  This should properly use those two tree codes for op= and
ctor, respectively.


Maybe it was so that the RHS in SET could refer to the op in the LHS?


I think it was just an oversight.  You need INIT_EXPR for the rhs to 
refer to the lhs.



- new_ctx.call = &new_call;
- return cxx_eval_constant_expression (&new_ctx, set, lval,
-  non_constant_p, overflow_p);
-   }
-}
+  /* 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);


...but if this optimization is so rarely triggered, this simplification is
OK too.


I'd say that's better so that we don't have to update the code (like
r234345 did).


Indeed, the patch is OK.

Jason



Re: [PATCH v3] c++: ICE with redundant capture [PR108829]

2023-02-20 Thread Jason Merrill via Gcc-patches

On 2/17/23 14:42, Marek Polacek wrote:

On Fri, Feb 17, 2023 at 04:32:50PM -0500, Patrick Palka wrote:

On Fri, 17 Feb 2023, Patrick Palka wrote:


On Fri, 17 Feb 2023, Marek Polacek wrote:


On Fri, Feb 17, 2023 at 03:00:39PM -0500, Patrick Palka wrote:

On Fri, 17 Feb 2023, Marek Polacek via Gcc-patches wrote:


Here we crash in is_capture_proxy:

   /* Location wrappers should be stripped or otherwise handled by the
  caller before using this predicate.  */
   gcc_checking_assert (!location_wrapper_p (decl));

so fixed as the comment suggests.  We only crash with the redundant
capture:

   int abyPage = [=, abyPage] { ... }

because prune_lambda_captures is only called when there was a default
capture, and with [=] only abyPage won't be in LAMBDA_EXPR_CAPTURE_LIST.


It's weird that we even get this far in var_to_maybe_prune.  Shouldn't
LAMBDA_CAPTURE_EXPLICIT_P be true for abyPage?


Ug, I was seduced by the ostensible obviousness and failed to notice
that check.  In that light, the correct fix ought to be this.  Thanks!

Bootstrap/regtest running on x86_64-pc-linux-gnu, ok for trunk if it
passes?

-- >8 --
Here we crash in is_capture_proxy:

   /* Location wrappers should be stripped or otherwise handled by the
  caller before using this predicate.  */
   gcc_checking_assert (!location_wrapper_p (decl));

We only crash with the redundant capture:

   int abyPage = [=, abyPage] { ... }

because prune_lambda_captures is only called when there was a default
capture, and with [=] only abyPage won't be in LAMBDA_EXPR_CAPTURE_LIST.

The problem is that LAMBDA_CAPTURE_EXPLICIT_P wasn't propagated
correctly and so var_to_maybe_prune proceeded where it shouldn't.

PR c++/108829

gcc/cp/ChangeLog:

* pt.cc (tsubst_lambda_expr): Propagate LAMBDA_CAPTURE_EXPLICIT_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/lambda/lambda-108829.C: New test.
---
  gcc/cp/pt.cc  |  4 
  gcc/testsuite/g++.dg/cpp0x/lambda/lambda-108829.C | 11 +++
  2 files changed, 15 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-108829.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b1ac7d4beb4..f747ce877b5 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19992,6 +19992,10 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
  if (id_equal (DECL_NAME (field), "__this"))
LAMBDA_EXPR_THIS_CAPTURE (r) = field;
}
+
+  if (LAMBDA_EXPR_CAPTURE_LIST (r))
+   LAMBDA_CAPTURE_EXPLICIT_P (LAMBDA_EXPR_CAPTURE_LIST (r))
+ = LAMBDA_CAPTURE_EXPLICIT_P (LAMBDA_EXPR_CAPTURE_LIST (t));


I'm not sure how the flag works for pack captures but it looks like
this would only propagate the flag to the last expanded capture if
the capture was originally a pack.


Testcase:

   template
   void f(Ts... ts) {
 constexpr int IDX_PAGE_SIZE = 4096;
 int abyPage = [=, ts...] { return IDX_PAGE_SIZE; }();
   }
   void h() {
 f<1>(0, 1);
   }


Thanks a lot for the testacase.  Revised patch below.  Look OK?

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK.


-- >8 --
Here we crash in is_capture_proxy:

   /* Location wrappers should be stripped or otherwise handled by the
  caller before using this predicate.  */
   gcc_checking_assert (!location_wrapper_p (decl));

We only crash with the redundant capture:

   int abyPage = [=, abyPage] { ... }

because prune_lambda_captures is only called when there was a default
capture, and with [=] only abyPage won't be in LAMBDA_EXPR_CAPTURE_LIST.

The problem is that LAMBDA_CAPTURE_EXPLICIT_P wasn't propagated
correctly and so var_to_maybe_prune proceeded where it shouldn't.

PR c++/108829

gcc/cp/ChangeLog:

* pt.cc (prepend_one_capture): Set LAMBDA_CAPTURE_EXPLICIT_P.
(tsubst_lambda_expr): Pass LAMBDA_CAPTURE_EXPLICIT_P to
prepend_one_capture.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/lambda/lambda-108829-2.C: New test.
* g++.dg/cpp0x/lambda/lambda-108829.C: New test.

Co-Authored by: Patrick Palka 
---
  gcc/cp/pt.cc|  9 ++---
  gcc/testsuite/g++.dg/cpp0x/lambda/lambda-108829-2.C | 11 +++
  gcc/testsuite/g++.dg/cpp0x/lambda/lambda-108829.C   | 11 +++
  3 files changed, 28 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-108829-2.C
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-108829.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b1ac7d4beb4..1a071e95004 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19870,10 +19870,11 @@ tsubst_non_call_postfix_expression (tree t, tree args,
  
  /* Subroutine of tsubst_lambda_expr: add the FIELD/INIT capture pair to the

 LAMBDA_EXPR_CAPTURE_LIST passed in LIST.  Do deduction for a previously
-   dependent init-capture.  */
+   dependent init-capture.  EXPLICIT_P is true if the original list had
+   explicit captures

<    1   2   3   4   5   6   7   8   9   10   >