[gcc r14-10075] testsuite: prune -freport-bug output

2024-04-22 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:0db19228a9feba5a8f4e13b21f25f3aa8a6c5e85

commit r14-10075-g0db19228a9feba5a8f4e13b21f25f3aa8a6c5e85
Author: Marek Polacek 
Date:   Fri Apr 19 13:51:41 2024 -0400

testsuite: prune -freport-bug output

When the compiler defaults to -freport-bug, a few dg-ice tests fail
with:

Excess errors:
Preprocessed source stored into /tmp/cc6hldZ0.out file, please attach this 
to your bugreport.

We could add -fno-report-bug to those tests.  But it seems to me that a
better fix would be to prune the "Preprocessed source stored..." message
in prune_gcc_output.

gcc/testsuite/ChangeLog:

* lib/prune.exp (prune_gcc_output): Also prune -freport-bug output.

Reviewed-by: Jakub Jelinek 

Diff:
---
 gcc/testsuite/lib/prune.exp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index f3d3c99fbcb..d00d37f015f 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -51,6 +51,7 @@ proc prune_gcc_output { text } {
 regsub -all "(^|\n)\[^\n\]*: re(compiling|linking)\[^\n\]*" $text "" text
 regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text
 regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text
+regsub -all "(^|\n)Preprocessed.*bugreport\[^\n\]*" $text "" text
 
 # Diagnostic inclusion stack
 regsub -all "(^|\n)(In file)?\[ \]+included from \[^\n\]*" $text "" text


[PATCH] testsuite: prune -freport-bug output

2024-04-19 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
I can defer to 15 if needed, of course.

-- >8 --
When the compiler defaults to -freport-bug, a few dg-ice tests fail
with:

Excess errors:
Preprocessed source stored into /tmp/cc6hldZ0.out file, please attach this to 
your bugreport.

We could add -fno-report-bug to those tests.  But it seems to me that a
better fix would be to prune the "Preprocessed source stored..." message
in prune_gcc_output.

gcc/testsuite/ChangeLog:

* lib/prune.exp (prune_gcc_output): Also prune -freport-bug output.
---
 gcc/testsuite/lib/prune.exp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index f3d3c99fbcb..d00d37f015f 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -51,6 +51,7 @@ proc prune_gcc_output { text } {
 regsub -all "(^|\n)\[^\n\]*: re(compiling|linking)\[^\n\]*" $text "" text
 regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text
 regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text
+regsub -all "(^|\n)Preprocessed.*bugreport\[^\n\]*" $text "" text
 
 # Diagnostic inclusion stack
 regsub -all "(^|\n)(In file)?\[ \]+included from \[^\n\]*" $text "" text

base-commit: d86472a6f041ccf3d1be0cf6bb15d1e0ad8f6dbe
-- 
2.44.0



Re: [PATCH] wwwdocs: Add note to changes.html for __has_{feature,extension}

2024-04-17 Thread Marek Polacek
On Mon, Apr 15, 2024 at 11:13:27AM +0100, Alex Coplan wrote:
> On 04/04/2024 11:00, Alex Coplan wrote:
> > Hi,
> > 
> > This adds a note to the GCC 14 release notes mentioning support for
> > __has_{feature,extension} (PR60512).
> > 
> > OK to commit?
> 
> Ping.  Is this changes.html patch OK?  I guess it needs a review from C++
> maintainers since it adds to the C++ section.
> 
> > 
> > Thanks,
> > Alex
> 
> > diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
> > index 9fd224c1..facead8d 100644
> > --- a/htdocs/gcc-14/changes.html
> > +++ b/htdocs/gcc-14/changes.html
> > @@ -242,6 +242,12 @@ a work-in-progress.
> >constinit and optimized dynamic initialization
> >  
> >
> > +  The Clang language extensions __has_feature and
> > +__has_extension have been implemented in GCC.  These
> > +are available from C, C++, and Objective-C(++).

Since the extension is for the whole c-family, not just C++, I think it
belongs to a "C family" section.  See e.g. 
.

Marek



[gcc r14-9950] c++: ICE with temporary of class type in array DMI [PR109966]

2024-04-12 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:6039925631780741ba77666ef2ef743aa2a925a8

commit r14-9950-g6039925631780741ba77666ef2ef743aa2a925a8
Author: Marek Polacek 
Date:   Mon Mar 11 17:45:55 2024 -0400

c++: ICE with temporary of class type in array DMI [PR109966]

This ICE started with the fairly complicated r13-765.  We crash in
gimplify_var_or_parm_decl because a stray VAR_DECL leaked there.
The problem is ultimately that potential_prvalue_result_of wasn't
correctly handling arrays and replace_placeholders_for_class_temp_r
replaced a PLACEHOLDER_EXPR in a TARGET_EXPR which is used in the
context of copy elision.  If I have

  M m[2] = { M{""}, M{""} };

then we don't invoke the M(const M&) copy-ctor.

One part of the fix is to use TARGET_EXPR_ELIDING_P rather than
potential_prvalue_result_of.  That unfortunately doesn't handle the
case like

  struct N { N(M); };
  N arr[2] = { M{""}, M{""} };

because TARGET_EXPRs that initialize a function argument are not
marked TARGET_EXPR_ELIDING_P even though gimplify_arg drops such
TARGET_EXPRs on the floor.  We can use a pset to avoid replacing
placeholders in them.

I made an attempt to use set_target_expr_eliding in
convert_for_arg_passing but that regressed constexpr-diag1.C, and does
not seem like a prudent change in stage 4 anyway.

PR c++/109966

gcc/cp/ChangeLog:

* typeck2.cc (potential_prvalue_result_of): Remove.
(replace_placeholders_for_class_temp_r): Check 
TARGET_EXPR_ELIDING_P.
Use a pset.  Don't replace_placeholders in TARGET_EXPRs that 
initialize
a function argument.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/nsdmi-aggr20.C: New test.
* g++.dg/cpp1y/nsdmi-aggr21.C: New test.

Diff:
---
 gcc/cp/typeck2.cc | 55 +---
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C | 17 +
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C | 59 +++
 3 files changed, 92 insertions(+), 39 deletions(-)

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 31198b2f9f5..2985bfdf9ec 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1399,41 +1399,6 @@ digest_init_flags (tree type, tree init, int flags, 
tsubst_flags_t complain)
   return digest_init_r (type, init, 0, flags, complain);
 }
 
-/* Return true if SUBOB initializes the same object as FULL_EXPR.
-   For instance:
-
- A a = A{};  // initializer
- A a = (A{});// initializer
- A a = (1, A{}); // initializer
- A a = true ? A{} : A{};  // initializer
- auto x = A{}.x; // temporary materialization
- auto x = foo(A{});  // temporary materialization
-
-   FULL_EXPR is the whole expression, SUBOB is its TARGET_EXPR subobject.  */
-
-static bool
-potential_prvalue_result_of (tree subob, tree full_expr)
-{
-  if (subob == full_expr)
-return true;
-  else if (TREE_CODE (full_expr) == TARGET_EXPR)
-{
-  tree init = TARGET_EXPR_INITIAL (full_expr);
-  if (TREE_CODE (init) == COND_EXPR)
-   return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 1))
-   || potential_prvalue_result_of (subob, TREE_OPERAND (init, 2)));
-  else if (TREE_CODE (init) == COMPOUND_EXPR)
-   return potential_prvalue_result_of (subob, TREE_OPERAND (init, 1));
-  /* ??? I don't know if this can be hit.  */
-  else if (TREE_CODE (init) == PAREN_EXPR)
-   {
- gcc_checking_assert (false);
- return potential_prvalue_result_of (subob, TREE_OPERAND (init, 0));
-   }
-}
-  return false;
-}
-
 /* Callback to replace PLACEHOLDER_EXPRs in a TARGET_EXPR (which isn't used
in the context of guaranteed copy elision).  */
 
@@ -1441,11 +1406,13 @@ static tree
 replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
 {
   tree t = *tp;
-  tree full_expr = *static_cast(data);
+  auto pset = static_cast *>(data);
 
   /* We're looking for a TARGET_EXPR nested in the whole expression.  */
   if (TREE_CODE (t) == TARGET_EXPR
-  && !potential_prvalue_result_of (t, full_expr))
+  /* That serves as temporary materialization, not an initializer.  */
+  && !TARGET_EXPR_ELIDING_P (t)
+  && !pset->add (t))
 {
   tree init = TARGET_EXPR_INITIAL (t);
   while (TREE_CODE (init) == COMPOUND_EXPR)
@@ -1460,6 +1427,16 @@ replace_placeholders_for_class_temp_r (tree *tp, int *, 
void *data)
  gcc_checking_assert (!find_placeholders (init));
}
 }
+  /* TARGET_EXPRs initializing function arguments are not marked as eliding,
+ even though gimplify_arg drops them on the floor.  Don't go replacing
+ placeholders in them.  */
+  else if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
+ 

gcc-wwwdocs branch master updated. d18a80a52a7ec2edd7ef9a583d8920d61c0b48e5

2024-04-12 Thread Marek Polacek via Gcc-cvs-wwwdocs
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gcc-wwwdocs".

The branch, master has been updated
   via  d18a80a52a7ec2edd7ef9a583d8920d61c0b48e5 (commit)
  from  3ca51fec661f3340fe308662405e602bcf3fe8d7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -
commit d18a80a52a7ec2edd7ef9a583d8920d61c0b48e5
Author: Marek Polacek 
Date:   Fri Apr 12 18:02:35 2024 -0400

cxx-dr-status: Update CWG 1996

diff --git a/htdocs/projects/cxx-dr-status.html 
b/htdocs/projects/cxx-dr-status.html
index 24c54cfd..a5f45359 100644
--- a/htdocs/projects/cxx-dr-status.html
+++ b/htdocs/projects/cxx-dr-status.html
@@ -14005,8 +14005,9 @@
   https://wg21.link/cwg1996;>1996
   drafting
   Reference list-initialization ignores conversion functions
-  -
-  https://gcc.gnu.org/PR;>PR90390
+  14
+  https://gcc.gnu.org/PR90390;>PR90390,
+ https://gcc.gnu.org/PR113141;>PR113141
 
 
   https://wg21.link/cwg1997;>1997
@@ -19928,7 +19929,7 @@
 
   This page is currently maintained by mailto:pola...@redhat.com;>pola...@redhat.com.
   Last update:
-Fri Apr 12 02:22:38 PM EDT 2024
+Fri Apr 12 06:02:20 PM EDT 2024
   
 
 

---

Summary of changes:
 htdocs/projects/cxx-dr-status.html | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)


hooks/post-receive
-- 
gcc-wwwdocs


Re: [PATCH v3] c++: ICE with temporary of class type in array DMI [PR109966]

2024-04-12 Thread Marek Polacek
On Fri, Apr 12, 2024 at 04:15:45PM -0400, Jason Merrill wrote:
> On 3/14/24 17:26, Marek Polacek wrote:
> > 
> > In the following patch, I'm taking a different tack.  I believe
> > we ought to use TARGET_EXPR_ELIDING_P.  The gimplify_arg bit I'm
> > talking about below is this:
> > 
> >/* Also strip a TARGET_EXPR that would force an extra copy.  */
> >if (TREE_CODE (*arg_p) == TARGET_EXPR)
> >  {
> >tree init = TARGET_EXPR_INITIAL (*arg_p);
> >if (init
> >&& !VOID_TYPE_P (TREE_TYPE (init)))
> >  *arg_p = init;
> >  }
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > 
> > -- >8 --
> > This ICE started with the fairly complicated r13-765.  We crash in
> > gimplify_var_or_parm_decl because a stray VAR_DECL leaked there.
> > The problem is ultimately that potential_prvalue_result_of wasn't
> > correctly handling arrays and replace_placeholders_for_class_temp_r
> > replaced a PLACEHOLDER_EXPR in a TARGET_EXPR which is used in the
> > context of copy elision.  If I have
> > 
> >M m[2] = { M{""}, M{""} };
> > 
> > then we don't invoke the M(const M&) copy-ctor.
> > 
> > One part of the fix is to use TARGET_EXPR_ELIDING_P rather than
> > potential_prvalue_result_of.  That unfortunately doesn't handle the
> > case like
> > 
> >struct N { N(M); };
> >N arr[2] = { M{""}, M{""} };
> > 
> > because TARGET_EXPRs that initialize a function argument are not
> > marked TARGET_EXPR_ELIDING_P even though gimplify_arg drops such
> > TARGET_EXPRs on the floor.  We can use a pset to avoid replacing
> > placeholders in them.
> > 
> > I made an attempt to use set_target_expr_eliding in
> > convert_for_arg_passing but that regressed constexpr-diag1.C, and does
> > not seem like a prudent change in stage 4 anyway.
> 
> I tried the same thing to see what you mean, and that doesn't look like a
> regression to me, just a different (and more accurate) diagnostic.
> 
> But you're right that this patch is safer, and the other approach can wait
> for stage 1.  Will you queue that up?  In the mean time, this patch is OK.

Yeah, happy to; I've opened 114707 to remember.
 
> > I just realized this could also check !TARGET_EXPR_ELIDING_P; there's no 
> > point
> > to adding an eliding TARGET_EXPR into the pset.
> 
> ...with this change.

Thanks.

Marek



gcc-wwwdocs branch master updated. 3ca51fec661f3340fe308662405e602bcf3fe8d7

2024-04-12 Thread Marek Polacek via Gcc-cvs-wwwdocs
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gcc-wwwdocs".

The branch, master has been updated
   via  3ca51fec661f3340fe308662405e602bcf3fe8d7 (commit)
  from  033976162ed4745f7f808f14ba62b1c055e35d16 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -
commit 3ca51fec661f3340fe308662405e602bcf3fe8d7
Author: Marek Polacek 
Date:   Fri Apr 12 14:36:44 2024 -0400

cxx-dr-status: Minor update

diff --git a/htdocs/projects/cxx-dr-status.html 
b/htdocs/projects/cxx-dr-status.html
index fb3046cd..24c54cfd 100644
--- a/htdocs/projects/cxx-dr-status.html
+++ b/htdocs/projects/cxx-dr-status.html
@@ -15,7 +15,7 @@
 
   This table tracks the implementation status of C++ defect reports in GCC.
   It is based on C++ Standard Core Language Issue Table of Contents, Revision
-  111 (https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html;>here).
+  113 (https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html;>here).
 
   
 
@@ -18528,7 +18528,7 @@
   https://wg21.link/cwg2642;>2642
   C++23
   Inconsistent use of T and C
-  ?
+  N/A
   
 
 
@@ -18612,7 +18612,7 @@
   https://wg21.link/cwg2654;>2654
   C++23
   Un-deprecation of compound volatile assignments
-  ?
+  13
   
 
 
@@ -19025,7 +19025,7 @@
   https://wg21.link/cwg2713;>2713
   DRWP
   Initialization of reference-to-aggregate from designated initializer 
list
-  ?
+  Yes
   
 
 
@@ -19375,8 +19375,8 @@
   https://wg21.link/cwg2763;>2763
   DR
   Ignorability of [[noreturn]] during constant evaluation
-  ?
-  
+  No
+  https://gcc.gnu.org/PR114705;>PR114705
 
 
   https://wg21.link/cwg2764;>2764
@@ -19578,7 +19578,7 @@
   https://wg21.link/cwg2792;>2792
   DR
   Clean up specification of noexcept operator
-  ?
+  Yes
   
 
 
@@ -19928,7 +19928,7 @@
 
   This page is currently maintained by mailto:pola...@redhat.com;>pola...@redhat.com.
   Last update:
-Thu Apr 11 07:49:50 PM EDT 2024
+Fri Apr 12 02:22:38 PM EDT 2024
   
 
 

---

Summary of changes:
 htdocs/projects/cxx-dr-status.html | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)


hooks/post-receive
-- 
gcc-wwwdocs


[wwwdocs] Update cxx-dr-status page

2024-04-11 Thread Marek Polacek
A big update.  I posted a script to generate new entries and check
the existing separately.

W3 validated.  Pushed.

commit 9e32f911b70a8c2303b9b60679ce337896ccffdd
Author: Marek Polacek 
Date:   Thu Apr 11 21:18:23 2024 -0400

cxx-dr-status: Update from C++ Core Language Issue TOC, Revision 113

diff --git a/htdocs/projects/cxx-dr-status.html 
b/htdocs/projects/cxx-dr-status.html
index b63c47df..fb3046cd 100644
--- a/htdocs/projects/cxx-dr-status.html
+++ b/htdocs/projects/cxx-dr-status.html
@@ -61,19 +61,18 @@
   ?
   
 
-
+
   https://wg21.link/cwg6;>6
-  open
-  Should the optimization that allows a class object to alias another 
- object also allow the case of a parameter in an inline function to 
alias its argument?
-  -
+  NAD
+  Should the optimization that allows a class object to alias another 
object also allow the case of a parameter in an inline function to alias its 
argument?
+  N/A
   
 
 
   https://wg21.link/cwg7;>7
   NAD
   Can a class with a private virtual base class be derived from?
-  ?
+  No
   
 
 
@@ -1212,7 +1211,7 @@
 
 
   https://wg21.link/cwg170;>170
-  tentatively ready
+  DRWP
   Pointer-to-member conversions
   ?
   
@@ -1644,19 +1643,19 @@
   ?
   
 
-
+
   https://wg21.link/cwg232;>232
-  drafting
+  NAD
   Is indirection through a null pointer undefined behavior?
-  -
+  N/A
   
 
-
+
   https://wg21.link/cwg233;>233
-  open
+  drafting
   References vs pointers in UDC overload resolution
-  -
-  
+  No
+  https://gcc.gnu.org/PR114697;>PR114697
 
 
   https://wg21.link/cwg234;>234
@@ -3104,11 +3103,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg440;>440
-  open
+  NAD
   Allow implicit pointer-to-member conversion on nontype template 
argument
-  -
+  N/A
   
 
 
@@ -3195,11 +3194,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg453;>453
-  drafting
+  tentatively ready
   References may only bind to "valid" objects
-  -
+  ?
   
 
 
@@ -3237,11 +3236,11 @@
   No
   https://gcc.gnu.org/PR96138;>PR96138
 
-
+
   https://wg21.link/cwg459;>459
-  open
+  NAD
   Hiding of template parameters by base class members
-  -
+  N/A
   
 
 
@@ -3335,11 +3334,11 @@
   -
   
 
-
+
   https://wg21.link/cwg473;>473
-  open
+  NAD
   Block-scope declarations of allocator functions
-  -
+  N/A
   
 
 
@@ -3552,11 +3551,11 @@
   -
   
 
-
+
   https://wg21.link/cwg504;>504
-  open
+  NAD
   Should use of a variable in its own initializer require a 
diagnostic?
-  -
+  ?
   https://gcc.gnu.org/PR18635;>PR18635
 
 
@@ -3720,11 +3719,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg528;>528
-  open
+  NAD
   Why are incomplete class types not allowed with 
typeid?
-  -
+  N/A
   
 
 
@@ -3752,7 +3751,7 @@
   https://wg21.link/cwg532;>532
   C++11
   Member/nonmember operator template partial ordering
-  ?
+  14
   
 
 
@@ -4504,11 +4503,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg640;>640
-  open
+  NAD
   Accessing destroyed local objects of static storage duration
-  -
+  N/A
   
 
 
@@ -5050,11 +5049,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg718;>718
-  open
+  NAD
   Non-class, non-function friend declarations
-  -
+  N/A
   
 
 
@@ -6326,9 +6325,9 @@
 
 
   https://wg21.link/cwg900;>900
-  DRWP
+  C++23
   Lifetime of temporaries in range-based for
-  ?
+  No
   
 
 
@@ -7214,11 +7213,11 @@
   N/A
   
 
-
+
   https://wg21.link/cwg1027;>1027
-  drafting
+  review
   Type consistency and reallocation of scalar types
-  -
+  ?
   
 
 
@@ -7293,7 +7292,7 @@
 
 
   https://wg21.link/cwg1038;>1038
-  review
+  DR
   Overload resolution of x.static_func
   ?
   
@@ -7650,7 +7649,7 @@
 
 
   https://wg21.link/cwg1089;>1089
-  drafting
+  open
   Template parameters in member selections
   -
   
@@ -8812,7 +8811,7 @@
 
 
   https://wg21.link/cwg1255;>1255
-  open
+  drafting
   Definition problems with constexpr functions
   -
   
@@ -9498,7 +9497,7 @@
 
 
   https://wg21.link/cwg1353;>1353
-  tentatively ready
+  DRWP
   Array and variant members and deleted special member functions
  

[PATCH] contrib: add cxx-dr-table.sh

2024-04-11 Thread Marek Polacek
Ok for trunk?

-- >8 --
I use this script to keep <https://gcc.gnu.org/projects/cxx-dr-status.html>
up-to-date.  I thought it might be good to have it in contrib/, so I've
polished it a little bit.

contrib/ChangeLog:

* cxx-dr-table.sh: New file.
---
 contrib/cxx-dr-table.sh | 108 
 1 file changed, 108 insertions(+)
 create mode 100755 contrib/cxx-dr-table.sh

diff --git a/contrib/cxx-dr-table.sh b/contrib/cxx-dr-table.sh
new file mode 100755
index 000..9d67d176cad
--- /dev/null
+++ b/contrib/cxx-dr-table.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+# Script to check/update <https://gcc.gnu.org/projects/cxx-dr-status.html>
+# from <https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html>.
+# Use --generate only to add new DRs; don't use it to update the existing
+# ones because it would rewrite the Notes column.
+# Use --check to check if the existing entries need to be updated.
+# May need $ iconv -f iso-8859-1 -t utf-8 cwg_toc.html > cwg_toc2.html
+
+# Written by Marek Polacek 
+
+AWK=/usr/bin/awk
+DIFF=/usr/bin/vimdiff
+SED=/usr/bin/sed
+
+usage()
+{
+  echo "Usage: $0 --check cwg_toc.html 
~/src/gcc-wwwdocs/htdocs/projects/cxx-dr-status.html"
+  echo "   or: $0 --generate cwg_toc.html"
+}
+
+fatal_usage()
+{
+  usage >&2
+  exit 1
+}
+
+# Generate new DR entries.
+do_generate() {
+  $AWK '/A NAME=/{
+# 2838
+num = gensub(/(<.+>)(<.+>)(<.+>)(.+)(<.+>)/, "\\4", "g", $0)
+getline
+# Eat 
+getline
+# Eat 6.7.6
+getline
+# open
+status = gensub(/(<.+>)(.+)(<.+>)/, "\\2", "g", $0)
+getline
+# Eat 
+getline
+title = $0
+
+# Generate the HTML fragment.
+if (status == "open" || status == "drafting") {
+  print ""
+} else {
+  print ""
+}
+print "  https://wg21.link/cwg; num "\">" num ""
+print "  " status ""
+print "  " title ""
+if (status == "open" || status == "drafting") {
+  print "  -"
+} else {
+  print "  ?"
+}
+print "  "
+print ""
+  }' $1
+}
+
+# Check existing DR entries against the ISO version.
+do_check() {
+  # Generate a table from the upstream table: DR# + status + summary
+  # First, fix the quotes.
+  $SED -i $1 -e 's/\(\|\)/"/g'
+  $AWK '/A NAME=/{ print; getline; getline; getline; print; getline; getline; 
print }' $1 | \
+  $AWK -v RS='<[^>]+>' -v ORS= '1' | iconv -f UTF-8 -t ASCII//TRANSLIT > $tmp1
+
+  # Generate a table from our table: DR# + status + summary
+  $AWK '/wg21.link.cwg/{ print; getline; print; getline; print }' $2 | \
+  $AWK -v RS='<[^>]+>' -v ORS= '1' > $tmp2
+  $SED -i $tmp2 -e 's/^[ \t]*//'
+
+  # Compare the tables.
+  $DIFF $tmp1 $tmp2
+}
+
+if [ $# -lt 2 ]; then
+  fatal_usage
+fi
+
+tmp1="$(mktemp)"
+tmp2="$(mktemp)"
+
+cleanup() {
+  rm -f -- "$tmp1" "$tmp2"
+}
+
+trap cleanup 0
+
+case "$1" in
+  -c | --check)
+if [ $# -lt 3 ]; then
+  fatal_usage
+fi
+do_check "$2" "$3"
+;;
+  -g | --generate)
+do_generate "$2"
+;;
+  *)
+fatal_usage
+;;
+esac
+
+exit

base-commit: d1a21a6f9474e519926d20a7c6d664be03aff3ee
-- 
2.44.0



gcc-wwwdocs branch master updated. 9e32f911b70a8c2303b9b60679ce337896ccffdd

2024-04-11 Thread Marek Polacek via Gcc-cvs-wwwdocs
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gcc-wwwdocs".

The branch, master has been updated
   via  9e32f911b70a8c2303b9b60679ce337896ccffdd (commit)
  from  edc6411ab81dde8a0621ee706e6ff951be645922 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -
commit 9e32f911b70a8c2303b9b60679ce337896ccffdd
Author: Marek Polacek 
Date:   Thu Apr 11 21:18:23 2024 -0400

cxx-dr-status: Update from C++ Core Language Issue TOC, Revision 113

diff --git a/htdocs/projects/cxx-dr-status.html 
b/htdocs/projects/cxx-dr-status.html
index b63c47df..fb3046cd 100644
--- a/htdocs/projects/cxx-dr-status.html
+++ b/htdocs/projects/cxx-dr-status.html
@@ -61,19 +61,18 @@
   ?
   
 
-
+
   https://wg21.link/cwg6;>6
-  open
-  Should the optimization that allows a class object to alias another 
- object also allow the case of a parameter in an inline function to 
alias its argument?
-  -
+  NAD
+  Should the optimization that allows a class object to alias another 
object also allow the case of a parameter in an inline function to alias its 
argument?
+  N/A
   
 
 
   https://wg21.link/cwg7;>7
   NAD
   Can a class with a private virtual base class be derived from?
-  ?
+  No
   
 
 
@@ -1212,7 +1211,7 @@
 
 
   https://wg21.link/cwg170;>170
-  tentatively ready
+  DRWP
   Pointer-to-member conversions
   ?
   
@@ -1644,19 +1643,19 @@
   ?
   
 
-
+
   https://wg21.link/cwg232;>232
-  drafting
+  NAD
   Is indirection through a null pointer undefined behavior?
-  -
+  N/A
   
 
-
+
   https://wg21.link/cwg233;>233
-  open
+  drafting
   References vs pointers in UDC overload resolution
-  -
-  
+  No
+  https://gcc.gnu.org/PR114697;>PR114697
 
 
   https://wg21.link/cwg234;>234
@@ -3104,11 +3103,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg440;>440
-  open
+  NAD
   Allow implicit pointer-to-member conversion on nontype template 
argument
-  -
+  N/A
   
 
 
@@ -3195,11 +3194,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg453;>453
-  drafting
+  tentatively ready
   References may only bind to "valid" objects
-  -
+  ?
   
 
 
@@ -3237,11 +3236,11 @@
   No
   https://gcc.gnu.org/PR96138;>PR96138
 
-
+
   https://wg21.link/cwg459;>459
-  open
+  NAD
   Hiding of template parameters by base class members
-  -
+  N/A
   
 
 
@@ -3335,11 +3334,11 @@
   -
   
 
-
+
   https://wg21.link/cwg473;>473
-  open
+  NAD
   Block-scope declarations of allocator functions
-  -
+  N/A
   
 
 
@@ -3552,11 +3551,11 @@
   -
   
 
-
+
   https://wg21.link/cwg504;>504
-  open
+  NAD
   Should use of a variable in its own initializer require a 
diagnostic?
-  -
+  ?
   https://gcc.gnu.org/PR18635;>PR18635
 
 
@@ -3720,11 +3719,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg528;>528
-  open
+  NAD
   Why are incomplete class types not allowed with 
typeid?
-  -
+  N/A
   
 
 
@@ -3752,7 +3751,7 @@
   https://wg21.link/cwg532;>532
   C++11
   Member/nonmember operator template partial ordering
-  ?
+  14
   
 
 
@@ -4504,11 +4503,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg640;>640
-  open
+  NAD
   Accessing destroyed local objects of static storage duration
-  -
+  N/A
   
 
 
@@ -5050,11 +5049,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg718;>718
-  open
+  NAD
   Non-class, non-function friend declarations
-  -
+  N/A
   
 
 
@@ -6326,9 +6325,9 @@
 
 
   https://wg21.link/cwg900;>900
-  DRWP
+  C++23
   Lifetime of temporaries in range-based for
-  ?
+  No
   
 
 
@@ -7214,11 +7213,11 @@
   N/A
   
 
-
+
   https://wg21.link/cwg1027;>1027
-  drafting
+  review
   Type consistency and reallocation of scalar types
-  -
+  ?
   
 
 
@@ -7293,7 +7292,7 @@
 
 
   https://wg21.link/cwg1038;>1038
-  review
+  DR
   Overload resolution of x.static_func
   ?
   
@@ -7650,7 +7649,7 @@
 
 
   https://wg21.link/cwg108

[gcc r14-9903] target: missing -Whardened with -fcf-protection=none [PR114606]

2024-04-10 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:b8b148bc22673689fda19711b428b544462be2e4

commit r14-9903-gb8b148bc22673689fda19711b428b544462be2e4
Author: Marek Polacek 
Date:   Fri Apr 5 12:37:19 2024 -0400

target: missing -Whardened with -fcf-protection=none [PR114606]

-Whardened warns when -fhardened couldn't enable a hardening option
because that option was disabled on the command line, e.g.:

$ ./cc1plus -quiet g.C -fhardened -O2 -fstack-protector
cc1plus: warning: '-fstack-protector-strong' is not enabled by '-fhardened' 
because it was specified on the command line [-Whardened]

but it doesn't work as expected with -fcf-protection=none:

$ ./cc1plus -quiet g.C -fhardened -O2 -fcf-protection=none

because we're checking == CF_NONE which doesn't distinguish between nothing
and -fcf-protection=none.  I should have used opts_set, like below.

PR target/114606

gcc/ChangeLog:

* config/i386/i386-options.cc (ix86_option_override_internal): Use
opts_set rather than checking == CF_NONE.

gcc/testsuite/ChangeLog:

* gcc.target/i386/fhardened-1.c: New test.
* gcc.target/i386/fhardened-2.c: New test.

Reviewed-by: Jakub Jelinek 

Diff:
---
 gcc/config/i386/i386-options.cc | 2 +-
 gcc/testsuite/gcc.target/i386/fhardened-1.c | 8 
 gcc/testsuite/gcc.target/i386/fhardened-2.c | 8 
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 7896d576977..68a2e1c6910 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -3242,7 +3242,7 @@ ix86_option_override_internal (bool main_args_p,
  on the command line.  */
   if (opts->x_flag_hardened && cf_okay_p)
 {
-  if (opts->x_flag_cf_protection == CF_NONE)
+  if (!opts_set->x_flag_cf_protection)
opts->x_flag_cf_protection = CF_FULL;
   else if (opts->x_flag_cf_protection != CF_FULL)
warning_at (UNKNOWN_LOCATION, OPT_Whardened,
diff --git a/gcc/testsuite/gcc.target/i386/fhardened-1.c 
b/gcc/testsuite/gcc.target/i386/fhardened-1.c
new file mode 100644
index 000..55d1718ff55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fhardened-1.c
@@ -0,0 +1,8 @@
+/* PR target/114606 */
+/* { dg-options "-fhardened -O2 -fcf-protection=none" } */
+
+#ifdef __CET__
+# error "-fcf-protection enabled when it should not be"
+#endif
+
+/* { dg-warning ".-fcf-protection=full. is not enabled by .-fhardened. because 
it was specified" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/fhardened-2.c 
b/gcc/testsuite/gcc.target/i386/fhardened-2.c
new file mode 100644
index 000..9b8c1381c19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fhardened-2.c
@@ -0,0 +1,8 @@
+/* PR target/114606 */
+/* { dg-options "-fhardened -O2" } */
+
+#if __CET__ != 3
+# error "-fcf-protection not enabled"
+#endif
+
+/* { dg-bogus ".-fcf-protection=full. is not enabled by .-fhardened. because 
it was specified" "" { target *-*-* } 0 } */


[wwwdocs] Document more C++ changes

2024-04-10 Thread Marek Polacek
I went through all cp/ commits in GCC 14 and documented a few interesting
user-visible changes, modulo Modules.

W3 validated.  Pushed.

commit d65752191baaa137eb6d604b802e7b9170a39752
Author: Marek Polacek 
Date:   Wed Apr 10 17:21:09 2024 -0400

gcc-14/changes: Document more C++ changes

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 4a063346..5c2439ab 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -273,6 +273,9 @@ a work-in-progress.
   
   Several C++23 features have been implemented:
 
+  https://wg21.link/P0847R7;>P0847R7, Deducing this
+  (https://gcc.gnu.org/PR102609;>PR102609)
+  
   https://wg21.link/P2280R4;>P2280R4, Using unknown
   references in constant expressions
   (https://gcc.gnu.org/PR106650;>PR106650)
@@ -289,12 +292,26 @@ a work-in-progress.
   
   Several C++ Defect Reports have been resolved, e.g.:
 
+  https://wg21.link/cwg532;>DR 532,
+  Member/nonmember operator template partial ordering
   https://wg21.link/cwg976;>DR 976,
   Deduction for const T& conversion operators
+  https://wg21.link/cwg2262;>DR 2262,
+   Attributes for asm-definition
+  https://wg21.link/cwg2359;>DR 2359,
+  Unintended copy initialization with designated initializers
+  https://wg21.link/cwg2386;>DR 2386,
+  tuple_size requirements for structured binding
   https://wg21.link/cwg2406;>DR 2406,
   [[fallthrough]] attribute and iteration statements
   https://wg21.link/cwg2543;>DR 2543,
   constinit and optimized dynamic initialization
+  https://wg21.link/cwg2586;>DR 2586,
+  Explicit object parameter for assignment and comparison
+  https://wg21.link/cwg2735;>DR 2735,
+  List-initialization and conversions in overload resolution
+  https://wg21.link/cwg2799;>DR 2799,
+  Inheriting default constructors
 
   
   
@@ -304,6 +321,85 @@ a work-in-progress.
 the template is instantiated ("required from here"),
 rather than just print filename and line/column numbers.
   
+  New built-in __type_pack_element to speed up traits
+  such as std::tuple_element
+  (https://gcc.gnu.org/PR100157;>PR100157)
+  goto can cross the initialization of a trivially initialized
+  object with a non-trivial destructor
+  (https://cplusplus.github.io/CWG/issues/2256.html;>DR 
2256)
+  -Wdangling-reference false positives have been reduced.  The
+  warning does not warn about std::span-like classes; there is
+  also a new attribute gnu::no_dangling to suppress the
+  warning.  See
+  https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#index-Wdangling-reference;>the
 manual
+  for more info.
+  noexcept(expr) is now mangled as per the Itanium ABI
+  the named return value optimization can now be performed even for
+  variables declared in an inner block of a function, see the
+  https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/testsuite/g%2B%2B.dg/opt/nrv23.C;h=9e1253cd830a84ad4de5ff3076a07c543afe344f;hb=7e0b65b239c3a0d68ce94896b236b03de666ffd6;>
+  test
+  New -Wnrvo warning, to warn if the named return value
+  optimization is not performed although it is allowed by
+  [class.copy.elision].  See
+  https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wnrvo;>the 
manual
+  for more info.
+  The backing array for std::initializer_list has been made
+  static, allowing combining multiple equivalent initializer-lists
+  (https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4d935f52b0d5c00fcc154461b87415ebd8791a94;>git)
+  
+  New -Welaborated-enum-base warning, to warn if an additional
+  enum-base is used in an elaborated-type-specifier
+  Better #include hints for missing headers
+  (https://gcc.gnu.org/PR110164;>PR110164)
+  The arguments of a variable template-id are coerced earlier than
+  before, so various problems are detected earlier
+  (https://gcc.gnu.org/PR89442;>PR89442)
+  -Wmissing-field-initializers is no longer emitted for
+  empty classes
+  (https://gcc.gnu.org/PR110064;>PR110064)
+  The constexpr code now tracks lifetimes in constant evaluation; this
+  change helps to detect bugs such as accessing a variable whose
+  lifetime has ended
+  (https://gcc.gnu.org/PR70331;>PR70331,
+  https://gcc.gnu.org/PR96630;>PR96630,
+  https://gcc.gnu.org/PR98675;>PR98675)
+  
+  Array destruction can now be devirtualized
+  In-class member variable template partial specializations are now
+  accepted (https://gcc.gnu.org/PR71954;>PR71954)
+  Improved diagnostic for explicit conversion functions: when a conversion
+  doesn't work out only because the conversion function necessary to do the
+  conversion couldn't be used because it was marked explicit, explain that
+  to the user
+  (

gcc-wwwdocs branch master updated. d65752191baaa137eb6d604b802e7b9170a39752

2024-04-10 Thread Marek Polacek via Gcc-cvs-wwwdocs
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gcc-wwwdocs".

The branch, master has been updated
   via  d65752191baaa137eb6d604b802e7b9170a39752 (commit)
  from  73b90bbb8534ccf21dc1d4c6edca36a894a84d3b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -
commit d65752191baaa137eb6d604b802e7b9170a39752
Author: Marek Polacek 
Date:   Wed Apr 10 17:21:09 2024 -0400

gcc-14/changes: Document more C++ changes

diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
index 4a063346..5c2439ab 100644
--- a/htdocs/gcc-14/changes.html
+++ b/htdocs/gcc-14/changes.html
@@ -273,6 +273,9 @@ a work-in-progress.
   
   Several C++23 features have been implemented:
 
+  https://wg21.link/P0847R7;>P0847R7, Deducing this
+  (https://gcc.gnu.org/PR102609;>PR102609)
+  
   https://wg21.link/P2280R4;>P2280R4, Using unknown
   references in constant expressions
   (https://gcc.gnu.org/PR106650;>PR106650)
@@ -289,12 +292,26 @@ a work-in-progress.
   
   Several C++ Defect Reports have been resolved, e.g.:
 
+  https://wg21.link/cwg532;>DR 532,
+  Member/nonmember operator template partial ordering
   https://wg21.link/cwg976;>DR 976,
   Deduction for const T& conversion operators
+  https://wg21.link/cwg2262;>DR 2262,
+   Attributes for asm-definition
+  https://wg21.link/cwg2359;>DR 2359,
+  Unintended copy initialization with designated initializers
+  https://wg21.link/cwg2386;>DR 2386,
+  tuple_size requirements for structured binding
   https://wg21.link/cwg2406;>DR 2406,
   [[fallthrough]] attribute and iteration statements
   https://wg21.link/cwg2543;>DR 2543,
   constinit and optimized dynamic initialization
+  https://wg21.link/cwg2586;>DR 2586,
+  Explicit object parameter for assignment and comparison
+  https://wg21.link/cwg2735;>DR 2735,
+  List-initialization and conversions in overload resolution
+  https://wg21.link/cwg2799;>DR 2799,
+  Inheriting default constructors
 
   
   
@@ -304,6 +321,85 @@ a work-in-progress.
 the template is instantiated ("required from here"),
 rather than just print filename and line/column numbers.
   
+  New built-in __type_pack_element to speed up traits
+  such as std::tuple_element
+  (https://gcc.gnu.org/PR100157;>PR100157)
+  goto can cross the initialization of a trivially initialized
+  object with a non-trivial destructor
+  (https://cplusplus.github.io/CWG/issues/2256.html;>DR 
2256)
+  -Wdangling-reference false positives have been reduced.  The
+  warning does not warn about std::span-like classes; there is
+  also a new attribute gnu::no_dangling to suppress the
+  warning.  See
+  https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#index-Wdangling-reference;>the
 manual
+  for more info.
+  noexcept(expr) is now mangled as per the Itanium ABI
+  the named return value optimization can now be performed even for
+  variables declared in an inner block of a function, see the
+  https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/testsuite/g%2B%2B.dg/opt/nrv23.C;h=9e1253cd830a84ad4de5ff3076a07c543afe344f;hb=7e0b65b239c3a0d68ce94896b236b03de666ffd6;>
+  test
+  New -Wnrvo warning, to warn if the named return value
+  optimization is not performed although it is allowed by
+  [class.copy.elision].  See
+  https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wnrvo;>the 
manual
+  for more info.
+  The backing array for std::initializer_list has been made
+  static, allowing combining multiple equivalent initializer-lists
+  (https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4d935f52b0d5c00fcc154461b87415ebd8791a94;>git)
+  
+  New -Welaborated-enum-base warning, to warn if an additional
+  enum-base is used in an elaborated-type-specifier
+  Better #include hints for missing headers
+  (https://gcc.gnu.org/PR110164;>PR110164)
+  The arguments of a variable template-id are coerced earlier than
+  before, so various problems are detected earlier
+  (https://gcc.gnu.org/PR89442;>PR89442)
+  -Wmissing-field-initializers is no longer emitted for
+  empty classes
+  (https://gcc.gnu.org/PR110064;>PR110064)
+  The constexpr code now tracks lifetimes in constant evaluation; this
+  change helps to detect bugs such as accessing a variable whose
+  lifetime has ended
+  (https://gcc.gnu.org/PR70331;>PR70331,
+  https://gcc.gnu.org/PR96630;>PR96630,
+  https://gcc.gnu.org/PR98675;>PR98675)
+  
+  Array des

Re: [PATCH] c++: Fix up maybe_warn_for_constant_evaluated calls [PR114580]

2024-04-05 Thread Marek Polacek
On Fri, Apr 05, 2024 at 09:40:48AM +0200, Jakub Jelinek wrote:
> Hi!
> 
> When looking at maybe_warn_for_constant_evaluated for the trivial
> infinite loops patch, I've noticed that it can emit weird diagnostics
> for if constexpr in templates, first warn that std::is_constant_evaluted()
> always evaluates to false (because the function template is not constexpr)
> and then during instantiation warn that std::is_constant_evaluted()
> always evaluates to true (because it is used in if constexpr condition).
> Now, only the latter is actually true, even when the if constexpr
> is in a non-constexpr function, it will still always evaluate to true.
> 
> So, the following patch fixes it to call maybe_warn_for_constant_evaluated
> always with IF_STMT_CONSTEXPR_P (if_stmt) as the second argument rather than
> true if it is if constexpr with non-dependent condition etc.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2024-04-05  Jakub Jelinek  
> 
>   PR c++/114580
>   * semantics.cc (finish_if_stmt_cond): Call
>   maybe_warn_for_constant_evaluated with IF_STMT_CONSTEXPR_P (if_stmt)
>   as the second argument, rather than true/false depending on if
>   it is if constexpr with non-dependent constant expression with
>   bool type.
> 
>   * g++.dg/cpp2a/is-constant-evaluated15.C: New test.
> 
> --- gcc/cp/semantics.cc.jj2024-04-03 09:58:33.407772541 +0200
> +++ gcc/cp/semantics.cc   2024-04-04 12:11:36.203886572 +0200
> @@ -1126,6 +1126,9 @@ tree
>  finish_if_stmt_cond (tree orig_cond, tree if_stmt)
>  {
>tree cond = maybe_convert_cond (orig_cond);
> +  maybe_warn_for_constant_evaluated (cond,
> +  /*constexpr_if=*/
> +  IF_STMT_CONSTEXPR_P (if_stmt));

I don't think we need the comment anymore since it's clear what the
argument does, and then the whole call can fit on a single line.

But either way, the patch looks good, thanks.

>if (IF_STMT_CONSTEXPR_P (if_stmt)
>&& !type_dependent_expression_p (cond)
>&& require_constant_expression (cond)
> @@ -1134,16 +1137,11 @@ finish_if_stmt_cond (tree orig_cond, tre
>converted to bool.  */
>&& TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node)
>  {
> -  maybe_warn_for_constant_evaluated (cond, /*constexpr_if=*/true);
>cond = instantiate_non_dependent_expr (cond);
>cond = cxx_constant_value (cond);
>  }
> -  else
> -{
> -  maybe_warn_for_constant_evaluated (cond, /*constexpr_if=*/false);
> -  if (processing_template_decl)
> - cond = orig_cond;
> -}
> +  else if (processing_template_decl)
> +cond = orig_cond;
>finish_cond (_COND (if_stmt), cond);
>add_stmt (if_stmt);
>THEN_CLAUSE (if_stmt) = push_stmt_list ();
> --- gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated15.C.jj   2024-04-04 
> 12:23:36.706962932 +0200
> +++ gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated15.C  2024-04-04 
> 12:22:29.915882859 +0200
> @@ -0,0 +1,28 @@
> +// PR c++/114580
> +// { dg-do compile { target c++17 } }
> +// { dg-options "-Wtautological-compare" }
> +
> +namespace std {
> +  constexpr inline bool
> +  is_constant_evaluated () noexcept
> +  {
> +#if __cpp_if_consteval >= 202106L
> +if consteval { return true; } else { return false; }
> +#else
> +return __builtin_is_constant_evaluated ();
> +#endif
> +  }
> +}
> +
> +template 
> +void foo ()
> +{
> +  if constexpr ((T) std::is_constant_evaluated ())   // { dg-warning 
> "'std::is_constant_evaluated' always evaluates to true in 'if constexpr'" }
> +;// { dg-bogus 
> "'std::is_constant_evaluated' always evaluates to false in a non-'constexpr' 
> function" }
> +}
> +
> +void
> +bar ()
> +{
> +  foo  ();
> +}
> 
>   Jakub
> 

Marek



[PATCH v2] target: missing -Whardened with -fcf-protection=none [PR114606]

2024-04-05 Thread Marek Polacek
On Fri, Apr 05, 2024 at 08:28:08PM +0200, Jakub Jelinek wrote:
> On Fri, Apr 05, 2024 at 02:22:18PM -0400, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > -Whardened warns when -fhardened couldn't enable a hardening option
> > because that option was disabled on the command line, e.g.:
> > 
> > $ ./cc1plus -quiet g.C -fhardened -O2 -fstack-protector
> > cc1plus: warning: '-fstack-protector-strong' is not enabled by '-fhardened' 
> > because it was specified on the command line [-Whardened]
> > 
> > but it doesn't work as expected with -fcf-protection=none:
> > 
> > $ ./cc1plus -quiet g.C -fhardened -O2 -fcf-protection=none
> > 
> > because we're checking == CF_NONE which doesn't distinguish between nothing
> > and -fcf-protection=none.  I should have used OPTION_SET_P, like below.
> > 
> > PR target/114606
> > 
> > gcc/ChangeLog:
> > 
> > * config/i386/i386-options.cc (ix86_option_override_internal): Use
> > OPTION_SET_P rather than checking == CF_NONE.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * gcc.target/i386/fhardened-1.c: New test.
> > * gcc.target/i386/fhardened-2.c: New test.
> > ---
> >  gcc/config/i386/i386-options.cc | 2 +-
> >  gcc/testsuite/gcc.target/i386/fhardened-1.c | 8 
> >  gcc/testsuite/gcc.target/i386/fhardened-2.c | 8 
> >  3 files changed, 17 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/gcc.target/i386/fhardened-1.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/fhardened-2.c
> > 
> > diff --git a/gcc/config/i386/i386-options.cc 
> > b/gcc/config/i386/i386-options.cc
> > index 7896d576977..20c6dc48090 100644
> > --- a/gcc/config/i386/i386-options.cc
> > +++ b/gcc/config/i386/i386-options.cc
> > @@ -3242,7 +3242,7 @@ ix86_option_override_internal (bool main_args_p,
> >   on the command line.  */
> >if (opts->x_flag_hardened && cf_okay_p)
> >  {
> > -  if (opts->x_flag_cf_protection == CF_NONE)
> > +  if (!OPTION_SET_P (flag_cf_protection))
> 
> This function is passed explicit opts and opts_set arguments, so it
> shouldn't be using flag_something macros nor OPTION_SET_P, as the former
> use global_options.x_flag_something rather than opts->x_flag_something
> and the latter uses global_options_set.x_flag_something.

Ah right, so the other uses of OPTION_SET_P in ix86_option_override_internal
are also wrong?

> So, I think you want to use if (!opts_set->x_flag_cf_protection)
> instead.

Fixed below, thanks.

New tests passed on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
-Whardened warns when -fhardened couldn't enable a hardening option
because that option was disabled on the command line, e.g.:

$ ./cc1plus -quiet g.C -fhardened -O2 -fstack-protector
cc1plus: warning: '-fstack-protector-strong' is not enabled by '-fhardened' 
because it was specified on the command line [-Whardened]

but it doesn't work as expected with -fcf-protection=none:

$ ./cc1plus -quiet g.C -fhardened -O2 -fcf-protection=none

because we're checking == CF_NONE which doesn't distinguish between nothing
and -fcf-protection=none.  I should have used opts_set, like below.

PR target/114606

gcc/ChangeLog:

* config/i386/i386-options.cc (ix86_option_override_internal): Use
opts_set rather than checking == CF_NONE.

gcc/testsuite/ChangeLog:

* gcc.target/i386/fhardened-1.c: New test.
* gcc.target/i386/fhardened-2.c: New test.
---
 gcc/config/i386/i386-options.cc | 2 +-
 gcc/testsuite/gcc.target/i386/fhardened-1.c | 8 
 gcc/testsuite/gcc.target/i386/fhardened-2.c | 8 
 3 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/fhardened-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/fhardened-2.c

diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 7896d576977..68a2e1c6910 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -3242,7 +3242,7 @@ ix86_option_override_internal (bool main_args_p,
  on the command line.  */
   if (opts->x_flag_hardened && cf_okay_p)
 {
-  if (opts->x_flag_cf_protection == CF_NONE)
+  if (!opts_set->x_flag_cf_protection)
opts->x_flag_cf_protection = CF_FULL;
   else if (opts->x_flag_cf_protection != CF_FULL)
warning_at (UNKNOWN_LOCATION, OPT_Whardened,
diff --git a/gcc/testsuite/gcc.target/i386/fhardened-1.c 
b/gcc/testsuite/gcc.target/i386/fhardened-1.c
new file mode 100644
index 000..55d1718ff55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fhardened-1.

[PATCH] target: missing -Whardened with -fcf-protection=none [PR114606]

2024-04-05 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
-Whardened warns when -fhardened couldn't enable a hardening option
because that option was disabled on the command line, e.g.:

$ ./cc1plus -quiet g.C -fhardened -O2 -fstack-protector
cc1plus: warning: '-fstack-protector-strong' is not enabled by '-fhardened' 
because it was specified on the command line [-Whardened]

but it doesn't work as expected with -fcf-protection=none:

$ ./cc1plus -quiet g.C -fhardened -O2 -fcf-protection=none

because we're checking == CF_NONE which doesn't distinguish between nothing
and -fcf-protection=none.  I should have used OPTION_SET_P, like below.

PR target/114606

gcc/ChangeLog:

* config/i386/i386-options.cc (ix86_option_override_internal): Use
OPTION_SET_P rather than checking == CF_NONE.

gcc/testsuite/ChangeLog:

* gcc.target/i386/fhardened-1.c: New test.
* gcc.target/i386/fhardened-2.c: New test.
---
 gcc/config/i386/i386-options.cc | 2 +-
 gcc/testsuite/gcc.target/i386/fhardened-1.c | 8 
 gcc/testsuite/gcc.target/i386/fhardened-2.c | 8 
 3 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/fhardened-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/fhardened-2.c

diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 7896d576977..20c6dc48090 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -3242,7 +3242,7 @@ ix86_option_override_internal (bool main_args_p,
  on the command line.  */
   if (opts->x_flag_hardened && cf_okay_p)
 {
-  if (opts->x_flag_cf_protection == CF_NONE)
+  if (!OPTION_SET_P (flag_cf_protection))
opts->x_flag_cf_protection = CF_FULL;
   else if (opts->x_flag_cf_protection != CF_FULL)
warning_at (UNKNOWN_LOCATION, OPT_Whardened,
diff --git a/gcc/testsuite/gcc.target/i386/fhardened-1.c 
b/gcc/testsuite/gcc.target/i386/fhardened-1.c
new file mode 100644
index 000..55d1718ff55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fhardened-1.c
@@ -0,0 +1,8 @@
+/* PR target/114606 */
+/* { dg-options "-fhardened -O2 -fcf-protection=none" } */
+
+#ifdef __CET__
+# error "-fcf-protection enabled when it should not be"
+#endif
+
+/* { dg-warning ".-fcf-protection=full. is not enabled by .-fhardened. because 
it was specified" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/fhardened-2.c 
b/gcc/testsuite/gcc.target/i386/fhardened-2.c
new file mode 100644
index 000..9b8c1381c19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fhardened-2.c
@@ -0,0 +1,8 @@
+/* PR target/114606 */
+/* { dg-options "-fhardened -O2" } */
+
+#if __CET__ != 3
+# error "-fcf-protection not enabled"
+#endif
+
+/* { dg-bogus ".-fcf-protection=full. is not enabled by .-fhardened. because 
it was specified" "" { target *-*-* } 0 } */

base-commit: e7d015b2506a1d9e84d9f7182e42e097147527e1
-- 
2.44.0



[gcc r14-9815] c++: add fixed test [PR91079]

2024-04-05 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:2b2d3a135a43cbafadd8957e0b2543f38c390437

commit r14-9815-g2b2d3a135a43cbafadd8957e0b2543f38c390437
Author: Marek Polacek 
Date:   Fri Apr 5 13:40:33 2024 -0400

c++: add fixed test [PR91079]

Fixed by r12-2975.

PR c++/91079
DR 1881

gcc/testsuite/ChangeLog:

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

Diff:
---
 gcc/testsuite/g++.dg/ext/is_std_layout5.C | 13 +
 1 file changed, 13 insertions(+)

diff --git a/gcc/testsuite/g++.dg/ext/is_std_layout5.C 
b/gcc/testsuite/g++.dg/ext/is_std_layout5.C
new file mode 100644
index 000..875f3c0948d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_std_layout5.C
@@ -0,0 +1,13 @@
+// PR c++/91079
+// DR 1881 - Standard-layout classes and unnamed bit-fields
+// { dg-do compile { target c++11 } }
+
+struct A { int a : 4; };
+struct B : A { int b : 3; };
+static_assert(__is_standard_layout(A), "");
+static_assert(!__is_standard_layout(B), "");
+
+struct C { int : 0; };
+struct D : C { int : 0; };
+static_assert(__is_standard_layout(C), "");
+static_assert(!__is_standard_layout(D), "");


[pushed] c++: add fixed test [PR91079]

2024-04-05 Thread Marek Polacek
Tested x86_64-pc-linux-gnu, applying to trunk.

-- >8 --
Fixed by r12-2975.

PR c++/91079
DR 1881

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_std_layout5.C: New test.
---
 gcc/testsuite/g++.dg/ext/is_std_layout5.C | 13 +
 1 file changed, 13 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_std_layout5.C

diff --git a/gcc/testsuite/g++.dg/ext/is_std_layout5.C 
b/gcc/testsuite/g++.dg/ext/is_std_layout5.C
new file mode 100644
index 000..875f3c0948d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_std_layout5.C
@@ -0,0 +1,13 @@
+// PR c++/91079
+// DR 1881 - Standard-layout classes and unnamed bit-fields
+// { dg-do compile { target c++11 } }
+
+struct A { int a : 4; };
+struct B : A { int b : 3; };
+static_assert(__is_standard_layout(A), "");
+static_assert(!__is_standard_layout(B), "");
+
+struct C { int : 0; };
+struct D : C { int : 0; };
+static_assert(__is_standard_layout(C), "");
+static_assert(!__is_standard_layout(D), "");

base-commit: e7d015b2506a1d9e84d9f7182e42e097147527e1
-- 
2.44.0



[pushed] c-family: remove dead #undef

2024-04-05 Thread Marek Polacek
Tested x86_64-pc-linux-gnu, applying to trunk.

-- >8 --
The #undef was added in r0-90320-g100d537d7a7b5c but it never did
anything.

gcc/c-family/ChangeLog:

* c-warn.cc (warn_about_parentheses): Remove an #undef.
---
 gcc/c-family/c-warn.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 8168696fa45..bff87be05ae 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -2176,7 +2176,6 @@ warn_about_parentheses (location_t loc, enum tree_code 
code,
}
   return;
 }
-#undef NOT_A_BOOLEAN_EXPR_P
 }
 
 /* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */

base-commit: 679f81a32f706645f45900fdb1659fb5fe607f77
-- 
2.44.0



[gcc r14-9810] c-family: remove dead #undef

2024-04-05 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:e4d074321bcafa6504ee6b77754b4450a4622f9d

commit r14-9810-ge4d074321bcafa6504ee6b77754b4450a4622f9d
Author: Marek Polacek 
Date:   Thu Apr 4 19:28:00 2024 -0400

c-family: remove dead #undef

The #undef was added in r0-90320-g100d537d7a7b5c but it never did
anything.

gcc/c-family/ChangeLog:

* c-warn.cc (warn_about_parentheses): Remove an #undef.

Diff:
---
 gcc/c-family/c-warn.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 8168696fa45..bff87be05ae 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -2176,7 +2176,6 @@ warn_about_parentheses (location_t loc, enum tree_code 
code,
}
   return;
 }
-#undef NOT_A_BOOLEAN_EXPR_P
 }
 
 /* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */


[gcc r14-9809] c++: constexpr error with fn redecl in local scope [PR111132]

2024-04-05 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:8c9063825ce726fcbbc067d8a6d062cc2d4acf5e

commit r14-9809-g8c9063825ce726fcbbc067d8a6d062cc2d4acf5e
Author: Marek Polacek 
Date:   Tue Apr 2 12:59:38 2024 -0400

c++: constexpr error with fn redecl in local scope [PR32]

We evaluate constexpr functions on the original, pre-genericization bodies.
That means that the function body we're evaluating will not have gone
through cp_genericize_r's "Map block scope extern declarations to visible
declarations with the same name and type in outer scopes if any".  Here:

  constexpr bool bar() { return true; } // #1
  constexpr bool foo() {
constexpr bool bar(void); // #2
return bar();
  }

it means that we:
1) register_constexpr_fundef (#1)
2) cp_genericize (#1)
   nothing interesting happens
3) register_constexpr_fundef (foo)
   does copy_fn, so we have two copies of the BIND_EXPR
4) cp_genericize (foo)
   this remaps #2 to #1, but only on one copy of the BIND_EXPR
5) retrieve_constexpr_fundef (foo)
   we find it, no problem
6) retrieve_constexpr_fundef (#2)
   and here #2 isn't found in constexpr_fundef_table, because
   we're working on the BIND_EXPR copy where #2 wasn't mapped to #1
   so we fail.  We've only registered #1.

It should work to use DECL_LOCAL_DECL_ALIAS (which used to be
extern_decl_map).  We evaluate constexpr functions on pre-cp_fold
bodies to avoid diagnostic problems, but the remapping I'm proposing
should not interfere with diagnostics.

This is not a problem for a global scope redeclaration; there we go
through duplicate_decls which keeps the DECL_UID:
  DECL_UID (olddecl) = olddecl_uid;
and DECL_UID is what constexpr_fundef_hasher::hash uses.

PR c++/32

gcc/cp/ChangeLog:

* constexpr.cc (get_function_named_in_call): Use
cp_get_fndecl_from_callee.
* cvt.cc (cp_get_fndecl_from_callee): If there's a
DECL_LOCAL_DECL_ALIAS, use it.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-redeclaration3.C: New test.
* g++.dg/cpp0x/constexpr-redeclaration4.C: New test.

Diff:
---
 gcc/cp/constexpr.cc   | 10 --
 gcc/cp/cvt.cc | 18 --
 gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C | 13 +
 gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C | 14 ++
 4 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa346fe01c9..410ccdf597f 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -702,16 +702,14 @@ build_constexpr_constructor_member_initializers (tree 
type, tree body)
 
 /* We have an expression tree T that represents a call, either CALL_EXPR
or AGGR_INIT_EXPR.  If the call is lexically to a named function,
-   retrun the _DECL for that function.  */
+   return the _DECL for that function.  */
 
 static tree
 get_function_named_in_call (tree t)
 {
-  tree fun = cp_get_callee (t);
-  if (fun && TREE_CODE (fun) == ADDR_EXPR
-  && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
-fun = TREE_OPERAND (fun, 0);
-  return fun;
+  tree callee = cp_get_callee (t);
+  tree fun = cp_get_fndecl_from_callee (callee, /*fold*/false);
+  return fun ? fun : callee;
 }
 
 /* Subroutine of check_constexpr_fundef.  BODY is the body of a function
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index cbed847b343..db086c017e8 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1001,8 +1001,22 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true 
*/)
 {
   if (fn == NULL_TREE)
 return fn;
+
+  /* We evaluate constexpr functions on the original, pre-genericization
+ bodies.  So block-scope extern declarations have not been mapped to
+ declarations in outer scopes.  Use the namespace-scope declaration,
+ if any, so that retrieve_constexpr_fundef can find it (PR32).  */
+  auto fn_or_local_alias = [] (tree f)
+{
+  if (DECL_LOCAL_DECL_P (f))
+   if (tree alias = DECL_LOCAL_DECL_ALIAS (f))
+ if (alias != error_mark_node)
+   return alias;
+  return f;
+};
+
   if (TREE_CODE (fn) == FUNCTION_DECL)
-return fn;
+return fn_or_local_alias (fn);
   tree type = TREE_TYPE (fn);
   if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
 return NULL_TREE;
@@ -1013,7 +1027,7 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true 
*/)
   || TREE_CODE (fn) == FDESC_EXPR)
 fn = TREE_OPERAND (fn, 0);
   if (TREE_CODE (fn) == FUNCTION_DECL)
-return fn;
+return fn_or_local_alias (fn);
   return NULL_TREE;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C
new file mode 100644
index 000..2b41b456fc3
--- /de

[PATCH v2] c++: constexpr error with fn redecl in local scope [PR111132]

2024-04-04 Thread Marek Polacek
On Thu, Apr 04, 2024 at 05:28:22PM -0400, Jason Merrill wrote:
> On 4/4/24 14:43, Marek Polacek wrote:
> > On Wed, Apr 03, 2024 at 01:14:46PM -0400, Jason Merrill wrote:
> > > On 4/2/24 13:52, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > > > 
> > > > -- >8 --
> > > > We evaluate constexpr functions on the original, pre-genericization 
> > > > bodies.
> > > > That means that the function body we're evaluating will not have gone
> > > > through cp_genericize_r's "Map block scope extern declarations to 
> > > > visible
> > > > declarations with the same name and type in outer scopes if any".  Here:
> > > > 
> > > > constexpr bool bar() { return true; } // #1
> > > > constexpr bool foo() {
> > > >   constexpr bool bar(void); // #2
> > > >   return bar();
> > > > }
> > > > 
> > > > it means that we:
> > > > 1) register_constexpr_fundef (#1)
> > > > 2) cp_genericize (#1)
> > > >  nothing interesting happens
> > > > 3) register_constexpr_fundef (foo)
> > > >  does copy_fn, so we have two copies of the BIND_EXPR
> > > > 4) cp_genericize (foo)
> > > >  this remaps #2 to #1, but only on one copy of the BIND_EXPR
> > > > 5) retrieve_constexpr_fundef (foo)
> > > >  we find it, no problem
> > > > 6) retrieve_constexpr_fundef (#2)
> > > >  and here #2 isn't found in constexpr_fundef_table, because
> > > >  we're working on the BIND_EXPR copy where #2 wasn't mapped to #1
> > > >  so we fail.  We've only registered #1.
> > > > 
> > > > It should work to use DECL_LOCAL_DECL_ALIAS (which used to be
> > > > extern_decl_map).  We evaluate constexpr functions on pre-cp_fold
> > > > bodies to avoid diagnostic problems, but the remapping I'm proposing
> > > > should not interfere with diagnostics.
> > > > 
> > > > This is not a problem for a global scope redeclaration; there we go
> > > > through duplicate_decls which keeps the DECL_UID:
> > > > DECL_UID (olddecl) = olddecl_uid;
> > > > and DECL_UID is what constexpr_fundef_hasher::hash uses.
> > > > 
> > > > PR c++/32
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (get_function_named_in_call): If there's
> > > > a DECL_LOCAL_DECL_ALIAS, use it.
> > > 
> > > Perhaps this function should use cp_get_fndecl_from_callee, and this 
> > > change
> > > should be made there instead?
> > 
> > It doesn't seem that get_function_named_in_call can use 
> > cp_get_fndecl_from_callee,
> > (or be replaced with cp_get_callee_fndecl_nofold).  We can get e.g. a 
> > CALL_EXPR
> > whose CALL_EXPR_FN is a TEMPLATE_ID_EXPR, and get_function_named_in_call
> > returns the TEMPLATE_ID_EXPR whereas cp_get_fndecl_from_callee would return
> > null:
> > 
> >if (TREE_CODE (fn) == FUNCTION_DECL)
> >  return fn;
> >tree type = TREE_TYPE (fn);
> >if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
> >  return NULL_TREE;
> 
> Why couldn't this function use cp_get_fndecl_from_callee and return the
> original argument if that function returns null?

It could.  (The lambda below could have been a goto but either should be fine.)

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

-- >8 --
We evaluate constexpr functions on the original, pre-genericization bodies.
That means that the function body we're evaluating will not have gone
through cp_genericize_r's "Map block scope extern declarations to visible
declarations with the same name and type in outer scopes if any".  Here:

  constexpr bool bar() { return true; } // #1
  constexpr bool foo() {
constexpr bool bar(void); // #2
return bar();
  }

it means that we:
1) register_constexpr_fundef (#1)
2) cp_genericize (#1)
   nothing interesting happens
3) register_constexpr_fundef (foo)
   does copy_fn, so we have two copies of the BIND_EXPR
4) cp_genericize (foo)
   this remaps #2 to #1, but only on one copy of the BIND_EXPR
5) retrieve_constexpr_fundef (foo)
   we find it, no problem
6) retrieve_constexpr_fundef (#2)
   and here #2 isn't found in constexpr_fundef_table, because
   we're working on the BIND_EXPR copy where #2 wasn't mapped to #1
   so we fail.  We've only registered #1.

It should work to use DECL_LOCAL_DECL_ALIAS (which used to be
ex

Re: [PATCH] c++: constexpr error with fn redecl in local scope [PR111132]

2024-04-04 Thread Marek Polacek
On Wed, Apr 03, 2024 at 01:14:46PM -0400, Jason Merrill wrote:
> On 4/2/24 13:52, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > 
> > -- >8 --
> > We evaluate constexpr functions on the original, pre-genericization bodies.
> > That means that the function body we're evaluating will not have gone
> > through cp_genericize_r's "Map block scope extern declarations to visible
> > declarations with the same name and type in outer scopes if any".  Here:
> > 
> >constexpr bool bar() { return true; } // #1
> >constexpr bool foo() {
> >  constexpr bool bar(void); // #2
> >  return bar();
> >}
> > 
> > it means that we:
> > 1) register_constexpr_fundef (#1)
> > 2) cp_genericize (#1)
> > nothing interesting happens
> > 3) register_constexpr_fundef (foo)
> > does copy_fn, so we have two copies of the BIND_EXPR
> > 4) cp_genericize (foo)
> > this remaps #2 to #1, but only on one copy of the BIND_EXPR
> > 5) retrieve_constexpr_fundef (foo)
> > we find it, no problem
> > 6) retrieve_constexpr_fundef (#2)
> > and here #2 isn't found in constexpr_fundef_table, because
> > we're working on the BIND_EXPR copy where #2 wasn't mapped to #1
> > so we fail.  We've only registered #1.
> > 
> > It should work to use DECL_LOCAL_DECL_ALIAS (which used to be
> > extern_decl_map).  We evaluate constexpr functions on pre-cp_fold
> > bodies to avoid diagnostic problems, but the remapping I'm proposing
> > should not interfere with diagnostics.
> > 
> > This is not a problem for a global scope redeclaration; there we go
> > through duplicate_decls which keeps the DECL_UID:
> >DECL_UID (olddecl) = olddecl_uid;
> > and DECL_UID is what constexpr_fundef_hasher::hash uses.
> > 
> > PR c++/32
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (get_function_named_in_call): If there's
> > a DECL_LOCAL_DECL_ALIAS, use it.
> 
> Perhaps this function should use cp_get_fndecl_from_callee, and this change
> should be made there instead?

It doesn't seem that get_function_named_in_call can use 
cp_get_fndecl_from_callee,
(or be replaced with cp_get_callee_fndecl_nofold).  We can get e.g. a CALL_EXPR
whose CALL_EXPR_FN is a TEMPLATE_ID_EXPR, and get_function_named_in_call
returns the TEMPLATE_ID_EXPR whereas cp_get_fndecl_from_callee would return
null:

  if (TREE_CODE (fn) == FUNCTION_DECL)
return fn;
  tree type = TREE_TYPE (fn);
  if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
return NULL_TREE;

Marek



[gcc r14-9759] c++: make __is_array return false for T[0] [PR114479]

2024-04-02 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:2f2924078ce51c2a0da3ad8f958f2d1de533969a

commit r14-9759-g2f2924078ce51c2a0da3ad8f958f2d1de533969a
Author: Marek Polacek 
Date:   Mon Apr 1 12:55:46 2024 -0400

c++: make __is_array return false for T[0] [PR114479]

When we switched to using the __is_array built-in trait to implement
std::is_array in r14-6623-g7fd9c349e45534, we started saying that
T[0] is an array.  There are various opinions as to whether that is
the best answer, but it seems prudent to keep the GCC 13 result.

PR c++/114479

gcc/cp/ChangeLog:

* semantics.cc (trait_expr_value) : Return false
for zero-sized arrays.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_array.C: Extend.

Diff:
---
 gcc/cp/semantics.cc |  8 +++-
 gcc/testsuite/g++.dg/ext/is_array.C | 12 
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 9838331d2a9..0015ff4fb62 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12439,7 +12439,13 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
   return CP_AGGREGATE_TYPE_P (type1);
 
 case CPTK_IS_ARRAY:
-  return type_code1 == ARRAY_TYPE;
+  return (type_code1 == ARRAY_TYPE
+ /* We don't want to report T[0] as being an array type.
+This is for compatibility with an implementation of
+std::is_array by template argument deduction, because
+compute_array_index_type_loc rejects a zero-size array
+in SFINAE context.  */
+ && !(TYPE_SIZE (type1) && integer_zerop (TYPE_SIZE (type1;
 
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
diff --git a/gcc/testsuite/g++.dg/ext/is_array.C 
b/gcc/testsuite/g++.dg/ext/is_array.C
index f1a6e08b87a..84993266629 100644
--- a/gcc/testsuite/g++.dg/ext/is_array.C
+++ b/gcc/testsuite/g++.dg/ext/is_array.C
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
+// { dg-options "" }
 
 #define SA(X) static_assert((X),#X)
 
@@ -10,18 +11,29 @@
 
 class ClassType { };
 
+constexpr int sz0 = 0;
+constexpr int sz2 = 2;
+
 SA_TEST_CATEGORY(__is_array, int[2], true);
 SA_TEST_CATEGORY(__is_array, int[], true);
+SA_TEST_CATEGORY(__is_array, int[0], false);
 SA_TEST_CATEGORY(__is_array, int[2][3], true);
 SA_TEST_CATEGORY(__is_array, int[][3], true);
+SA_TEST_CATEGORY(__is_array, int[0][3], false);
+SA_TEST_CATEGORY(__is_array, int[3][0], false);
 SA_TEST_CATEGORY(__is_array, float*[2], true);
 SA_TEST_CATEGORY(__is_array, float*[], true);
 SA_TEST_CATEGORY(__is_array, float*[2][3], true);
 SA_TEST_CATEGORY(__is_array, float*[][3], true);
 SA_TEST_CATEGORY(__is_array, ClassType[2], true);
 SA_TEST_CATEGORY(__is_array, ClassType[], true);
+SA_TEST_CATEGORY(__is_array, ClassType[0], false);
 SA_TEST_CATEGORY(__is_array, ClassType[2][3], true);
 SA_TEST_CATEGORY(__is_array, ClassType[][3], true);
+SA_TEST_CATEGORY(__is_array, ClassType[0][3], false);
+SA_TEST_CATEGORY(__is_array, ClassType[2][0], false);
+SA_TEST_CATEGORY(__is_array, int[sz2], true);
+SA_TEST_CATEGORY(__is_array, int[sz0], false);
 
 // Sanity check.
 SA_TEST_CATEGORY(__is_array, ClassType, false);


[gcc r13-8560] c++: ICE with scoped enum in switch condition [PR103825]

2024-04-02 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:22510e4a68aa9ca850db34ae62c21c58442d8ab3

commit r13-8560-g22510e4a68aa9ca850db34ae62c21c58442d8ab3
Author: Marek Polacek 
Date:   Fri Mar 29 16:59:37 2024 -0400

c++: ICE with scoped enum in switch condition [PR103825]

Here we ICE when gimplifying

  enum class Type { Pawn };
  struct Piece {
Type type : 4;
  };
  void foo() {
switch (Piece().type)
  case Type::Pawn:;
  }

because we ended up with TYPE_PRECISION (cond) < TYPE_PRECISION (case).
That's because the case expr type here is the unlowered type Type,
whereas the conditional's type is the lowered .  This
is not supposed to happen: see the comment in pop_switch around the
is_bitfield_expr_with_lowered_type check.

But here we did not revert to the lowered SWITCH_STMT_TYPE, because
the conditional contains a TARGET_EXPR, which has side-effects, which
means that finish_switch_cond -> maybe_cleanup_point_expr wraps it
in a CLEANUP_POINT_EXPR.  And is_bitfield_expr_with_lowered_type does
not see through those.

PR c++/103825

gcc/cp/ChangeLog:

* typeck.cc (is_bitfield_expr_with_lowered_type): Handle
CLEANUP_POINT_EXPR.

gcc/testsuite/ChangeLog:

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

(cherry picked from commit daa2e7c7ffe49b788357f7f2c9ef1c9b125c1f8c)

Diff:
---
 gcc/cp/typeck.cc|  1 +
 gcc/testsuite/g++.dg/cpp0x/enum44.C | 30 ++
 2 files changed, 31 insertions(+)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 56bb21ab251..81bc9edd955 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -2400,6 +2400,7 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
 case NEGATE_EXPR:
 case NON_LVALUE_EXPR:
 case BIT_NOT_EXPR:
+case CLEANUP_POINT_EXPR:
   return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
 
 case COMPONENT_REF:
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum44.C 
b/gcc/testsuite/g++.dg/cpp0x/enum44.C
new file mode 100644
index 000..92408c92217
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum44.C
@@ -0,0 +1,30 @@
+// PR c++/103825
+// { dg-do compile { target c++11 } }
+
+enum class Type { Pawn };
+struct Piece {
+  Type type : 4;
+};
+
+void
+foo ()
+{
+  switch (Piece().type)
+case Type::Pawn:;
+
+  auto x = Piece().type;
+  switch (x)
+case Type::Pawn:;
+}
+
+enum class En {A};
+struct St {En field :1;};
+
+void
+bar ()
+{
+  volatile St s = {En::A};
+  switch(s.field) {
+case En::A : break;
+  }
+}


[gcc r14-9758] c++: ICE with scoped enum in switch condition [PR103825]

2024-04-02 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:daa2e7c7ffe49b788357f7f2c9ef1c9b125c1f8c

commit r14-9758-gdaa2e7c7ffe49b788357f7f2c9ef1c9b125c1f8c
Author: Marek Polacek 
Date:   Fri Mar 29 16:59:37 2024 -0400

c++: ICE with scoped enum in switch condition [PR103825]

Here we ICE when gimplifying

  enum class Type { Pawn };
  struct Piece {
Type type : 4;
  };
  void foo() {
switch (Piece().type)
  case Type::Pawn:;
  }

because we ended up with TYPE_PRECISION (cond) < TYPE_PRECISION (case).
That's because the case expr type here is the unlowered type Type,
whereas the conditional's type is the lowered .  This
is not supposed to happen: see the comment in pop_switch around the
is_bitfield_expr_with_lowered_type check.

But here we did not revert to the lowered SWITCH_STMT_TYPE, because
the conditional contains a TARGET_EXPR, which has side-effects, which
means that finish_switch_cond -> maybe_cleanup_point_expr wraps it
in a CLEANUP_POINT_EXPR.  And is_bitfield_expr_with_lowered_type does
not see through those.

PR c++/103825

gcc/cp/ChangeLog:

* typeck.cc (is_bitfield_expr_with_lowered_type): Handle
CLEANUP_POINT_EXPR.

gcc/testsuite/ChangeLog:

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

Diff:
---
 gcc/cp/typeck.cc|  1 +
 gcc/testsuite/g++.dg/cpp0x/enum44.C | 30 ++
 2 files changed, 31 insertions(+)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 88ed38e4f30..e5a52dc2b39 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -2400,6 +2400,7 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
 case NEGATE_EXPR:
 case NON_LVALUE_EXPR:
 case BIT_NOT_EXPR:
+case CLEANUP_POINT_EXPR:
   return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
 
 case COMPONENT_REF:
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum44.C 
b/gcc/testsuite/g++.dg/cpp0x/enum44.C
new file mode 100644
index 000..92408c92217
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum44.C
@@ -0,0 +1,30 @@
+// PR c++/103825
+// { dg-do compile { target c++11 } }
+
+enum class Type { Pawn };
+struct Piece {
+  Type type : 4;
+};
+
+void
+foo ()
+{
+  switch (Piece().type)
+case Type::Pawn:;
+
+  auto x = Piece().type;
+  switch (x)
+case Type::Pawn:;
+}
+
+enum class En {A};
+struct St {En field :1;};
+
+void
+bar ()
+{
+  volatile St s = {En::A};
+  switch(s.field) {
+case En::A : break;
+  }
+}


[PATCH] c++: constexpr error with fn redecl in local scope [PR111132]

2024-04-02 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?

-- >8 --
We evaluate constexpr functions on the original, pre-genericization bodies.
That means that the function body we're evaluating will not have gone
through cp_genericize_r's "Map block scope extern declarations to visible
declarations with the same name and type in outer scopes if any".  Here:

  constexpr bool bar() { return true; } // #1
  constexpr bool foo() {
constexpr bool bar(void); // #2
return bar();
  }

it means that we:
1) register_constexpr_fundef (#1)
2) cp_genericize (#1)
   nothing interesting happens
3) register_constexpr_fundef (foo)
   does copy_fn, so we have two copies of the BIND_EXPR
4) cp_genericize (foo)
   this remaps #2 to #1, but only on one copy of the BIND_EXPR
5) retrieve_constexpr_fundef (foo)
   we find it, no problem
6) retrieve_constexpr_fundef (#2)
   and here #2 isn't found in constexpr_fundef_table, because
   we're working on the BIND_EXPR copy where #2 wasn't mapped to #1
   so we fail.  We've only registered #1.

It should work to use DECL_LOCAL_DECL_ALIAS (which used to be
extern_decl_map).  We evaluate constexpr functions on pre-cp_fold
bodies to avoid diagnostic problems, but the remapping I'm proposing
should not interfere with diagnostics.

This is not a problem for a global scope redeclaration; there we go
through duplicate_decls which keeps the DECL_UID:
  DECL_UID (olddecl) = olddecl_uid;
and DECL_UID is what constexpr_fundef_hasher::hash uses.

PR c++/32

gcc/cp/ChangeLog:

* constexpr.cc (get_function_named_in_call): If there's
a DECL_LOCAL_DECL_ALIAS, use it.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-redeclaration3.C: New test.
* g++.dg/cpp0x/constexpr-redeclaration4.C: New test.
---
 gcc/cp/constexpr.cc   | 19 +++
 .../g++.dg/cpp0x/constexpr-redeclaration3.C   | 13 +
 .../g++.dg/cpp0x/constexpr-redeclaration4.C   | 14 ++
 3 files changed, 42 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa346fe01c9..b47f0e984c0 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -702,15 +702,26 @@ build_constexpr_constructor_member_initializers (tree 
type, tree body)
 
 /* We have an expression tree T that represents a call, either CALL_EXPR
or AGGR_INIT_EXPR.  If the call is lexically to a named function,
-   retrun the _DECL for that function.  */
+   return the _DECL for that function.  */
 
 static tree
 get_function_named_in_call (tree t)
 {
   tree fun = cp_get_callee (t);
-  if (fun && TREE_CODE (fun) == ADDR_EXPR
-  && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
-fun = TREE_OPERAND (fun, 0);
+  if (fun)
+{
+  if (TREE_CODE (fun) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
+   fun = TREE_OPERAND (fun, 0);
+  /* We evaluate constexpr functions on the original, pre-genericization
+bodies.  So block-scope extern declarations have not been mapped to
+declarations in outer scopes.  Use the namespace-scope declaration,
+if any, so that retrieve_constexpr_fundef can find it (PR32).  */
+  if (TREE_CODE (fun) == FUNCTION_DECL && DECL_LOCAL_DECL_P (fun))
+   if (tree alias = DECL_LOCAL_DECL_ALIAS (fun))
+ if (alias != error_mark_node)
+   fun = alias;
+}
   return fun;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C
new file mode 100644
index 000..2b41b456fc3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration3.C
@@ -0,0 +1,13 @@
+// PR c++/32
+// { dg-do compile { target c++11 } }
+
+constexpr bool bar(void) {
+return true;
+}
+
+constexpr bool foo() {
+constexpr bool bar(void);
+return bar();
+}
+
+static_assert(foo(), "");
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C
new file mode 100644
index 000..c58247218c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-redeclaration4.C
@@ -0,0 +1,14 @@
+// PR c++/32
+// { dg-do compile { target c++11 } }
+
+constexpr bool bar(void) {
+return true;
+}
+
+constexpr bool bar(void);
+
+constexpr bool foo() {
+return bar();
+}
+
+static_assert(foo(), "");

base-commit: 0e64bbb8823f7b3757befc878ed177dfb59943d1
-- 
2.44.0



[PATCH] c++: make __is_array return false for T[0] [PR114479]

2024-04-01 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
When we switched to using the __is_array built-in trait to implement
std::is_array in r14-6623-g7fd9c349e45534, we started saying that
T[0] is an array.  There are various opinions as to whether that is
the best answer, but it seems prudent to keep the GCC 13 result.

PR c++/114479

gcc/cp/ChangeLog:

* semantics.cc (trait_expr_value) : Return false
for zero-sized arrays.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_array.C: Extend.
---
 gcc/cp/semantics.cc |  4 +++-
 gcc/testsuite/g++.dg/ext/is_array.C | 12 
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 9838331d2a9..f561c119dfd 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12439,7 +12439,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
   return CP_AGGREGATE_TYPE_P (type1);
 
 case CPTK_IS_ARRAY:
-  return type_code1 == ARRAY_TYPE;
+  return (type_code1 == ARRAY_TYPE
+ /* We don't want to report T[0] as being an array type.  */
+ && !(TYPE_SIZE (type1) && integer_zerop (TYPE_SIZE (type1;
 
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
diff --git a/gcc/testsuite/g++.dg/ext/is_array.C 
b/gcc/testsuite/g++.dg/ext/is_array.C
index f1a6e08b87a..84993266629 100644
--- a/gcc/testsuite/g++.dg/ext/is_array.C
+++ b/gcc/testsuite/g++.dg/ext/is_array.C
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
+// { dg-options "" }
 
 #define SA(X) static_assert((X),#X)
 
@@ -10,18 +11,29 @@
 
 class ClassType { };
 
+constexpr int sz0 = 0;
+constexpr int sz2 = 2;
+
 SA_TEST_CATEGORY(__is_array, int[2], true);
 SA_TEST_CATEGORY(__is_array, int[], true);
+SA_TEST_CATEGORY(__is_array, int[0], false);
 SA_TEST_CATEGORY(__is_array, int[2][3], true);
 SA_TEST_CATEGORY(__is_array, int[][3], true);
+SA_TEST_CATEGORY(__is_array, int[0][3], false);
+SA_TEST_CATEGORY(__is_array, int[3][0], false);
 SA_TEST_CATEGORY(__is_array, float*[2], true);
 SA_TEST_CATEGORY(__is_array, float*[], true);
 SA_TEST_CATEGORY(__is_array, float*[2][3], true);
 SA_TEST_CATEGORY(__is_array, float*[][3], true);
 SA_TEST_CATEGORY(__is_array, ClassType[2], true);
 SA_TEST_CATEGORY(__is_array, ClassType[], true);
+SA_TEST_CATEGORY(__is_array, ClassType[0], false);
 SA_TEST_CATEGORY(__is_array, ClassType[2][3], true);
 SA_TEST_CATEGORY(__is_array, ClassType[][3], true);
+SA_TEST_CATEGORY(__is_array, ClassType[0][3], false);
+SA_TEST_CATEGORY(__is_array, ClassType[2][0], false);
+SA_TEST_CATEGORY(__is_array, int[sz2], true);
+SA_TEST_CATEGORY(__is_array, int[sz0], false);
 
 // Sanity check.
 SA_TEST_CATEGORY(__is_array, ClassType, false);

base-commit: bba118db3f63cb1e3953a014aa3ac2ad89908950
-- 
2.44.0



[PATCH] c++: ICE with scoped enum in switch condition [PR114451]

2024-03-29 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?

-- >8 --
Here we ICE when gimplifying

  enum class Type { Pawn };
  struct Piece {
Type type : 4;
  };
  void foo() {
switch (Piece().type)
  case Type::Pawn:;
  }

because we ended up with TYPE_PRECISION (cond) < TYPE_PRECISION (case).
That's because the case expr type here is the unlowered type Type,
whereas the conditional's type is the lowered .  This
is not supposed to happen: see the comment in pop_switch around the
is_bitfield_expr_with_lowered_type check.

But here we did not revert to the lowered SWITCH_STMT_TYPE, because
the conditional contains a TARGET_EXPR, which has side-effects, which
means that finish_switch_cond -> maybe_cleanup_point_expr wraps it
in a CLEANUP_POINT_EXPR.  And is_bitfield_expr_with_lowered_type does
not see through those.

PR c++/103825

gcc/cp/ChangeLog:

* typeck.cc (is_bitfield_expr_with_lowered_type): Handle
CLEANUP_POINT_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/enum44.C: New test.
---
 gcc/cp/typeck.cc|  1 +
 gcc/testsuite/g++.dg/cpp0x/enum44.C | 30 +
 2 files changed, 31 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum44.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index f5a0a2273be..9a096b51d55 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -2400,6 +2400,7 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
 case NEGATE_EXPR:
 case NON_LVALUE_EXPR:
 case BIT_NOT_EXPR:
+case CLEANUP_POINT_EXPR:
   return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
 
 case COMPONENT_REF:
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum44.C 
b/gcc/testsuite/g++.dg/cpp0x/enum44.C
new file mode 100644
index 000..92408c92217
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum44.C
@@ -0,0 +1,30 @@
+// PR c++/103825
+// { dg-do compile { target c++11 } }
+
+enum class Type { Pawn };
+struct Piece {
+  Type type : 4;
+};
+
+void
+foo ()
+{
+  switch (Piece().type)
+case Type::Pawn:;
+
+  auto x = Piece().type;
+  switch (x)
+case Type::Pawn:;
+}
+
+enum class En {A};
+struct St {En field :1;};
+
+void
+bar ()
+{
+  volatile St s = {En::A};
+  switch(s.field) {
+case En::A : break;
+  }
+}

base-commit: 4c18ace1cb69a31af4ac719850a66de79ed12e93
-- 
2.44.0



[pushed] c++: add fixed test [PR100557]

2024-03-26 Thread Marek Polacek
Tested x86_64-pc-linux-gnu, applying to trunk.

-- >8 --
We used to hit the "Error reporting routines re-entered." ICE here but
it was fixed by Patrick's r14-3809.

PR c++/100557

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-pr100557.C: New test.
---
 .../g++.dg/cpp2a/concepts-pr100557.C  | 21 +++
 1 file changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C

diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C
new file mode 100644
index 000..8dcd0eaca51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C
@@ -0,0 +1,21 @@
+// PR c++/100557
+// { dg-do compile { target c++20 } }
+
+template  _Tp declval();
+
+struct print_tag_;
+
+bool tag_invoke(print_tag_, auto);
+bool tag_invoke(print_tag_, auto obj) requires requires { *obj; };
+
+template 
+auto try_tag_invoke() noexcept(tag_invoke(declval, declval()...)) 
// { dg-error "no matching function for call" }
+-> decltype(tag_invoke(CPO(), declval()...));
+
+struct print_tag_ {
+  void operator()(auto... args) noexcept(noexcept( try_tag_invoke()));
+} print;
+
+void foo() {
+  print(0);
+}

base-commit: 2f47ca046eecf8f2fcae23df3ccee44d943ef512
-- 
2.44.0



[gcc r14-9674] c++: add fixed test [PR100557]

2024-03-26 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:c0e199e4dbe652cd16d7248f0bfe166540f5d95b

commit r14-9674-gc0e199e4dbe652cd16d7248f0bfe166540f5d95b
Author: Marek Polacek 
Date:   Tue Mar 26 10:39:48 2024 -0400

c++: add fixed test [PR100557]

We used to hit the "Error reporting routines re-entered." ICE here but
it was fixed by Patrick's r14-3809.

PR c++/100557

gcc/testsuite/ChangeLog:

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

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

diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C
new file mode 100644
index 000..8dcd0eaca51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr100557.C
@@ -0,0 +1,21 @@
+// PR c++/100557
+// { dg-do compile { target c++20 } }
+
+template  _Tp declval();
+
+struct print_tag_;
+
+bool tag_invoke(print_tag_, auto);
+bool tag_invoke(print_tag_, auto obj) requires requires { *obj; };
+
+template 
+auto try_tag_invoke() noexcept(tag_invoke(declval, declval()...)) 
// { dg-error "no matching function for call" }
+-> decltype(tag_invoke(CPO(), declval()...));
+
+struct print_tag_ {
+  void operator()(auto... args) noexcept(noexcept( try_tag_invoke()));
+} print;
+
+void foo() {
+  print(0);
+}


[gcc r14-9659] c++: ICE with noexcept and local specialization, again [PR114349]

2024-03-25 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:8651991fe2ea90a7276e91673b15b5c3865f14d7

commit r14-9659-g8651991fe2ea90a7276e91673b15b5c3865f14d7
Author: Marek Polacek 
Date:   Fri Mar 15 09:23:28 2024 -0400

c++: ICE with noexcept and local specialization, again [PR114349]

Patrick noticed that my r14-9339-gdc6c3bfb59baab patch is wrong;
we're dealing with a noexcept-spec there, not a noexcept-expr, so
setting cp_noexcept_operand et al is incorrect.  Back to the drawing
board then.

To fix noexcept84.C, we should probably avoid doing push_to_top_level
in certain cases.  maybe_push_to_top_level didn't work here as-is, so
I changed it to not push to top level if decl_function_context is
non-null, when we are not dealing with a lambda.

This also fixes c++/114349, introduced by r14-9339.

PR c++/114349

gcc/cp/ChangeLog:

* name-lookup.cc (maybe_push_to_top_level): For a non-lambda,
don't push to top level if decl_function_context is non-null.
* pt.cc (maybe_instantiate_noexcept): Use maybe_push_to_top_level.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept85.C: New test.
* g++.dg/cpp0x/noexcept86.C: New test.

Diff:
---
 gcc/cp/name-lookup.cc   | 11 +++
 gcc/cp/pt.cc| 11 ++-
 gcc/testsuite/g++.dg/cpp0x/noexcept85.C | 33 +
 gcc/testsuite/g++.dg/cpp0x/noexcept86.C | 25 +
 4 files changed, 67 insertions(+), 13 deletions(-)

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index dce4caf8981..7af7f00e34c 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8664,10 +8664,13 @@ maybe_push_to_top_level (tree d)
 {
   /* Push if D isn't function-local, or is a lambda function, for which name
  resolution is already done.  */
-  bool push_to_top
-= !(current_function_decl
-   && !LAMBDA_FUNCTION_P (d)
-   && decl_function_context (d) == current_function_decl);
+  const bool push_to_top
+= (LAMBDA_FUNCTION_P (d)
+   || (TREE_CODE (d) == TYPE_DECL
+  && TREE_TYPE (d)
+  && LAMBDA_TYPE_P (TREE_TYPE (d)))
+   || !current_function_decl
+   || !decl_function_context (d));
 
   if (push_to_top)
 push_to_top_level ();
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8cf0d5b7a8d..7b00a8615d2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26855,7 +26855,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
}
   else if (push_tinst_level (fn))
{
- push_to_top_level ();
+ const bool push_to_top = maybe_push_to_top_level (fn);
  push_access_scope (fn);
  push_deferring_access_checks (dk_no_deferred);
  input_location = DECL_SOURCE_LOCATION (fn);
@@ -26878,17 +26878,10 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  if (orig_fn)
++processing_template_decl;
 
- ++cp_unevaluated_operand;
- ++c_inhibit_evaluation_warnings;
- ++cp_noexcept_operand;
  /* Do deferred instantiation of the noexcept-specifier.  */
  noex = tsubst_expr (DEFERRED_NOEXCEPT_PATTERN (noex),
  DEFERRED_NOEXCEPT_ARGS (noex),
  tf_warning_or_error, fn);
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
- --cp_noexcept_operand;
-
  /* Build up the noexcept-specification.  */
  spec = build_noexcept_spec (noex, tf_warning_or_error);
 
@@ -26898,7 +26891,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  pop_deferring_access_checks ();
  pop_access_scope (fn);
  pop_tinst_level ();
- pop_from_top_level ();
+ maybe_pop_from_top_level (push_to_top);
}
   else
spec = noexcept_false_spec;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept85.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept85.C
new file mode 100644
index 000..b415bb46bc9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept85.C
@@ -0,0 +1,33 @@
+// PR c++/114349
+// { dg-do compile { target c++11 } }
+
+using A = struct {};
+template  class, typename, typename>
+using B = A;
+template 
+using C = typename T::D;
+struct E {
+  using D = B;
+};
+template  constexpr bool foo (A) { return false; }
+template  struct F {
+  using G = T;
+  using H = E;
+  F(const F &);
+  void operator=(F) noexcept(foo  (H::D{}));
+};
+template 
+using I = F;
+template 
+using J = I;
+struct K {
+  typedef J L;
+  L k;
+  K();
+};
+struct M {
+  bool bar () const;
+  K::L m;
+};
+K n;
+bool M::bar () const { n.k = m; return true; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept86.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept86.C
new file mode 100644
index 000..2d040c090f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept

[gcc r14-9658] c++: broken direct-init with trailing array member [PR114439]

2024-03-25 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:de0886d48032332d10e4acb5d15c8789b281b6fe

commit r14-9658-gde0886d48032332d10e4acb5d15c8789b281b6fe
Author: Marek Polacek 
Date:   Mon Mar 25 15:32:20 2024 -0400

c++: broken direct-init with trailing array member [PR114439]

can_init_array_with_p is wrongly saying that the init for 's' here:

  struct S {
int *list = arr;
int arr[];
  };

  struct A {
A() {}
S s[2]{};
  };

is invalid.  But as process_init_constructor_array says, for "non-constant
initialization of trailing elements with no explicit initializers" we use
a VEC_INIT_EXPR wrapped in a TARGET_EXPR, built in process_init_constructor.

Unfortunately we didn't have a test for this scenario so I didn't
realize can_init_array_with_p must handle it.

PR c++/114439

gcc/cp/ChangeLog:

* init.cc (can_init_array_with_p): Return true for a VEC_INIT_EXPR
wrapped in a TARGET_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/init/array65.C: New test.

Diff:
---
 gcc/cp/init.cc  |  6 +-
 gcc/testsuite/g++.dg/init/array65.C | 38 +
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index dbd37d47cbf..a93ce00800c 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -950,12 +950,16 @@ can_init_array_with_p (tree type, tree init)
  mem-initializers of a constructor.  */
   if (DECL_DEFAULTED_FN (current_function_decl))
 return true;
-  /* As an extension, we allow copying from a compound literal.  */
   if (TREE_CODE (init) == TARGET_EXPR)
 {
   init = TARGET_EXPR_INITIAL (init);
+  /* As an extension, we allow copying from a compound literal.  */
   if (TREE_CODE (init) == CONSTRUCTOR)
return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
+  /* VEC_INIT_EXPR is used for non-constant initialization of trailing
+elements with no explicit initializers.  */
+  else if (TREE_CODE (init) == VEC_INIT_EXPR)
+   return true;
 }
 
   return false;
diff --git a/gcc/testsuite/g++.dg/init/array65.C 
b/gcc/testsuite/g++.dg/init/array65.C
new file mode 100644
index 000..0b144f45a9d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array65.C
@@ -0,0 +1,38 @@
+// PR c++/114439
+// { dg-do compile { target c++11 } }
+
+struct S {
+  int *list = arr;
+  __extension__ int arr[];
+};
+
+struct R {
+  int *list = arr;
+  int arr[2];
+};
+
+struct A {
+  A() {}
+  S s[2]{};
+};
+
+struct A2 {
+  A2() {}
+  S s[2]{ {}, {} };
+};
+
+struct B {
+  B() {}
+  R r[2]{};
+};
+
+struct B2 {
+  B2() {}
+  R r[2]{ {}, {} };
+};
+
+struct S1 { S1(); };
+struct S2 {
+  S2() {}
+  S1 a[1] {};
+};


[PATCH v3] c++: ICE with noexcept and local specialization, again [PR114349]

2024-03-25 Thread Marek Polacek
On Mon, Mar 25, 2024 at 03:40:10PM -0400, Jason Merrill wrote:
> On 3/22/24 17:30, Marek Polacek wrote:
> > On Thu, Mar 21, 2024 at 05:27:37PM -0400, Jason Merrill wrote:
> > > On 3/21/24 17:01, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > Patrick noticed that my r14-9339-gdc6c3bfb59baab patch is wrong;
> > > > we're dealing with a noexcept-spec there, not a noexcept-expr, so
> > > > setting cp_noexcept_operand et al is incorrect.  Back to the drawing
> > > > board then.
> > > > 
> > > > To fix noexcept84.C, we should probably avoid doing push_to_top_level
> > > > in certain cases.  Patrick suggested checking:
> > > > 
> > > > const bool push_to_top = current_function_decl != fn;
> > > > 
> > > > which works, but I'm not sure I follow the logic there.  I also came
> > > > up with
> > > > 
> > > > const bool push_to_top = !decl_function_context (fn);
> > > > 
> > > > which also works.  But ultimately I went with 
> > > > !DECL_TEMPLATE_INSTANTIATED;
> > > > if DECL_TEMPLATE_INSTANTIATED is set, we've already pushed to top level
> > > > if it was necessary in instantiate_body.
> > > 
> > > This sort of thing is what maybe_push_to_top_level is for, does that also
> > > work?
> > 
> > Sadly -- and I should have mentioned that -- no.  maybe_push_to_top_level 
> > asks:
> > 
> >bool push_to_top
> >  = !(current_function_decl
> > && !LAMBDA_FUNCTION_P (d)
> > && decl_function_context (d) == current_function_decl);
> > 
> > here both d and current_function_decl are test()::S::S(), and
> > decl_function_context (d) is test().  (current_function_decl was
> > set to test()::S::S() by an earlier push_access_scope call.)
> > 
> > But I want it to work, and I think using maybe_ would be a way nicer
> > fix.  So what if we don't push to top level if decl_function_context
> > is non-null?  I had to add the LAMBDA_TYPE_P check though: it looks
> > that we always have to push to top level for lambdas, but sometimes
> > we get a lambda's TYPE_DECL, and LAMBDA_FUNCTION_P doesn't catch
> > that.  An example is lambda-nested4.C.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Patrick noticed that my r14-9339-gdc6c3bfb59baab patch is wrong;
> > we're dealing with a noexcept-spec there, not a noexcept-expr, so
> > setting cp_noexcept_operand et al is incorrect.  Back to the drawing
> > board then.
> > 
> > To fix noexcept84.C, we should probably avoid doing push_to_top_level
> > in certain cases.  maybe_push_to_top_level didn't work here as-is, so
> > I changed it to not push to top level if decl_function_context is
> > non-null, when we are not dealing with a lambda.
> > 
> > This also fixes c++/114349, introduced by r14-9339.
> > 
> > PR c++/114349
> > 
> > gcc/cp/ChangeLog:
> > 
> > * name-lookup.cc (maybe_push_to_top_level): For a non-lambda,
> > don't push to top level if decl_function_context is non-null.
> > * pt.cc (maybe_instantiate_noexcept): Use maybe_push_to_top_level.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/noexcept85.C: New test.
> > * g++.dg/cpp0x/noexcept86.C: New test.
> > ---
> >   gcc/cp/name-lookup.cc   | 12 ++---
> >   gcc/cp/pt.cc| 11 ++---
> >   gcc/testsuite/g++.dg/cpp0x/noexcept85.C | 33 +
> >   gcc/testsuite/g++.dg/cpp0x/noexcept86.C | 25 +++
> >   4 files changed, 68 insertions(+), 13 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept85.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept86.C
> > 
> > diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
> > index dce4caf8981..4b2b27bdd0d 100644
> > --- a/gcc/cp/name-lookup.cc
> > +++ b/gcc/cp/name-lookup.cc
> > @@ -8664,10 +8664,14 @@ maybe_push_to_top_level (tree d)
> >   {
> > /* Push if D isn't function-local, or is a lambda function, for which 
> > name
> >resolution is already done.  */
> > -  bool push_to_top
> > -= !(current_function_decl
> > -   && !LAMBDA_FUNCTION_P (d)
> > -   && decl_function_context (d) == current_function_decl);
> > +  const bool push_to_to

[PATCH] c++: broken direct-init with trailing array member [PR114439]

2024-03-25 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
can_init_array_with_p is wrongly saying that the init for 's' here:

  struct S {
int *list = arr;
int arr[];
  };

  struct A {
A() {}
S s[2]{};
  };

is invalid.  But as process_init_constructor_array says, for "non-constant
initialization of trailing elements with no explicit initializers" we use
a VEC_INIT_EXPR wrapped in a TARGET_EXPR, built in process_init_constructor.

Unfortunately we didn't have a test for this scenario so I didn't
realize can_init_array_with_p must handle it.

PR c++/114439

gcc/cp/ChangeLog:

* init.cc (can_init_array_with_p): Return true for a VEC_INIT_EXPR
wrapped in a TARGET_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/init/array65.C: New test.
---
 gcc/cp/init.cc  |  6 -
 gcc/testsuite/g++.dg/init/array65.C | 38 +
 2 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/init/array65.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index dbd37d47cbf..a93ce00800c 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -950,12 +950,16 @@ can_init_array_with_p (tree type, tree init)
  mem-initializers of a constructor.  */
   if (DECL_DEFAULTED_FN (current_function_decl))
 return true;
-  /* As an extension, we allow copying from a compound literal.  */
   if (TREE_CODE (init) == TARGET_EXPR)
 {
   init = TARGET_EXPR_INITIAL (init);
+  /* As an extension, we allow copying from a compound literal.  */
   if (TREE_CODE (init) == CONSTRUCTOR)
return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
+  /* VEC_INIT_EXPR is used for non-constant initialization of trailing
+elements with no explicit initializers.  */
+  else if (TREE_CODE (init) == VEC_INIT_EXPR)
+   return true;
 }
 
   return false;
diff --git a/gcc/testsuite/g++.dg/init/array65.C 
b/gcc/testsuite/g++.dg/init/array65.C
new file mode 100644
index 000..0b144f45a9d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array65.C
@@ -0,0 +1,38 @@
+// PR c++/114439
+// { dg-do compile { target c++11 } }
+
+struct S {
+  int *list = arr;
+  __extension__ int arr[];
+};
+
+struct R {
+  int *list = arr;
+  int arr[2];
+};
+
+struct A {
+  A() {}
+  S s[2]{};
+};
+
+struct A2 {
+  A2() {}
+  S s[2]{ {}, {} };
+};
+
+struct B {
+  B() {}
+  R r[2]{};
+};
+
+struct B2 {
+  B2() {}
+  R r[2]{ {}, {} };
+};
+
+struct S1 { S1(); };
+struct S2 {
+  S2() {}
+  S1 a[1] {};
+};

base-commit: 18555b914316e8c1fb11ee821f2ee839d834e58e
-- 
2.44.0



Re: [PATCH v2] c++: direct-init of an array of class type [PR59465]

2024-03-25 Thread Marek Polacek
On Mon, Mar 25, 2024 at 01:39:39PM +0100, Stephan Bergmann wrote:
> On 3/25/24 13:07, Jakub Jelinek wrote:
> > On Mon, Mar 25, 2024 at 12:36:46PM +0100, Stephan Bergmann wrote:
> > > This started to break
> > > 
> > > > $ cat test.cc
> > > > struct S1 { S1(); };
> > > > struct S2 {
> > > >  S2() {}
> > > >  S1 a[1] {};
> > > > };
> > > 
> > > > $ g++ -fsyntax-only test.cc
> > > > test.cc: In constructor ‘S2::S2()’:
> > > > test.cc:3:10: error: invalid initializer for array member ‘S1 S2::a [1]’
> > > >  3 | S2() {}
> > > >|  ^
> > 
> > https://gcc.gnu.org/PR114439 ?
> 
> yes, sorry, missed that already-existing bugracker issue

I have a patch now, sorry about the breakage.  I'm surprised we had no test
covering this :(.

Marek



[PATCH v2] c++: ICE with noexcept and local specialization, again [PR114349]

2024-03-22 Thread Marek Polacek
On Thu, Mar 21, 2024 at 05:27:37PM -0400, Jason Merrill wrote:
> On 3/21/24 17:01, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Patrick noticed that my r14-9339-gdc6c3bfb59baab patch is wrong;
> > we're dealing with a noexcept-spec there, not a noexcept-expr, so
> > setting cp_noexcept_operand et al is incorrect.  Back to the drawing
> > board then.
> > 
> > To fix noexcept84.C, we should probably avoid doing push_to_top_level
> > in certain cases.  Patrick suggested checking:
> > 
> >const bool push_to_top = current_function_decl != fn;
> > 
> > which works, but I'm not sure I follow the logic there.  I also came
> > up with
> > 
> >const bool push_to_top = !decl_function_context (fn);
> > 
> > which also works.  But ultimately I went with !DECL_TEMPLATE_INSTANTIATED;
> > if DECL_TEMPLATE_INSTANTIATED is set, we've already pushed to top level
> > if it was necessary in instantiate_body.
> 
> This sort of thing is what maybe_push_to_top_level is for, does that also
> work?

Sadly -- and I should have mentioned that -- no.  maybe_push_to_top_level asks:

  bool push_to_top
= !(current_function_decl
   && !LAMBDA_FUNCTION_P (d)
   && decl_function_context (d) == current_function_decl);

here both d and current_function_decl are test()::S::S(), and
decl_function_context (d) is test().  (current_function_decl was
set to test()::S::S() by an earlier push_access_scope call.)

But I want it to work, and I think using maybe_ would be a way nicer
fix.  So what if we don't push to top level if decl_function_context
is non-null?  I had to add the LAMBDA_TYPE_P check though: it looks
that we always have to push to top level for lambdas, but sometimes
we get a lambda's TYPE_DECL, and LAMBDA_FUNCTION_P doesn't catch
that.  An example is lambda-nested4.C.

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

-- >8 --
Patrick noticed that my r14-9339-gdc6c3bfb59baab patch is wrong;
we're dealing with a noexcept-spec there, not a noexcept-expr, so
setting cp_noexcept_operand et al is incorrect.  Back to the drawing
board then.

To fix noexcept84.C, we should probably avoid doing push_to_top_level
in certain cases.  maybe_push_to_top_level didn't work here as-is, so
I changed it to not push to top level if decl_function_context is
non-null, when we are not dealing with a lambda.

This also fixes c++/114349, introduced by r14-9339.

PR c++/114349

gcc/cp/ChangeLog:

* name-lookup.cc (maybe_push_to_top_level): For a non-lambda,
don't push to top level if decl_function_context is non-null.
* pt.cc (maybe_instantiate_noexcept): Use maybe_push_to_top_level.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept85.C: New test.
* g++.dg/cpp0x/noexcept86.C: New test.
---
 gcc/cp/name-lookup.cc   | 12 ++---
 gcc/cp/pt.cc| 11 ++---
 gcc/testsuite/g++.dg/cpp0x/noexcept85.C | 33 +
 gcc/testsuite/g++.dg/cpp0x/noexcept86.C | 25 +++
 4 files changed, 68 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept85.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept86.C

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index dce4caf8981..4b2b27bdd0d 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8664,10 +8664,14 @@ maybe_push_to_top_level (tree d)
 {
   /* Push if D isn't function-local, or is a lambda function, for which name
  resolution is already done.  */
-  bool push_to_top
-= !(current_function_decl
-   && !LAMBDA_FUNCTION_P (d)
-   && decl_function_context (d) == current_function_decl);
+  const bool push_to_top
+= (LAMBDA_FUNCTION_P (d)
+   || (TREE_CODE (d) == TYPE_DECL
+  && TREE_TYPE (d)
+  && LAMBDA_TYPE_P (TREE_TYPE (d)))
+   || !current_function_decl
+   || (!decl_function_context (d)
+  && decl_function_context (d) != current_function_decl));
 
   if (push_to_top)
 push_to_top_level ();
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8cf0d5b7a8d..7b00a8615d2 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26855,7 +26855,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
}
   else if (push_tinst_level (fn))
{
- push_to_top_level ();
+ const bool push_to_top = maybe_push_to_top_level (fn);
  push_access_scope (fn);
  push_deferring_access_checks (dk_no_deferred);
  input_location = DECL_SOURCE_LOCATION (fn);
@@ -26878,17 +26878,10 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  if (orig_fn)
++processing_template_decl;
 
- ++cp_unevaluated_operand;
-  

[gcc r14-9622] c++: direct-init of an array of class type [PR59465]

2024-03-22 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:d1d8fd2884b44598d80de1038b086eec41519d4b

commit r14-9622-gd1d8fd2884b44598d80de1038b086eec41519d4b
Author: Marek Polacek 
Date:   Thu Feb 22 18:49:08 2024 -0500

c++: direct-init of an array of class type [PR59465]

...from another array in a mem-initializer should not be accepted.

We already reject

  struct string {} a[1];
  string x[1](a);

but

  struct pair {
string s[1];
pair() : s(a) {}
  };

is wrongly accepted.

It started to be accepted with r0-110915-ga034826198b771:
<https://gcc.gnu.org/pipermail/gcc-patches/2011-August/320236.html>
which was supposed to be a cleanup, not a deliberate change to start
accepting the code.  The build_vec_init_expr code was added in r165976:
<https://gcc.gnu.org/pipermail/gcc-patches/2010-October/297582.html>.

It appears that we do the magic copy array when we have a defaulted
constructor and we generate code for its mem-initializer which
initializes an array.  I also see that we go that path for compound
literals.  So when initializing an array member, we can limit building
up a VEC_INIT_EXPR to those special cases.

PR c++/59465

gcc/cp/ChangeLog:

* init.cc (can_init_array_with_p): New.
(perform_member_init): Check it.

gcc/testsuite/ChangeLog:

* g++.dg/init/array62.C: New test.
* g++.dg/init/array63.C: New test.
* g++.dg/init/array64.C: New test.

Diff:
---
 gcc/cp/init.cc  | 31 ---
 gcc/testsuite/g++.dg/init/array62.C | 19 +++
 gcc/testsuite/g++.dg/init/array63.C | 13 +
 gcc/testsuite/g++.dg/init/array64.C | 22 ++
 4 files changed, 82 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index d2586fad86b..dbd37d47cbf 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -934,6 +934,33 @@ find_uninit_fields (tree *t, hash_set 
*uninitialized, tree member)
 }
 }
 
+/* Return true if it's OK to initialize an array TYPE from INIT.  Mere mortals
+   can't copy arrays, but the compiler can do so with a VEC_INIT_EXPR in
+   certain cases.  */
+
+static bool
+can_init_array_with_p (tree type, tree init)
+{
+  if (!init)
+/* Value-init, OK.  */
+return true;
+  if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init)))
+return false;
+  /* We're called from synthesize_method, and we're processing the
+ mem-initializers of a constructor.  */
+  if (DECL_DEFAULTED_FN (current_function_decl))
+return true;
+  /* As an extension, we allow copying from a compound literal.  */
+  if (TREE_CODE (init) == TARGET_EXPR)
+{
+  init = TARGET_EXPR_INITIAL (init);
+  if (TREE_CODE (init) == CONSTRUCTOR)
+   return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
+}
+
+  return false;
+}
+
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
arguments.  If TREE_LIST is void_type_node, an empty initializer
list was given; if NULL_TREE no initializer was given.  UNINITIALIZED
@@ -1087,9 +1114,7 @@ perform_member_init (tree member, tree init, 
hash_set )
 {
   if (TREE_CODE (type) == ARRAY_TYPE)
{
- if (init == NULL_TREE
- || same_type_ignoring_top_level_qualifiers_p (type,
-   TREE_TYPE (init)))
+ if (can_init_array_with_p (type, init))
{
  if (TYPE_DOMAIN (type) && TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
{
diff --git a/gcc/testsuite/g++.dg/init/array62.C 
b/gcc/testsuite/g++.dg/init/array62.C
new file mode 100644
index 000..2a786a36e4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array62.C
@@ -0,0 +1,19 @@
+// PR c++/59465
+// { dg-do compile }
+
+struct string {} a[1];
+struct pair {
+  string s[1];
+  pair() : s(a) {} // { dg-error "invalid initializer for array member" }
+};
+
+struct S {
+  char s[10];
+  S() : s("aaa") {}
+};
+
+void
+g ()
+{
+  string x[1](a); // { dg-error "array must be initialized" }
+}
diff --git a/gcc/testsuite/g++.dg/init/array63.C 
b/gcc/testsuite/g++.dg/init/array63.C
new file mode 100644
index 000..57e98056168
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array63.C
@@ -0,0 +1,13 @@
+// PR c++/59465
+// { dg-do compile }
+
+struct I {
+const bool b;
+};
+struct O {
+I a[2];
+static I const data[2];
+O() : a(data){}  // { dg-error "invalid initializer for array member" }
+};
+
+I const O::data[2] = {true, false};
diff --git a/gcc/testsuite/g++.dg/init/array64.C 
b/gcc/testsuite/g++.dg/init/array64.C
new file mode 100644
index 000..e0afdfab39a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array64.C
@@ -0,0 +1,22 @@
+// PR c++/59465
+// { dg-do compile }
+
+static const int my_size = 10;
+
+cla

Re: [PATCH] c++: ICE with noexcept and local specialization [PR114114]

2024-03-21 Thread Marek Polacek
On Fri, Mar 15, 2024 at 12:12:49PM -0400, Patrick Palka wrote:
> On Fri, 15 Mar 2024, Marek Polacek wrote:
> 
> > On Fri, Mar 15, 2024 at 10:35:07AM -0400, Patrick Palka wrote:
> > > On Tue, 5 Mar 2024, Marek Polacek wrote:
> > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > Here we ICE because we call register_local_specialization while
> > > > local_specializations is null, so
> > > > 
> > > >   local_specializations->put ();
> > > > 
> > > > crashes on null this.  It's null since maybe_instantiate_noexcept calls
> > > > push_to_top_level which creates a new scope.  Normally, I would have
> > > > guessed that we need a new local_specialization_stack.  But here we're
> > > > dealing with an operand of a noexcept, which is an unevaluated operand,
> > > > and those aren't registered in the hash map.  maybe_instantiate_noexcept
> > > > wasn't signalling that it's substituting an unevaluated operand though.
> > > 
> > > It thought it was noexcept-exprs rather than noexcept-specs that are
> > > unevaluated contexts?
> > 
> > Yes, sigh.  It would have to be noexcept(noexcept(x)).  I was looking at
> > cp_parser_unary_expression/RID_NOEXCEPT but that's a noexcept-expr.  So
> > what can we do here, set a new local_specialization_stack?  That wasn't
> > that straightforward when I tried.  Or maybe just
> 
> Maybe we can avoid doing push_to_top_level (which clears
> local_specializations) from maybe_instantiate_noexcept if
> current_function_decl == fn?

Thanks, I agree that not doing push_to_top_level in the first place
is a better fix.  I just sent a patch that does that.
 
> Relatedly I wonder if we can avoid calling regenerate_decl_from_template
> for local class member functions since they can't be redeclared?

Good point.  I've tried the below, but that breaks a lot of contracts tests.
I have not pursued it further than that.

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a7ba8b5af92..5352453a5d3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26623,6 +26623,12 @@ regenerate_decl_from_template (tree decl, tree tmpl, 
tree args)
   if (DECL_UNIQUE_FRIEND_P (decl))
goto done;
 
+  /* [class.mem.general]/5 says that a member shall not be declared twice
+in the member-specification (unless it's a nested class or member class
+template or an enumeration).  */
+  if (DECL_CLASS_SCOPE_P (decl))
+   goto done;
+
   /* Use the source location of the definition.  */
   DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl);
 

Marek



[PATCH] c++: ICE with noexcept and local specialization, again [PR114349]

2024-03-21 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Patrick noticed that my r14-9339-gdc6c3bfb59baab patch is wrong;
we're dealing with a noexcept-spec there, not a noexcept-expr, so
setting cp_noexcept_operand et al is incorrect.  Back to the drawing
board then.

To fix noexcept84.C, we should probably avoid doing push_to_top_level
in certain cases.  Patrick suggested checking:

  const bool push_to_top = current_function_decl != fn;

which works, but I'm not sure I follow the logic there.  I also came
up with

  const bool push_to_top = !decl_function_context (fn);

which also works.  But ultimately I went with !DECL_TEMPLATE_INSTANTIATED;
if DECL_TEMPLATE_INSTANTIATED is set, we've already pushed to top level
if it was necessary in instantiate_body.

This also fixes c++/114349, introduced by r14-9339.

PR c++/114349

gcc/cp/ChangeLog:

* pt.cc (maybe_instantiate_noexcept): Don't push_to_top_level if
fn has already been instantiated.  Don't save/restore
cp_unevaluated_operand, c_inhibit_evaluation_warnings, and
cp_noexcept_operand around the tsubst_expr call.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept85.C: New test.
* g++.dg/cpp0x/noexcept86.C: New test.
---
 gcc/cp/pt.cc| 17 ++---
 gcc/testsuite/g++.dg/cpp0x/noexcept85.C | 33 +
 gcc/testsuite/g++.dg/cpp0x/noexcept86.C | 25 +++
 3 files changed, 66 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept85.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept86.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8cf0d5b7a8d..b7ebd93ac7d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26855,7 +26855,12 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
}
   else if (push_tinst_level (fn))
{
- push_to_top_level ();
+ /* If we've already instantiated FN, there's no need to push to
+top level (as instantiate_body already pushed to top level if
+needed).  */
+ const bool push_to_top = !DECL_TEMPLATE_INSTANTIATED (fn);
+ if (push_to_top)
+   push_to_top_level ();
  push_access_scope (fn);
  push_deferring_access_checks (dk_no_deferred);
  input_location = DECL_SOURCE_LOCATION (fn);
@@ -26878,17 +26883,10 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  if (orig_fn)
++processing_template_decl;
 
- ++cp_unevaluated_operand;
- ++c_inhibit_evaluation_warnings;
- ++cp_noexcept_operand;
  /* Do deferred instantiation of the noexcept-specifier.  */
  noex = tsubst_expr (DEFERRED_NOEXCEPT_PATTERN (noex),
  DEFERRED_NOEXCEPT_ARGS (noex),
  tf_warning_or_error, fn);
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
- --cp_noexcept_operand;
-
  /* Build up the noexcept-specification.  */
  spec = build_noexcept_spec (noex, tf_warning_or_error);
 
@@ -26898,7 +26896,8 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  pop_deferring_access_checks ();
  pop_access_scope (fn);
  pop_tinst_level ();
- pop_from_top_level ();
+ if (push_to_top)
+   pop_from_top_level ();
}
   else
spec = noexcept_false_spec;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept85.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept85.C
new file mode 100644
index 000..b415bb46bc9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept85.C
@@ -0,0 +1,33 @@
+// PR c++/114349
+// { dg-do compile { target c++11 } }
+
+using A = struct {};
+template  class, typename, typename>
+using B = A;
+template 
+using C = typename T::D;
+struct E {
+  using D = B;
+};
+template  constexpr bool foo (A) { return false; }
+template  struct F {
+  using G = T;
+  using H = E;
+  F(const F &);
+  void operator=(F) noexcept(foo  (H::D{}));
+};
+template 
+using I = F;
+template 
+using J = I;
+struct K {
+  typedef J L;
+  L k;
+  K();
+};
+struct M {
+  bool bar () const;
+  K::L m;
+};
+K n;
+bool M::bar () const { n.k = m; return true; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept86.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept86.C
new file mode 100644
index 000..2d040c090f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept86.C
@@ -0,0 +1,25 @@
+// PR c++/114349
+// { dg-do compile { target c++14 } }
+
+struct B
+{
+  int i;
+};
+
+template 
+void
+goo ()
+{
+  constexpr bool is_yes = BA;
+  struct C
+  {
+static auto g(B b) noexcept(is_yes) { }
+  };
+  C::g({});
+}
+
+void
+x ()
+{
+  goo();
+}

base-commit: 48d49200510198cafcab55601cd8e5f8eb541f01
-- 
2.44.0



[PATCH v2] c++: direct-init of an array of class type [PR59465]

2024-03-21 Thread Marek Polacek
On Wed, Mar 20, 2024 at 09:21:02PM -0400, Jason Merrill wrote:
> On 3/1/24 19:58, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  I don't
> > claim that this has to go to 14 though.
> > 
> > -- >8 --
> > ...from another array in a mem-initializer should not be accepted.
> > 
> > We already reject
> > 
> >struct string {} a[1];
> >string x[1](a);
> > 
> > but
> > 
> >struct pair {
> >  string s[1];
> >  pair() : s(a) {}
> >};
> > 
> > is wrongly accepted.
> > 
> > It started to be accepted with r0-110915-ga034826198b771:
> > <https://gcc.gnu.org/pipermail/gcc-patches/2011-August/320236.html>
> > which was supposed to be a cleanup, not a deliberate change to start
> > accepting the code.  The build_vec_init_expr code was added in r165976:
> > <https://gcc.gnu.org/pipermail/gcc-patches/2010-October/297582.html>.
> > 
> > It appears that we do the magic copy array when we have a defaulted
> > constructor and we generate code for its mem-initializer which
> > initializes an array.  I also see that we go that path for compound
> > literals.  So when initializing an array member, we can limit building
> > up a VEC_INIT_EXPR to those special cases.
> > 
> > PR c++/59465
> > 
> > gcc/cp/ChangeLog:
> > 
> > * init.cc (can_init_array_with_p): New.
> > (perform_member_init): Check it.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/init/array62.C: New test.
> > * g++.dg/init/array63.C: New test.
> > * g++.dg/init/array64.C: New test.
> > ---
> >   gcc/cp/init.cc  | 27 ++-
> >   gcc/testsuite/g++.dg/init/array62.C | 19 +++
> >   gcc/testsuite/g++.dg/init/array63.C | 13 +
> >   gcc/testsuite/g++.dg/init/array64.C | 22 ++
> >   4 files changed, 80 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/g++.dg/init/array62.C
> >   create mode 100644 gcc/testsuite/g++.dg/init/array63.C
> >   create mode 100644 gcc/testsuite/g++.dg/init/array64.C
> > 
> > diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
> > index d2586fad86b..fb8c0e521fb 100644
> > --- a/gcc/cp/init.cc
> > +++ b/gcc/cp/init.cc
> > @@ -934,6 +934,31 @@ find_uninit_fields (tree *t, hash_set 
> > *uninitialized, tree member)
> >   }
> >   }
> > +/* Return true if it's OK to initialize an array from INIT.  Mere mortals
> > +   can't copy arrays, but the compiler can do so with a VEC_INIT_EXPR in
> > +   certain cases.  */
> > +
> > +static bool
> > +can_init_array_with_p (tree init)
> > +{
> > +  if (!init)
> > +return true;
> > +
> > +  /* We're called from synthesize_method, and we're processing the
> > + mem-initializers of a constructor.  */
> > +  if (DECL_DEFAULTED_FN (current_function_decl))
> > +return true;
> > +  /* As an extension, we allow copying from a compound literal.  */
> > +  else if (TREE_CODE (init) == TARGET_EXPR)
> > +{
> > +  init = TARGET_EXPR_INITIAL (init);
> > +  if (TREE_CODE (init) == CONSTRUCTOR)
> > +   return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
> > +}
> > +
> > +  return false;
> > +}
> > +
> >   /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
> >  arguments.  If TREE_LIST is void_type_node, an empty initializer
> >  list was given; if NULL_TREE no initializer was given.  UNINITIALIZED
> > @@ -1085,7 +1110,7 @@ perform_member_init (tree member, tree init, 
> > hash_set )
> > else if (type_build_ctor_call (type)
> >|| (init && CLASS_TYPE_P (strip_array_types (type
> >   {
> > -  if (TREE_CODE (type) == ARRAY_TYPE)
> > +  if (TREE_CODE (type) == ARRAY_TYPE && can_init_array_with_p (init))
> > {
> >   if (init == NULL_TREE
> >   || same_type_ignoring_top_level_qualifiers_p (type,
> 
> It seems like these last two existing lines also fall under "init is
> suitable to initialize type", so let's fold them into the new function.

Sounds good.  Here it is:

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

-- >8 --
...from another array in a mem-initializer should not be accepted.

We already reject

  struct string {} a[1];
  string x[1](a);

but

  struct pair {
string s[1];
pair() : s(a) {}
  };

is wrongly accepted.

It started to be accepted with r0-110915-ga034826198b7

[gcc r14-9596] c++: explicit inst of template method not generated [PR110323]

2024-03-21 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:081f8937cb82da311c224da04b0c6cbd57a8fb5d

commit r14-9596-g081f8937cb82da311c224da04b0c6cbd57a8fb5d
Author: Marek Polacek 
Date:   Thu Mar 7 20:41:23 2024 -0500

c++: explicit inst of template method not generated [PR110323]

Consider

  constexpr int VAL = 1;
  struct foo {
  template 
  void bar(typename std::conditional::type arg) { }
  };
  template void foo::bar<1>(int arg);

where we since r11-291 fail to emit the code for the explicit
instantiation.  That's because cp_walk_subtrees/TYPENAME_TYPE now
walks TYPE_CONTEXT ('conditional' here) as well, and in a template
finds the B==VAL template argument.  VAL is constexpr, which implies const,
which in the global scope implies static.  constrain_visibility_for_template
then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC.
Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't
emit any code.

I thought the fix would be some ODR-esque check to not consider
constexpr variables/fns that are used just for their value.  But
it turned out to be tricky.  For instance, we can't skip
determine_visibility in a template; we can't even skip it for value-dep
expressions.  For example, no-linkage-expr1.C has

  using P = struct {}*;
  template 
  void f(int(*)[((P)0, N)]) {}

where ((P)0, N) is value-dep, but N is not relevant here: we have to
ferret out the anonymous type.  When instantiating, it's already gone.

This patch uses decl_constant_var_p.  This is to implement (an
approximation) [basic.def.odr]#14.5.1 and [basic.def.odr]#5.2.

PR c++/110323

gcc/cp/ChangeLog:

* decl2.cc (min_vis_expr_r) : Do nothing for
decl_constant_var_p VAR_DECLs.

gcc/testsuite/ChangeLog:

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

Diff:
---
 gcc/cp/decl2.cc|  7 +++-
 .../g++.dg/template/explicit-instantiation6.C  | 43 ++
 .../g++.dg/template/explicit-instantiation7.C  | 22 +++
 3 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 2562d8aeff6..1339f210dde 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2718,7 +2718,12 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
   /* Fall through.  */
 case VAR_DECL:
 case FUNCTION_DECL:
-  if (! TREE_PUBLIC (t))
+  if (decl_constant_var_p (t))
+   /* The ODR allows definitions in different TUs to refer to distinct
+  constant variables with internal or no linkage, so such a reference
+  shouldn't affect visibility (PR110323).  FIXME but only if the
+  lvalue-rvalue conversion is applied.  */;
+  else if (! TREE_PUBLIC (t))
tpvis = VISIBILITY_ANON;
   else
tpvis = DECL_VISIBILITY (t);
diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation6.C 
b/gcc/testsuite/g++.dg/template/explicit-instantiation6.C
new file mode 100644
index 000..8b77c9deb20
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-instantiation6.C
@@ -0,0 +1,43 @@
+// PR c++/110323
+// { dg-do compile { target c++14 } }
+
+template
+struct conditional { using type = T; };
+
+template
+struct conditional { using type = F; };
+
+constexpr int VAL = 1;
+
+static constexpr int getval () { return 1; }
+
+template
+constexpr int TVAL = 1;
+
+static struct S {
+  constexpr operator bool() { return true; }
+} s;
+
+struct foo {
+template 
+void bar(typename conditional::type arg) { }
+
+template 
+void qux(typename conditional, int, float>::type arg) { }
+
+template 
+void sox(typename conditional::type arg) 
{ }
+
+template 
+void nim(typename conditional::type arg) { }
+};
+
+template void foo::bar<1>(int arg);
+template void foo::qux<1>(int arg);
+template void foo::sox<1>(int arg);
+template void foo::nim<1>(int arg);
+
+// { dg-final { scan-assembler 
"_ZN3foo3barILi1EEEvN11conditionalIXeqT_L_ZL3VALEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3quxILi1EEEvN11conditionalIXeqT_L_Z4TVALIiEEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3soxILi1EEEvN11conditionalIXeqT_nxL_ZL3VALEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3nimILi1EEEvN11conditionalIXneT_szL_ZL3VALEEifE4typeE" } }
diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation7.C 
b/gcc/testsuite/g++.dg/template/explicit-instantiation7.C
new file mode 100644
index 000..9a870e808fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-instantiation7.C
@@ -0,0 +1,22 @@
+// PR c++/110323
+// { dg-do compile { target c++11 } }
+
+using P = struct { }*;
+us

[gcc r14-9558] testsuite: fix target for linkage-1.C

2024-03-19 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:7a6261332de58fd47283d694d8cd61ea7cdb324c

commit r14-9558-g7a6261332de58fd47283d694d8cd61ea7cdb324c
Author: Marek Polacek 
Date:   Tue Mar 19 17:15:38 2024 -0400

testsuite: fix target for linkage-1.C

This test fails in C++11 due to:

linkage-1.C:3:8: error: 'f' function uses 'auto' type specifier without 
trailing return type
3 | inline auto f() {
  |^~~~
linkage-1.C:3:8: note: deduced return type only available with '-std=c++14' 
or '-std=gnu++14'

Compile it in C++14 thus.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/linkage-1.C: Use target c++14.

Diff:
---
 gcc/testsuite/g++.dg/cpp2a/linkage-1.C | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/g++.dg/cpp2a/linkage-1.C 
b/gcc/testsuite/g++.dg/cpp2a/linkage-1.C
index 888ed6fa5b5..2b83ffe55b7 100644
--- a/gcc/testsuite/g++.dg/cpp2a/linkage-1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/linkage-1.C
@@ -1,4 +1,4 @@
-// { dg-do compile { target c++11 } }
+// { dg-do compile { target c++14 } }
 
 inline auto f() {
   struct A {};


[pushed] testsuite: fix target for linkage-1.C

2024-03-19 Thread Marek Polacek
Tested x86_64-pc-linux-gnu, applying to trunk.

-- >8 --
This test fails in C++11 due to:

linkage-1.C:3:8: error: 'f' function uses 'auto' type specifier without 
trailing return type
3 | inline auto f() {
  |^~~~
linkage-1.C:3:8: note: deduced return type only available with '-std=c++14' or 
'-std=gnu++14'

Compile it in C++14 thus.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/linkage-1.C: Use target c++14.
---
 gcc/testsuite/g++.dg/cpp2a/linkage-1.C | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/g++.dg/cpp2a/linkage-1.C 
b/gcc/testsuite/g++.dg/cpp2a/linkage-1.C
index 888ed6fa5b5..2b83ffe55b7 100644
--- a/gcc/testsuite/g++.dg/cpp2a/linkage-1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/linkage-1.C
@@ -1,4 +1,4 @@
-// { dg-do compile { target c++11 } }
+// { dg-do compile { target c++14 } }
 
 inline auto f() {
   struct A {};

base-commit: 9c91f8a88b2db50c8faf70786d3cef27b39ac9fc
-- 
2.44.0



Re: [PATCH] c++: direct-init of an array of class type [PR59465]

2024-03-19 Thread Marek Polacek
Ping.  Though I reckon it may be better to defer this to 15.

On Fri, Mar 01, 2024 at 07:58:51PM -0500, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  I don't
> claim that this has to go to 14 though.
> 
> -- >8 --
> ...from another array in a mem-initializer should not be accepted.
> 
> We already reject
> 
>   struct string {} a[1];
>   string x[1](a);
> 
> but
> 
>   struct pair {
> string s[1];
> pair() : s(a) {}
>   };
> 
> is wrongly accepted.
> 
> It started to be accepted with r0-110915-ga034826198b771:
> <https://gcc.gnu.org/pipermail/gcc-patches/2011-August/320236.html>
> which was supposed to be a cleanup, not a deliberate change to start
> accepting the code.  The build_vec_init_expr code was added in r165976:
> <https://gcc.gnu.org/pipermail/gcc-patches/2010-October/297582.html>.
> 
> It appears that we do the magic copy array when we have a defaulted
> constructor and we generate code for its mem-initializer which
> initializes an array.  I also see that we go that path for compound
> literals.  So when initializing an array member, we can limit building
> up a VEC_INIT_EXPR to those special cases.
> 
>   PR c++/59465
> 
> gcc/cp/ChangeLog:
> 
>   * init.cc (can_init_array_with_p): New.
>   (perform_member_init): Check it.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/init/array62.C: New test.
>   * g++.dg/init/array63.C: New test.
>   * g++.dg/init/array64.C: New test.
> ---
>  gcc/cp/init.cc  | 27 ++-
>  gcc/testsuite/g++.dg/init/array62.C | 19 +++
>  gcc/testsuite/g++.dg/init/array63.C | 13 +
>  gcc/testsuite/g++.dg/init/array64.C | 22 ++
>  4 files changed, 80 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/init/array62.C
>  create mode 100644 gcc/testsuite/g++.dg/init/array63.C
>  create mode 100644 gcc/testsuite/g++.dg/init/array64.C
> 
> diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
> index d2586fad86b..fb8c0e521fb 100644
> --- a/gcc/cp/init.cc
> +++ b/gcc/cp/init.cc
> @@ -934,6 +934,31 @@ find_uninit_fields (tree *t, hash_set 
> *uninitialized, tree member)
>  }
>  }
>  
> +/* Return true if it's OK to initialize an array from INIT.  Mere mortals
> +   can't copy arrays, but the compiler can do so with a VEC_INIT_EXPR in
> +   certain cases.  */
> +
> +static bool
> +can_init_array_with_p (tree init)
> +{
> +  if (!init)
> +return true;
> +
> +  /* We're called from synthesize_method, and we're processing the
> + mem-initializers of a constructor.  */
> +  if (DECL_DEFAULTED_FN (current_function_decl))
> +return true;
> +  /* As an extension, we allow copying from a compound literal.  */
> +  else if (TREE_CODE (init) == TARGET_EXPR)
> +{
> +  init = TARGET_EXPR_INITIAL (init);
> +  if (TREE_CODE (init) == CONSTRUCTOR)
> + return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
> +}
> +
> +  return false;
> +}
> +
>  /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
> arguments.  If TREE_LIST is void_type_node, an empty initializer
> list was given; if NULL_TREE no initializer was given.  UNINITIALIZED
> @@ -1085,7 +1110,7 @@ perform_member_init (tree member, tree init, 
> hash_set )
>else if (type_build_ctor_call (type)
>  || (init && CLASS_TYPE_P (strip_array_types (type
>  {
> -  if (TREE_CODE (type) == ARRAY_TYPE)
> +  if (TREE_CODE (type) == ARRAY_TYPE && can_init_array_with_p (init))
>   {
> if (init == NULL_TREE
> || same_type_ignoring_top_level_qualifiers_p (type,
> diff --git a/gcc/testsuite/g++.dg/init/array62.C 
> b/gcc/testsuite/g++.dg/init/array62.C
> new file mode 100644
> index 000..6d3935d7a66
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/init/array62.C
> @@ -0,0 +1,19 @@
> +// PR c++/59465
> +// { dg-do compile }
> +
> +struct string {} a[1];
> +struct pair {
> +  string s[1];
> +  pair() : s(a) {} // { dg-error "array must be initialized" }
> +};
> +
> +struct S {
> +  char s[10];
> +  S() : s("aaa") {}
> +};
> +
> +void
> +g ()
> +{
> +  string x[1](a); // { dg-error "array must be initialized" }
> +}
> diff --git a/gcc/testsuite/g++.dg/init/array63.C 
> b/gcc/testsuite/g++.dg/init/array63.C
> new file mode 100644
> index 000..96bc9a64b26
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/init/array63.C
> @@ -0,0 +1,13 @@
> +// PR c++/59465
> +// { dg-do compile }
> +
> +struct I {
> +const bool b

Re: [PATCH v3] c++: ICE with temporary of class type in array DMI [PR109966]

2024-03-19 Thread Marek Polacek
On Thu, Mar 14, 2024 at 05:26:59PM -0400, Marek Polacek wrote:
> @@ -1441,11 +1406,13 @@ static tree
>  replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
>  {
>tree t = *tp;
> -  tree full_expr = *static_cast(data);
> +  auto pset = static_cast *>(data);
>  
>/* We're looking for a TARGET_EXPR nested in the whole expression.  */
>if (TREE_CODE (t) == TARGET_EXPR
> -  && !potential_prvalue_result_of (t, full_expr))
> +  /* That serves as temporary materialization, not an initializer.  */
> +  && !TARGET_EXPR_ELIDING_P (t)
> +  && !pset->add (t))
>  {
>tree init = TARGET_EXPR_INITIAL (t);
>while (TREE_CODE (init) == COMPOUND_EXPR)
> @@ -1460,6 +1427,16 @@ replace_placeholders_for_class_temp_r (tree *tp, int 
> *, void *data)
> gcc_checking_assert (!find_placeholders (init));
>   }
>  }
> +  /* TARGET_EXPRs initializing function arguments are not marked as eliding,
> + even though gimplify_arg drops them on the floor.  Don't go replacing
> + placeholders in them.  */
> +  else if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
> +for (int i = 0; i < call_expr_nargs (t); ++i)
> +  {
> + tree arg = get_nth_callarg (t, i);
> + if (TREE_CODE (arg) == TARGET_EXPR)

I just realized this could also check !TARGET_EXPR_ELIDING_P; there's no point
to adding an eliding TARGET_EXPR into the pset.

> +   pset->add (arg);
> +  }

Marek



[PATCH v2] c++: explicit inst of template method not generated [PR110323]

2024-03-19 Thread Marek Polacek
On Mon, Mar 18, 2024 at 09:10:27PM -0400, Jason Merrill wrote:
> On 3/15/24 13:48, Marek Polacek wrote:
> > On Thu, Mar 14, 2024 at 03:39:04PM -0400, Jason Merrill wrote:
> > > On 3/8/24 12:02, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > Consider
> > > > 
> > > > constexpr int VAL = 1;
> > > > struct foo {
> > > > template 
> > > > void bar(typename std::conditional::type 
> > > > arg) { }
> > > > };
> > > > template void foo::bar<1>(int arg);
> > > > 
> > > > where we since r11-291 fail to emit the code for the explicit
> > > > instantiation.  That's because cp_walk_subtrees/TYPENAME_TYPE now
> > > > walks TYPE_CONTEXT ('conditional' here) as well, and in a template
> > > > finds the B==VAL template argument.  VAL is constexpr, which implies 
> > > > const,
> > > > which in the global scope implies static.  
> > > > constrain_visibility_for_template
> > > > then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC.
> > > > Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't
> > > > emit any code.
> > > > 
> > > > I thought the fix would be some ODR-esque check to not consider
> > > > constexpr variables/fns that are used just for their value.  But
> > > > it turned out to be tricky.  For instance, we can't skip
> > > > determine_visibility in a template; we can't even skip it for value-dep
> > > > expressions.  For example, no-linkage-expr1.C has
> > > > 
> > > > using P = struct {}*;
> > > > template 
> > > > void f(int(*)[((P)0, N)]) {}
> > > > 
> > > > where ((P)0, N) is value-dep, but N is not relevant here: we have to
> > > > ferret out the anonymous type.  When instantiating, it's already gone.
> > > 
> > > Hmm, how is that different from the B == VAL case?  In both cases we're
> > > naming an internal entity that gets folded away.
> > > 
> > > I guess the difference is that B == VAL falls under the special allowance 
> > > in
> > > https://eel.is/c++draft/basic.def.odr#14.5.1 because it's a constant used 
> > > as
> > > a prvalue, and therefore is not odr-used under
> > > https://eel.is/c++draft/basic.def.odr#5.2
> > > 
> > > So I would limit this change to decl_constant_var_p.  Really we should 
> > > also
> > > be checking that the lvalue-rvalue conversion is applied, but that's more
> > > complicated.
> > 
> > Thanks.  My previous version had it, but it didn't handle
> > 
> >static constexpr int getval () { return 1; }
> > 
> >template 
> >void baz(typename conditional::type arg) { }
> > 
> > I'd say that "getval()" is one of "manifestly constant-evaluated 
> > expressions that
> > are not value-dependent", so it should be treated the same as B == VAL.
> 
> But it doesn't satisfy the 14.5 rule that corresponding names need to refer
> to the same entity; since getval names a function, it doesn't get the
> special exemption from that rule that VAL gets.
> 
> So this should not be treated the same as B == VAL.
 
Thanks for the explanation.

> > I don't know if this is important to handle.  Do you want me to poke 
> > further or
> > should we just go with decl_constant_var_p and leave it at that for now?
> 
> Just decl_constant_var_p.

Here it is:

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

-- >8 --
Consider

  constexpr int VAL = 1;
  struct foo {
  template 
  void bar(typename std::conditional::type arg) { }
  };
  template void foo::bar<1>(int arg);

where we since r11-291 fail to emit the code for the explicit
instantiation.  That's because cp_walk_subtrees/TYPENAME_TYPE now
walks TYPE_CONTEXT ('conditional' here) as well, and in a template
finds the B==VAL template argument.  VAL is constexpr, which implies const,
which in the global scope implies static.  constrain_visibility_for_template
then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC.
Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't
emit any code.

I thought the fix would be some ODR-esque check to not consider
constexpr variables/fns that are used just for their value.  But
it turned out to be tricky.  For instance, we can't skip
det

Re: [PATCH] c++: explicit inst of template method not generated [PR110323]

2024-03-15 Thread Marek Polacek
On Thu, Mar 14, 2024 at 03:39:04PM -0400, Jason Merrill wrote:
> On 3/8/24 12:02, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Consider
> > 
> >constexpr int VAL = 1;
> >struct foo {
> >template 
> >void bar(typename std::conditional::type arg) { }
> >};
> >template void foo::bar<1>(int arg);
> > 
> > where we since r11-291 fail to emit the code for the explicit
> > instantiation.  That's because cp_walk_subtrees/TYPENAME_TYPE now
> > walks TYPE_CONTEXT ('conditional' here) as well, and in a template
> > finds the B==VAL template argument.  VAL is constexpr, which implies const,
> > which in the global scope implies static.  constrain_visibility_for_template
> > then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC.
> > Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't
> > emit any code.
> > 
> > I thought the fix would be some ODR-esque check to not consider
> > constexpr variables/fns that are used just for their value.  But
> > it turned out to be tricky.  For instance, we can't skip
> > determine_visibility in a template; we can't even skip it for value-dep
> > expressions.  For example, no-linkage-expr1.C has
> > 
> >using P = struct {}*;
> >template 
> >void f(int(*)[((P)0, N)]) {}
> > 
> > where ((P)0, N) is value-dep, but N is not relevant here: we have to
> > ferret out the anonymous type.  When instantiating, it's already gone.
> 
> Hmm, how is that different from the B == VAL case?  In both cases we're
> naming an internal entity that gets folded away.
> 
> I guess the difference is that B == VAL falls under the special allowance in
> https://eel.is/c++draft/basic.def.odr#14.5.1 because it's a constant used as
> a prvalue, and therefore is not odr-used under
> https://eel.is/c++draft/basic.def.odr#5.2
> 
> So I would limit this change to decl_constant_var_p.  Really we should also
> be checking that the lvalue-rvalue conversion is applied, but that's more
> complicated.

Thanks.  My previous version had it, but it didn't handle

  static constexpr int getval () { return 1; }

  template 
  void baz(typename conditional::type arg) { }

I'd say that "getval()" is one of "manifestly constant-evaluated expressions 
that
are not value-dependent", so it should be treated the same as B == VAL.  I
don't know if this is important to handle.  Do you want me to poke further or
should we just go with decl_constant_var_p and leave it at that for now?

Marek



Re: [PATCH] c++: ICE with noexcept and local specialization [PR114114]

2024-03-15 Thread Marek Polacek
On Fri, Mar 15, 2024 at 10:35:07AM -0400, Patrick Palka wrote:
> On Tue, 5 Mar 2024, Marek Polacek wrote:
> 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Here we ICE because we call register_local_specialization while
> > local_specializations is null, so
> > 
> >   local_specializations->put ();
> > 
> > crashes on null this.  It's null since maybe_instantiate_noexcept calls
> > push_to_top_level which creates a new scope.  Normally, I would have
> > guessed that we need a new local_specialization_stack.  But here we're
> > dealing with an operand of a noexcept, which is an unevaluated operand,
> > and those aren't registered in the hash map.  maybe_instantiate_noexcept
> > wasn't signalling that it's substituting an unevaluated operand though.
> 
> It thought it was noexcept-exprs rather than noexcept-specs that are
> unevaluated contexts?

Yes, sigh.  It would have to be noexcept(noexcept(x)).  I was looking at
cp_parser_unary_expression/RID_NOEXCEPT but that's a noexcept-expr.  So
what can we do here, set a new local_specialization_stack?  That wasn't
that straightforward when I tried.  Or maybe just

--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -15649,7 +15649,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
  {
if (DECL_LANG_SPECIFIC (r))
  DECL_TEMPLATE_INFO (r) = NULL_TREE;
-   if (!cp_unevaluated_operand)
+   if (!cp_unevaluated_operand && local_specializations)
  register_local_specialization (r, t);
  }

?



[PATCH v3] c++: ICE with temporary of class type in array DMI [PR109966]

2024-03-14 Thread Marek Polacek
On Tue, Mar 12, 2024 at 06:26:14PM -0400, Jason Merrill wrote:
> On 3/12/24 11:56, Marek Polacek wrote:
> > On Tue, Mar 12, 2024 at 09:57:14AM -0400, Jason Merrill wrote:
> > > On 3/11/24 19:27, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > > > 
> > > > -- >8 --
> > > > This ICE started with the fairly complicated r13-765.  We crash in
> > > > gimplify_var_or_parm_decl because a stray VAR_DECL leaked there.
> > > > The problem is ultimately that potential_prvalue_result_of wasn't
> > > > correctly handling arrays and replace_placeholders_for_class_temp_r
> > > > replaced a PLACEHOLDER_EXPR in a TARGET_EXPR which is used in the
> > > > context of copy elision.  If I have
> > > > 
> > > > M m[2] = { M{""}, M{""} };
> > > > 
> > > > then we don't invoke the M(const M&) copy-ctor.  I think the fix is
> > > > to detect such a case in potential_prvalue_result_of.
> > > > 
> > > > PR c++/109966
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * typeck2.cc (potential_prvalue_result_of): Add walk_subtrees
> > > > parameter.  Handle initializing an array from a
> > > > brace-enclosed-initializer.
> > > > (replace_placeholders_for_class_temp_r): Pass walk_subtrees 
> > > > down to
> > > > potential_prvalue_result_of.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp1y/nsdmi-aggr20.C: New test.
> > > > * g++.dg/cpp1y/nsdmi-aggr21.C: New test.
> > > > ---
> > > >gcc/cp/typeck2.cc | 27 ---
> > > >gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C | 17 +++
> > > >gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C | 59 
> > > > +++
> > > >3 files changed, 96 insertions(+), 7 deletions(-)
> > > >create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C
> > > >create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C
> > > > 
> > > > diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
> > > > index 31198b2f9f5..8b99ce78e9a 100644
> > > > --- a/gcc/cp/typeck2.cc
> > > > +++ b/gcc/cp/typeck2.cc
> > > > @@ -1406,46 +1406,59 @@ digest_init_flags (tree type, tree init, int 
> > > > flags, tsubst_flags_t complain)
> > > > A a = (A{});  // initializer
> > > > A a = (1, A{});   // initializer
> > > > A a = true ? A{} : A{};  // initializer
> > > > + A arr[1] = { A{} };  // initializer
> > > > auto x = A{}.x;   // temporary materialization
> > > > auto x = foo(A{});// temporary materialization
> > > >   FULL_EXPR is the whole expression, SUBOB is its TARGET_EXPR 
> > > > subobject.  */
> > > >static bool
> > > > -potential_prvalue_result_of (tree subob, tree full_expr)
> > > > +potential_prvalue_result_of (tree subob, tree full_expr, int 
> > > > *walk_subtrees)
> > > >{
> > > > +#define RECUR(t) potential_prvalue_result_of (subob, t, walk_subtrees)
> > > >  if (subob == full_expr)
> > > >return true;
> > > >  else if (TREE_CODE (full_expr) == TARGET_EXPR)
> > > >{
> > > >  tree init = TARGET_EXPR_INITIAL (full_expr);
> > > >  if (TREE_CODE (init) == COND_EXPR)
> > > > -   return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 
> > > > 1))
> > > > -   || potential_prvalue_result_of (subob, TREE_OPERAND 
> > > > (init, 2)));
> > > > +   return (RECUR (TREE_OPERAND (init, 1))
> > > > +   || RECUR (TREE_OPERAND (init, 2)));
> > > >  else if (TREE_CODE (init) == COMPOUND_EXPR)
> > > > -   return potential_prvalue_result_of (subob, TREE_OPERAND (init, 
> > > > 1));
> > > > +   return RECUR (TREE_OPERAND (init, 1));
> > > >  /* ??? I don't know if this can be hit.  */
> > > >  else if (TREE_CODE (init) == PAREN_EXPR)
> > > > {
> > > >   gcc_checking_assert (false);
> > > > - return potential_prvalue_result_of (subob, TRE

[PATCH v2] c++: ICE with temporary of class type in array DMI [PR109966]

2024-03-12 Thread Marek Polacek
On Tue, Mar 12, 2024 at 09:57:14AM -0400, Jason Merrill wrote:
> On 3/11/24 19:27, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > 
> > -- >8 --
> > This ICE started with the fairly complicated r13-765.  We crash in
> > gimplify_var_or_parm_decl because a stray VAR_DECL leaked there.
> > The problem is ultimately that potential_prvalue_result_of wasn't
> > correctly handling arrays and replace_placeholders_for_class_temp_r
> > replaced a PLACEHOLDER_EXPR in a TARGET_EXPR which is used in the
> > context of copy elision.  If I have
> > 
> >M m[2] = { M{""}, M{""} };
> > 
> > then we don't invoke the M(const M&) copy-ctor.  I think the fix is
> > to detect such a case in potential_prvalue_result_of.
> > 
> > PR c++/109966
> > 
> > gcc/cp/ChangeLog:
> > 
> > * typeck2.cc (potential_prvalue_result_of): Add walk_subtrees
> > parameter.  Handle initializing an array from a
> > brace-enclosed-initializer.
> > (replace_placeholders_for_class_temp_r): Pass walk_subtrees down to
> > potential_prvalue_result_of.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp1y/nsdmi-aggr20.C: New test.
> > * g++.dg/cpp1y/nsdmi-aggr21.C: New test.
> > ---
> >   gcc/cp/typeck2.cc | 27 ---
> >   gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C | 17 +++
> >   gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C | 59 +++
> >   3 files changed, 96 insertions(+), 7 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C
> > 
> > diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
> > index 31198b2f9f5..8b99ce78e9a 100644
> > --- a/gcc/cp/typeck2.cc
> > +++ b/gcc/cp/typeck2.cc
> > @@ -1406,46 +1406,59 @@ digest_init_flags (tree type, tree init, int flags, 
> > tsubst_flags_t complain)
> >A a = (A{});   // initializer
> >A a = (1, A{});// initializer
> >A a = true ? A{} : A{};  // initializer
> > + A arr[1] = { A{} };  // initializer
> >auto x = A{}.x;// temporary materialization
> >auto x = foo(A{}); // temporary materialization
> >  FULL_EXPR is the whole expression, SUBOB is its TARGET_EXPR subobject. 
> >  */
> >   static bool
> > -potential_prvalue_result_of (tree subob, tree full_expr)
> > +potential_prvalue_result_of (tree subob, tree full_expr, int 
> > *walk_subtrees)
> >   {
> > +#define RECUR(t) potential_prvalue_result_of (subob, t, walk_subtrees)
> > if (subob == full_expr)
> >   return true;
> > else if (TREE_CODE (full_expr) == TARGET_EXPR)
> >   {
> > tree init = TARGET_EXPR_INITIAL (full_expr);
> > if (TREE_CODE (init) == COND_EXPR)
> > -   return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 1))
> > -   || potential_prvalue_result_of (subob, TREE_OPERAND (init, 2)));
> > +   return (RECUR (TREE_OPERAND (init, 1))
> > +   || RECUR (TREE_OPERAND (init, 2)));
> > else if (TREE_CODE (init) == COMPOUND_EXPR)
> > -   return potential_prvalue_result_of (subob, TREE_OPERAND (init, 1));
> > +   return RECUR (TREE_OPERAND (init, 1));
> > /* ??? I don't know if this can be hit.  */
> > else if (TREE_CODE (init) == PAREN_EXPR)
> > {
> >   gcc_checking_assert (false);
> > - return potential_prvalue_result_of (subob, TREE_OPERAND (init, 0));
> > + return RECUR (TREE_OPERAND (init, 0));
> > }
> >   }
> > +  /* The array case listed above.  */
> > +  else if (TREE_CODE (full_expr) == CONSTRUCTOR
> > +  && TREE_CODE (TREE_TYPE (full_expr)) == ARRAY_TYPE)
> > +for (constructor_elt : CONSTRUCTOR_ELTS (full_expr))
> > +  if (e.value == subob)
> > +   {
> > + *walk_subtrees = 0;
> 
> Why clear walk_subtrees?  Won't that mean we fail to replace any
> placeholders nested within an array element initializer?

Right.  I couldn't find a testcase where that would cause a problem
but I think I just wasn't inventive enough.

Originally, I was checking same_type_ignoring_top_level_qualifiers_p
but that's not going to work for code like

  struct N { N(M); };
  N arr[2] = { M{""}, M{""} };

or with operator M().  But I suppose I could just use can_convert
like below.  What do you think about that?

dg.exp passed, full regtest running.

-- >8 --
This

[PATCH] c++: ICE with temporary of class type in array DMI [PR109966]

2024-03-11 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?

-- >8 --
This ICE started with the fairly complicated r13-765.  We crash in
gimplify_var_or_parm_decl because a stray VAR_DECL leaked there.
The problem is ultimately that potential_prvalue_result_of wasn't
correctly handling arrays and replace_placeholders_for_class_temp_r
replaced a PLACEHOLDER_EXPR in a TARGET_EXPR which is used in the
context of copy elision.  If I have

  M m[2] = { M{""}, M{""} };

then we don't invoke the M(const M&) copy-ctor.  I think the fix is
to detect such a case in potential_prvalue_result_of.

PR c++/109966

gcc/cp/ChangeLog:

* typeck2.cc (potential_prvalue_result_of): Add walk_subtrees
parameter.  Handle initializing an array from a
brace-enclosed-initializer.
(replace_placeholders_for_class_temp_r): Pass walk_subtrees down to
potential_prvalue_result_of.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/nsdmi-aggr20.C: New test.
* g++.dg/cpp1y/nsdmi-aggr21.C: New test.
---
 gcc/cp/typeck2.cc | 27 ---
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C | 17 +++
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C | 59 +++
 3 files changed, 96 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 31198b2f9f5..8b99ce78e9a 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1406,46 +1406,59 @@ digest_init_flags (tree type, tree init, int flags, 
tsubst_flags_t complain)
  A a = (A{});// initializer
  A a = (1, A{}); // initializer
  A a = true ? A{} : A{};  // initializer
+ A arr[1] = { A{} };  // initializer
  auto x = A{}.x; // temporary materialization
  auto x = foo(A{});  // temporary materialization
 
FULL_EXPR is the whole expression, SUBOB is its TARGET_EXPR subobject.  */
 
 static bool
-potential_prvalue_result_of (tree subob, tree full_expr)
+potential_prvalue_result_of (tree subob, tree full_expr, int *walk_subtrees)
 {
+#define RECUR(t) potential_prvalue_result_of (subob, t, walk_subtrees)
   if (subob == full_expr)
 return true;
   else if (TREE_CODE (full_expr) == TARGET_EXPR)
 {
   tree init = TARGET_EXPR_INITIAL (full_expr);
   if (TREE_CODE (init) == COND_EXPR)
-   return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 1))
-   || potential_prvalue_result_of (subob, TREE_OPERAND (init, 2)));
+   return (RECUR (TREE_OPERAND (init, 1))
+   || RECUR (TREE_OPERAND (init, 2)));
   else if (TREE_CODE (init) == COMPOUND_EXPR)
-   return potential_prvalue_result_of (subob, TREE_OPERAND (init, 1));
+   return RECUR (TREE_OPERAND (init, 1));
   /* ??? I don't know if this can be hit.  */
   else if (TREE_CODE (init) == PAREN_EXPR)
{
  gcc_checking_assert (false);
- return potential_prvalue_result_of (subob, TREE_OPERAND (init, 0));
+ return RECUR (TREE_OPERAND (init, 0));
}
 }
+  /* The array case listed above.  */
+  else if (TREE_CODE (full_expr) == CONSTRUCTOR
+  && TREE_CODE (TREE_TYPE (full_expr)) == ARRAY_TYPE)
+for (constructor_elt : CONSTRUCTOR_ELTS (full_expr))
+  if (e.value == subob)
+   {
+ *walk_subtrees = 0;
+ return true;
+   }
+
   return false;
+#undef RECUR
 }
 
 /* Callback to replace PLACEHOLDER_EXPRs in a TARGET_EXPR (which isn't used
in the context of guaranteed copy elision).  */
 
 static tree
-replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
+replace_placeholders_for_class_temp_r (tree *tp, int *walk_subtrees, void 
*data)
 {
   tree t = *tp;
   tree full_expr = *static_cast(data);
 
   /* We're looking for a TARGET_EXPR nested in the whole expression.  */
   if (TREE_CODE (t) == TARGET_EXPR
-  && !potential_prvalue_result_of (t, full_expr))
+  && !potential_prvalue_result_of (t, full_expr, walk_subtrees))
 {
   tree init = TARGET_EXPR_INITIAL (t);
   while (TREE_CODE (init) == COMPOUND_EXPR)
diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C 
b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C
new file mode 100644
index 000..4796d861e83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr20.C
@@ -0,0 +1,17 @@
+// PR c++/109966
+// { dg-do compile { target c++14 } }
+
+#define SA(X) static_assert ((X),#X)
+
+struct A {
+  int a;
+  int b = a;
+};
+
+struct B {
+  int x = 0;
+  int y[1]{A{x}.b};
+};
+
+constexpr B b = { };
+SA(b.y[0] == 0);
diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C 
b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C
new file mode 100644
index 000..efec45bc1a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr21.C
@@ -0,0 +1,59 @@
+// PR c++/109966
+// { dg-do compile { target c++14 } }
+
+struct k {
+  k(const 

[PATCH] c++: explicit inst of template method not generated [PR110323]

2024-03-08 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Consider

  constexpr int VAL = 1;
  struct foo {
  template 
  void bar(typename std::conditional::type arg) { }
  };
  template void foo::bar<1>(int arg);

where we since r11-291 fail to emit the code for the explicit
instantiation.  That's because cp_walk_subtrees/TYPENAME_TYPE now
walks TYPE_CONTEXT ('conditional' here) as well, and in a template
finds the B==VAL template argument.  VAL is constexpr, which implies const,
which in the global scope implies static.  constrain_visibility_for_template
then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC.
Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't
emit any code.

I thought the fix would be some ODR-esque check to not consider
constexpr variables/fns that are used just for their value.  But
it turned out to be tricky.  For instance, we can't skip
determine_visibility in a template; we can't even skip it for value-dep
expressions.  For example, no-linkage-expr1.C has

  using P = struct {}*;
  template 
  void f(int(*)[((P)0, N)]) {}

where ((P)0, N) is value-dep, but N is not relevant here: we have to
ferret out the anonymous type.  When instantiating, it's already gone.

The best I could come up with is to disregard _DECL in min_vis_expr_r
in a template while still checking type_visibility, even in a template.

PR c++/110323

gcc/cp/ChangeLog:

* decl2.cc (min_vis_expr_r) : Do nothing in a template.

gcc/testsuite/ChangeLog:

* g++.dg/template/explicit-instantiation6.C: New test.
* g++.dg/template/explicit-instantiation7.C: New test.
---
 gcc/cp/decl2.cc   |  6 ++-
 .../g++.dg/template/explicit-instantiation6.C | 53 +++
 .../g++.dg/template/explicit-instantiation7.C | 22 
 3 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/template/explicit-instantiation6.C
 create mode 100644 gcc/testsuite/g++.dg/template/explicit-instantiation7.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 6c9fd415d40..3e035a7bf9f 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2718,7 +2718,11 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
   /* Fall through.  */
 case VAR_DECL:
 case FUNCTION_DECL:
-  if (! TREE_PUBLIC (t))
+  if (processing_template_decl)
+   /* In a template, we can't trust _DECLs, either.  It's possible
+  they won't be ODR-used, and we could wrongly think the linkage
+  is internal (PR110323).  */;
+  else if (! TREE_PUBLIC (t))
tpvis = VISIBILITY_ANON;
   else
tpvis = DECL_VISIBILITY (t);
diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation6.C 
b/gcc/testsuite/g++.dg/template/explicit-instantiation6.C
new file mode 100644
index 000..399c7d72756
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-instantiation6.C
@@ -0,0 +1,53 @@
+// PR c++/110323
+// { dg-do compile { target c++14 } }
+
+template
+struct conditional { using type = T; };
+
+template
+struct conditional { using type = F; };
+
+constexpr int VAL = 1;
+
+static constexpr int getval () { return 1; }
+
+template
+constexpr int TVAL = 1;
+
+static struct S {
+  constexpr operator bool() { return true; }
+} s;
+
+struct foo {
+template 
+void bar(typename conditional::type arg) { }
+
+template 
+void baz(typename conditional::type arg) { }
+
+template 
+void qux(typename conditional, int, float>::type arg) { }
+
+template 
+void lox(typename conditional::type arg) { }
+
+template 
+void sox(typename conditional::type arg) 
{ }
+
+template 
+void nim(typename conditional::type arg) { }
+};
+
+template void foo::bar<1>(int arg);
+template void foo::baz<1>(int arg);
+template void foo::qux<1>(int arg);
+template void foo::lox<1>(int arg);
+template void foo::sox<1>(int arg);
+template void foo::nim<1>(int arg);
+
+// { dg-final { scan-assembler 
"_ZN3foo3barILi1EEEvN11conditionalIXeqT_L_ZL3VALEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3bazILi1EEEvN11conditionalIXeqT_clL_ZL6getvalvEEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3quxILi1EEEvN11conditionalIXeqT_L_Z4TVALIiEEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3loxILi1EEEvN11conditionalIXeqT_L_ZL1sEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3soxILi1EEEvN11conditionalIXeqT_nxL_ZL3VALEEifE4typeE" } }
+// { dg-final { scan-assembler 
"_ZN3foo3nimILi1EEEvN11conditionalIXneT_szL_ZL3VALEEifE4typeE" } }
diff --git a/gcc/testsuite/g++.dg/template/explicit-instantiation7.C 
b/gcc/testsuite/g++.dg/template/explicit-instantiation7.C
new file mode 100644
index 000..9a870e808fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/explicit-instantiation7.C
@@ -0,0 +1,22 @@
+// PR c++/110323
+// { dg-do compile { target c++11 } }
+
+using P = struct { }*;
+using N = struct A { }*;
+
+template

[gcc r14-9364] c++: ICE with variable template and [[deprecated]] [PR110031]

2024-03-07 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:9f915684624413f96e1a5ffada398ccd1c533e38

commit r14-9364-g9f915684624413f96e1a5ffada398ccd1c533e38
Author: Marek Polacek 
Date:   Mon Mar 4 12:35:18 2024 -0500

c++: ICE with variable template and [[deprecated]] [PR110031]

lookup_and_finish_template_variable already has and uses the complain
parameter but it is not passing it down to mark_used so we got the
default tf_warning_or_error, which causes various problems when
lookup_and_finish_template_variable gets called with complain=tf_none.

PR c++/110031

gcc/cp/ChangeLog:

* pt.cc (lookup_and_finish_template_variable): Pass complain to
mark_used.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/inline-var11.C: New test.

Diff:
---
 gcc/cp/pt.cc  |  2 +-
 gcc/testsuite/g++.dg/cpp1z/inline-var11.C | 32 +++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d73f6d93485..040ced45187 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10533,7 +10533,7 @@ lookup_and_finish_template_variable (tree templ, tree 
targs,
   if (var == error_mark_node)
 return error_mark_node;
   var = finish_template_variable (var, complain);
-  mark_used (var);
+  mark_used (var, complain);
   return var;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/inline-var11.C 
b/gcc/testsuite/g++.dg/cpp1z/inline-var11.C
new file mode 100644
index 000..d92911ed3a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inline-var11.C
@@ -0,0 +1,32 @@
+// PR c++/110031
+// { dg-do compile { target c++17 } }
+
+template 
+[[deprecated]]
+inline constexpr bool t = true ;
+
+template 
+struct enableif;
+
+template<>
+struct enableif
+{
+using y = int;
+};
+template 
+using enableif_t = typename enableif::y;
+
+template > = 0>   // { dg-warning "deprecated" }
+struct A {  A(T &&)  {  }};
+
+template 
+struct A {
+  A(T &&) = delete;
+  A() = delete;
+};
+
+int main(void)
+{
+  A a(5.3); // { dg-error "use of deleted function" }
+  return 0;
+}


[gcc r14-9339] c++: ICE with noexcept and local specialization [PR114114]

2024-03-06 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:dc6c3bfb59baab28b998e18396c06087b6d9b0ed

commit r14-9339-gdc6c3bfb59baab28b998e18396c06087b6d9b0ed
Author: Marek Polacek 
Date:   Tue Mar 5 13:33:10 2024 -0500

c++: ICE with noexcept and local specialization [PR114114]

Here we ICE because we call register_local_specialization while
local_specializations is null, so

  local_specializations->put ();

crashes on null this.  It's null since maybe_instantiate_noexcept calls
push_to_top_level which creates a new scope.  Normally, I would have
guessed that we need a new local_specialization_stack.  But here we're
dealing with an operand of a noexcept, which is an unevaluated operand,
and those aren't registered in the hash map.  maybe_instantiate_noexcept
wasn't signalling that it's substituting an unevaluated operand though.

PR c++/114114

gcc/cp/ChangeLog:

* pt.cc (maybe_instantiate_noexcept): Save/restore
cp_unevaluated_operand, c_inhibit_evaluation_warnings, and
cp_noexcept_operand around the tsubst_expr call.

gcc/testsuite/ChangeLog:

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

Diff:
---
 gcc/cp/pt.cc|  6 ++
 gcc/testsuite/g++.dg/cpp0x/noexcept84.C | 32 
 2 files changed, 38 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a6e6c804130..d73f6d93485 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26879,10 +26879,16 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  if (orig_fn)
++processing_template_decl;
 
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ ++cp_noexcept_operand;
  /* Do deferred instantiation of the noexcept-specifier.  */
  noex = tsubst_expr (DEFERRED_NOEXCEPT_PATTERN (noex),
  DEFERRED_NOEXCEPT_ARGS (noex),
  tf_warning_or_error, fn);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ --cp_noexcept_operand;
 
  /* Build up the noexcept-specification.  */
  spec = build_noexcept_spec (noex, tf_warning_or_error);
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept84.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept84.C
new file mode 100644
index 000..06f33264f77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept84.C
@@ -0,0 +1,32 @@
+// PR c++/114114
+// { dg-do compile { target c++11 } }
+
+template
+constexpr void
+test ()
+{
+  constexpr bool is_yes = B;
+  struct S {
+constexpr S() noexcept(is_yes) { }
+  };
+  S s;
+}
+
+constexpr bool foo() { return true; }
+
+template
+constexpr void
+test2 ()
+{
+  constexpr T (*pfn)() = 
+  struct S {
+constexpr S() noexcept(pfn()) { }
+  };
+  S s;
+}
+
+int main()
+{
+  test();
+  test2();
+}


[PATCH] c++: ICE with noexcept and local specialization [PR114114]

2024-03-05 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here we ICE because we call register_local_specialization while
local_specializations is null, so

  local_specializations->put ();

crashes on null this.  It's null since maybe_instantiate_noexcept calls
push_to_top_level which creates a new scope.  Normally, I would have
guessed that we need a new local_specialization_stack.  But here we're
dealing with an operand of a noexcept, which is an unevaluated operand,
and those aren't registered in the hash map.  maybe_instantiate_noexcept
wasn't signalling that it's substituting an unevaluated operand though.

PR c++/114114

gcc/cp/ChangeLog:

* pt.cc (maybe_instantiate_noexcept): Save/restore
cp_unevaluated_operand, c_inhibit_evaluation_warnings, and
cp_noexcept_operand around the tsubst_expr call.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept84.C: New test.
---
 gcc/cp/pt.cc|  6 +
 gcc/testsuite/g++.dg/cpp0x/noexcept84.C | 32 +
 2 files changed, 38 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept84.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c4bc54a8fdb..11f7d33c766 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26869,10 +26869,16 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
  if (orig_fn)
++processing_template_decl;
 
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ ++cp_noexcept_operand;
  /* Do deferred instantiation of the noexcept-specifier.  */
  noex = tsubst_expr (DEFERRED_NOEXCEPT_PATTERN (noex),
  DEFERRED_NOEXCEPT_ARGS (noex),
  tf_warning_or_error, fn);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ --cp_noexcept_operand;
 
  /* Build up the noexcept-specification.  */
  spec = build_noexcept_spec (noex, tf_warning_or_error);
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept84.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept84.C
new file mode 100644
index 000..06f33264f77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept84.C
@@ -0,0 +1,32 @@
+// PR c++/114114
+// { dg-do compile { target c++11 } }
+
+template
+constexpr void
+test ()
+{
+  constexpr bool is_yes = B;
+  struct S {
+constexpr S() noexcept(is_yes) { }
+  };
+  S s;
+}
+
+constexpr bool foo() { return true; }
+
+template
+constexpr void
+test2 ()
+{
+  constexpr T (*pfn)() = 
+  struct S {
+constexpr S() noexcept(pfn()) { }
+  };
+  S s;
+}
+
+int main()
+{
+  test();
+  test2();
+}

base-commit: 8776468d9e57ace5f832c1368243a6dbce9984d5
-- 
2.44.0



[PATCH] c++: ICE with variable template and [[deprecated]] [PR110031]

2024-03-04 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?

-- >8 --
lookup_and_finish_template_variable already has and uses the complain
parameter but it is not passing it down to mark_used so we got the
default tf_warning_or_error, which causes various problems when
lookup_and_finish_template_variable gets called with complain=tf_none.

PR c++/110031

gcc/cp/ChangeLog:

* pt.cc (lookup_and_finish_template_variable): Pass complain to
mark_used.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/inline-var11.C: New test.
---
 gcc/cp/pt.cc  |  2 +-
 gcc/testsuite/g++.dg/cpp1z/inline-var11.C | 32 +++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/inline-var11.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c4bc54a8fdb..48d2b3cbac6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10533,7 +10533,7 @@ lookup_and_finish_template_variable (tree templ, tree 
targs,
   if (var == error_mark_node)
 return error_mark_node;
   var = finish_template_variable (var, complain);
-  mark_used (var);
+  mark_used (var, complain);
   return var;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/inline-var11.C 
b/gcc/testsuite/g++.dg/cpp1z/inline-var11.C
new file mode 100644
index 000..d92911ed3a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inline-var11.C
@@ -0,0 +1,32 @@
+// PR c++/110031
+// { dg-do compile { target c++17 } }
+
+template 
+[[deprecated]]
+inline constexpr bool t = true ;
+
+template 
+struct enableif;
+
+template<>
+struct enableif
+{
+using y = int;
+};
+template 
+using enableif_t = typename enableif::y;
+
+template > = 0>   // { dg-warning "deprecated" }
+struct A {  A(T &&)  {  }};
+
+template 
+struct A {
+  A(T &&) = delete;
+  A() = delete;
+};
+
+int main(void)
+{
+  A a(5.3); // { dg-error "use of deleted function" }
+  return 0;
+}

base-commit: a89c5df317d1de74871e2a05c36aed9cbbb21f42
-- 
2.44.0



Re: [PATCH] c++: lambda capturing structured bindings [PR85889]

2024-03-04 Thread Marek Polacek
On Fri, Mar 01, 2024 at 07:58:24PM -0500, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for 15?  (Or even trunk?)
> 
> -- >8 --
> <https://wg21.link/p1381r1> clarifies that it's OK to capture structured
> bindings.
> 
> [expr.prim.lambda.capture]/4 says "The identifier in a simple-capture shall
> denote a local entity" and [basic.pre]/3: "An entity is a [...] structured
> binding".
> 
> It doesn't appear that this was made a DR, so, strictly speaking, we
> should have a -Wc++20-extensions warning, like clang++.
> 
>   PR c++/85889
> 
> gcc/cp/ChangeLog:
> 
>   * lambda.cc (add_capture): Add a pedwarn for capturing structured
>   bindings.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/cpp2a/decomp3.C: Use -Wno-c++20-extensions.
>   * g++.dg/cpp1z/decomp60.C: New test.
> ---
>  gcc/cp/lambda.cc  |  9 +
>  gcc/testsuite/g++.dg/cpp1z/decomp60.C | 12 
>  gcc/testsuite/g++.dg/cpp2a/decomp3.C  |  2 +-
>  3 files changed, 22 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp60.C
> 
> diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
> index 4b1f9391fee..470f9d2c4f1 100644
> --- a/gcc/cp/lambda.cc
> +++ b/gcc/cp/lambda.cc
> @@ -607,6 +607,15 @@ add_capture (tree lambda, tree id, tree orig_init, bool 
> by_reference_p,
>TCTX_CAPTURE_BY_COPY, type))
>   return error_mark_node;
>   }
> +
> +  if (cxx_dialect < cxx20)
> + {
> +   tree stripped_init = tree_strip_any_location_wrapper (initializer);

I was missing an auto_diagnostic_group here.  Fixed.

> +   if (DECL_DECOMPOSITION_P (stripped_init)
> +   && pedwarn (input_location, OPT_Wc__20_extensions,
> +   "captured structured bindings are a C++20 extension"))
> + inform (DECL_SOURCE_LOCATION (stripped_init), "declared here");



Re: [PATCH v5] c++: implement [[gnu::non_owning]] [PR110358]

2024-03-04 Thread Marek Polacek
On Mon, Mar 04, 2024 at 11:00:18AM +, Jonathan Wakely wrote:
> On 01/03/24 15:38 -0500, Jason Merrill wrote:
> > On 3/1/24 14:24, Marek Polacek wrote:
> > > +@smallexample
> > > +template 
> > > +[[gnu::no_dangling(std::is_reference_v)]] int foo (T& t) @{
> > 
> > I think this function should return a reference.
> 
> The condition in the attribute can only ever be true if you call this
> function with an explicit template argument list: foo(i). Is
> that intentional?

Not intentional.  I just wanted to make it clear that the user
can use something like std::is_reference as the attribute argument,
but I didn't think about it very long.
 
> And if T is non-const it can't be called with a temporary and so
> dangling seems less of a problem for this function anyway, right?

Right.
 
> Would it make more sense as something like this?
> 
> template 
> [[gnu::no_dangling(std::is_lvalue_reference_v)]]
> decltype(auto) foo(T&& t) {
>   ...
> }
> 
> Or is this getting too complex/subtle for a simple example?

I like your example; it's only slightly more complex than the
original one and most likely more realistic.  I'm pushing the
following patch.  Thanks!

[pushed] doc: update [[gnu::no_dangling]]

...to offer a more realistic example.

gcc/ChangeLog:

* doc/extend.texi: Update [[gnu::no_dangling]].
---
 gcc/doc/extend.texi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f679c81acf2..df0982fdfda 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -29370,7 +29370,8 @@ Or:
 
 @smallexample
 template 
-[[gnu::no_dangling(std::is_reference_v)]] int& foo (T& t) @{
+[[gnu::no_dangling(std::is_lvalue_reference_v)]]
+decltype(auto) foo(T&& t) @{
   @dots{}
 @};
 @end smallexample

base-commit: 77eb86be8841989651b3150a020dd1a95910cc00
-- 
2.44.0



[PATCH] c++: DECL_DECOMPOSITION_P cleanup

2024-03-01 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for 15?

-- >8 --
DECL_DECOMPOSITION_P already checks VAR_P but we repeat the check
in a lot of places.

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Don't check VAR_P before
DECL_DECOMPOSITION_P.
* init.cc (build_aggr_init): Likewise.
* parser.cc (cp_parser_range_for): Likewise.
(do_range_for_auto_deduction): Likewise.
(cp_convert_range_for): Likewise.
(cp_convert_omp_range_for): Likewise.
(cp_finish_omp_range_for): Likewise.
* pt.cc (extract_locals_r): Likewise.
(tsubst_omp_for_iterator): Likewise.
(tsubst_decomp_names): Likewise.
(tsubst_stmt): Likewise.
* typeck.cc (maybe_warn_about_returning_address_of_local): Likewise.
---
 gcc/cp/decl.cc   |  3 +--
 gcc/cp/init.cc   |  2 +-
 gcc/cp/parser.cc | 11 ---
 gcc/cp/pt.cc | 11 +++
 gcc/cp/typeck.cc |  3 +--
 5 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index dbc3df24e77..13df91ce17c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1928,8 +1928,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, 
bool was_hidden)
  inform (olddecl_loc, "previous declaration %q#D", olddecl);
  return error_mark_node;
}
-  else if ((VAR_P (olddecl) && DECL_DECOMPOSITION_P (olddecl))
-  || (VAR_P (newdecl) && DECL_DECOMPOSITION_P (newdecl)))
+  else if (DECL_DECOMPOSITION_P (olddecl) || DECL_DECOMPOSITION_P 
(newdecl))
/* A structured binding must be unique in its declarative region.  */;
   else if (DECL_IMPLICIT_TYPEDEF_P (olddecl)
   || DECL_IMPLICIT_TYPEDEF_P (newdecl))
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index d2586fad86b..bcfb4d350bc 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -1979,7 +1979,7 @@ build_aggr_init (tree exp, tree init, int flags, 
tsubst_flags_t complain)
   tree itype = init ? TREE_TYPE (init) : NULL_TREE;
   int from_array = 0;
 
-  if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp))
+  if (DECL_DECOMPOSITION_P (exp))
{
  from_array = 1;
  init = mark_rvalue_use (init);
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a310b9e8c07..8a6ced17c5c 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -14117,7 +14117,6 @@ cp_parser_range_for (cp_parser *parser, tree scope, 
tree init, tree range_decl,
  /* For decomposition declaration get all of the corresponding
 declarations out of the way.  */
  if (TREE_CODE (v) == ARRAY_REF
- && VAR_P (TREE_OPERAND (v, 0))
  && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
{
  tree d = range_decl;
@@ -14238,7 +14237,7 @@ do_range_for_auto_deduction (tree decl, tree 
range_expr, cp_decomp *decomp)
iter_decl, auto_node,
tf_warning_or_error,
adc_variable_type);
- if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+ if (DECL_DECOMPOSITION_P (decl))
cp_finish_decomp (decl, decomp);
}
 }
@@ -14437,7 +14436,7 @@ cp_convert_range_for (tree statement, tree range_decl, 
tree range_expr,
   cp_finish_decl (range_decl, deref_begin,
  /*is_constant_init*/false, NULL_TREE,
  LOOKUP_ONLYCONVERTING, decomp);
-  if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
+  if (DECL_DECOMPOSITION_P (range_decl))
 cp_finish_decomp (range_decl, decomp);
 
   warn_for_range_copy (range_decl, deref_begin);
@@ -44288,7 +44287,6 @@ cp_convert_omp_range_for (tree _pre_body, tree ,
{
  tree v = DECL_VALUE_EXPR (decl);
  if (TREE_CODE (v) == ARRAY_REF
- && VAR_P (TREE_OPERAND (v, 0))
  && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
{
  d = TREE_OPERAND (v, 0);
@@ -44393,7 +44391,6 @@ cp_convert_omp_range_for (tree _pre_body, tree ,
 {
   tree v = DECL_VALUE_EXPR (orig_decl);
   if (TREE_CODE (v) == ARRAY_REF
- && VAR_P (TREE_OPERAND (v, 0))
  && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
{
  tree d = orig_decl;
@@ -44471,7 +44468,7 @@ cp_finish_omp_range_for (tree orig, tree begin)
   tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2);
   cp_decomp decomp_d, *decomp = NULL;
 
-  if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+  if (DECL_DECOMPOSITION_P (decl))
 {
   decomp = _d;
   decomp_d.decl = TREE_VEC_ELT (TREE_CHAIN (orig), 3);
@@ -44497,7 +44494,7 @@ cp_finish_omp_range_for (tree orig, tree begin)
NULL_TREE, tf_warning_or_error),
  /*is_constant_init*/false, NULL_TREE,
  LOOKUP_ONLYCONVERTING, decomp);
-  if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+  if 

[PATCH] c++: direct-init of an array of class type [PR59465]

2024-03-01 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  I don't
claim that this has to go to 14 though.

-- >8 --
...from another array in a mem-initializer should not be accepted.

We already reject

  struct string {} a[1];
  string x[1](a);

but

  struct pair {
string s[1];
pair() : s(a) {}
  };

is wrongly accepted.

It started to be accepted with r0-110915-ga034826198b771:

which was supposed to be a cleanup, not a deliberate change to start
accepting the code.  The build_vec_init_expr code was added in r165976:
.

It appears that we do the magic copy array when we have a defaulted
constructor and we generate code for its mem-initializer which
initializes an array.  I also see that we go that path for compound
literals.  So when initializing an array member, we can limit building
up a VEC_INIT_EXPR to those special cases.

PR c++/59465

gcc/cp/ChangeLog:

* init.cc (can_init_array_with_p): New.
(perform_member_init): Check it.

gcc/testsuite/ChangeLog:

* g++.dg/init/array62.C: New test.
* g++.dg/init/array63.C: New test.
* g++.dg/init/array64.C: New test.
---
 gcc/cp/init.cc  | 27 ++-
 gcc/testsuite/g++.dg/init/array62.C | 19 +++
 gcc/testsuite/g++.dg/init/array63.C | 13 +
 gcc/testsuite/g++.dg/init/array64.C | 22 ++
 4 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/init/array62.C
 create mode 100644 gcc/testsuite/g++.dg/init/array63.C
 create mode 100644 gcc/testsuite/g++.dg/init/array64.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index d2586fad86b..fb8c0e521fb 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -934,6 +934,31 @@ find_uninit_fields (tree *t, hash_set 
*uninitialized, tree member)
 }
 }
 
+/* Return true if it's OK to initialize an array from INIT.  Mere mortals
+   can't copy arrays, but the compiler can do so with a VEC_INIT_EXPR in
+   certain cases.  */
+
+static bool
+can_init_array_with_p (tree init)
+{
+  if (!init)
+return true;
+
+  /* We're called from synthesize_method, and we're processing the
+ mem-initializers of a constructor.  */
+  if (DECL_DEFAULTED_FN (current_function_decl))
+return true;
+  /* As an extension, we allow copying from a compound literal.  */
+  else if (TREE_CODE (init) == TARGET_EXPR)
+{
+  init = TARGET_EXPR_INITIAL (init);
+  if (TREE_CODE (init) == CONSTRUCTOR)
+   return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
+}
+
+  return false;
+}
+
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
arguments.  If TREE_LIST is void_type_node, an empty initializer
list was given; if NULL_TREE no initializer was given.  UNINITIALIZED
@@ -1085,7 +1110,7 @@ perform_member_init (tree member, tree init, 
hash_set )
   else if (type_build_ctor_call (type)
   || (init && CLASS_TYPE_P (strip_array_types (type
 {
-  if (TREE_CODE (type) == ARRAY_TYPE)
+  if (TREE_CODE (type) == ARRAY_TYPE && can_init_array_with_p (init))
{
  if (init == NULL_TREE
  || same_type_ignoring_top_level_qualifiers_p (type,
diff --git a/gcc/testsuite/g++.dg/init/array62.C 
b/gcc/testsuite/g++.dg/init/array62.C
new file mode 100644
index 000..6d3935d7a66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array62.C
@@ -0,0 +1,19 @@
+// PR c++/59465
+// { dg-do compile }
+
+struct string {} a[1];
+struct pair {
+  string s[1];
+  pair() : s(a) {} // { dg-error "array must be initialized" }
+};
+
+struct S {
+  char s[10];
+  S() : s("aaa") {}
+};
+
+void
+g ()
+{
+  string x[1](a); // { dg-error "array must be initialized" }
+}
diff --git a/gcc/testsuite/g++.dg/init/array63.C 
b/gcc/testsuite/g++.dg/init/array63.C
new file mode 100644
index 000..96bc9a64b26
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array63.C
@@ -0,0 +1,13 @@
+// PR c++/59465
+// { dg-do compile }
+
+struct I {
+const bool b;
+};
+struct O {
+I a[2];
+static I const data[2];
+O() : a(data){}  // { dg-error "array must be initialized" }
+};
+
+I const O::data[2] = {true, false};
diff --git a/gcc/testsuite/g++.dg/init/array64.C 
b/gcc/testsuite/g++.dg/init/array64.C
new file mode 100644
index 000..bbdd70c6df8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array64.C
@@ -0,0 +1,22 @@
+// PR c++/59465
+// { dg-do compile }
+
+static const int my_size = 10;
+
+class UserType
+{
+public:
+  UserType(): f_(){}
+private:
+int f_;
+};
+
+typedef UserType Array[my_size];
+
+class Foo
+{
+public:
+  Foo(Array& m) : m_(m) {};  // { dg-error "array must be initialized" }
+private:
+  Array m_;
+};

base-commit: 574fd1f17f100c7c355ad26bc525ab5a3386bb2d
-- 
2.44.0



[PATCH] c++: lambda capturing structured bindings [PR85889]

2024-03-01 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for 15?  (Or even trunk?)

-- >8 --
 clarifies that it's OK to capture structured
bindings.

[expr.prim.lambda.capture]/4 says "The identifier in a simple-capture shall
denote a local entity" and [basic.pre]/3: "An entity is a [...] structured
binding".

It doesn't appear that this was made a DR, so, strictly speaking, we
should have a -Wc++20-extensions warning, like clang++.

PR c++/85889

gcc/cp/ChangeLog:

* lambda.cc (add_capture): Add a pedwarn for capturing structured
bindings.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/decomp3.C: Use -Wno-c++20-extensions.
* g++.dg/cpp1z/decomp60.C: New test.
---
 gcc/cp/lambda.cc  |  9 +
 gcc/testsuite/g++.dg/cpp1z/decomp60.C | 12 
 gcc/testsuite/g++.dg/cpp2a/decomp3.C  |  2 +-
 3 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp60.C

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 4b1f9391fee..470f9d2c4f1 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -607,6 +607,15 @@ add_capture (tree lambda, tree id, tree orig_init, bool 
by_reference_p,
 TCTX_CAPTURE_BY_COPY, type))
return error_mark_node;
}
+
+  if (cxx_dialect < cxx20)
+   {
+ tree stripped_init = tree_strip_any_location_wrapper (initializer);
+ if (DECL_DECOMPOSITION_P (stripped_init)
+ && pedwarn (input_location, OPT_Wc__20_extensions,
+ "captured structured bindings are a C++20 extension"))
+   inform (DECL_SOURCE_LOCATION (stripped_init), "declared here");
+   }
 }
 
   /* Add __ to the beginning of the field name so that user code
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp60.C 
b/gcc/testsuite/g++.dg/cpp1z/decomp60.C
new file mode 100644
index 000..b6117f3af58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp60.C
@@ -0,0 +1,12 @@
+// PR c++/85889
+// { dg-do compile { target c++17 } }
+// { dg-options "" }
+
+struct X { int i, j; };
+void f() {
+  X x{};
+  auto [i, j] = x;
+  []() { }; // { dg-warning "captured structured bindings" "" { target 
c++17_only } }
+  [i]() { }; // { dg-warning "captured structured bindings" "" { target 
c++17_only } }
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp2a/decomp3.C 
b/gcc/testsuite/g++.dg/cpp2a/decomp3.C
index 5e77973d41f..25ab8319975 100644
--- a/gcc/testsuite/g++.dg/cpp2a/decomp3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/decomp3.C
@@ -1,6 +1,6 @@
 // P1381R1
 // { dg-do compile { target c++11 } }
-// { dg-options "" }
+// { dg-options "-Wno-c++20-extensions" }
 
 struct Foo { int a : 1; int b; };
 

base-commit: 574fd1f17f100c7c355ad26bc525ab5a3386bb2d
-- 
2.44.0



[PATCH v5] c++: implement [[gnu::non_owning]] [PR110358]

2024-03-01 Thread Marek Polacek
On Fri, Mar 01, 2024 at 01:19:40PM -0500, Jason Merrill wrote:
> On 3/1/24 12:39, Marek Polacek wrote:
> >   @option{-Wdangling-reference} also warns about code like
> >   @smallexample
> > @@ -3932,6 +3935,10 @@ struct Span @{
> >   as @code{std::span}-like; that is, the class is a non-union class
> >   that has a pointer data member and a trivial destructor.
> > +The warning can be disabled by using the @code{gnu::no_dangling} attribute
> > +on a function (@pxref{Common Function Attributes}), or a class type
> > +(@pxref{C++ Attributes}).
> 
> It seems surprising that one is in a generic attributes section and the
> other in the C++-specific section.  Maybe both uses could be covered in the
> C++ attributes section?

Arg yes, definitely.  Done here.
 
> >   This warning is enabled by @option{-Wall}.
> >   @opindex Wdelete-non-virtual-dtor
> > diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling1.C 
> > b/gcc/testsuite/g++.dg/ext/attr-no-dangling1.C
> > new file mode 100644
> > index 000..02eabbc5003
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling1.C
> > @@ -0,0 +1,38 @@
> > +// { dg-do compile { target c++11 } }
> > +// { dg-options "-Wdangling-reference" }
> > +
> > +int g = 42;
> > +
> > +struct [[gnu::no_dangling]] A {
> > +  int *i;
> > +  int () { return *i; }
> > +};
> > +
> > +struct A2 {
> > +  int *i;
> > +  [[gnu::no_dangling]] int () { return *i; }
> > +  [[gnu::no_dangling]] static int  (const int &) { return * }
> > +};
> > +
> > +union [[gnu::no_dangling]] U { };
> > +
> > +A a() { return A{}; }
> > +A2 a2() { return A2{}; }
> > +
> > +class X { };
> > +const X x1;
> > +const X x2;
> > +
> > +[[gnu::no_dangling]] const X& get(const int& i)
> > +{
> > +   return i == 0 ? x1 : x2;
> > +}
> > +
> > +void
> > +test ()
> > +{
> > +  [[maybe_unused]] const X& x = get (10);  // { dg-bogus "dangling" }
> > +  [[maybe_unused]] const int  = a().foo();   // { dg-bogus 
> > "dangling" }
> > +  [[maybe_unused]] const int  = a2().foo();  // { dg-bogus 
> > "dangling" }
> > +  [[maybe_unused]] const int  = a2().bar(10);// { dg-bogus 
> > "dangling" }
> > +}
> 
> Do you want to add destructors to A/A2 like you did in other tests?

Added.  I think this test predates the recent heuristic.

Ok for trunk?

-- >8 --
Since -Wdangling-reference has false positives that can't be
prevented, we should offer an easy way to suppress the warning.
Currently, that is only possible by using a #pragma, either around the
enclosing class or around the call site.  But #pragma GCC diagnostic tend
to be onerous.  A better solution would be to have an attribute.

To that end, this patch adds a new attribute, [[gnu::no_dangling]].
This attribute takes an optional bool argument to support cases like:

  template 
  struct [[gnu::no_dangling(std::is_reference_v)]] S {
 // ...
  };

PR c++/110358
PR c++/109642

gcc/cp/ChangeLog:

* call.cc (no_dangling_p): New.
(reference_like_class_p): Use it.
(do_warn_dangling_reference): Use it.  Don't warn when the function
or its enclosing class has attribute gnu::no_dangling.
* tree.cc (cxx_gnu_attributes): Add gnu::no_dangling.
(handle_no_dangling_attribute): New.

gcc/ChangeLog:

* doc/extend.texi: Document gnu::no_dangling.
* doc/invoke.texi: Mention that gnu::no_dangling disables
-Wdangling-reference.

gcc/testsuite/ChangeLog:

* g++.dg/ext/attr-no-dangling1.C: New test.
* g++.dg/ext/attr-no-dangling2.C: New test.
* g++.dg/ext/attr-no-dangling3.C: New test.
* g++.dg/ext/attr-no-dangling4.C: New test.
* g++.dg/ext/attr-no-dangling5.C: New test.
* g++.dg/ext/attr-no-dangling6.C: New test.
* g++.dg/ext/attr-no-dangling7.C: New test.
* g++.dg/ext/attr-no-dangling8.C: New test.
* g++.dg/ext/attr-no-dangling9.C: New test.
---
 gcc/cp/call.cc   | 38 ++--
 gcc/cp/tree.cc   | 26 
 gcc/doc/extend.texi  | 47 ++
 gcc/doc/invoke.texi  |  6 ++
 gcc/testsuite/g++.dg/ext/attr-no-dangling1.C | 40 
 gcc/testsuite/g++.dg/ext/attr-no-dangling2.C | 29 +
 gcc/testsuite/g++.dg/ext/attr-no-dangling3.C | 24 
 gcc/testsuite/g++.dg/ext/attr-no-dangling4.C | 14 +
 gcc/testsuite/g++.dg/ext/attr-no-dangling5.C | 31 ++
 gcc/testsuite/g++.dg/ext/attr-no-dangling6.C | 65 
 gcc/testsuite/g++.dg/ext/

[PATCH v4] c++: implement [[gnu::non_owning]] [PR110358]

2024-03-01 Thread Marek Polacek
On Thu, Feb 29, 2024 at 07:30:02PM -0500, Jason Merrill wrote:
> On 2/29/24 19:12, Marek Polacek wrote:
> > On Wed, Feb 28, 2024 at 06:03:54PM -0500, Jason Merrill wrote:
> > 
> > > Hmm, if we're also going to allow the attribute to be applied to a 
> > > function,
> > > the name doesn't make so much sense.  For a class, it says that the class
> > > refers to its initializer; for a function, it says that the function 
> > > return
> > > value *doesn't* refer to its argument.
> > 
> > Yeah, that's a fair point; I guess "non_owning" would be too perplexing.
> > 
> > > If we want something that can apply to both classes and functions, we're
> > > probably back to an attribute that just suppresses the warning, with a
> > > different name.
> > > 
> > > Or I guess we could have two attributes, but that seems like a lot.
> > > 
> > > WDYT?
> > 
> > I think we don't want two separate attributes, and we do want that one
> > attribute to apply to both fns and classes.  We could implement something
> > like
> > 
> >[[gnu::no_warning("Wdangling-reference")]]
> >[[gnu::no_warning("Wdangling-reference", bool)]]
> > 
> > but first, that's a lot of typing, second, it would be confusing because
> > it wouldn't work for any other warning.  We already have [[unused]] and
> > [[maybe_unused]] whose effect is to suppress a warning.  It think our
> > best bet is to do the most straightforward thing: [[gnu::no_dangling]],
> > which this patch implements.  I didn't call it no_dangling_reference in
> > the hope that it can, some day, be also used for some -Wdangling-pointer
> > purposes.
> > 
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Since -Wdangling-reference has false positives that can't be
> > prevented, we should offer an easy way to suppress the warning.
> > Currently, that is only possible by using a #pragma, either around the
> > enclosing class or around the call site.  But #pragma GCC diagnostic tend
> > to be onerous.  A better solution would be to have an attribute.
> > 
> > To that end, this patch adds a new attribute, [[gnu::no_dangling]].
> > This attribute takes an optional bool argument to support cases like:
> > 
> >template 
> >struct [[gnu::no_dangling(std::is_reference_v)]] S {
> >   // ...
> >};
> > 
> > PR c++/110358
> > PR c++/109642
> > 
> > gcc/cp/ChangeLog:
> > 
> > * call.cc (no_dangling_p): New.
> > (reference_like_class_p): Use it.
> > (do_warn_dangling_reference): Use it.  Don't warn when the function
> > or its enclosing class has attribute gnu::no_dangling.
> > * tree.cc (cxx_gnu_attributes): Add gnu::no_dangling.
> > (handle_no_dangling_attribute): New.
> > 
> > gcc/ChangeLog:
> > 
> > * doc/extend.texi: Document gnu::no_dangling.
> > * doc/invoke.texi: Mention that gnu::no_dangling disables
> > -Wdangling-reference.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/ext/attr-no-dangling1.C: New test.
> > * g++.dg/ext/attr-no-dangling2.C: New test.
> > * g++.dg/ext/attr-no-dangling3.C: New test.
> > * g++.dg/ext/attr-no-dangling4.C: New test.
> > * g++.dg/ext/attr-no-dangling5.C: New test.
> > * g++.dg/ext/attr-no-dangling6.C: New test.
> > * g++.dg/ext/attr-no-dangling7.C: New test.
> > * g++.dg/ext/attr-no-dangling8.C: New test.
> > * g++.dg/ext/attr-no-dangling9.C: New test.
> > ---
> >   gcc/cp/call.cc   | 38 ++--
> >   gcc/cp/tree.cc   | 26 
> >   gcc/doc/extend.texi  | 21 +++
> >   gcc/doc/invoke.texi  | 21 +++
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling1.C | 38 
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling2.C | 29 +
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling3.C | 24 
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling4.C | 14 +
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling5.C | 31 ++
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling6.C | 65 
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling7.C | 31 ++
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling8.C | 30 +
> >   gcc/testsuite/g++.dg/ext/attr-no-dangling9.C | 25 
> >   13 files changed, 387 insertions(+), 6 deletions(-)
> &g

[PATCH v3] c++: implement [[gnu::non_owning]] [PR110358]

2024-02-29 Thread Marek Polacek
On Wed, Feb 28, 2024 at 06:03:54PM -0500, Jason Merrill wrote:
> On 2/21/24 19:35, Marek Polacek wrote:
> > On Fri, Jan 26, 2024 at 04:04:35PM -0500, Jason Merrill wrote:
> > > On 1/25/24 20:37, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > Since -Wdangling-reference has false positives that can't be
> > > > prevented, we should offer an easy way to suppress the warning.
> > > > Currently, that is only possible by using a #pragma, either around the
> > > > enclosing class or around the call site.  But #pragma GCC diagnostic 
> > > > tend
> > > > to be onerous.  A better solution would be to have an attribute.  Such
> > > > an attribute should not be tied to this particular warning though.  [*]
> > > > 
> > > > The warning bogusly triggers for classes that are like std::span,
> > > > std::reference_wrapper, and std::ranges::ref_view.  The common property
> > > > seems to be that these classes are only wrappers around some data.  So
> > > > I chose the name non_owning, but I'm not attached to it.  I hope that
> > > > in the future the attribute can be used for something other than this
> > > > diagnostic.
> > > 
> > > You decided not to pursue Barry's request for a bool argument to the
> > > attribute?
> > 
> > At first I thought it'd be an unnecessary complication but it was actually
> > pretty easy.  Better to accept the optional argument from the get-go
> > otherwise people would have to add > GCC 14 checks.
> > > Might it be more useful for the attribute to make reference_like_class_p
> > > return true, so that we still warn about a temporary of another type 
> > > passing
> > > through it?
> > 
> > Good point.  Fixed.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Since -Wdangling-reference has false positives that can't be
> > prevented, we should offer an easy way to suppress the warning.
> > Currently, that is only possible by using a #pragma, either around the
> > enclosing class or around the call site.  But #pragma GCC diagnostic tend
> > to be onerous.  A better solution would be to have an attribute.  Such
> > an attribute should not be tied to this particular warning though.
> > 
> > The warning bogusly triggers for classes that are like std::span,
> > std::reference_wrapper, and std::ranges::ref_view.  The common property
> > seems to be that these classes are only wrappers around some data.  So
> > I chose the name non_owning, but I'm not attached to it.  I hope that
> > in the future the attribute can be used for something other than this
> > diagnostic.
> > 
> > This attribute takes an optional bool argument to support cases like:
> > 
> >template 
> >struct [[gnu::non_owning(std::is_reference_v)]] S {
> >   // ...
> >};
> > 
> > PR c++/110358
> > PR c++/109642
> > 
> > gcc/cp/ChangeLog:
> > 
> > * call.cc (non_owning_p): New.
> > (reference_like_class_p): Use it.
> > (do_warn_dangling_reference): Use it.  Don't warn when the function
> > or its enclosing class has attribute gnu::non_owning.
> > * tree.cc (cxx_gnu_attributes): Add gnu::non_owning.
> > (handle_non_owning_attribute): New.
> > 
> > gcc/ChangeLog:
> > 
> > * doc/extend.texi: Document gnu::non_owning.
> > * doc/invoke.texi: Mention that gnu::non_owning disables
> > -Wdangling-reference.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/ext/attr-non-owning1.C: New test.
> > * g++.dg/ext/attr-non-owning2.C: New test.
> > * g++.dg/ext/attr-non-owning3.C: New test.
> > * g++.dg/ext/attr-non-owning4.C: New test.
> > * g++.dg/ext/attr-non-owning5.C: New test.
> > * g++.dg/ext/attr-non-owning6.C: New test.
> > * g++.dg/ext/attr-non-owning7.C: New test.
> > * g++.dg/ext/attr-non-owning8.C: New test.
> > * g++.dg/ext/attr-non-owning9.C: New test.
> > ---
> >   gcc/cp/call.cc  | 38 ++--
> >   gcc/cp/tree.cc  | 26 +
> >   gcc/doc/extend.texi | 25 
> >   gcc/doc/invoke.texi | 21 +++
> >   gcc/testsuite/g++.dg/ext/attr-non-owning1.C | 38 
> >   gcc/testsuite/g++.dg/ext/attr-non-owning2.C | 29 ++

Re: [pushed] testsuite: fix Wmismatched-new-delete-8.C with -m32

2024-02-22 Thread Marek Polacek
On Thu, Feb 22, 2024 at 04:06:51PM -0800, Andrew Pinski wrote:
> On Thu, Feb 22, 2024, 15:56 Marek Polacek  wrote:
> 
> > Tested x86_64-pc-linux-gnu, applying to trunk.
> 
> 
> I backported/pushed the change to 13 branch already so please apply it
> there too.

Ah right.  Done.

Marek



[pushed] testsuite: fix Wmismatched-new-delete-8.C with -m32

2024-02-22 Thread Marek Polacek
Tested x86_64-pc-linux-gnu, applying to trunk.

-- >8 --
This fixes
error: 'operator new' takes type 'size_t' ('unsigned int') as first parameter 
[-fpermissive]

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wmismatched-new-delete-8.C: Use __SIZE_TYPE__.
---
 gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C 
b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C
index 0ddc056c6df..e8fd7a85b8c 100644
--- a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C
@@ -11,7 +11,7 @@ static inline T * construct_at(void *at, ARGS && args)
  struct Placeable : T
  {
   Placeable(ARGS && args) : T(args) { }
-  void * operator new (long unsigned int, void *ptr) { return ptr; }
+  void * operator new (__SIZE_TYPE__, void *ptr) { return ptr; }
   void operator delete (void *, void *) { }
  };
  return new (at) Placeable(static_cast(args));

base-commit: 37127ed975e09813eaa2d1cf1062055fce45dd16
-- 
2.43.2



Re: [PATCH] c++: -Wuninitialized when binding a ref to uninit DM [PR113987]

2024-02-22 Thread Marek Polacek
On Thu, Feb 22, 2024 at 08:34:45AM +, Jason Merrill wrote:
> On 2/20/24 19:15, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > This PR asks that our -Wuninitialized for mem-initializers does
> > not warn when binding a reference to an uninitialized data member.
> > We already check !INDIRECT_TYPE_P in find_uninit_fields_r, but
> > that won't catch binding a parameter of a reference type to an
> > uninitialized field, as in:
> > 
> >struct S { S (int&); };
> >struct T {
> >T() : s(i) {}
> >S s;
> >int i;
> >};
> > 
> > This patch adds a new function to handle this case.
> 
> For type_build_ctor_call types like S, it's weird that we currently
> find_uninit_fields before building the initialization.  What if we move the
> check after the build_aggr_init so we have the actual initializer instead of
> just the expression?

Thanks.  I've tried but unfortunately I'm not getting anywhere.  One
problem is that immediately after the find_uninit_fields call we may
change the TREE_LIST in

  if (init && TREE_CODE (init) == TREE_LIST)
 //...

so we'd have to cope with that somehow.  Sinking find_uninit_fields
into one of the conditions below looks like a complication.  Another
problem is that calling find_uninit_fields on the result of
build_aggr_init call causes a bogus warning: we create something like
E::E (&((struct F *) this)->e, ((struct F *) this)->a)
and then warn that the this object is uninitialized.  So I'm not sure
if that fix would be simpler.

Marek



[PATCH v2] c++: implement [[gnu::non_owning]] [PR110358]

2024-02-21 Thread Marek Polacek
On Fri, Jan 26, 2024 at 04:04:35PM -0500, Jason Merrill wrote:
> On 1/25/24 20:37, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Since -Wdangling-reference has false positives that can't be
> > prevented, we should offer an easy way to suppress the warning.
> > Currently, that is only possible by using a #pragma, either around the
> > enclosing class or around the call site.  But #pragma GCC diagnostic tend
> > to be onerous.  A better solution would be to have an attribute.  Such
> > an attribute should not be tied to this particular warning though.  [*]
> > 
> > The warning bogusly triggers for classes that are like std::span,
> > std::reference_wrapper, and std::ranges::ref_view.  The common property
> > seems to be that these classes are only wrappers around some data.  So
> > I chose the name non_owning, but I'm not attached to it.  I hope that
> > in the future the attribute can be used for something other than this
> > diagnostic.
> 
> You decided not to pursue Barry's request for a bool argument to the
> attribute?

At first I thought it'd be an unnecessary complication but it was actually
pretty easy.  Better to accept the optional argument from the get-go
otherwise people would have to add > GCC 14 checks.
 
> Might it be more useful for the attribute to make reference_like_class_p
> return true, so that we still warn about a temporary of another type passing
> through it?

Good point.  Fixed.

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

-- >8 --
Since -Wdangling-reference has false positives that can't be
prevented, we should offer an easy way to suppress the warning.
Currently, that is only possible by using a #pragma, either around the
enclosing class or around the call site.  But #pragma GCC diagnostic tend
to be onerous.  A better solution would be to have an attribute.  Such
an attribute should not be tied to this particular warning though.

The warning bogusly triggers for classes that are like std::span,
std::reference_wrapper, and std::ranges::ref_view.  The common property
seems to be that these classes are only wrappers around some data.  So
I chose the name non_owning, but I'm not attached to it.  I hope that
in the future the attribute can be used for something other than this
diagnostic.

This attribute takes an optional bool argument to support cases like:

  template 
  struct [[gnu::non_owning(std::is_reference_v)]] S {
 // ...
  };

PR c++/110358
PR c++/109642

gcc/cp/ChangeLog:

* call.cc (non_owning_p): New.
(reference_like_class_p): Use it.
(do_warn_dangling_reference): Use it.  Don't warn when the function
or its enclosing class has attribute gnu::non_owning.
* tree.cc (cxx_gnu_attributes): Add gnu::non_owning.
(handle_non_owning_attribute): New.

gcc/ChangeLog:

* doc/extend.texi: Document gnu::non_owning.
* doc/invoke.texi: Mention that gnu::non_owning disables
-Wdangling-reference.

gcc/testsuite/ChangeLog:

* g++.dg/ext/attr-non-owning1.C: New test.
* g++.dg/ext/attr-non-owning2.C: New test.
* g++.dg/ext/attr-non-owning3.C: New test.
* g++.dg/ext/attr-non-owning4.C: New test.
* g++.dg/ext/attr-non-owning5.C: New test.
* g++.dg/ext/attr-non-owning6.C: New test.
* g++.dg/ext/attr-non-owning7.C: New test.
* g++.dg/ext/attr-non-owning8.C: New test.
* g++.dg/ext/attr-non-owning9.C: New test.
---
 gcc/cp/call.cc  | 38 ++--
 gcc/cp/tree.cc  | 26 +
 gcc/doc/extend.texi | 25 
 gcc/doc/invoke.texi | 21 +++
 gcc/testsuite/g++.dg/ext/attr-non-owning1.C | 38 
 gcc/testsuite/g++.dg/ext/attr-non-owning2.C | 29 +
 gcc/testsuite/g++.dg/ext/attr-non-owning3.C | 24 
 gcc/testsuite/g++.dg/ext/attr-non-owning4.C | 14 +
 gcc/testsuite/g++.dg/ext/attr-non-owning5.C | 31 ++
 gcc/testsuite/g++.dg/ext/attr-non-owning6.C | 65 +
 gcc/testsuite/g++.dg/ext/attr-non-owning7.C | 31 ++
 gcc/testsuite/g++.dg/ext/attr-non-owning8.C | 30 ++
 gcc/testsuite/g++.dg/ext/attr-non-owning9.C | 25 
 13 files changed, 391 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning1.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning2.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning3.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning4.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning5.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning6.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning7.C
 create mode 100644 gcc/testsuite/g++.dg/ext/at

[PATCH] c++: -Wuninitialized when binding a ref to uninit DM [PR113987]

2024-02-20 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
This PR asks that our -Wuninitialized for mem-initializers does
not warn when binding a reference to an uninitialized data member.
We already check !INDIRECT_TYPE_P in find_uninit_fields_r, but
that won't catch binding a parameter of a reference type to an
uninitialized field, as in:

  struct S { S (int&); };
  struct T {
  T() : s(i) {}
  S s;
  int i;
  };

This patch adds a new function to handle this case.

PR c++/113987

gcc/cp/ChangeLog:

* call.cc (conv_binds_to_reference_parm_p): New.
* cp-tree.h (conv_binds_to_reference_parm_p): Declare.
* init.cc (find_uninit_fields_r): Call it.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wuninitialized-15.C: Turn dg-warning into dg-bogus.
* g++.dg/warn/Wuninitialized-34.C: New test.
---
 gcc/cp/call.cc| 24 ++
 gcc/cp/cp-tree.h  |  1 +
 gcc/cp/init.cc|  3 +-
 gcc/testsuite/g++.dg/warn/Wuninitialized-15.C |  3 +-
 gcc/testsuite/g++.dg/warn/Wuninitialized-34.C | 32 +++
 5 files changed, 60 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wuninitialized-34.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 1dac1470d3b..c40ef2e3028 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -14551,4 +14551,28 @@ maybe_show_nonconverting_candidate (tree to, tree 
from, tree arg, int flags)
"function was not considered");
 }
 
+/* We're converting EXPR to TYPE.  If that conversion involves a conversion
+   function and we're binding EXPR to a reference parameter of that function,
+   return true.  */
+
+bool
+conv_binds_to_reference_parm_p (tree type, tree expr)
+{
+  conversion_obstack_sentinel cos;
+  conversion *c = implicit_conversion (type, TREE_TYPE (expr), expr,
+  /*c_cast_p=*/false, LOOKUP_NORMAL,
+  tf_none);
+  if (c && !c->bad_p && c->user_conv_p)
+for (; c; c = next_conversion (c))
+  if (c->kind == ck_user)
+   for (z_candidate *cand = c->cand; cand; cand = cand->next)
+ if (cand->viable == 1)
+   for (size_t i = 0; i < cand->num_convs; ++i)
+ if (cand->convs[i]->kind == ck_ref_bind
+ && conv_get_original_expr (cand->convs[i]) == expr)
+   return true;
+
+  return false;
+}
+
 #include "gt-cp-call.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 334c11396c2..ce2d85f1f86 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6845,6 +6845,7 @@ extern void cp_warn_deprecated_use_scopes (tree);
 extern tree get_function_version_dispatcher(tree);
 extern bool any_template_arguments_need_structural_equality_p (tree);
 extern void maybe_show_nonconverting_candidate (tree, tree, tree, int);
+extern bool conv_binds_to_reference_parm_p (tree, tree);
 
 /* in class.cc */
 extern tree build_vfield_ref   (tree, tree);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index ac37330527e..1a341f7e606 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -906,7 +906,8 @@ find_uninit_fields_r (tree *tp, int *walk_subtrees, void 
*data)
warning_at (EXPR_LOCATION (init), OPT_Wuninitialized,
"reference %qD is not yet bound to a value when used "
"here", field);
- else if (!INDIRECT_TYPE_P (type) || is_this_parameter (d->member))
+ else if ((!INDIRECT_TYPE_P (type) || is_this_parameter (d->member))
+  && !conv_binds_to_reference_parm_p (type, init))
warning_at (EXPR_LOCATION (init), OPT_Wuninitialized,
"member %qD is used uninitialized", field);
  *walk_subtrees = false;
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C 
b/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C
index 89e90668c41..2fd33037bfd 100644
--- a/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C
@@ -65,8 +65,7 @@ struct H {
   G g;
   A a2;
   H() : g(a1) { }
-  // ??? clang++ doesn't warn here
-  H(int) : g(a2) { } // { dg-warning "member .H::a2. is used uninitialized" }
+  H(int) : g(a2) { } // { dg-bogus "member .H::a2. is used uninitialized" }
 };
 
 struct I {
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-34.C 
b/gcc/testsuite/g++.dg/warn/Wuninitialized-34.C
new file mode 100644
index 000..28226d8032e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-34.C
@@ -0,0 +1,32 @@
+// PR c++/113987
+// { dg-do compile }
+// { dg-options "-Wuninitialized" }
+
+struct t1 {
+t1(int);
+};
+struct t2 {
+t2(int&, int = 0);
+t2(double&, int = 0);
+};
+struct t3 {
+t3(int&);
+};
+struct t4 {};
+void f1(int&);
+struct t {
+t() :
+  v1(i),  // { dg-warning "is used uninitialized" }
+  v2(i),
+  v3(i),
+  v4((f1(i), t4())),
+

[PATCH v3] c++: wrong looser excep spec for dep noexcept [PR113158]

2024-02-16 Thread Marek Polacek
On Fri, Feb 16, 2024 at 04:39:47PM -0500, Patrick Palka wrote:
> On Fri, 16 Feb 2024, Marek Polacek wrote:
> > +  /* We also have to defer checking when we're in a template and couldn't
> > + instantiate & evaluate the noexcept to true/false.  */
> > +  if (processing_template_decl)
> > +if ((base_throw
> > +&& (base_throw != noexcept_true_spec
> > +|| base_throw != noexcept_false_spec))
> 
> Shouldn't these innermost || be &&?

D'oh, yes, what a dumb mistake.  But that shows that we could also just
always return true in a template ;).

Fixed.  dg.exp passed so far.

-- >8 --
Here we find ourselves in maybe_check_overriding_exception_spec in
a template context where we can't instantiate a dependent noexcept.
That's OK, but we have to defer the checking otherwise we give wrong
errors.

PR c++/113158

gcc/cp/ChangeLog:

* search.cc (maybe_check_overriding_exception_spec): Defer checking
when a noexcept couldn't be instantiated & evaluated to false/true.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept83.C: New test.
---
 gcc/cp/search.cc| 11 
 gcc/testsuite/g++.dg/cpp0x/noexcept83.C | 37 +
 2 files changed, 48 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept83.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index c948839dc53..827f48e8604 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1975,6 +1975,17 @@ maybe_check_overriding_exception_spec (tree overrider, 
tree basefn)
   || UNPARSED_NOEXCEPT_SPEC_P (over_throw))
 return true;
 
+  /* We also have to defer checking when we're in a template and couldn't
+ instantiate & evaluate the noexcept to true/false.  */
+  if (processing_template_decl)
+if ((base_throw
+&& base_throw != noexcept_true_spec
+&& base_throw != noexcept_false_spec)
+   || (over_throw
+   && over_throw != noexcept_true_spec
+   && over_throw != noexcept_false_spec))
+  return true;
+
   if (!comp_except_specs (base_throw, over_throw, ce_derived))
 {
   auto_diagnostic_group d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept83.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept83.C
new file mode 100644
index 000..47832bbb44d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept83.C
@@ -0,0 +1,37 @@
+// PR c++/113158
+// { dg-do compile { target c++11 } }
+
+template
+struct V {
+  static constexpr bool t = false;
+};
+struct base {
+virtual int f() = 0;
+};
+
+template
+struct derived : base {
+int f() noexcept(V::t) override;
+};
+
+struct base2 {
+virtual int f() noexcept = 0;
+};
+
+template
+struct W {
+  static constexpr bool t = B;
+};
+
+template
+struct derived2 : base2 {
+int f() noexcept(W::t) override; // { dg-error "looser exception 
specification" }
+};
+
+void
+g ()
+{
+  derived d1;
+  derived2 d2; // { dg-message "required from here" }
+  derived2 d3;
+}

base-commit: cd503b0616462445381a8232fb753239d319af76
-- 
2.43.2



[PATCH v2] c++: wrong looser excep spec for dep noexcept [PR113158]

2024-02-16 Thread Marek Polacek
On Fri, Feb 16, 2024 at 03:58:02PM -0500, Jason Merrill wrote:
> On 2/15/24 17:17, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > By the ??? below I mean that maybe_instantiate_noexcept could return
> > a tristate, and then maybe_check_overriding_exception_spec could check
> > 
> >if (maybe_instantiate_noexcept ().is_unknown ())
> >  return true;
> > 
> > and we don't have to add any new checks to maybe_check_o_e_spec.
> > 
> > -- >8 --
> > Here we find ourselves in maybe_check_overriding_exception_spec in
> > a template context where we can't instantiate a dependent noexcept.
> > That's OK, but we have to defer the checking otherwise we give wrong
> > errors.
> > 
> > PR c++/113158
> > 
> > gcc/cp/ChangeLog:
> > 
> > * search.cc (maybe_check_overriding_exception_spec): Defer checking
> > when a noexcept couldn't be instantiated.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/noexcept83.C: New test.
> > ---
> >   gcc/cp/search.cc|  7 +
> >   gcc/testsuite/g++.dg/cpp0x/noexcept83.C | 37 +
> >   2 files changed, 44 insertions(+)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept83.C
> > 
> > diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
> > index c948839dc53..73d254d6b84 100644
> > --- a/gcc/cp/search.cc
> > +++ b/gcc/cp/search.cc
> > @@ -1975,6 +1975,13 @@ maybe_check_overriding_exception_spec (tree 
> > overrider, tree basefn)
> > || UNPARSED_NOEXCEPT_SPEC_P (over_throw))
> >   return true;
> > +  /* We also have to defer checking when we're in a template and couldn't
> > + instantiate the noexcept yet.
> > + ??? maybe_instantiate_noexcept already checked these.  Use tristate?  
> > */
> > +  if (type_dependent_expression_p (base_throw)
> > +  || type_dependent_expression_p (over_throw))
> 
> I think we also want to avoid comparing value-dependent expressions, but
> actually checking either one seems like more work than needed here; I'd
> think we want to defer in a template if the specifiers aren't both exactly
> true or false.

Yeah, that'll work too.  So like this?

Bootstrap/regtest running; dg.exp passed.  FWIW, the new check only
triggered on the new test.

Thanks,

-- >8 --
Here we find ourselves in maybe_check_overriding_exception_spec in
a template context where we can't instantiate a dependent noexcept.
That's OK, but we have to defer the checking otherwise we give wrong
errors.

PR c++/113158

gcc/cp/ChangeLog:

* search.cc (maybe_check_overriding_exception_spec): Defer checking
when a noexcept couldn't be instantiated & evaluated to false/true.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept83.C: New test.
---
 gcc/cp/search.cc| 11 
 gcc/testsuite/g++.dg/cpp0x/noexcept83.C | 37 +
 2 files changed, 48 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept83.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index c948839dc53..554ba71f4a7 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1975,6 +1975,17 @@ maybe_check_overriding_exception_spec (tree overrider, 
tree basefn)
   || UNPARSED_NOEXCEPT_SPEC_P (over_throw))
 return true;
 
+  /* We also have to defer checking when we're in a template and couldn't
+ instantiate & evaluate the noexcept to true/false.  */
+  if (processing_template_decl)
+if ((base_throw
+&& (base_throw != noexcept_true_spec
+|| base_throw != noexcept_false_spec))
+   || (over_throw
+   && (over_throw != noexcept_true_spec
+   || over_throw != noexcept_false_spec)))
+  return true;
+
   if (!comp_except_specs (base_throw, over_throw, ce_derived))
 {
   auto_diagnostic_group d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept83.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept83.C
new file mode 100644
index 000..47832bbb44d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept83.C
@@ -0,0 +1,37 @@
+// PR c++/113158
+// { dg-do compile { target c++11 } }
+
+template
+struct V {
+  static constexpr bool t = false;
+};
+struct base {
+virtual int f() = 0;
+};
+
+template
+struct derived : base {
+int f() noexcept(V::t) override;
+};
+
+struct base2 {
+virtual int f() noexcept = 0;
+};
+
+template
+struct W {
+  static constexpr bool t = B;
+};
+
+template
+struct derived2 : base2 {
+int f() noexcept(W::t) override; // { dg-error "looser exception 
specification" }
+};
+
+void
+g ()
+{
+  derived d1;
+  derived2 d2; // { dg-message "required from here" }
+  derived2 d3;
+}

base-commit: 40b8d7b73ad2ce498758c1d9bd38ebdbc26b918b
-- 
2.43.2



Re: [COMMITTED] c++: Add testcase for this PR [PR97990]

2024-02-16 Thread Marek Polacek
On Fri, Feb 16, 2024 at 11:00:34AM -0800, Andrew Pinski wrote:
> This testcase was fixed by r14-5934-gf26d68d5d128c8 but we should add
> one to make sure it does not regress again.
> 
> Committed as obvious after a quick test on the testcase.
> 
>   PR c++/97990
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/torture/vector-struct-1.C: New test.
> 
> Signed-off-by: Andrew Pinski 
> ---
>  gcc/testsuite/g++.dg/torture/vector-struct-1.C | 18 ++
>  1 file changed, 18 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/torture/vector-struct-1.C
> 
> diff --git a/gcc/testsuite/g++.dg/torture/vector-struct-1.C 
> b/gcc/testsuite/g++.dg/torture/vector-struct-1.C
> new file mode 100644
> index 000..e2747417e2d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/torture/vector-struct-1.C
> @@ -0,0 +1,18 @@
> +/* PR c++/97990 */
> +/* This used to crash with lto and strict aliasing enabled as the
> +   vector type variant still had TYPE_ALIAS_SET set on it. */

You don't have -Wstrict-aliasing here without which the test didn't ICE.

> +typedef __attribute__((__vector_size__(sizeof(short short TSimd;
> +TSimd hh(int);
> +struct y6
> +{
> +  TSimd VALUE;
> +  ~y6();
> +};
> +template 
> +auto f2(T1 p1, T2){
> +  return hh(p1) <= 0;
> +}
> +void f1(){
> +  f2(0, y6{});
> +}
> -- 
> 2.43.0
> 

Marek



[PATCH v2] c++: implicit move with throw [PR113853]

2024-02-16 Thread Marek Polacek
On Thu, Feb 15, 2024 at 04:36:40PM -0500, Jason Merrill wrote:
> On 2/15/24 10:19, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Here we have
> > 
> >template
> >auto is_throwable(T t) -> decltype(throw t, true) { ... }
> > 
> > where we didn't properly mark 't' as IMPLICIT_RVALUE_P, which caused
> > the wrong overload to have been chosen.  Jason figured out it's because
> > we don't correctly implement [expr.prim.id.unqual]#4.2, which post-P2266
> > says that an id-expression is move-eligible if
> > 
> > "the id-expression (possibly parenthesized) is the operand of
> > a throw-expression, and names an implicitly movable entity that belongs
> > to a scope that does not contain the compound-statement of the innermost
> > lambda-expression, try-block, or function-try-block (if any) whose
> > compound-statement or ctor-initializer contains the throw-expression."
> > 
> > I worked out that it's trying to say that given
> > 
> >struct X {
> >  X();
> >  X(const X&);
> >  X(X&&) = delete;
> >};
> > 
> > the following should fail: the scope of the throw is an sk_try, and it's
> > also x's scope S, and S "does not contain the compound-statement of the
> > *try-block" so x is move-eligible, so we move, so we fail.
> > 
> >void f ()
> >try {
> >  X x;
> >  throw x;  // use of deleted function
> >} catch (...) {
> >}
> > 
> > Whereas here:
> > 
> >void g (X x)
> >try {
> >  throw x;
> >} catch (...) {
> >}
> > 
> > the throw is again in an sk_try, but x's scope is an sk_function_parms
> > which *does* contain the {} of the *try-block, so x is not move-eligible,
> > so we don't move, so we use X(const X&), and the code is fine.
> > 
> > The current code also doesn't seem to handle
> > 
> >void h (X x) {
> >  void z (decltype(throw x, true));
> >}
> > 
> > where there's no enclosing lambda or sk_try so we should move.
> > 
> > I'm not doing anything about lambdas because we shouldn't reach the
> > code at the end of the function: the DECL_HAS_VALUE_EXPR_P check
> > shouldn't let us go further.
> > 
> > PR c++/113789
> > PR c++/113853
> > 
> > gcc/cp/ChangeLog:
> > 
> > * typeck.cc (treat_lvalue_as_rvalue_p): Update code to better
> > reflect [expr.prim.id.unqual]#4.2.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/sfinae69.C: Remove dg-bogus.
> > * g++.dg/cpp0x/sfinae70.C: New test.
> > * g++.dg/cpp0x/sfinae71.C: New test.
> > * g++.dg/cpp0x/sfinae72.C: New test.
> > * g++.dg/cpp2a/implicit-move4.C: New test.
> > ---
> >   gcc/cp/typeck.cc| 32 +--
> >   gcc/testsuite/g++.dg/cpp0x/sfinae69.C   |  2 +-
> >   gcc/testsuite/g++.dg/cpp0x/sfinae70.C   | 16 ++
> >   gcc/testsuite/g++.dg/cpp0x/sfinae71.C   | 17 ++
> >   gcc/testsuite/g++.dg/cpp0x/sfinae72.C   | 17 ++
> >   gcc/testsuite/g++.dg/cpp2a/implicit-move4.C | 59 +
> >   6 files changed, 126 insertions(+), 17 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae70.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae71.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae72.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp2a/implicit-move4.C
> > 
> > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> > index 132c55cfc6d..0dc44cd87ca 100644
> > --- a/gcc/cp/typeck.cc
> > +++ b/gcc/cp/typeck.cc
> > @@ -10837,37 +10837,37 @@ treat_lvalue_as_rvalue_p (tree expr, bool 
> > return_p)
> >parenthesized) id-expression that names an implicitly movable entity
> >declared in the body or parameter-declaration-clause of the innermost
> >enclosing function or lambda-expression, */
> > -  if (DECL_CONTEXT (retval) != current_function_decl)
> > -return NULL_TREE;
> > if (return_p)
> >   {
> > +  if (DECL_CONTEXT (retval) != current_function_decl)
> > +   return NULL_TREE;
> > expr = move (expr);
> > if (expr == error_mark_node)
> > return NULL_TREE;
> > return set_implicit_rvalue_p (expr);
> >   }
> > -  /* if the operand of a throw-expression is a (possibly parenthesized)
> > - id-expression that n

[PATCH] c++: wrong looser excep spec for dep noexcept [PR113158]

2024-02-15 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

By the ??? below I mean that maybe_instantiate_noexcept could return
a tristate, and then maybe_check_overriding_exception_spec could check

  if (maybe_instantiate_noexcept ().is_unknown ())
return true;

and we don't have to add any new checks to maybe_check_o_e_spec.

-- >8 --
Here we find ourselves in maybe_check_overriding_exception_spec in
a template context where we can't instantiate a dependent noexcept.
That's OK, but we have to defer the checking otherwise we give wrong
errors.

PR c++/113158

gcc/cp/ChangeLog:

* search.cc (maybe_check_overriding_exception_spec): Defer checking
when a noexcept couldn't be instantiated.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept83.C: New test.
---
 gcc/cp/search.cc|  7 +
 gcc/testsuite/g++.dg/cpp0x/noexcept83.C | 37 +
 2 files changed, 44 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept83.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index c948839dc53..73d254d6b84 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1975,6 +1975,13 @@ maybe_check_overriding_exception_spec (tree overrider, 
tree basefn)
   || UNPARSED_NOEXCEPT_SPEC_P (over_throw))
 return true;
 
+  /* We also have to defer checking when we're in a template and couldn't
+ instantiate the noexcept yet.
+ ??? maybe_instantiate_noexcept already checked these.  Use tristate?  */
+  if (type_dependent_expression_p (base_throw)
+  || type_dependent_expression_p (over_throw))
+return true;
+
   if (!comp_except_specs (base_throw, over_throw, ce_derived))
 {
   auto_diagnostic_group d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept83.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept83.C
new file mode 100644
index 000..47832bbb44d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept83.C
@@ -0,0 +1,37 @@
+// PR c++/113158
+// { dg-do compile { target c++11 } }
+
+template
+struct V {
+  static constexpr bool t = false;
+};
+struct base {
+virtual int f() = 0;
+};
+
+template
+struct derived : base {
+int f() noexcept(V::t) override;
+};
+
+struct base2 {
+virtual int f() noexcept = 0;
+};
+
+template
+struct W {
+  static constexpr bool t = B;
+};
+
+template
+struct derived2 : base2 {
+int f() noexcept(W::t) override; // { dg-error "looser exception 
specification" }
+};
+
+void
+g ()
+{
+  derived d1;
+  derived2 d2; // { dg-message "required from here" }
+  derived2 d3;
+}

base-commit: b3b3bd250f0a7c22b7d46d3522c8b94c6a35d22a
prerequisite-patch-id: 3beddc8cae6ef7f28cd7eac7240d5f4dad08e5f7
-- 
2.43.0



[PATCH] c++: wrong looser exception spec with deleted fn

2024-02-15 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

IMHO trivial enough to go ahead now seeing as it doesn't introduce
new errors.

-- >8 --
I noticed we don't implement the "unless the overriding function is
defined as deleted" wording added to [except.spec] via CWG 1351.

DR 1351

gcc/cp/ChangeLog:

* search.cc (maybe_check_overriding_exception_spec): Don't error about
a looser exception specification if the overrider is deleted.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept82.C: New test.
---
 gcc/cp/search.cc| 11 +--
 gcc/testsuite/g++.dg/cpp0x/noexcept82.C | 14 ++
 2 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept82.C

diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index 2b4ed5d024e..c948839dc53 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1949,7 +1949,11 @@ locate_field_accessor (tree basetype_path, tree 
field_decl, bool const_p)
 }
 
 /* Check throw specifier of OVERRIDER is at least as strict as
-   the one of BASEFN.  */
+   the one of BASEFN.  This is due to [except.spec]: "If a virtual function
+   has a non-throwing exception specification, all declarations, including
+   the definition, of any function that overrides that virtual function in
+   any derived class shall have a non-throwing exception specification,
+   unless the overriding function is defined as deleted."  */
 
 bool
 maybe_check_overriding_exception_spec (tree overrider, tree basefn)
@@ -1959,7 +1963,10 @@ maybe_check_overriding_exception_spec (tree overrider, 
tree basefn)
   tree base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
   tree over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
 
-  if (DECL_INVALID_OVERRIDER_P (overrider))
+  if (DECL_INVALID_OVERRIDER_P (overrider)
+  /* CWG 1351 added the "unless the overriding function is defined as
+deleted" wording.  */
+  || DECL_DELETED_FN (overrider))
 return true;
 
   /* Can't check this yet.  Pretend this is fine and let
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept82.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept82.C
new file mode 100644
index 000..c996613139b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept82.C
@@ -0,0 +1,14 @@
+// DR 1351, Problems with implicitly-declared exception-specifications
+// { dg-do compile { target c++11 } }
+
+struct B {
+  virtual void f() noexcept;
+  virtual void g();
+  virtual void h() noexcept = delete;
+};
+
+struct D: B {
+  void f(); // { dg-error "looser" }
+  void g() noexcept;// OK
+  void h() = delete;// OK
+};

base-commit: 0d5d1c75f5c68b6064640c3154ae5f4c0b464905
-- 
2.43.0



[PATCH] c++: implicit move with throw [PR113853]

2024-02-15 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here we have

  template
  auto is_throwable(T t) -> decltype(throw t, true) { ... }

where we didn't properly mark 't' as IMPLICIT_RVALUE_P, which caused
the wrong overload to have been chosen.  Jason figured out it's because
we don't correctly implement [expr.prim.id.unqual]#4.2, which post-P2266
says that an id-expression is move-eligible if

"the id-expression (possibly parenthesized) is the operand of
a throw-expression, and names an implicitly movable entity that belongs
to a scope that does not contain the compound-statement of the innermost
lambda-expression, try-block, or function-try-block (if any) whose
compound-statement or ctor-initializer contains the throw-expression."

I worked out that it's trying to say that given

  struct X {
X();
X(const X&);
X(X&&) = delete;
  };

the following should fail: the scope of the throw is an sk_try, and it's
also x's scope S, and S "does not contain the compound-statement of the
*try-block" so x is move-eligible, so we move, so we fail.

  void f ()
  try {
X x;
throw x;  // use of deleted function
  } catch (...) {
  }

Whereas here:

  void g (X x)
  try {
throw x;
  } catch (...) {
  }

the throw is again in an sk_try, but x's scope is an sk_function_parms
which *does* contain the {} of the *try-block, so x is not move-eligible,
so we don't move, so we use X(const X&), and the code is fine.

The current code also doesn't seem to handle

  void h (X x) {
void z (decltype(throw x, true));
  }

where there's no enclosing lambda or sk_try so we should move.

I'm not doing anything about lambdas because we shouldn't reach the
code at the end of the function: the DECL_HAS_VALUE_EXPR_P check
shouldn't let us go further.

PR c++/113789
PR c++/113853

gcc/cp/ChangeLog:

* typeck.cc (treat_lvalue_as_rvalue_p): Update code to better
reflect [expr.prim.id.unqual]#4.2.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/sfinae69.C: Remove dg-bogus.
* g++.dg/cpp0x/sfinae70.C: New test.
* g++.dg/cpp0x/sfinae71.C: New test.
* g++.dg/cpp0x/sfinae72.C: New test.
* g++.dg/cpp2a/implicit-move4.C: New test.
---
 gcc/cp/typeck.cc| 32 +--
 gcc/testsuite/g++.dg/cpp0x/sfinae69.C   |  2 +-
 gcc/testsuite/g++.dg/cpp0x/sfinae70.C   | 16 ++
 gcc/testsuite/g++.dg/cpp0x/sfinae71.C   | 17 ++
 gcc/testsuite/g++.dg/cpp0x/sfinae72.C   | 17 ++
 gcc/testsuite/g++.dg/cpp2a/implicit-move4.C | 59 +
 6 files changed, 126 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae70.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae71.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae72.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/implicit-move4.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 132c55cfc6d..0dc44cd87ca 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10837,37 +10837,37 @@ treat_lvalue_as_rvalue_p (tree expr, bool return_p)
  parenthesized) id-expression that names an implicitly movable entity
  declared in the body or parameter-declaration-clause of the innermost
  enclosing function or lambda-expression, */
-  if (DECL_CONTEXT (retval) != current_function_decl)
-return NULL_TREE;
   if (return_p)
 {
+  if (DECL_CONTEXT (retval) != current_function_decl)
+   return NULL_TREE;
   expr = move (expr);
   if (expr == error_mark_node)
return NULL_TREE;
   return set_implicit_rvalue_p (expr);
 }
 
-  /* if the operand of a throw-expression is a (possibly parenthesized)
- id-expression that names an implicitly movable entity whose scope does not
- extend beyond the compound-statement of the innermost try-block or
- function-try-block (if any) whose compound-statement or ctor-initializer
- encloses the throw-expression, */
+  /* if the id-expression (possibly parenthesized) is the operand of
+ a throw-expression, and names an implicitly movable entity that belongs
+ to a scope that does not contain the compound-statement of the innermost
+ lambda-expression, try-block, or function-try-block (if any) whose
+ compound-statement or ctor-initializer contains the throw-expression.  */
 
   /* C++20 added move on throw of parms.  */
   if (TREE_CODE (retval) == PARM_DECL && cxx_dialect < cxx20)
 return NULL_TREE;
 
   for (cp_binding_level *b = current_binding_level;
-   ; b = b->level_chain)
-{
-  for (tree decl = b->names; decl; decl = TREE_CHAIN (decl))
-   if (decl == retval)
- return set_implicit_rvalue_p (move (expr));
-  if (b->kind == sk_function_parms
- || b->kind == sk_try
- || b->kind == sk_namespace)
+   b->kind != sk_namespace; b = b->level_chain)
+if (b->kind == sk_try)
+  {
+   for (tree decl = b->names; decl; decl = TREE_CHAIN (decl))
+ 

[PATCH] c++: adjust the extra ; warning [PR113760]

2024-02-13 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
A minimal fix to quash an extra ; warning.  I have a more complete
patch for GCC 15.

DR 1693
PR c++/113760

gcc/cp/ChangeLog:

* parser.cc (cp_parser_member_declaration): Only pedwarn about an extra
semicolon in C++98.

gcc/testsuite/ChangeLog:

* g++.dg/semicolon-fixits.C: Run in C++98 only.
* g++.dg/warn/pedantic2.C: Adjust dg-warning.
* g++.old-deja/g++.jason/parse11.C: Adjust dg-error.
* g++.dg/DRs/dr1693-1.C: New test.
* g++.dg/DRs/dr1693-2.C: New test.
---
 gcc/cp/parser.cc   | 2 +-
 gcc/testsuite/g++.dg/DRs/dr1693-1.C| 9 +
 gcc/testsuite/g++.dg/DRs/dr1693-2.C| 9 +
 gcc/testsuite/g++.dg/semicolon-fixits.C| 1 +
 gcc/testsuite/g++.dg/warn/pedantic2.C  | 4 ++--
 gcc/testsuite/g++.old-deja/g++.jason/parse11.C | 4 ++--
 6 files changed, 24 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/DRs/dr1693-1.C
 create mode 100644 gcc/testsuite/g++.dg/DRs/dr1693-2.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 68ab74d70b9..9d0914435fb 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -27999,7 +27999,7 @@ cp_parser_member_declaration (cp_parser* parser)
   if (!decl_specifiers.any_specifiers_p)
{
  cp_token *token = cp_lexer_peek_token (parser->lexer);
- if (!in_system_header_at (token->location))
+ if (cxx_dialect < cxx11 && !in_system_header_at (token->location))
{
  gcc_rich_location richloc (token->location);
  richloc.add_fixit_remove ();
diff --git a/gcc/testsuite/g++.dg/DRs/dr1693-1.C 
b/gcc/testsuite/g++.dg/DRs/dr1693-1.C
new file mode 100644
index 000..ed27026109c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr1693-1.C
@@ -0,0 +1,9 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "" }
+
+struct S {
+  int a;
+  ;
+};
diff --git a/gcc/testsuite/g++.dg/DRs/dr1693-2.C 
b/gcc/testsuite/g++.dg/DRs/dr1693-2.C
new file mode 100644
index 000..c52259d4602
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr1693-2.C
@@ -0,0 +1,9 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-pedantic-errors" }
+
+struct S {
+  int a;
+  ;// { dg-error "extra" "" { target c++98_only } }
+};
diff --git a/gcc/testsuite/g++.dg/semicolon-fixits.C 
b/gcc/testsuite/g++.dg/semicolon-fixits.C
index a9cc783b172..198e306c950 100644
--- a/gcc/testsuite/g++.dg/semicolon-fixits.C
+++ b/gcc/testsuite/g++.dg/semicolon-fixits.C
@@ -1,3 +1,4 @@
+// { dg-do compile { target c++98_only } }
 /* { dg-options "-fdiagnostics-show-caret -Wpedantic" } */
 
 /* Struct with extra semicolon.  */
diff --git a/gcc/testsuite/g++.dg/warn/pedantic2.C 
b/gcc/testsuite/g++.dg/warn/pedantic2.C
index 6c834162c1b..37d77daaef3 100644
--- a/gcc/testsuite/g++.dg/warn/pedantic2.C
+++ b/gcc/testsuite/g++.dg/warn/pedantic2.C
@@ -5,6 +5,6 @@ class foo
   foo() {};
   void bar() {};
 
-  foo(int) {};;  // { dg-warning "extra" }
-  void bar(int) {};;  // { dg-warning "extra" }
+  foo(int) {};;  // { dg-warning "extra" "" { target c++98_only } }
+  void bar(int) {};;  // { dg-warning "extra" "" { target c++98_only } }
 };
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/parse11.C 
b/gcc/testsuite/g++.old-deja/g++.jason/parse11.C
index 40864c108ba..157a9c46287 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/parse11.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/parse11.C
@@ -3,7 +3,7 @@
 
 class aClass 
 { 
-  ; // { dg-error "" } missing declaration
+  ; // { dg-error "" "" { target c++98_only } } missing declaration
 private: 
-  ; // { dg-error "" } missing declaration
+  ; // { dg-error "" "" { target c++98_only } } missing declaration
 }; 

base-commit: ab71fd7ac7a2307723117c796e7ae4d7e9711058
-- 
2.43.0



Re: [PATCH] c++: DR 569, DR 1693: fun with semicolons [PR113760]

2024-02-13 Thread Marek Polacek
On Tue, Feb 13, 2024 at 03:41:53PM -0500, Jason Merrill wrote:
> On 2/13/24 14:43, Marek Polacek wrote:
> > On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
> > > On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> > > > Sadly, I must admit this is looking like GCC 15 material.
> > > 
> > > If deferred for GCC 15, can't we at least do some minimal
> > > change and just guard the member pedwarn with cxx_dialect < something?
> > 
> > I could do something like that, but...
> > 
> > > Given that -Wextra-semi isn't on by default nor included in
> > > -Wall -W, I think even accepting this for GCC 14 wouldn't be that
> > > risky.
> > 
> > ...I also don't think it's that risky but technically, it's not
> > a regression I think.
> > > Jason's decision.
> > > 
> > > +  /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
> > > +effect in C++11 and below.  DR 1693 added "empty-declaration" to 
> > > the
> > > +syntax for "member-declaration".  */
> > > +  else if (pedantic && cxx_dialect < cxx14)
> > > 
> > > If it was a DR, did it apply just to C++14 or changed C++11 as well?
> > 
> > It's got Status: C++14 so I thought that C++11/C++98 had not been
> > adjusted.
> 
> That's just the timeframe it was accepted in; below that it says "moved to
> DR" which usually means it applies to earlier standards, whereas "accepted"
> or "applied to WP" do not.
> 
> For 14 let's go with the minimal change Jakub suggests.

Okay.  Do we want to pedwarn about the extra ; here

  struct S {
int a;;
  };

only in C++98 or C++11 too?

Marek



Re: [PATCH] c++: DR 569, DR 1693: fun with semicolons [PR113760]

2024-02-13 Thread Marek Polacek
On Tue, Feb 13, 2024 at 02:43:39PM -0500, Marek Polacek wrote:
> On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
> > On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> > > Sadly, I must admit this is looking like GCC 15 material.
> > 
> > If deferred for GCC 15, can't we at least do some minimal
> > change and just guard the member pedwarn with cxx_dialect < something?
> 
> I could do something like that, but...
> 
> > Given that -Wextra-semi isn't on by default nor included in
> > -Wall -W, I think even accepting this for GCC 14 wouldn't be that
> > risky.
> 
> ...I also don't think it's that risky but technically, it's not
> a regression I think.
>  
> > Jason's decision.
> > 
> > +  /* If -Wextra-semi wasn't specified, warn only when -pedantic is in  
> > 
> >   
> > +effect in C++11 and below.  DR 1693 added "empty-declaration" to 
> > the 
> > 
> > +syntax for "member-declaration".  */   
> > 
> >   
> > +  else if (pedantic && cxx_dialect < cxx14)
> > 
> >   
> > 
> > If it was a DR, did it apply just to C++14 or changed C++11 as well?
> 
> It's got Status: C++14 so I thought that C++11/C++98 had not been
> adjusted. 

...but then so was DR 1601 which I implemented in 
https://gcc.gnu.org/git/?p=gcc.git=commit;h=e295e3d981355c61b72eca2ee58864958655cc31
and made it apply to C++11 as well.

So I'm starting to lean towards adjusting this patch to
make DR 1693 apply to C++11 as well, but not C++98.  Probably
not a very important distinction in practice though.

Marek



Re: [PATCH] c++: DR 569, DR 1693: fun with semicolons [PR113760]

2024-02-13 Thread Marek Polacek
On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
> On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> > Sadly, I must admit this is looking like GCC 15 material.
> 
> If deferred for GCC 15, can't we at least do some minimal
> change and just guard the member pedwarn with cxx_dialect < something?

I could do something like that, but...

> Given that -Wextra-semi isn't on by default nor included in
> -Wall -W, I think even accepting this for GCC 14 wouldn't be that
> risky.

...I also don't think it's that risky but technically, it's not
a regression I think.
 
> Jason's decision.
> 
> +  /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
>   
>   
> +effect in C++11 and below.  DR 1693 added "empty-declaration" to the 
>   
>   
> +syntax for "member-declaration".  */ 
>   
>   
> +  else if (pedantic && cxx_dialect < cxx14)  
>   
>   
> 
> If it was a DR, did it apply just to C++14 or changed C++11 as well?

It's got Status: C++14 so I thought that C++11/C++98 had not been
adjusted. 

Marek



[PATCH] c++: DR 569, DR 1693: fun with semicolons [PR113760]

2024-02-13 Thread Marek Polacek
Sadly, I must admit this is looking like GCC 15 material.

Bootstrapped/regtested on x86_64-pc-linux-gnu.

-- >8 --
Prompted by c++/113760, I started looking into a bogus "extra ;"
warning in C++14.  It quickly turned out that if I want to fix
this for good, the fix will not be so small.

This patch touches on DR 569, an extra ; at namespace scope should
be allowed since C++11:

  struct S {
  };
  ; // pedwarn in C++98

It also implements DR 1693, which allows superfluous semicolons in
class definitions since C++14:

  struct S {
int a;
; // pedwarn in C++98 + C++11
  };

Note that a single semicolon is valid after a member function definition:

  struct S {
void foo () {}; // only warns with -Wextra-semi
  };

There's a new function maybe_warn_extra_semi to handle all of the above
in a single place.  So now they all get a fix-it hint.

-Wextra-semi turns on all "extra ;" diagnostics.  Currently, options
like -Wc++11-compat or -Wc++11-extensions are not considered.

DR 1693
PR c++/113760
DR 569

gcc/c-family/ChangeLog:

* c.opt (Wextra-semi): Initialize to -1.

gcc/cp/ChangeLog:

* parser.cc (extra_semi_kind): New.
(maybe_warn_extra_semi): New.
(cp_parser_declaration): Call maybe_warn_extra_semi.
(cp_parser_member_declaration): Likewise.

gcc/ChangeLog:

* doc/invoke.texi: Update -Wextra-semi documentation.

gcc/testsuite/ChangeLog:

* g++.dg/semicolon-fixits.C: Use -Wextra-semi instead of -Wpedantic.
* g++.dg/warn/pedantic2.C: Adjust dg-warning.
* g++.old-deja/g++.jason/parse11.C: Adjust dg-error.
* g++.dg/diagnostic/semicolon1.C: New test.
* g++.dg/diagnostic/semicolon10.C: New test.
* g++.dg/diagnostic/semicolon11.C: New test.
* g++.dg/diagnostic/semicolon12.C: New test.
* g++.dg/diagnostic/semicolon13.C: New test.
* g++.dg/diagnostic/semicolon14.C: New test.
* g++.dg/diagnostic/semicolon15.C: New test.
* g++.dg/diagnostic/semicolon16.C: New test.
* g++.dg/diagnostic/semicolon17.C: New test.
* g++.dg/diagnostic/semicolon2.C: New test.
* g++.dg/diagnostic/semicolon3.C: New test.
* g++.dg/diagnostic/semicolon4.C: New test.
* g++.dg/diagnostic/semicolon5.C: New test.
* g++.dg/diagnostic/semicolon6.C: New test.
* g++.dg/diagnostic/semicolon7.C: New test.
* g++.dg/diagnostic/semicolon8.C: New test.
* g++.dg/diagnostic/semicolon9.C: New test.
---
 gcc/c-family/c.opt|  2 +-
 gcc/cp/parser.cc  | 92 +++
 gcc/doc/invoke.texi   | 29 +-
 gcc/testsuite/g++.dg/diagnostic/semicolon1.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon10.C | 11 +++
 gcc/testsuite/g++.dg/diagnostic/semicolon11.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon12.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon13.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon14.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon15.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon16.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon17.C | 29 ++
 gcc/testsuite/g++.dg/diagnostic/semicolon2.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon3.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon4.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon5.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon6.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon7.C  | 18 
 gcc/testsuite/g++.dg/diagnostic/semicolon8.C  | 11 +++
 gcc/testsuite/g++.dg/diagnostic/semicolon9.C  | 11 +++
 gcc/testsuite/g++.dg/semicolon-fixits.C   |  2 +-
 gcc/testsuite/g++.dg/warn/pedantic2.C |  4 +-
 .../g++.old-deja/g++.jason/parse11.C  |  4 +-
 23 files changed, 472 insertions(+), 23 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon1.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon10.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon11.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon12.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon13.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon14.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon15.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon16.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon17.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon2.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon3.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon4.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon5.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon6.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon7.C
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon8.C
 create mode 100644 

Re: [PATCH] attribs: Don't canonicalize lookup_scoped_attribute_spec argument [PR113674]

2024-02-12 Thread Marek Polacek
On Mon, Feb 12, 2024 at 06:30:55PM +0100, Jakub Jelinek wrote:
> Hi!
> 
> The C and C++ FEs when parsing attributes already canonicalize them
> (i.e. if they start with __ and end with __ substrings, we remove those).
> lookup_attribute already verifies in gcc_assert that the first character
> of name is not an underscore, and even lookup_scoped_attribute_spec doesn't
> attempt to canonicalize the namespace it is passed.  But for some historic
> reason it was canonicalizing the name argument, which misbehaves when
> an attribute starts with  and ends with .
> I believe it is just wrong to try to canonicalize
> lookup_scope_attribute_spec name attribute, it should have been
> canonicalized already, in other spots where it is called it is already
> canonicalized before.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Looks fine.  extract_attribute_substring was added in
https://gcc.gnu.org/pipermail/gcc-patches/2007-July/221563.html
but with no tests.  I see that without it gcc.dg/attr-noinline.c
was failing, but that hasn't been the case for many years now.  So
I don't know why it would be necessary to keep it.
 
Marek



Re: [PATCH 2/1] c++: Also support lambdas attached to TYPE_DECLs in modules

2024-02-12 Thread Marek Polacek
On Sun, Feb 11, 2024 at 02:54:18PM +1100, Nathaniel Shead wrote:
> Bootstrapped and regtested (so far just modules.exp and dg.exp) on
> x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?
> 
> (Also I noticed I forgot to add the PR to the changelog in my last
> patch, I've fixed that locally.)
> 
> -- >8 --
> 
> After fixing PR111710, I noticed that we currently ICE when declaring a
> type that derives from 'decltype([]{})'. As far as I can tell this
> should be legal code, since by [basic.link] p15.2 a lambda defined in a
> class-specifier should not be TU-local.
> 
> This patch also adds a bunch of tests for unevaluated lambdas in other
> contexts, which generally seem to work now.
> 
> One interesting case is 'E::f' in the attached testcase: it appears to
> get a merge kind of 'MK_field', rather than 'MK_keyed' as most other
> lambdas do. I'm not entirely sure if this will cause issues in the
> future, but I haven't been able to construct a testcase that causes
> problems with this, and conversely wrapping the class body in
> 'start_lambda_scope' causes issues with symbol duplication in COMDAT
> groups, so I've left it as-is for now.

Hi Nathaniel,
 
> gcc/cp/ChangeLog:
> 
>   * module.cc (trees_out::key_mergeable): Also support TYPE_DECLs.
>   (maybe_key_decl): Likewise.
>   * parser.cc (cp_parser_class_head): Start a lambda scope when
>   parsing base classes.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/modules/lambda-7_a.C:
>   * g++.dg/modules/lambda-7_b.C:

sorry to be pointing out nits, but this CL entry is missing a description.
No need to repost the patch because of that, of couse.

Marek



[PATCH] c++: ICE with reinterpret_cast and switch [PR113545]

2024-02-10 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Jason, this is the patch you proposed for PR113545.  It looks very safe
so I'm posting it here so that it's not forgotten.

PR c++/113545

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_switch_expr): If the condition doesn't reduce
to an INTEGER_CST, consider it non-constant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-reinterpret3.C: Remove dg-ice.
---
 gcc/cp/constexpr.cc | 10 ++
 gcc/testsuite/g++.dg/cpp1y/constexpr-reinterpret3.C |  4 +---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 2ebb1470dd5..fa346fe01c9 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -7106,6 +7106,16 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
   cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue,
   non_constant_p, overflow_p);
   VERIFY_CONSTANT (cond);
+  if (TREE_CODE (cond) != INTEGER_CST)
+{
+  /* If the condition doesn't reduce to an INTEGER_CST it isn't a usable
+switch condition even if it's constant enough for other things
+(c++/113545).  */
+  gcc_checking_assert (ctx->quiet);
+  *non_constant_p = true;
+  return t;
+}
+
   *jump_target = cond;
 
   tree body
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-reinterpret3.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-reinterpret3.C
index 51feb2e558e..adc0b418df9 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-reinterpret3.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-reinterpret3.C
@@ -1,7 +1,5 @@
 // PR c++/113545
-// { dg-do compile { target c++14 } }
-// Please change the above "dg-do compile" to "dg-do run" when the ICE is 
resolved.
-// { dg-ice "PR112545 - constexpr function with switch called for 
reinterpret_cast" }
+// { dg-do run { target c++14 } }
 
 char foo;
 

base-commit: 93e1559bea434a681208e5e7a21513d7da2844d6
prerequisite-patch-id: 9dda211bd29817f18d2d46c3c5a7bbe3708cf9f2
-- 
2.43.0



[PATCH] c++: SFINAE-unfriendly error on throwing pointer [PR112436]

2024-02-10 Thread Marek Polacek
Probably stage1 material but it should be safe...

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

-- >8 --
On the heels of r14-8903, this patch adds further complain parameters
so that we don't emit "invalid use of incomplete type" from inside
a concept.

PR c++/112436

gcc/cp/ChangeLog:

* except.cc (expand_start_catch_block): Pass tf_warning_or_error to
is_admissible_throw_operand_or_catch_parameter.
(build_throw): Pass complain to
is_admissible_throw_operand_or_catch_parameter.
(complete_ptr_ref_or_void_ptr_p): Add a tsubst_flags_t parameter.  Use
it.  Return bool.  Call complete_type_or_maybe_complain instead of
complete_type_or_else.
(is_admissible_throw_operand_or_catch_parameter): Add a tsubst_flags_t
parameter.  Use it.  Guard error calls.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-pr112436.C: New test.
---
 gcc/cp/except.cc  | 66 ++-
 .../g++.dg/cpp2a/concepts-pr112436.C  |  9 +++
 2 files changed, 44 insertions(+), 31 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C

diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index ea3d6f57396..f1ffda22fd3 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -39,8 +39,8 @@ static tree do_end_catch (tree);
 static void initialize_handler_parm (tree, tree);
 static tree do_allocate_exception (tree);
 static tree wrap_cleanups_r (tree *, int *, void *);
-static int complete_ptr_ref_or_void_ptr_p (tree, tree);
-static bool is_admissible_throw_operand_or_catch_parameter (tree, bool);
+static bool is_admissible_throw_operand_or_catch_parameter (tree, bool,
+   tsubst_flags_t);
 
 /* Sets up all the global eh stuff that needs to be initialized at the
start of compilation.  */
@@ -398,7 +398,8 @@ expand_start_catch_block (tree decl)
 
   if (decl)
 {
-  if (!is_admissible_throw_operand_or_catch_parameter (decl, false))
+  if (!is_admissible_throw_operand_or_catch_parameter (decl, false,
+  tf_warning_or_error))
decl = error_mark_node;
 
   type = prepare_eh_type (TREE_TYPE (decl));
@@ -626,11 +627,10 @@ build_throw (location_t loc, tree exp, tsubst_flags_t 
complain)
 warning_at (loc, 0,
"throwing NULL, which has integral, not pointer type");
 
-  if (exp != NULL_TREE)
-{
-  if (!is_admissible_throw_operand_or_catch_parameter (exp, true))
-   return error_mark_node;
-}
+  if (exp && !is_admissible_throw_operand_or_catch_parameter (exp,
+ /*is_throw=*/true,
+ complain))
+return error_mark_node;
 
   if (! doing_eh ())
 return error_mark_node;
@@ -815,28 +815,26 @@ build_throw (location_t loc, tree exp, tsubst_flags_t 
complain)
Return the zero on failure and nonzero on success. FROM can be
the expr or decl from whence TYPE came, if available.  */
 
-static int
-complete_ptr_ref_or_void_ptr_p (tree type, tree from)
+static bool
+complete_ptr_ref_or_void_ptr_p (tree type, tree from, tsubst_flags_t complain)
 {
-  int is_ptr;
-
   /* Check complete.  */
-  type = complete_type_or_else (type, from);
+  type = complete_type_or_maybe_complain (type, from, complain);
   if (!type)
-return 0;
+return false;
 
   /* Or a pointer or ref to one, or cv void *.  */
-  is_ptr = TYPE_PTR_P (type);
+  const bool is_ptr = TYPE_PTR_P (type);
   if (is_ptr || TYPE_REF_P (type))
 {
   tree core = TREE_TYPE (type);
 
   if (is_ptr && VOID_TYPE_P (core))
/* OK */;
-  else if (!complete_type_or_else (core, from))
-   return 0;
+  else if (!complete_type_or_maybe_complain (core, from, complain))
+   return false;
 }
-  return 1;
+  return true;
 }
 
 /* If IS_THROW is true return truth-value if T is an expression admissible
@@ -846,13 +844,14 @@ complete_ptr_ref_or_void_ptr_p (tree type, tree from)
for its type plus rvalue reference type is also not admissible.  */
 
 static bool
-is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
+is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw,
+   tsubst_flags_t complain)
 {
   tree expr = is_throw ? t : NULL_TREE;
   tree type = TREE_TYPE (t);
 
   /* C++11 [except.handle] The exception-declaration shall not denote
- an incomplete type, an abstract class type, or an rvalue reference 
+ an incomplete type, an abstract class type, or an rvalue reference
  type.  */
 
   /* 15.1/4 [...] The type of the throw-expression shall not be an
@@ -862,7 +861,7 @@ is_admissible_throw_operand_or_catch_parameter (tree t, 
bool is_throw)
restrictions on type matching mentioned in 15.3, the operand

[PATCH v4] c++: DR2237, cdtor and template-id tweaks [PR107126]

2024-02-09 Thread Marek Polacek
On Fri, Feb 09, 2024 at 10:20:04AM -0500, Jason Merrill wrote:
> On 2/8/24 16:26, Marek Polacek wrote:
> > This patch does *not* fix
> > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
> > where the C++20 diagnostic is missing altogether.
> 
> What would it take to fix that as well?

It's the "further DR2237 fix" below which is basically a one liner.
I'd thought it would be more involved than that.
 
> > * doc/invoke.texi: Document -Wdeprecated-template-id-cdtor.
> 
> Was it ever deprecated?  I'm not seeing that in
> 
> https://timsong-cpp.github.io/cppwp/n4659/#depr (C++17)

Aha, [diff] != [depr]...
 
> Let's drop the word "deprecated" from the option name and documentation.

Done throughout.
 
> > @@ -32331,11 +32338,11 @@ cp_parser_constructor_declarator_p (cp_parser 
> > *parser, cp_parser_flags flags,
> > if (next_token->type != CPP_NAME
> > && next_token->type != CPP_SCOPE
> > && next_token->type != CPP_NESTED_NAME_SPECIFIER
> > -  /* DR 2237 (C++20 only): A simple-template-id is no longer valid as 
> > the
> > -declarator-id of a constructor or destructor.  */
> > -  && (next_token->type != CPP_TEMPLATE_ID || cxx_dialect >= cxx20))
> > +  && next_token->type != CPP_TEMPLATE_ID)
> >   return false;
> > +  const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
> 
> Please incorporate your "further DR2237 fix" patch into this one.

Patches squashed.
 
> > @@ -32552,6 +32559,19 @@ cp_parser_constructor_declarator_p (cp_parser 
> > *parser, cp_parser_flags flags,
> > /* We did not really want to consume any tokens.  */
> > cp_parser_abort_tentative_parse (parser);
> > +  /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
> > + declarator-id of a constructor or destructor.  */
> > +  if (constructor_p && saw_template_id)
> > +{
> > +  gcc_checking_assert
> > +   (!cp_parser_uncommitted_to_tentative_parse_p (parser));
> 
> Now I see the abort_ just above, so this seems unnecessary after all.

Done, thanks.

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

-- >8 --
Since my r11-532 changes to implement DR2237, for this test:

  template
  struct S {
S();
  };

in C++20 we emit the ugly:

q.C:3:8: error: expected unqualified-id before ')' token
3 |   S();

which doesn't explain what the problem is.  This patch improves that
diagnostic, reduces the error to a pedwarn, and adds a -Wc++20-compat
diagnostic.  We now say:

q.C:3:7: warning: template-id not allowed for constructor in C++20 
[-Wtemplate-id-cdtor]
3 |   S();
q.C:3:7: note: remove the '< >'

This patch also fixes
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
where the C++20 diagnostic was missing altogether: The problem was that I 
checked
for CPP_TEMPLATE_ID too early, at a point at which cp_parser_template_id may not
have been called yet.  So let's check for it at the end of the function, after
the tentative parse and rollback.

-Wc++20-compat triggered in libitm/; I sent a patch for that.

DR 2237
PR c++/107126
PR c++/97202

gcc/c-family/ChangeLog:

* c-opts.cc (c_common_post_options): In C++20 or with -Wc++20-compat,
turn on -Wtemplate-id-cdtor.
* c.opt (Wtemplate-id-cdtor): New.

gcc/cp/ChangeLog:

* parser.cc (cp_parser_unqualified_id): Downgrade the DR2237 error to
a pedwarn.
(cp_parser_constructor_declarator_p): Likewise.

gcc/ChangeLog:

* doc/invoke.texi: Document -Wtemplate-id-cdtor.

gcc/testsuite/ChangeLog:

* g++.dg/DRs/dr2237.C: Adjust dg-error.
* g++.dg/parse/constructor2.C: Likewise.
* g++.dg/template/error34.C: Likewise.
* g++.old-deja/g++.pt/ctor2.C: Likewise.
* g++.dg/DRs/dr2237-2.C: New test.
* g++.dg/DRs/dr2237-3.C: New test.
* g++.dg/DRs/dr2237-4.C: New test.
* g++.dg/DRs/dr2237-5.C: New test.
* g++.dg/warn/Wtemplate-id-cdtor-1.C: New test.
* g++.dg/warn/Wtemplate-id-cdtor-2.C: New test.
* g++.dg/warn/Wtemplate-id-cdtor-3.C: New test.
* g++.dg/warn/Wtemplate-id-cdtor-4.C: New test.
---
 gcc/c-family/c-opts.cc|  5 +++
 gcc/c-family/c.opt|  4 +++
 gcc/cp/parser.cc  | 33 ++-
 gcc/doc/invoke.texi   | 19 ++-
 gcc/testsuite/g++.dg/DRs/dr2237-2.C   |  9 +
 gcc/testsuite/g++.dg/DRs/dr2237-3.C   | 16 +
 gcc/testsuite/g++.dg/DRs/dr2237-4.C   | 11 +++
 gcc/testsuite/g++.dg/DRs/dr2237-5.C   |  7 
 gcc/testsuite/g++.dg/DRs/dr2237.C |  2 +-
 g

[PATCH] c++: fix ICE with __type_pack_element [PR113834]

2024-02-09 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here we crash on this invalid code because we seem to infinitely recurse
and end up with __type_pack_element with index that doesn't tree_fits_shwi_p
which then crashes on tree_to_shwi.

Thanks to Jakub for suggesting a nicer fix than my original one.

PR c++/113834

gcc/cp/ChangeLog:

* semantics.cc (finish_type_pack_element): Perform range checking
before tree_to_shwi.

gcc/testsuite/ChangeLog:

* g++.dg/ext/type_pack_element4.C: New test.
---
 gcc/cp/semantics.cc   |  7 +++
 gcc/testsuite/g++.dg/ext/type_pack_element4.C | 17 +
 2 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/type_pack_element4.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 3299e270446..57840176863 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4650,20 +4650,19 @@ finish_type_pack_element (tree idx, tree types, 
tsubst_flags_t complain)
error ("%<__type_pack_element%> index is not an integral constant");
   return error_mark_node;
 }
-  HOST_WIDE_INT val = tree_to_shwi (idx);
-  if (val < 0)
+  if (tree_int_cst_sgn (idx) < 0)
 {
   if (complain & tf_error)
error ("%<__type_pack_element%> index is negative");
   return error_mark_node;
 }
-  if (val >= TREE_VEC_LENGTH (types))
+  if (wi::to_widest (idx) >= TREE_VEC_LENGTH (types))
 {
   if (complain & tf_error)
error ("%<__type_pack_element%> index is out of range");
   return error_mark_node;
 }
-  return TREE_VEC_ELT (types, val);
+  return TREE_VEC_ELT (types, tree_to_shwi (idx));
 }
 
 /* Implement the __direct_bases keyword: Return the direct base classes
diff --git a/gcc/testsuite/g++.dg/ext/type_pack_element4.C 
b/gcc/testsuite/g++.dg/ext/type_pack_element4.C
new file mode 100644
index 000..aa508c79090
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/type_pack_element4.C
@@ -0,0 +1,17 @@
+// PR c++/113834
+// { dg-do compile { target c++17 } }
+
+template  class tuple{};
+template 
+__type_pack_element<__i, _Elements...> (tuple<_Elements...> &__t) 
noexcept; // { dg-error "index is out of range" }
+tuple data;
+template 
+unsigned take_impl(unsigned idx) {
+  if constexpr (Level != -1){
+return take_impl(get(data)); // { dg-error "" }
+  }
+  return 0;
+}
+int main() {
+  take_impl<2>(0);
+}

base-commit: c9bdcb0c3433ce09f5bb713a51a14130858578a2
-- 
2.43.0



[PATCH v3] c++: make build_throw SFINAE-friendly [PR98388]

2024-02-09 Thread Marek Polacek
On Fri, Feb 09, 2024 at 10:07:33AM -0500, Jason Merrill wrote:
> On 2/8/24 17:20, Marek Polacek wrote:
> > On Thu, Feb 08, 2024 at 04:53:45PM -0500, Jason Merrill wrote:
> > > On 2/8/24 11:51, Marek Polacek wrote:
> > > > On Thu, Feb 08, 2024 at 08:49:28AM -0500, Patrick Palka wrote:
> > > > > On Wed, 7 Feb 2024, Marek Polacek wrote:
> > > > > 
> > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > > > 
> > > > > > -- >8 --
> > > > > > Here the problem is that we give hard errors while substituting
> > > > > > template parameters during overload resolution of is_throwable
> > > > > > which has an invalid throw in decltype.
> > > > > > 
> > > > > > The backtrace shows that fn_type_unification -> instantiate_template
> > > > > > -> tsubst* passes complain=0 as expected, but build_throw doesn't
> > > > > > have a complain parameter.  So let's add one.  Also remove a 
> > > > > > redundant
> > > > > > local variable which I should have removed in my P2266 patch.
> > > > > > 
> > > > > > But there's still something not quite clear to me.  I claim that 'b'
> > > > > > in the testcase should evaluate to false since the first overload 
> > > > > > ought
> > > > > > to have been discarded.  EDG 6.6 agrees, but clang++, msvc, and icx 
> > > > > > evaluate
> > > > > > it to true.  Who's right?
> > > 
> > > I think it should be true since P1155, which we implement in C++20 mode 
> > > and
> > > above (or rather, we implement the sequel P2266); since then we implicitly
> > > move from the function parameter.
> > > 
> > > The patch looks good except that we should test this expected value.
> > 
> > I could add
> > #if __cplusplus >= 202002L
> > static_assert (b, "move from the function parameter");
> > #else
> > static_assert (!b, "no move from the function parameter");
> > #endif
> > 
> > but that's going to fail for C++20 and above.
> 
> Ah, because treat_lvalue_as_rvalue_p doesn't recognize t as being from the
> current scope in the trailing return type.  But that shouldn't be necessary:
> 
> https://eel.is/c++draft/expr.prim.id.unqual#4.2 says it's move-eligible
> "if the id-expression (possibly parenthesized) is the operand of a
> throw-expression ([expr.throw]), and names an implicitly movable entity that
> belongs to a scope that does not contain the compound-statement of the
> innermost lambda-expression, try-block, or function-try-block (if any) whose
> compound-statement or ctor-initializer contains the throw-expression."
> 
> here there is no enclosing lambda or try, so it seems move-eligible.

...and as a result, 't' will be an xvalue, therefore moveonly(moveonly&&)
should be used, therefore the first overload should be used, which means 'b'
is true.

> > I wonder if this is the
> > second half of the problem in 113789?
> > 
> > I could comment the first static_assert and add a FIXME if that sounds good?
> 
> dg-bogus would be better than commenting it out.

Ok, in this patch the only change I made is:

+#if __cplusplus >= 202002L
+static_assert (b, "move from the function parameter"); // { dg-bogus "" 
"PR113853" { xfail c++20 } }
+#else
+static_assert (!b, "no move from the function parameter");
+#endif
 
> Will you also look into fixing the treat_ bug?  That can be a separate
> patch.

I'd like to.  I opened <https://gcc.gnu.org/PR113853>.

-- >8 --
Here the problem is that we give hard errors while substituting
template parameters during overload resolution of is_throwable
which has an invalid throw in decltype.

The backtrace shows that fn_type_unification -> instantiate_template
-> tsubst* passes complain=0 as expected, but build_throw doesn't
have a complain parameter.  So let's add one.  Also remove a redundant
local variable which I should have removed in my P2266 patch.

There's still one problem for which I opened <https://gcc.gnu.org/PR113853>.
We need to patch up treat_lvalue_as_rvalue_p and remove the dg-bogus.

Thanks to Patrick for notifying me of this PR.  This doesn't fully fix
113789; there I think I'll have to figure our why a candidate wasn't
discarded from the overload set.

gcc/cp/ChangeLog:

* coroutines.cc (coro_rewrite_function_body): Pass tf_warning_or_error
to build_throw.
(morph_fn_to_coro): Likewise.
* cp-tree.

Re: [PATCH v2] c++: make build_throw SFINAE-friendly [PR98388]

2024-02-08 Thread Marek Polacek
On Thu, Feb 08, 2024 at 04:53:45PM -0500, Jason Merrill wrote:
> On 2/8/24 11:51, Marek Polacek wrote:
> > On Thu, Feb 08, 2024 at 08:49:28AM -0500, Patrick Palka wrote:
> > > On Wed, 7 Feb 2024, Marek Polacek wrote:
> > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > Here the problem is that we give hard errors while substituting
> > > > template parameters during overload resolution of is_throwable
> > > > which has an invalid throw in decltype.
> > > > 
> > > > The backtrace shows that fn_type_unification -> instantiate_template
> > > > -> tsubst* passes complain=0 as expected, but build_throw doesn't
> > > > have a complain parameter.  So let's add one.  Also remove a redundant
> > > > local variable which I should have removed in my P2266 patch.
> > > > 
> > > > But there's still something not quite clear to me.  I claim that 'b'
> > > > in the testcase should evaluate to false since the first overload ought
> > > > to have been discarded.  EDG 6.6 agrees, but clang++, msvc, and icx 
> > > > evaluate
> > > > it to true.  Who's right?
> 
> I think it should be true since P1155, which we implement in C++20 mode and
> above (or rather, we implement the sequel P2266); since then we implicitly
> move from the function parameter.
> 
> The patch looks good except that we should test this expected value.

I could add
#if __cplusplus >= 202002L
static_assert (b, "move from the function parameter");
#else
static_assert (!b, "no move from the function parameter");
#endif

but that's going to fail for C++20 and above.  I wonder if this is the
second half of the problem in 113789?

I could comment the first static_assert and add a FIXME if that sounds good?
 
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae69.C
> > @@ -0,0 +1,16 @@
> > +// PR c++/98388
> > +// { dg-do compile { target c++11 } }
> > +
> > +struct moveonly {
> > +moveonly() = default;
> > +moveonly(moveonly&&) = default;
> > +};
> > +
> > +template
> > +constexpr auto is_throwable(T t) -> decltype(throw t, true) {
> > +return true;
> > +}
> > +template
> > +constexpr bool is_throwable(...) { return false; }
> > +
> > +constexpr bool b = is_throwable(moveonly{});

Marek



[PATCH v3] c++: DR2237, cdtor and template-id tweaks [PR107126]

2024-02-08 Thread Marek Polacek
On Wed, Feb 07, 2024 at 05:19:56PM -0500, Jason Merrill wrote:
> On 2/5/24 22:11, Marek Polacek wrote:
> > On Mon, Feb 05, 2024 at 10:14:34AM -0500, Jason Merrill wrote:
> > > On 2/3/24 10:24, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > I'm not certain OPT_Wc__20_extensions is the best thing for something
> > > > from [diff.cpp17]; would you prefer something else?
> > > 
> > > I think it wants its own flag, that is enabled in C++20 or by
> > > -Wc++20-compat.
> > 
> > That seems best.  I called it -Wdeprecated-template-id-cdtor.
> > > > +   if (cxx_dialect >= cxx20)
> > > > + {
> > > > +   if (!cp_parser_simulate_error (parser))
> > > > + pedwarn (tilde_loc, OPT_Wc__20_extensions,
> > > > +  "template-id not allowed for destructor");
> > > > +   return error_mark_node;
> > > > + }
> > > > +   warning_at (tilde_loc, OPT_Wc__20_compat,
> > > > +   "template-id not allowed for destructor in 
> > > > C++20");
> > > 
> > > After a pedwarn we should accept the code, not return error_mark_node.
> > 
> > /facepalm, yes.
> > > I'm also concerned about pedwarn/warnings not guarded by
> > > !cp_parser_uncommited_to_tentative_parse; that often leads to warning 
> > > about
> > > a tentative parse as a declaration that is eventually abandoned in favor 
> > > of
> > > a perfectly fine parse as an expression.
> > 
> > Done.
> > > It would be good for cp_parser_context to add a vec of warnings to emit at
> > > cp_parser_parse_definitely time, and then
> > > cp_parser_pedwarn/cp_parser_warning to fill it...
> > 
> > That would be nice; I don't think we can fix bugs like PR61259 otherwise.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Since my r11-532 changes to implement DR2237, for this test:
> > 
> >template
> >struct S {
> >  S();
> >};
> > 
> > in C++20 we emit the ugly:
> > 
> > q.C:3:8: error: expected unqualified-id before ')' token
> >  3 |   S();
> > 
> > which doesn't explain what the problem is.  This patch improves that
> > diagnostic, reduces the error to a pedwarn, and adds a -Wc++20-compat
> > diagnostic.  We now say:
> > 
> > q.C:3:7: warning: template-id not allowed for constructor in C++20 
> > [-Wdeprecated-template-id-cdtor]
> >  3 |   S();
> > q.C:3:7: note: remove the '< >'
> > 
> > This patch does *not* fix
> > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
> > where the C++20 diagnostic is missing altogether.
> > 
> > -Wc++20-compat triggered in libitm/; I sent a patch for that.
> > 
> > DR 2237
> > PR c++/107126
> > PR c++/97202
> > 
> > gcc/c-family/ChangeLog:
> > 
> > * c-opts.cc (c_common_post_options): In C++20 or with -Wc++20-compat,
> > turn on -Wdeprecated-template-id-cdtor.
> > * c.opt (Wdeprecated-template-id-cdtor): New.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * parser.cc (cp_parser_unqualified_id): Downgrade the DR2237 error to
> > a pedwarn.
> > (cp_parser_constructor_declarator_p): Likewise.
> > 
> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > index 3748ccd49ff..473eaf4f1f7 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -6717,12 +6717,17 @@ cp_parser_unqualified_id (cp_parser* parser,
> > /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
> >declarator-id of a constructor or destructor.  */
> > -   if (token->type == CPP_TEMPLATE_ID && declarator_p
> > -   && cxx_dialect >= cxx20)
> > +   if (token->type == CPP_TEMPLATE_ID
> > +   && declarator_p
> > +   && !cp_parser_uncommitted_to_tentative_parse_p (parser)
> > +   && !cp_parser_simulate_error (parser))
> 
> Calling both _uncommitted_ and _simulate_ here is redundant since _simulate_
> checks _uncommitted_; since you check _uncommitted_ first, _simulate_ will
> never do anything.

Oops, pardon me.
 
> And checking either of them before cxx_dialect seems wrong; we don't want
> _simulate_ in pre-C++20 mode where it isn't an error, but we do want
&

[PATCH v2] c++: make build_throw SFINAE-friendly [PR98388]

2024-02-08 Thread Marek Polacek
On Thu, Feb 08, 2024 at 08:49:28AM -0500, Patrick Palka wrote:
> On Wed, 7 Feb 2024, Marek Polacek wrote:
> 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Here the problem is that we give hard errors while substituting
> > template parameters during overload resolution of is_throwable
> > which has an invalid throw in decltype.
> > 
> > The backtrace shows that fn_type_unification -> instantiate_template
> > -> tsubst* passes complain=0 as expected, but build_throw doesn't
> > have a complain parameter.  So let's add one.  Also remove a redundant
> > local variable which I should have removed in my P2266 patch.
> > 
> > But there's still something not quite clear to me.  I claim that 'b'
> > in the testcase should evaluate to false since the first overload ought
> > to have been discarded.  EDG 6.6 agrees, but clang++, msvc, and icx evaluate
> > it to true.  Who's right?
> > 
> > Thanks to Patrick for notifying me of this PR.  This doesn't fully fix
> > 113789; there I think I'll have to figure our why a candidate wasn't
> > discarded from the overload set.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * coroutines.cc (coro_rewrite_function_body): Pass tf_warning_or_error
> > to build_throw.
> > (morph_fn_to_coro): Likewise.
> > * cp-tree.h (build_throw): Adjust.
> > * except.cc (expand_end_catch_block): Pass tf_warning_or_error to
> > build_throw.
> > (build_throw): Add a tsubst_flags_t parameter.  Use it.  Remove
> > redundant variable.  Guard an inform call.
> > * parser.cc (cp_parser_throw_expression): Pass tf_warning_or_error
> > to build_throw.
> > * pt.cc (tsubst_expr) : Pass complain to build_throw.
> > 
> > libcc1/ChangeLog:
> > 
> > * libcp1plugin.cc (plugin_build_unary_expr): Pass tf_error to
> > build_throw.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/sfinae69.C: New test.
> > ---
> >  gcc/cp/coroutines.cc  |  4 ++--
> >  gcc/cp/cp-tree.h  |  3 ++-
> >  gcc/cp/except.cc  | 31 +++
> >  gcc/cp/parser.cc  |  2 +-
> >  gcc/cp/pt.cc  |  2 +-
> >  gcc/testsuite/g++.dg/cpp0x/sfinae69.C | 16 ++
> >  libcc1/libcp1plugin.cc|  4 ++--
> >  7 files changed, 37 insertions(+), 25 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae69.C
> > 
> > diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
> > index 3194c911e8c..9b037edbd14 100644
> > --- a/gcc/cp/coroutines.cc
> > +++ b/gcc/cp/coroutines.cc
> > @@ -4246,7 +4246,7 @@ coro_rewrite_function_body (location_t fn_start, tree 
> > fnbody, tree orig,
> >   boolean_type_node, i_a_r_c);
> >finish_if_stmt_cond (not_iarc, not_iarc_if);
> >/* If the initial await resume called value is false, rethrow...  */
> > -  tree rethrow = build_throw (fn_start, NULL_TREE);
> > +  tree rethrow = build_throw (fn_start, NULL_TREE, 
> > tf_warning_or_error);
> >suppress_warning (rethrow);
> >finish_expr_stmt (rethrow);
> >finish_then_clause (not_iarc_if);
> > @@ -5151,7 +5151,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
> > *destroyer)
> >tree del_coro_fr = coro_get_frame_dtor (coro_fp, orig, frame_size,
> >   promise_type, fn_start);
> >finish_expr_stmt (del_coro_fr);
> > -  tree rethrow = build_throw (fn_start, NULL_TREE);
> > +  tree rethrow = build_throw (fn_start, NULL_TREE, 
> > tf_warning_or_error);
> >suppress_warning (rethrow);
> >finish_expr_stmt (rethrow);
> >finish_handler (handler);
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 969c7239c97..334c11396c2 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -7185,7 +7185,8 @@ extern void init_exception_processing (void);
> >  extern tree expand_start_catch_block   (tree);
> >  extern void expand_end_catch_block (void);
> >  extern tree build_exc_ptr  (void);
> > -extern tree build_throw(location_t, tree);
> > +extern tree build_throw(location_t, tree,
> > +tsubst_flags_t);
> >  extern int nothrow_libfn_p (const_tree

Re: [PATCH] c++: Don't ICE for unknown parameter to constexpr'd switch-statement, PR113545

2024-02-08 Thread Marek Polacek
On Thu, Feb 08, 2024 at 05:07:21PM +0100, Hans-Peter Nilsson wrote:
> > Date: Thu, 8 Feb 2024 10:44:31 -0500
> > From: Marek Polacek 
> > Cc: ja...@redhat.com, gcc-patches@gcc.gnu.org
> > Content-Type: text/plain; charset=us-ascii
> > Content-Disposition: inline
> > 
> > On Thu, Feb 08, 2024 at 04:40:40PM +0100, Hans-Peter Nilsson wrote:
> > > > Date: Wed, 7 Feb 2024 21:11:59 -0500
> > > > From: Marek Polacek 
> > > 
> > > > On Wed, Feb 07, 2024 at 04:32:57PM -0500, Jason Merrill wrote:
> > > > > On 2/6/24 19:23, Hans-Peter Nilsson wrote:
> > > > > > > Date: Mon, 22 Jan 2024 14:33:59 -0500
> > > > > > > From: Marek Polacek 
> > > > > > 
> > > > > > > On Mon, Jan 22, 2024 at 06:02:32PM +0100, Hans-Peter Nilsson 
> > > > > > > wrote:
> > > > > > > > I don't really know whether this is the right way to treat
> > > > > > > > CONVERT_EXPR as below, but...  Regtested native
> > > > > > > > x86_64-linux-gnu.  Ok to commit?
> > > > > > > 
> > > > > > > Thanks for taking a look at this problem.
> > > > > > 
> > > > > > Thanks for the initial review.
> > > 
> > > > > Incidentally, these testcases seem to require C++14; you can't have a 
> > > > > switch
> > > > > in a constexpr function in C++11.
> > > > > 
> > > > > Jason
> > > > 
> > > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > > index 2ebb1470dd5..fa346fe01c9 100644
> > > > > --- a/gcc/cp/constexpr.cc
> > > > > +++ b/gcc/cp/constexpr.cc
> > > > > @@ -7106,6 +7106,16 @@ cxx_eval_switch_expr (const constexpr_ctx 
> > > > > *ctx, tree t,
> > > > >cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue,
> > > > >  non_constant_p, overflow_p);
> > > > >VERIFY_CONSTANT (cond);
> > > > > +  if (TREE_CODE (cond) != INTEGER_CST)
> > > > > +{
> > > > > +  /* If the condition doesn't reduce to an INTEGER_CST it isn't 
> > > > > a usable
> > > > > +  switch condition even if it's constant enough for other things
> > > > > +  (c++/113545).  */
> > > > > +  gcc_checking_assert (ctx->quiet);
> > > > > +  *non_constant_p = true;
> > > > > +  return t;
> > > > > +}
> > > > > +
> > > > >*jump_target = cond;
> > > > >  
> > > > >tree body
> > > > 
> > > > The patch makes sense to me, although I'm afraid that losing the
> > > > REINTERPRET_CAST_P flag will cause other issues.
> > > > 
> > > > HP, sorry that I never got back to you.  I would be more than happy to
> > > > take the patch above, add some tests and test/bootstrap it, unless you
> > > > want to do that yourself.
> > > > 
> > > > Thanks & sorry again,
> > > 
> > > No worries, feel very welcome to deal with handling the
> > > actual fix.  Also, you're better prepared than me, when it
> > > comes to dealing with any possible fallout. :)
> > > 
> > > I'll send an updated version of the test-cases, moving them
> > > to the C++14 test directory (cpp1y, right?) and qualify them
> > > as c++14 instead, as Jason pointed out.
> > 
> > Right, cpp1y is c++14.  Note that we wouldn't push the tests separately
> > to the patch itself, unless it's something that already works.  Thanks,
> > 
> > Marek
> 
> But, the tests work.  They passes as-is, as they track the
> ICE, but will XPASS (that part) once a fix is committed (at
> which time: "I checked that these behave as expected (xfail
> as ICE properly) without the previosly posted patch to
> cp/constexpr.cc and XPASS with it applied."

I'm confused; are you planning to use the dg-ice directive I invented
some years ago?  I wanted to encourage people to add tests for
old unfixed PRs so that if a fix fixes an (un)related older problem, we
know it before pushing the patch.
(I don't think an XFAIL will work for an ICE -- that prompted dg-ice.)
 
> Once the fix works, the xfail for the ICE should be removed.
> (Hm, better comment on the patches in a reply to that message. :)
> 
> The point is that for this type of bug it's useful to have a
> test-case tracking it, before a fix is committed.

I'd tend to agree but here we already have a fix, so one commit seems
better than multiple commits.  But if that's what you want to do, I
guess I'm not going to stand in your way.

Marek



Re: [PATCH] c++: Don't ICE for unknown parameter to constexpr'd switch-statement, PR113545

2024-02-08 Thread Marek Polacek
On Thu, Feb 08, 2024 at 04:40:40PM +0100, Hans-Peter Nilsson wrote:
> > Date: Wed, 7 Feb 2024 21:11:59 -0500
> > From: Marek Polacek 
> 
> > On Wed, Feb 07, 2024 at 04:32:57PM -0500, Jason Merrill wrote:
> > > On 2/6/24 19:23, Hans-Peter Nilsson wrote:
> > > > > Date: Mon, 22 Jan 2024 14:33:59 -0500
> > > > > From: Marek Polacek 
> > > > 
> > > > > On Mon, Jan 22, 2024 at 06:02:32PM +0100, Hans-Peter Nilsson wrote:
> > > > > > I don't really know whether this is the right way to treat
> > > > > > CONVERT_EXPR as below, but...  Regtested native
> > > > > > x86_64-linux-gnu.  Ok to commit?
> > > > > 
> > > > > Thanks for taking a look at this problem.
> > > > 
> > > > Thanks for the initial review.
> 
> > > Incidentally, these testcases seem to require C++14; you can't have a 
> > > switch
> > > in a constexpr function in C++11.
> > > 
> > > Jason
> > 
> > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > index 2ebb1470dd5..fa346fe01c9 100644
> > > --- a/gcc/cp/constexpr.cc
> > > +++ b/gcc/cp/constexpr.cc
> > > @@ -7106,6 +7106,16 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, 
> > > tree t,
> > >cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue,
> > >  non_constant_p, overflow_p);
> > >VERIFY_CONSTANT (cond);
> > > +  if (TREE_CODE (cond) != INTEGER_CST)
> > > +{
> > > +  /* If the condition doesn't reduce to an INTEGER_CST it isn't a 
> > > usable
> > > +  switch condition even if it's constant enough for other things
> > > +  (c++/113545).  */
> > > +  gcc_checking_assert (ctx->quiet);
> > > +  *non_constant_p = true;
> > > +  return t;
> > > +}
> > > +
> > >*jump_target = cond;
> > >  
> > >tree body
> > 
> > The patch makes sense to me, although I'm afraid that losing the
> > REINTERPRET_CAST_P flag will cause other issues.
> > 
> > HP, sorry that I never got back to you.  I would be more than happy to
> > take the patch above, add some tests and test/bootstrap it, unless you
> > want to do that yourself.
> > 
> > Thanks & sorry again,
> 
> No worries, feel very welcome to deal with handling the
> actual fix.  Also, you're better prepared than me, when it
> comes to dealing with any possible fallout. :)
> 
> I'll send an updated version of the test-cases, moving them
> to the C++14 test directory (cpp1y, right?) and qualify them
> as c++14 instead, as Jason pointed out.

Right, cpp1y is c++14.  Note that we wouldn't push the tests separately
to the patch itself, unless it's something that already works.  Thanks,

Marek



Re: [PATCH] c++: Don't ICE for unknown parameter to constexpr'd switch-statement, PR113545

2024-02-07 Thread Marek Polacek
On Wed, Feb 07, 2024 at 04:32:57PM -0500, Jason Merrill wrote:
> On 2/6/24 19:23, Hans-Peter Nilsson wrote:
> > > Date: Mon, 22 Jan 2024 14:33:59 -0500
> > > From: Marek Polacek 
> > 
> > > On Mon, Jan 22, 2024 at 06:02:32PM +0100, Hans-Peter Nilsson wrote:
> > > > I don't really know whether this is the right way to treat
> > > > CONVERT_EXPR as below, but...  Regtested native
> > > > x86_64-linux-gnu.  Ok to commit?
> > > 
> > > Thanks for taking a look at this problem.
> > 
> > Thanks for the initial review.
> > 
> > > > brgds, H-P
> > > > 
> > > > -- >8 --
> > > > That gcc_unreachable at the default-label seems to be over
> > > > the top.  It seems more correct to just say "that's not
> > > > constant" to whatever's not known (to be constant), when
> > > > looking for matches in switch-statements.
> > > 
> > > Unfortunately this doesn't seem correct to me; I don't think we
> > > should have gotten that far.  It appears that we lose track of
> > > the reinterpret_cast, which is not allowed in a constant expression:
> > > <http://eel.is/c++draft/expr.const#5.15>.
> > > 
> > > cp_convert -> ... -> convert_to_integer_1 gives us a CONVERT_EXPR
> > > but we only set REINTERPRET_CAST_P on NOP_EXPRs:
> > > 
> > >expr = cp_convert (type, expr, complain);
> > >if (TREE_CODE (expr) == NOP_EXPR)
> > >  /* Mark any nop_expr that created as a reintepret_cast.  */
> > >  REINTERPRET_CAST_P (expr) = true;
> > > 
> > > so when evaluating baz we get (long unsigned int) , which
> > > passes verify_constant.
> > > I don't have a good suggestion yet, sorry.
> > 
> > But, with this patch, we're letting the non-constant case
> > take the same path and failing for the same reason, albeit
> > much later than desired, for the switch code as for the
> > if-chain code.  Isn't that better than the current ICE?
> > 
> > I mean, if there's a risk of accepts-invalid (like, some
> > non-constant case incorrectly "constexpr'd"), then that risk
> > is as already there, for the if-chain case.
> > 
> > Anyway, this is a bit too late in the release season and
> > isn't a regression, thus I can't argue for it being a
> > suitable stop-gap measure...
> > 
> > I'm unassigning myself from the PR as I have no clue how to
> > fix the actual non-constexpr-operand-seen-too-late bug.
> 
> I think it would be better to check in cxx_eval_switch_expr that the
> condition is an INTEGER_CST, since VERIFY_CONSTANT isn't specific enough in
> this case, like the attached:
> 
> > Though, I'm asking again; any clue regarding:
> > 
> > "I briefly considered one of the cpp[0-9a-z]* subdirectories
> > but found no rule.
> > 
> > Isn't constexpr c++11 and therefor cpp0x isn't a good match
> > (contrary to the many constexpr tests therein)?
> > 
> > What *is* the actual rule for putting a test in
> > g++.dg/cpp0x, cpp1x and cpp1y (et al)?
> > (I STFW but found nothing.)"
> 
> C++11 was called C++0x until it was actually done, a couple of years later
> than expected.  Since that experience the C++ committee has moved to
> time-based rather than feature-based releases...
> 
> Incidentally, these testcases seem to require C++14; you can't have a switch
> in a constexpr function in C++11.
> 
> Jason

> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 2ebb1470dd5..fa346fe01c9 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -7106,6 +7106,16 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
>cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue,
>  non_constant_p, overflow_p);
>VERIFY_CONSTANT (cond);
> +  if (TREE_CODE (cond) != INTEGER_CST)
> +{
> +  /* If the condition doesn't reduce to an INTEGER_CST it isn't a usable
> +  switch condition even if it's constant enough for other things
> +  (c++/113545).  */
> +  gcc_checking_assert (ctx->quiet);
> +  *non_constant_p = true;
> +  return t;
> +}
> +
>*jump_target = cond;
>  
>tree body

The patch makes sense to me, although I'm afraid that losing the
REINTERPRET_CAST_P flag will cause other issues.

HP, sorry that I never got back to you.  I would be more than happy to
take the patch above, add some tests and test/bootstrap it, unless you
want to do that yourself.

Thanks & sorry again,

Marek



[PATCH] c++: make build_throw SFINAE-friendly [PR98388]

2024-02-07 Thread Marek Polacek
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here the problem is that we give hard errors while substituting
template parameters during overload resolution of is_throwable
which has an invalid throw in decltype.

The backtrace shows that fn_type_unification -> instantiate_template
-> tsubst* passes complain=0 as expected, but build_throw doesn't
have a complain parameter.  So let's add one.  Also remove a redundant
local variable which I should have removed in my P2266 patch.

But there's still something not quite clear to me.  I claim that 'b'
in the testcase should evaluate to false since the first overload ought
to have been discarded.  EDG 6.6 agrees, but clang++, msvc, and icx evaluate
it to true.  Who's right?

Thanks to Patrick for notifying me of this PR.  This doesn't fully fix
113789; there I think I'll have to figure our why a candidate wasn't
discarded from the overload set.

gcc/cp/ChangeLog:

* coroutines.cc (coro_rewrite_function_body): Pass tf_warning_or_error
to build_throw.
(morph_fn_to_coro): Likewise.
* cp-tree.h (build_throw): Adjust.
* except.cc (expand_end_catch_block): Pass tf_warning_or_error to
build_throw.
(build_throw): Add a tsubst_flags_t parameter.  Use it.  Remove
redundant variable.  Guard an inform call.
* parser.cc (cp_parser_throw_expression): Pass tf_warning_or_error
to build_throw.
* pt.cc (tsubst_expr) : Pass complain to build_throw.

libcc1/ChangeLog:

* libcp1plugin.cc (plugin_build_unary_expr): Pass tf_error to
build_throw.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/sfinae69.C: New test.
---
 gcc/cp/coroutines.cc  |  4 ++--
 gcc/cp/cp-tree.h  |  3 ++-
 gcc/cp/except.cc  | 31 +++
 gcc/cp/parser.cc  |  2 +-
 gcc/cp/pt.cc  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/sfinae69.C | 16 ++
 libcc1/libcp1plugin.cc|  4 ++--
 7 files changed, 37 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae69.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 3194c911e8c..9b037edbd14 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4246,7 +4246,7 @@ coro_rewrite_function_body (location_t fn_start, tree 
fnbody, tree orig,
  boolean_type_node, i_a_r_c);
   finish_if_stmt_cond (not_iarc, not_iarc_if);
   /* If the initial await resume called value is false, rethrow...  */
-  tree rethrow = build_throw (fn_start, NULL_TREE);
+  tree rethrow = build_throw (fn_start, NULL_TREE, tf_warning_or_error);
   suppress_warning (rethrow);
   finish_expr_stmt (rethrow);
   finish_then_clause (not_iarc_if);
@@ -5151,7 +5151,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
   tree del_coro_fr = coro_get_frame_dtor (coro_fp, orig, frame_size,
  promise_type, fn_start);
   finish_expr_stmt (del_coro_fr);
-  tree rethrow = build_throw (fn_start, NULL_TREE);
+  tree rethrow = build_throw (fn_start, NULL_TREE, tf_warning_or_error);
   suppress_warning (rethrow);
   finish_expr_stmt (rethrow);
   finish_handler (handler);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 969c7239c97..334c11396c2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7185,7 +7185,8 @@ extern void init_exception_processing (void);
 extern tree expand_start_catch_block   (tree);
 extern void expand_end_catch_block (void);
 extern tree build_exc_ptr  (void);
-extern tree build_throw(location_t, tree);
+extern tree build_throw(location_t, tree,
+tsubst_flags_t);
 extern int nothrow_libfn_p (const_tree);
 extern void check_handlers (tree);
 extern tree finish_noexcept_expr   (tree, tsubst_flags_t);
diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index d17a57d3fbc..ed704b6c28a 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -486,7 +486,8 @@ expand_end_catch_block (void)
  || DECL_DESTRUCTOR_P (current_function_decl))
   && !in_nested_catch ())
 {
-  tree rethrow = build_throw (input_location, NULL_TREE);
+  tree rethrow = build_throw (input_location, NULL_TREE,
+ tf_warning_or_error);
   /* Disable all warnings for the generated rethrow statement.  */
   suppress_warning (rethrow);
   finish_expr_stmt (rethrow);
@@ -607,7 +608,7 @@ wrap_cleanups_r (tree *tp, int *walk_subtrees, void * 
/*data*/)
 /* Build a throw expression.  */
 
 tree
-build_throw (location_t loc, tree exp)
+build_throw (location_t loc, tree exp, tsubst_flags_t complain)
 {
   if 

Re: [wwwdocs] Add 2 more C++26 core papers

2024-02-07 Thread Marek Polacek
On Wed, Feb 07, 2024 at 10:58:18AM +0100, Jakub Jelinek wrote:
> Hi!
> 
> cppreference has 2 more Kona papers listed and it seems eel.is/c++draft/
> has those papers incorporated.
> 
> Ok for wwwdocs?

Patch is OK.  W3 validates fine too.  Thanks,
 
> diff --git a/htdocs/projects/cxx-status.html b/htdocs/projects/cxx-status.html
> index c265edc0..65030980 100644
> --- a/htdocs/projects/cxx-status.html
> +++ b/htdocs/projects/cxx-status.html
> @@ -117,12 +117,24 @@
> __cpp_placeholder_variables >= 202306L 
>  
>  
> +
> +   Pack indexing 
> +   https://wg21.link/P2662R3;>P2662R3
> +href="https://gcc.gnu.org/PR113798;>No
> +   __cpp_pack_indexing >= 202311L 
> +
>  
> Removing deprecated arithmetic conversion on enumerations 
>https://wg21.link/P2864R2;>P2864R2 ( href="./cxx-dr-status.html">DR) 
> 14
> 
>  
> +
> +   Template parameter initialization 
> +   https://wg21.link/P2308R1;>P2308R1 ( href="./cxx-dr-status.html">DR) 
> +href="https://gcc.gnu.org/PR113800;>No
> +   
> +
>  

Re: [PATCH] c++: Disallow this specifier except for parameter declarations [PR113788]

2024-02-06 Thread Marek Polacek
On Tue, Feb 06, 2024 at 09:37:44PM +0100, Jakub Jelinek wrote:
> Hi!
> 
> The deducing this patchset added parsing of this specifier to
> cp_parser_decl_specifier_seq unconditionally, but in the C++ grammar
> this[opt] only appears in the parameter-declaration non-terminal, so
> rather than checking in all the callers of cp_parser_decl_specifier_seq
> except for cp_parser_parameter_declaration that this specifier didn't
> appear I think it is far easier and closer to what the standard says
> to only parse this specifier when called from
> cp_parser_parameter_declaration.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

FWIW, the patch looks good to me.

> 2024-02-06  Jakub Jelinek  
> 
>   PR c++/113788
>   * parser.cc (CP_PARSER_FLAGS_PARAMETER): New enumerator.
>   (cp_parser_decl_specifier_seq): Parse RID_THIS only if
>   CP_PARSER_FLAGS_PARAMETER is set in flags.
>   (cp_parser_parameter_declaration): Or in CP_PARSER_FLAGS_PARAMETER
>   when calling cp_parser_decl_specifier_seq.
> 
>   * g++.dg/parse/pr113788.C: New test.
> 
> --- gcc/cp/parser.cc.jj   2024-01-17 10:34:45.337660930 +0100
> +++ gcc/cp/parser.cc  2024-02-06 18:31:35.587193903 +0100
> @@ -2088,7 +2088,9 @@ enum
>/* When parsing of the noexcept-specifier should be delayed.  */
>CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40,
>/* When parsing a consteval declarator.  */
> -  CP_PARSER_FLAGS_CONSTEVAL = 0x80
> +  CP_PARSER_FLAGS_CONSTEVAL = 0x80,
> +  /* When parsing a parameter declaration.  */
> +  CP_PARSER_FLAGS_PARAMETER = 0x100
>  };
>  
>  /* This type is used for parameters and variables which hold
> @@ -16342,7 +16344,7 @@ cp_parser_decl_specifier_seq (cp_parser*
>/* Special case for "this" specifier, indicating a parm is an xobj 
> parm.
>The "this" specifier must be the first specifier in the declaration,
>after any attributes.  */
> -  if (token->keyword == RID_THIS)
> +  if (token->keyword == RID_THIS && (flags & CP_PARSER_FLAGS_PARAMETER))
>   {
> cp_lexer_consume_token (parser->lexer);
> if (token != first_specifier)
> @@ -25607,7 +25609,7 @@ cp_parser_parameter_declaration (cp_pars
>/* Parse the declaration-specifiers.  */
>cp_token *decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
>cp_parser_decl_specifier_seq (parser,
> - flags,
> + flags | CP_PARSER_FLAGS_PARAMETER,
>   _specifiers,
>   _class_or_enum);
>  
> --- gcc/testsuite/g++.dg/parse/pr113788.C.jj  2024-02-06 18:40:29.553791028 
> +0100
> +++ gcc/testsuite/g++.dg/parse/pr113788.C 2024-02-06 18:41:23.326045703 
> +0100
> @@ -0,0 +1,20 @@
> +// PR c++/113788
> +// { dg-do compile { target c++11 } }
> +
> +struct S { int a, b; };
> +struct U {
> +  void foo () { this int g = 1; }// { dg-error "expected ';' before 
> 'int'" }
> +};
> +this auto h = 1; // { dg-error "expected unqualified-id 
> before 'this'" }
> +
> +int
> +main ()
> +{
> +  S s = { 1, 2 };
> +  short t[3] = { 3, 4, 5 };
> +  this auto &[a, b] = s; // { dg-error "invalid use of 'this' in 
> non-member function" }
> +  this auto &[c, d, e] = t;  // { dg-error "invalid use of 'this' in 
> non-member function" }
> +  this int f = 1;// { dg-error "invalid use of 'this' in 
> non-member function" }
> +  for (this auto  : t) // { dg-error "invalid use of 'this' in 
> non-member function" }
> +;// { dg-error "expected" }
> +}// { dg-error "expected" }
> 
>   Jakub
> 

Marek



[pushed] c++: add fixed test [PR94231]

2024-02-06 Thread Marek Polacek
Tested x86_64-pc-linux-gnu, applying to trunk.

-- >8 --
I was suprised to find out that r14-8759 fixed this accepts-invalid.

clang version 17.0.6 rejects the test as well; clang version 19.0.0git
crashes for which I opened
.

PR c++/94231

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/deleted17.C: New test.
---
 gcc/testsuite/g++.dg/cpp0x/deleted17.C | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/deleted17.C

diff --git a/gcc/testsuite/g++.dg/cpp0x/deleted17.C 
b/gcc/testsuite/g++.dg/cpp0x/deleted17.C
new file mode 100644
index 000..3bebe881165
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/deleted17.C
@@ -0,0 +1,20 @@
+// PR c++/94231
+// { dg-do compile { target c++11 } }
+
+struct F {F(F&&)=delete;};
+
+template
+struct M {
+  F f;
+  M();
+  M(const M&);
+  M(M&&);
+};
+
+template
+M::M(M&&)=default; // { dg-error "use of deleted function" }
+
+M<> f() {
+  M<> m;
+  return m;
+}

base-commit: 8ec2f1922a14ee3636840d1ebc1c40d26e6043a4
-- 
2.43.0



[PATCH] c++: further DR 2237 fix [PR97202]

2024-02-05 Thread Marek Polacek
Technically, not a regression.  But it's such a simple fix for such
rare code that I think we should put it in now and be done with
DR 2237.

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

-- >8 --
With a redundant inline specifier like this:

  template struct S : Base {
inline S() {}
  };

we don't detect the simple-template-id as the declarator-id of the
constructor.  The problem is that I check for CPP_TEMPLATE_ID too early,
at a point at which cp_parser_template_id may not have been called yet.
So let's check for it at the end of the function, after the tentative
parse and rollback.

PR c++/97202

gcc/cp/ChangeLog:

* parser.cc (cp_parser_constructor_declarator_p): Check CPP_TEMPLATE_ID
at the end of the function.

gcc/testsuite/ChangeLog:

* g++.dg/DRs/dr2237-5.C: New test.
---
 gcc/cp/parser.cc| 4 +---
 gcc/testsuite/g++.dg/DRs/dr2237-5.C | 7 +++
 2 files changed, 8 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-5.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 473eaf4f1f7..8befd26feab 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -32337,8 +32337,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, 
cp_parser_flags flags,
   && next_token->type != CPP_TEMPLATE_ID)
 return false;
 
-  const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
-
   /* Parse tentatively; we are going to roll back all of the tokens
  consumed here.  */
   cp_parser_parse_tentatively (parser);
@@ -32558,7 +32556,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, 
cp_parser_flags flags,
   /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the
  declarator-id of a constructor or destructor.  */
   if (constructor_p
-  && saw_template_id
+  && cp_lexer_peek_token (parser->lexer)->type == CPP_TEMPLATE_ID
   && !cp_parser_uncommitted_to_tentative_parse_p (parser))
 {
   auto_diagnostic_group d;
diff --git a/gcc/testsuite/g++.dg/DRs/dr2237-5.C 
b/gcc/testsuite/g++.dg/DRs/dr2237-5.C
new file mode 100644
index 000..fd51968f7e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2237-5.C
@@ -0,0 +1,7 @@
+// PR c++/97202
+// { dg-options "" }
+
+template struct S : Base {
+  inline S() {} // { dg-warning "template-id not allowed for 
constructor" "" { target c++20 } }
+  inline ~S() {} // { dg-warning "template-id not allowed for 
destructor" "" { target c++20 } }
+};

base-commit: c5d34912ad576be1ef19be92f7eabde54b9089eb
prerequisite-patch-id: 2987a013eda8bc2ca9d8373eedac82067a654a5c
-- 
2.43.0



  1   2   3   4   5   6   7   8   9   10   >