[PATCH v7] c++: Move consteval folding to cp_fold_r

2023-09-18 Thread Marek Polacek via Gcc-patches
On Sat, Sep 16, 2023 at 04:22:44PM -0400, Jason Merrill wrote:
> On 9/15/23 16:32, Marek Polacek wrote:
> > On Fri, Sep 15, 2023 at 02:08:46PM -0400, Jason Merrill wrote:
> > > On 9/13/23 20:02, Marek Polacek wrote:
> > > > On Wed, Sep 13, 2023 at 05:57:47PM -0400, Jason Merrill wrote:
> > > > > On 9/13/23 16:56, Marek Polacek wrote:
> > > > > > On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:
> > > > > > > On 9/8/23 14:24, Marek Polacek wrote:
> > > > > > > > +  switch (TREE_CODE (stmt))
> > > > > > > > +{
> > > > > > > > +/* Unfortunately we must handle code like
> > > > > > > > +false ? bar () : 42
> > > > > > > > +   where we have to check bar too.  */
> > > > > > > > +case COND_EXPR:
> > > > > > > > +  if (cp_fold_immediate_r (_OPERAND (stmt, 1), 
> > > > > > > > walk_subtrees, data))
> > > > > > > > +   return error_mark_node;
> > > > > > > > +  if (TREE_OPERAND (stmt, 2)
> > > > > > > > + && cp_fold_immediate_r (_OPERAND (stmt, 2), 
> > > > > > > > walk_subtrees, data))
> > > > > > > > +   return error_mark_node;
> > > > > > > 
> > > > > > > Is this necessary?  Doesn't walk_tree already walk into the arms 
> > > > > > > of
> > > > > > > COND_EXPR?
> > > > > > 
> > > > > > Unfortunately yes.  The cp_fold call in cp_fold_r could fold the ?: 
> > > > > > into
> > > > > > a constant before we see it here.  I've added a comment saying just 
> > > > > > that.
> > > > > 
> > > > > Ah.  But in that case I guess we need to walk into the arms, not just 
> > > > > check
> > > > > the top-level expression in them.
> > > > Arg, of course.  I was fooled into thinking that it would recurse, but
> > > > you're right.  Fixed by using cp_walk_tree as I intended.  Tested in
> > > > consteval34.C.
> > > > 
> > > > > But maybe cp_fold_r should do that before the cp_fold, instead of this
> > > > > function?
> > > > 
> > > > I...am not sure how that would be better than what I did.
> > > 
> > > Callers of cp_fold_immediate don't need this because cp_fold_r isn't
> > > involved, so it isn't folding anything.
> > 
> > This is true.
> > > cp_fold_r can walk the arms with cp_fold_r and then clear *walk_subtrees 
> > > to
> > > avoid walking the arms again normally.
> > 
> > I didn't think we wanted to do everything cp_fold_r does even in dead
> > branches, but ok.
> 
> Ah, that's a good point.  With the recursive walk in cp_fold_immediate_r, I
> suppose we could suppress it when called from cp_fold_immediate with a new
> fold_flag?  That would still allow for cp_walk_tree_without_duplicates.

Yeah, I like that.  Done here.
 
> Incidentally, I notice you check for null op2 of COND_EXPR, should probably
> also check op1.

Added, though I'm not sure it's necessary.  I've added some more tests to
consteval34.C to also check for a ?: c.

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

-- >8 --
In the review of P2564:

it turned out that in order to correctly handle an example in the paper,
we should stop doing immediate evaluation in build_over_call and
bot_replace, and instead do it in cp_fold_r.  This patch does that.

Another benefit is that this is a pretty significant simplification, at
least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
doesn't compile yet).

The main drawback seems to be that cp_fold_r doesn't process
uninstantiated templates.  We still have to handle things like
"false ? foo () : 1".  To that end, I've added cp_fold_immediate, called
on dead branches in cxx_eval_conditional_expression.

You'll see that I've reintroduced ADDR_EXPR_DENOTES_CALL_P here.  This
is to detect

  *()) ()
  (s.*::foo) ()

which were deemed ill-formed.

gcc/cp/ChangeLog:

* call.cc (build_over_call): Set ADDR_EXPR_DENOTES_CALL_P.  Don't handle
immediate_invocation_p here.
* constexpr.cc (cxx_eval_call_expression): Use mce_true for
DECL_IMMEDIATE_FUNCTION_P.
(cxx_eval_conditional_expression): Call cp_fold_immediate.
* cp-gimplify.cc (enum fold_flags): Add ff_fold_immediate.
(maybe_replace_decl): Make static.
(cp_fold_r): Expand immediate invocations.
(cp_fold_immediate_r): New.
(cp_fold_immediate): New.
* cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.
(cp_fold_immediate): Declare.
* tree.cc (bot_replace): Don't handle immediate invocations here.

libstdc++-v3/ChangeLog:

* testsuite/20_util/allocator/105975.cc: Add dg-error.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/consteval-if2.C: Add xfail.
* g++.dg/cpp2a/consteval-memfn1.C: Adjust.
* g++.dg/cpp2a/consteval11.C: Remove dg-message.
* g++.dg/cpp2a/consteval3.C: Remove dg-message and dg-error.
* g++.dg/cpp2a/consteval9.C: Remove dg-message.
* g++.dg/cpp2a/consteval32.C: New test.
* g++.dg/cpp2a/consteval33.C: New test.
* g++.dg/cpp2a/consteval34.C: 

[PATCH v6] c++: Move consteval folding to cp_fold_r

2023-09-15 Thread Marek Polacek via Gcc-patches
On Fri, Sep 15, 2023 at 02:08:46PM -0400, Jason Merrill wrote:
> On 9/13/23 20:02, Marek Polacek wrote:
> > On Wed, Sep 13, 2023 at 05:57:47PM -0400, Jason Merrill wrote:
> > > On 9/13/23 16:56, Marek Polacek wrote:
> > > > On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:
> > > > > On 9/8/23 14:24, Marek Polacek wrote:
> > > > > > +  switch (TREE_CODE (stmt))
> > > > > > +{
> > > > > > +/* Unfortunately we must handle code like
> > > > > > +false ? bar () : 42
> > > > > > +   where we have to check bar too.  */
> > > > > > +case COND_EXPR:
> > > > > > +  if (cp_fold_immediate_r (_OPERAND (stmt, 1), 
> > > > > > walk_subtrees, data))
> > > > > > +   return error_mark_node;
> > > > > > +  if (TREE_OPERAND (stmt, 2)
> > > > > > + && cp_fold_immediate_r (_OPERAND (stmt, 2), 
> > > > > > walk_subtrees, data))
> > > > > > +   return error_mark_node;
> > > > > 
> > > > > Is this necessary?  Doesn't walk_tree already walk into the arms of
> > > > > COND_EXPR?
> > > > 
> > > > Unfortunately yes.  The cp_fold call in cp_fold_r could fold the ?: into
> > > > a constant before we see it here.  I've added a comment saying just 
> > > > that.
> > > 
> > > Ah.  But in that case I guess we need to walk into the arms, not just 
> > > check
> > > the top-level expression in them.
> > Arg, of course.  I was fooled into thinking that it would recurse, but
> > you're right.  Fixed by using cp_walk_tree as I intended.  Tested in
> > consteval34.C.
> > 
> > > But maybe cp_fold_r should do that before the cp_fold, instead of this
> > > function?
> > 
> > I...am not sure how that would be better than what I did.
> 
> Callers of cp_fold_immediate don't need this because cp_fold_r isn't
> involved, so it isn't folding anything.

This is true.
 
> cp_fold_r can walk the arms with cp_fold_r and then clear *walk_subtrees to
> avoid walking the arms again normally.

I didn't think we wanted to do everything cp_fold_r does even in dead
branches, but ok.

I figured that we need to recurse on the conditional of the COND_EXPR too.
It can be, for example:

  &((const struct S *) VIEW_CONVERT_EXPR(q))->b != 0B

which is supposed to be evaluated into:

  &((const struct S *) )->b != 0B

otherwise we'd get ICEs like "error: constant not recomputed when 'ADDR_EXPR'
changed".

> cp_fold_r uses data->pset to avoid walking the same tree twice;
> cp_fold_immediate_r currently doesn't do anything to avoid that.  If
> cp_fold_immediate_r doesn't itself call cp_walk_tree, cp_fold_immediate can
> use cp_walk_tree_without_duplicates.

Adjusted.
 
> > > > > > +  break;
> > > > > > +
> > > > > > case PTRMEM_CST:
> > > > > >   if (TREE_CODE (PTRMEM_CST_MEMBER (stmt)) == FUNCTION_DECL
> > > > > >   && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER 
> > > > > > (stmt)))
> > > > > > {
> > > > > > - if (!data->pset.add (stmt))
> > > > > > + if (!data->pset.add (stmt) && (complain & tf_error))
> > > > > > error_at (PTRMEM_CST_LOCATION (stmt),
> > > > > >   "taking address of an immediate function 
> > > > > > %qD",
> > > > > >   PTRMEM_CST_MEMBER (stmt));
> > > > > >   stmt = *stmt_p = build_zero_cst (TREE_TYPE (stmt));
> > > > > 
> > > > > It looks like this will overwrite *stmt_p even if we didn't give an 
> > > > > error.
> > > > 
> > > > I suppose that could result in missing errors, adjusted.  And there's no
> > > > point in setting stmt.
> > > > > > - break;
> > > > > > + return error_mark_node;
> > > > > > }
> > > > > >   break;
> > > > > > +/* Expand immediate invocations.  */
> > > > > > +case CALL_EXPR:
> > > > > > +case AGGR_INIT_EXPR:
> > > > > > +  if (tree fn = cp_get_callee (stmt))
> > > > > > +   if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P 
> > > > > > (fn))
> > > > > > + if (tree fndecl = cp_get_fndecl_from_callee (fn, 
> > > > > > /*fold*/false))
> > > > > > +   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
> > > > > > + {
> > > > > > +   *stmt_p = stmt = cxx_constant_value (stmt, complain);
> > > > > 
> > > > > Likewise.
> > > > 
> > > > I think we have to keep setting *stmt_p to actually evaluate consteval
> > > > functions.
> > > 
> > > But only when it succeeds; we don't want to set it to error_mark_node if 
> > > we
> > > aren't complaining.
> > 
> > Hmm, probably not.  Fixed, thanks.
> > 
> > +   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
> > + {
> > +   stmt = cxx_constant_value (stmt, complain);
> > +   if (stmt == error_mark_node && (complain & tf_error))
> > + return error_mark_node;
> > +   *stmt_p = stmt;
> > + }
> 
> This seems backwards; like with the ADDR_EXPR/PTRMEM_CST cases, I think we
> want to return error_mark_node regardless of complain, but only set *stmt_p
> when complaining.

Ug.  I really hope it's alright this time.


Re: RFC: Introduce -fhardened to enable security-related flags

2023-09-15 Thread Marek Polacek via Gcc-patches
On Fri, Sep 01, 2023 at 10:09:28PM +, Qing Zhao via Gcc-patches wrote:
> 
> 
> > On Aug 29, 2023, at 3:42 PM, Marek Polacek via Gcc-patches 
> >  wrote:
> > 
> > Improving the security of software has been a major trend in the recent
> > years.  Fortunately, GCC offers a wide variety of flags that enable extra
> > hardening.  These flags aren't enabled by default, though.  And since
> > there are a lot of hardening flags, with more to come, it's been difficult
> > to keep on top of them; more so for the users of GCC who ought not to be
> > expected to keep track of all the new options.
> > 
> > To alleviate some of the problems I mentioned, we thought it would
> > be useful to provide a new umbrella option that enables a reasonable set
> > of hardening flags.  What's "reasonable" in this context is not easy to
> > pin down.  Surely, there must be no ABI impact, the option cannot cause
> > severe performance issues, and, I suspect, it should not cause build
> > errors by enabling stricter compile-time errors (such as, -Wimplicit-int,
> > -Wint-conversion).  Including a controversial option in -fhardened
> > would likely cause that users would not use -fhardened at all.  It's
> > roughly akin to -Wall or -O2 -- those also enable a reasonable set of
> > options, and evolve over time, and are not kept in sync with other
> > compilers.
> > 
> > Currently, -fhardened enables:
> > 
> >  -D_FORTIFY_SOURCE=3 (or =2 for older glibcs)
> >  -D_GLIBCXX_ASSERTIONS
> >  -ftrivial-auto-var-init=zero
> >  -fPIE  -pie  -Wl,-z,relro,-z,now
> >  -fstack-protector-strong
> >  -fstack-clash-protection
> >  -fcf-protection=full (x86 GNU/Linux only)
> > 
> > -fsanitize=undefined is specifically not enabled.  -fstrict-flex-arrays is
> > also liable to break a lot of code so I didn't include it.
> > 
> > Appended is a proof-of-concept patch.  It doesn't implement --help=hardened
> > yet.  A fairly crucial point is that -fhardened will not override options
> > that were specified on the command line (before or after -fhardened).  For
> > example,
> > 
> > -D_FORTIFY_SOURCE=1 -fhardened
> > 
> > means that _FORTIFY_SOURCE=1 will be used.  Similarly,
> > 
> >  -fhardened -fstack-protector
> > 
> > will not enable -fstack-protector-strong.
> > 
> > Thoughts?
> 
> In general, I think that it is a very good idea to provide umbrella options
>  for software security purpose.  Thanks a lot for this work!

And thank you for taking a look!

> 1. I do agree with Martin, multiple-level control for this purpose might be 
> needed,
> similar as multiple levels for warnings, and multiple levels for 
> optimizations.

As I just mentioned in the other email, I'm reluctant to add
more levels, like -fhardened=2, at this time.  I think it's confusing,
because if there are multiple choices, then as a user you have to
figure out which one you want and this option is supposed to simplify
things, not to puzzle people with one more decision.
 
> Similar as optimization options, can we organize all the security options 
> together 
> In our manual, then the user will have a good central place to get more and 
> complete
> Information of the security features our compiler provides? 

Maybe.  But going through all the options and deciding whether
it's a security options may be too big a task, especially if we
are not exactly sure how we define security.
 
> 2. What’s the major criteria to decide which security feature should go into 
> this list?
> Later, when we have new security features, how to decide whether to add them 
> to
> This list or not?

>From my original post:

What's "reasonable" in this context is not easy to
pin down.  Surely, there must be no ABI impact, the option cannot cause
severe performance issues, and, I suspect, it should not cause build
errors by enabling stricter compile-time errors (such as, -Wimplicit-int,
-Wint-conversion).  Including a controversial option in -fhardened
would likely cause that users would not use -fhardened at all.

> I am wondering why -fzero-call-used-regs is not included in the list and also 
> Why chose -ftrivial-auto-var-init=zero instead of 
> -ftrivial-auto-var-init=pattern? 

I can't readily evaluate the effect of -fzero-call-used-regs.  But I did
change =zero to =pattern.

> 3. Looks like currently, -fhardened excludes all compilation-time Warning 
> options for security purpose,
> (For example, -Warray-bounds, --Wstringop-overflow…)

Correct.

> And also excludes all sanitizer options for security purpose 
> (-fsanitizer=undifined)

Correct.

> So, shall we also provide an umbrella option for compilation-time warning 
> options for security purpose

I don't think so... we already have -Wall and -Wextra.

> And a umbrella option for sanitizer options (is the -fsanitizer=undefined 
> this one)?

Yes, -fsanitizer=undefined is already an umbrella option.

Thanks,

Marek



Re: RFC: Introduce -fhardened to enable security-related flags

2023-09-15 Thread Marek Polacek via Gcc-patches
On Mon, Sep 04, 2023 at 11:40:34PM +0100, Richard Sandiford wrote:
> Qing Zhao via Gcc-patches  writes:
> >> On Aug 29, 2023, at 3:42 PM, Marek Polacek via Gcc-patches 
> >>  wrote:
> >> 
> >> Improving the security of software has been a major trend in the recent
> >> years.  Fortunately, GCC offers a wide variety of flags that enable extra
> >> hardening.  These flags aren't enabled by default, though.  And since
> >> there are a lot of hardening flags, with more to come, it's been difficult
> >> to keep on top of them; more so for the users of GCC who ought not to be
> >> expected to keep track of all the new options.
> >> 
> >> To alleviate some of the problems I mentioned, we thought it would
> >> be useful to provide a new umbrella option that enables a reasonable set
> >> of hardening flags.  What's "reasonable" in this context is not easy to
> >> pin down.  Surely, there must be no ABI impact, the option cannot cause
> >> severe performance issues, and, I suspect, it should not cause build
> >> errors by enabling stricter compile-time errors (such as, -Wimplicit-int,
> >> -Wint-conversion).  Including a controversial option in -fhardened
> >> would likely cause that users would not use -fhardened at all.  It's
> >> roughly akin to -Wall or -O2 -- those also enable a reasonable set of
> >> options, and evolve over time, and are not kept in sync with other
> >> compilers.
> >> 
> >> Currently, -fhardened enables:
> >> 
> >>  -D_FORTIFY_SOURCE=3 (or =2 for older glibcs)
> >>  -D_GLIBCXX_ASSERTIONS
> >>  -ftrivial-auto-var-init=zero
> >>  -fPIE  -pie  -Wl,-z,relro,-z,now
> >>  -fstack-protector-strong
> >>  -fstack-clash-protection
> >>  -fcf-protection=full (x86 GNU/Linux only)
> >> 
> >> -fsanitize=undefined is specifically not enabled.  -fstrict-flex-arrays is
> >> also liable to break a lot of code so I didn't include it.
> >> 
> >> Appended is a proof-of-concept patch.  It doesn't implement --help=hardened
> >> yet.  A fairly crucial point is that -fhardened will not override options
> >> that were specified on the command line (before or after -fhardened).  For
> >> example,
> >> 
> >> -D_FORTIFY_SOURCE=1 -fhardened
> >> 
> >> means that _FORTIFY_SOURCE=1 will be used.  Similarly,
> >> 
> >>  -fhardened -fstack-protector
> >> 
> >> will not enable -fstack-protector-strong.
> >> 
> >> Thoughts?
> >
> > In general, I think that it is a very good idea to provide umbrella options
> >  for software security purpose.  Thanks a lot for this work!
> >
> > 1. I do agree with Martin, multiple-level control for this purpose might be 
> > needed,
> > similar as multiple levels for warnings, and multiple levels for 
> > optimizations.
> >
> > Similar as optimization options, can we organize all the security options 
> > together 
> > In our manual, then the user will have a good central place to get more and 
> > complete
> > Information of the security features our compiler provides? 
> >
> > 2. What’s the major criteria to decide which security feature should go 
> > into this list?
> > Later, when we have new security features, how to decide whether to add 
> > them to
> > This list or not?
> > I am wondering why -fzero-call-used-regs is not included in the list and 
> > also
> 
> FWIW, I wondered the same thing.  Not a strong conviction that it should
> be included -- maybe the code bloat is too much on some targets.  But it
> might be acceptable for the -fhardened equivalent of -O3, at least if
> restricted to GPRs.

I have no opinion here.  I trust you so if you think it'd make sense, I will
add it.  :)

The patch I posted today:
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630550.html
doesn't include that option yet.

> > Why chose -ftrivial-auto-var-init=zero instead of 
> > -ftrivial-auto-var-init=pattern? 
> 
> Yeah, IIRC -ftrivial-auto-var-init=zero was controversial with some
> Clang maintainers because it effectively creates a language dialect.
> -ftrivial-auto-var-init=pattern wasn't controversial in the same way.

Thanks.  I've adjusted the patch to enable -ftrivial-auto-var-init=pattern
rather than -ftrivial-auto-var-init=zero.

Marek



Re: RFC: Introduce -fhardened to enable security-related flags

2023-09-15 Thread Marek Polacek via Gcc-patches
On Wed, Aug 30, 2023 at 03:08:46PM +0200, Richard Biener wrote:
> On Wed, Aug 30, 2023 at 12:51 PM Jakub Jelinek via Gcc-patches
>  wrote:
> >
> > On Tue, Aug 29, 2023 at 03:42:27PM -0400, Marek Polacek via Gcc-patches 
> > wrote:
> > > +   if (UNLIKELY (flag_hardened)
> > > +   && (opt->code == OPT_D || opt->code == OPT_U))
> > > + {
> > > +   if (!fortify_seen_p)
> > > + fortify_seen_p = !strncmp (opt->arg, "_FORTIFY_SOURCE", 15);
> >
> > Perhaps this should check that the char after it is either '\0' or '=', we
> > shouldn't care if user defines or undefines _FORTIFY_SOURCE_WHATEVER macro.
> >
> > > +   if (!cxx_assert_seen_p)
> > > + cxx_assert_seen_p = !strcmp (opt->arg, 
> > > "_GLIBCXX_ASSERTIONS");
> >
> > Like we don't care in this case about -D_GLIBCXX_ASSERTIONS42
> >
> > > + }
> > > + }
> > > +
> > > +  if (flag_hardened)
> > > + {
> > > +   if (!fortify_seen_p && optimize > 0)
> > > + {
> > > +   if (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 35)
> > > + cpp_define (parse_in, "_FORTIFY_SOURCE=3");
> > > +   else
> > > + cpp_define (parse_in, "_FORTIFY_SOURCE=2");
> >
> > I wonder if it wouldn't be better to enable _FORTIFY_SOURCE=2 by default for
> > -fhardened only for targets which actually have such a support in the C
> > library.  There is some poor man's _FORTIFY_SOURCE support in libssp,
> > but e.g. one has to link with -lssp in that case and compile with
> > -isystem `gcc -print-include-filename=include`/ssp .
> > For glibc that is >= 2.3.4, 
> > https://maskray.me/blog/2022-11-06-fortify-source
> > mentions NetBSD support since 2006, newlib since 2017, some Darwin libc,
> > bionic (but seems they have only some clang support and dropped GCC
> > support) and some third party reimplementation of libssp.
> > Or do we just enable it and hope that either it works well or isn't
> > supported at all quietly?  E.g. it would certainly break the ssp case
> > where -isystem finds ssp headers but -lssp isn't linked in.
> >
> > > @@ -4976,6 +4993,22 @@ process_command (unsigned int 
> > > decoded_options_count,
> > >  #endif
> > >  }
> > >
> > > +  /* TODO: check if -static -pie works and maybe use it.  */
> > > +  if (flag_hardened && !any_link_options_p && !static_p)
> > > +{
> > > +  save_switch ("-pie", 0, NULL, /*validated=*/true, /*known=*/false);
> > > +  /* TODO: check if BIND_NOW/RELRO is supported.  */
> > > +  if (true)
> > > + {
> > > +   /* These are passed straight down to collect2 so we have to break
> > > +  it up like this.  */
> > > +   add_infile ("-z", "*");
> > > +   add_infile ("now", "*");
> > > +   add_infile ("-z", "*");
> > > +   add_infile ("relro", "*");
> >
> > As the TODO comment says, to do that we need to check at configure time that
> > linker supports -z now and -z relro options.
> >
> > > @@ -1117,9 +1121,12 @@ finish_options (struct gcc_options *opts, struct 
> > > gcc_options *opts_set,
> > >  }
> > >
> > >/* We initialize opts->x_flag_stack_protect to -1 so that targets
> > > - can set a default value.  */
> > > + can set a default value.  With --enable-default-ssp or -fhardened
> > > + the default is -fstack-protector-strong.  */
> > >if (opts->x_flag_stack_protect == -1)
> > > -opts->x_flag_stack_protect = DEFAULT_FLAG_SSP;
> > > +opts->x_flag_stack_protect = (opts->x_flag_hardened
> > > +   ? SPCT_FLAG_STRONG
> > > +   : DEFAULT_FLAG_SSP);
> >
> > This needs to be careful, -fstack-protector isn't supported on all targets
> > (e.g. ia64) and we don't want toplev.cc warning:
> >   /* Targets must be able to place spill slots at lower addresses.  If the
> >  target already uses a soft frame pointer, the transition is trivial.  
> > */
> >   if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
> > {
> >   warning_at (UNKNOWN_LOCATION, 0,
> >   "%<-fstack-protector%>

Re: RFC: Introduce -fhardened to enable security-related flags

2023-09-15 Thread Marek Polacek via Gcc-patches
On Wed, Aug 30, 2023 at 12:50:40PM +0200, Jakub Jelinek wrote:
> On Tue, Aug 29, 2023 at 03:42:27PM -0400, Marek Polacek via Gcc-patches wrote:
> > + if (UNLIKELY (flag_hardened)
> > + && (opt->code == OPT_D || opt->code == OPT_U))
> > +   {
> > + if (!fortify_seen_p)
> > +   fortify_seen_p = !strncmp (opt->arg, "_FORTIFY_SOURCE", 15);
> 
> Perhaps this should check that the char after it is either '\0' or '=', we
> shouldn't care if user defines or undefines _FORTIFY_SOURCE_WHATEVER macro.

Right, should be fixed in
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630550.html
 
> > + if (!cxx_assert_seen_p)
> > +   cxx_assert_seen_p = !strcmp (opt->arg, "_GLIBCXX_ASSERTIONS");
> 
> Like we don't care in this case about -D_GLIBCXX_ASSERTIONS42

This too.
 
> > +   }
> > +   }
> > +
> > +  if (flag_hardened)
> > +   {
> > + if (!fortify_seen_p && optimize > 0)
> > +   {
> > + if (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 35)
> > +   cpp_define (parse_in, "_FORTIFY_SOURCE=3");
> > + else
> > +   cpp_define (parse_in, "_FORTIFY_SOURCE=2");
> 
> I wonder if it wouldn't be better to enable _FORTIFY_SOURCE=2 by default for
> -fhardened only for targets which actually have such a support in the C
> library.  There is some poor man's _FORTIFY_SOURCE support in libssp,
> but e.g. one has to link with -lssp in that case and compile with
> -isystem `gcc -print-include-filename=include`/ssp .
> For glibc that is >= 2.3.4, https://maskray.me/blog/2022-11-06-fortify-source
> mentions NetBSD support since 2006, newlib since 2017, some Darwin libc,
> bionic (but seems they have only some clang support and dropped GCC
> support) and some third party reimplementation of libssp.
> Or do we just enable it and hope that either it works well or isn't
> supported at all quietly?  E.g. it would certainly break the ssp case
> where -isystem finds ssp headers but -lssp isn't linked in.

I don't really have an idea how this should be handled.  I left it as
it was.
 
> > @@ -4976,6 +4993,22 @@ process_command (unsigned int decoded_options_count,
> >  #endif
> >  }
> >  
> > +  /* TODO: check if -static -pie works and maybe use it.  */
> > +  if (flag_hardened && !any_link_options_p && !static_p)
> > +{
> > +  save_switch ("-pie", 0, NULL, /*validated=*/true, /*known=*/false);
> > +  /* TODO: check if BIND_NOW/RELRO is supported.  */
> > +  if (true)
> > +   {
> > + /* These are passed straight down to collect2 so we have to break
> > +it up like this.  */
> > + add_infile ("-z", "*");
> > + add_infile ("now", "*");
> > + add_infile ("-z", "*");
> > + add_infile ("relro", "*");
> 
> As the TODO comment says, to do that we need to check at configure time that
> linker supports -z now and -z relro options.

I've added configure checks in
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630550.html

> > @@ -1117,9 +1121,12 @@ finish_options (struct gcc_options *opts, struct 
> > gcc_options *opts_set,
> >  }
> >  
> >/* We initialize opts->x_flag_stack_protect to -1 so that targets
> > - can set a default value.  */
> > + can set a default value.  With --enable-default-ssp or -fhardened
> > + the default is -fstack-protector-strong.  */
> >if (opts->x_flag_stack_protect == -1)
> > -opts->x_flag_stack_protect = DEFAULT_FLAG_SSP;
> > +opts->x_flag_stack_protect = (opts->x_flag_hardened
> > + ? SPCT_FLAG_STRONG
> > + : DEFAULT_FLAG_SSP);
> 
> This needs to be careful, -fstack-protector isn't supported on all targets
> (e.g. ia64) and we don't want toplev.cc warning:
>   /* Targets must be able to place spill slots at lower addresses.  If the
>  target already uses a soft frame pointer, the transition is trivial.  */
>   if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
> {
>   warning_at (UNKNOWN_LOCATION, 0,
>   "%<-fstack-protector%> not supported for this target");
>   flag_stack_protect = 0;
> }
> to be emitted whenever using -fhardened, it should not be enabled there
> silently (for ia64 Fedora/RHEL gcc actually had a short patch to make it
> work, turn the target into FRAME_GROWS_DOWNWARD one if -fstack-protect* was
> enabled and otherwise keep it !FRAME_GROWS_DOWNWARD).

Unfortunately, I found out that I can't just check FRAME_GROWS_DOWNWARD.
Some targets like rs6000 and mips use flag_stack_protect in the definition
of FRAME_GROWS_DOWNWARD, and that is not usable in finish_options.  There,
you have to use opts->x_flag_*.  Besides, some targets like BPF don't
support -fstack-protector at all, but in finish_options we can't know that
yet (AFAIK).

I fixed it, but in a very ugly way, using a new global.  :/

Thanks,

Marek



Re: RFC: Introduce -fhardened to enable security-related flags

2023-09-15 Thread Marek Polacek via Gcc-patches
On Wed, Aug 30, 2023 at 05:06:57PM +0800, Xi Ruoyao via Gcc-patches wrote:
> On Tue, 2023-08-29 at 15:42 -0400, Marek Polacek via Gcc-patches wrote:
> > + if (UNLIKELY (flag_hardened)
> > + && (opt->code == OPT_D || opt->code == OPT_U))
> > +   {
> > + if (!fortify_seen_p)
> > +   fortify_seen_p = !strncmp (opt->arg, "_FORTIFY_SOURCE", 15);
> > + if (!cxx_assert_seen_p)
> > +   cxx_assert_seen_p = !strcmp (opt->arg, 
> > "_GLIBCXX_ASSERTIONS");
> 
> It looks like there is some minor logic issue here: the first strncmp
> will mistakenly match "-D_FORTIFY_SOURCE_FAKE", and the second strcmp
> will not match "-D_GLIBCXX_ASSERTIONS=1".

Thanks, you're right.  Should be fixed in
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630550.html

Marek



Re: RFC: Introduce -fhardened to enable security-related flags

2023-09-15 Thread Marek Polacek via Gcc-patches
On Wed, Aug 30, 2023 at 10:46:14AM +0200, Martin Uecker wrote:
> > Improving the security of software has been a major trend in the recent
> > years.  Fortunately, GCC offers a wide variety of flags that enable extra
> > hardening.  These flags aren't enabled by default, though.  And since
> > there are a lot of hardening flags, with more to come, it's been difficult
> > to keep on top of them; more so for the users of GCC who ought not to be
> > expected to keep track of all the new options.
> > 
> > To alleviate some of the problems I mentioned, we thought it would
> > be useful to provide a new umbrella option that enables a reasonable set
> > of hardening flags.  What's "reasonable" in this context is not easy to
> > pin down.  Surely, there must be no ABI impact, the option cannot cause
> > severe performance issues, and, I suspect, it should not cause build
> > errors by enabling stricter compile-time errors (such as, -Wimplicit-int,
> > -Wint-conversion).  Including a controversial option in -fhardened
> > would likely cause that users would not use -fhardened at all.  It's
> > roughly akin to -Wall or -O2 -- those also enable a reasonable set of
> > options, and evolve over time, and are not kept in sync with other
> > compilers.
> > 
> > Currently, -fhardened enables:
> > 
> >   -D_FORTIFY_SOURCE=3 (or =2 for older glibcs)
> >   -D_GLIBCXX_ASSERTIONS
> >   -ftrivial-auto-var-init=zero
> >   -fPIE  -pie  -Wl,-z,relro,-z,now
> >   -fstack-protector-strong
> >   -fstack-clash-protection
> >   -fcf-protection=full (x86 GNU/Linux only)
> > 
> > -fsanitize=undefined is specifically not enabled.  -fstrict-flex-arrays is
> > also liable to break a lot of code so I didn't include it.
> > 
> > Appended is a proof-of-concept patch.  It doesn't implement --help=hardened
> > yet.  A fairly crucial point is that -fhardened will not override options
> > that were specified on the command line (before or after -fhardened).  For
> > example,
> >  
> >  -D_FORTIFY_SOURCE=1 -fhardened
> > 
> > means that _FORTIFY_SOURCE=1 will be used.  Similarly,
> > 
> >   -fhardened -fstack-protector
> > 
> > will not enable -fstack-protector-strong.
> > 
> > Thoughts?
> 
> I think this is a great idea!  Considering that it is difficult to
> decide what shoud be activated and what not and the baseline should
> not cause compile errors,  I wonder whether there should be higher
> levels  similar to -O1,2,3 ? 
 
Thanks.  I would like to avoid any levels if at all possible; I think
they would be confusing.

> Although it would be nice to have a one-letter or very short
> option similar to -O2 or -Wall, but maybe this is not possible 
> because all short ones are already taken. Of course, 
> "-fhardening" would  already a huge  improvement to the 
> current situation.

There are some free ones, like -Z, but I'm not confident I could take
it :).

Marek



[PATCH] gcc: Introduce -fhardened

2023-09-15 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, powerpc64le-unknown-linux-gnu,
and aarch64-unknown-linux-gnu; ok for trunk?

-- >8 --
In 
I proposed -fhardened, a new umbrella option that enables a reasonable set
of hardening flags.  The read of the room seems to be that the option
would be useful.  So here's a patch implementing that option.

Currently, -fhardened enables:

  -D_FORTIFY_SOURCE=3 (or =2 for older glibcs)
  -D_GLIBCXX_ASSERTIONS
  -ftrivial-auto-var-init=pattern
  -fPIE  -pie  -Wl,-z,relro,-z,now
  -fstack-protector-strong
  -fstack-clash-protection
  -fcf-protection=full (x86 GNU/Linux only)

-fhardened will not override options that were specified on the command line
(before or after -fhardened).  For example,

 -D_FORTIFY_SOURCE=1 -fhardened

means that _FORTIFY_SOURCE=1 will be used.  Similarly,

  -fhardened -fstack-protector

will not enable -fstack-protector-strong.

In DW_AT_producer it is reflected only as -fhardened; it doesn't expand
to anything.  I think we need a better way to show what it actually
enables.

gcc/c-family/ChangeLog:

* c-opts.cc (c_finish_options): Maybe cpp_define _FORTIFY_SOURCE
and _GLIBCXX_ASSERTIONS.

gcc/ChangeLog:

* common.opt (fhardened): New option.
* config.in: Regenerate.
* config/bpf/bpf.cc: Include "opts.h".
(bpf_option_override): If flag_stack_protector_set_by_fhardened_p, do
not inform that -fstack-protector does not work.
* config/i386/i386-options.cc (ix86_option_override_internal): When
-fhardened, maybe enable -fcf-protection=full.
* configure: Regenerate.
* configure.ac: Check if the linker supports '-z now' and '-z relro'.
* doc/invoke.texi: Document -fhardened.
* gcc.cc (driver_handle_option): Remember if any link options or -static
were specified on the command line.
(process_command): When -fhardened, maybe enable -pie and
-Wl,-z,relro,-z,now.
* opts.cc (flag_stack_protector_set_by_fhardened_p): New global.
(finish_options): When -fhardened, enable
-ftrivial-auto-var-init=pattern and -fstack-protector-strong.
(print_help_hardened): New.
(print_help): Call it.
* toplev.cc (process_options): When -fhardened, enable
-fstack-clash-protection.  If flag_stack_protector_set_by_fhardened_p,
do not warn that -fstack-protector not supported for this target.

gcc/testsuite/ChangeLog:

* gcc.misc-tests/help.exp: Test -fhardened.
* c-c++-common/fhardened-1.S: New test.
* c-c++-common/fhardened-1.c: New test.
* c-c++-common/fhardened-10.c: New test.
* c-c++-common/fhardened-11.c: New test.
* c-c++-common/fhardened-12.c: New test.
* c-c++-common/fhardened-13.c: New test.
* c-c++-common/fhardened-14.c: New test.
* c-c++-common/fhardened-2.c: New test.
* c-c++-common/fhardened-3.c: New test.
* c-c++-common/fhardened-5.c: New test.
* c-c++-common/fhardened-6.c: New test.
* c-c++-common/fhardened-7.c: New test.
* c-c++-common/fhardened-8.c: New test.
* c-c++-common/fhardened-9.c: New test.
* gcc.target/i386/cf_check-6.c: New test.
---
 gcc/c-family/c-opts.cc | 29 
 gcc/common.opt |  4 ++
 gcc/config.in  | 12 +
 gcc/config/bpf/bpf.cc  |  8 ++--
 gcc/config/i386/i386-options.cc| 11 -
 gcc/configure  | 50 +++-
 gcc/configure.ac   | 42 -
 gcc/doc/invoke.texi| 29 +++-
 gcc/gcc.cc | 39 +++-
 gcc/opts.cc| 53 --
 gcc/opts.h |  1 +
 gcc/testsuite/c-c++-common/fhardened-1.S   |  6 +++
 gcc/testsuite/c-c++-common/fhardened-1.c   | 14 ++
 gcc/testsuite/c-c++-common/fhardened-10.c  | 10 
 gcc/testsuite/c-c++-common/fhardened-11.c  | 10 
 gcc/testsuite/c-c++-common/fhardened-12.c  | 11 +
 gcc/testsuite/c-c++-common/fhardened-13.c  |  6 +++
 gcc/testsuite/c-c++-common/fhardened-14.c  |  6 +++
 gcc/testsuite/c-c++-common/fhardened-2.c   |  9 
 gcc/testsuite/c-c++-common/fhardened-3.c   | 12 +
 gcc/testsuite/c-c++-common/fhardened-5.c   | 11 +
 gcc/testsuite/c-c++-common/fhardened-6.c   | 11 +
 gcc/testsuite/c-c++-common/fhardened-7.c   |  7 +++
 gcc/testsuite/c-c++-common/fhardened-8.c   |  7 +++
 gcc/testsuite/c-c++-common/fhardened-9.c   |  6 +++
 gcc/testsuite/gcc.misc-tests/help.exp  |  2 +
 gcc/testsuite/gcc.target/i386/cf_check-6.c | 12 +
 gcc/toplev.cc  | 11 -
 28 files changed, 416 insertions(+), 13 deletions(-)
 create mode 100644 

[PATCH v5] c++: Move consteval folding to cp_fold_r

2023-09-13 Thread Marek Polacek via Gcc-patches
On Wed, Sep 13, 2023 at 05:57:47PM -0400, Jason Merrill wrote:
> On 9/13/23 16:56, Marek Polacek wrote:
> > On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:
> > > On 9/8/23 14:24, Marek Polacek wrote:
> > > > +  switch (TREE_CODE (stmt))
> > > > +{
> > > > +/* Unfortunately we must handle code like
> > > > +false ? bar () : 42
> > > > +   where we have to check bar too.  */
> > > > +case COND_EXPR:
> > > > +  if (cp_fold_immediate_r (_OPERAND (stmt, 1), walk_subtrees, 
> > > > data))
> > > > +   return error_mark_node;
> > > > +  if (TREE_OPERAND (stmt, 2)
> > > > + && cp_fold_immediate_r (_OPERAND (stmt, 2), 
> > > > walk_subtrees, data))
> > > > +   return error_mark_node;
> > > 
> > > Is this necessary?  Doesn't walk_tree already walk into the arms of
> > > COND_EXPR?
> > 
> > Unfortunately yes.  The cp_fold call in cp_fold_r could fold the ?: into
> > a constant before we see it here.  I've added a comment saying just that.
> 
> Ah.  But in that case I guess we need to walk into the arms, not just check
> the top-level expression in them.
 
Arg, of course.  I was fooled into thinking that it would recurse, but
you're right.  Fixed by using cp_walk_tree as I intended.  Tested in
consteval34.C.

> But maybe cp_fold_r should do that before the cp_fold, instead of this
> function?

I...am not sure how that would be better than what I did.

> > > > +  break;
> > > > +
> > > >case PTRMEM_CST:
> > > >  if (TREE_CODE (PTRMEM_CST_MEMBER (stmt)) == FUNCTION_DECL
> > > >   && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (stmt)))
> > > > {
> > > > - if (!data->pset.add (stmt))
> > > > + if (!data->pset.add (stmt) && (complain & tf_error))
> > > > error_at (PTRMEM_CST_LOCATION (stmt),
> > > >   "taking address of an immediate function %qD",
> > > >   PTRMEM_CST_MEMBER (stmt));
> > > >   stmt = *stmt_p = build_zero_cst (TREE_TYPE (stmt));
> > > 
> > > It looks like this will overwrite *stmt_p even if we didn't give an error.
> > 
> > I suppose that could result in missing errors, adjusted.  And there's no
> > point in setting stmt.
> > > > - break;
> > > > + return error_mark_node;
> > > > }
> > > >  break;
> > > > +/* Expand immediate invocations.  */
> > > > +case CALL_EXPR:
> > > > +case AGGR_INIT_EXPR:
> > > > +  if (tree fn = cp_get_callee (stmt))
> > > > +   if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P 
> > > > (fn))
> > > > + if (tree fndecl = cp_get_fndecl_from_callee (fn, 
> > > > /*fold*/false))
> > > > +   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
> > > > + {
> > > > +   *stmt_p = stmt = cxx_constant_value (stmt, complain);
> > > 
> > > Likewise.
> > 
> > I think we have to keep setting *stmt_p to actually evaluate consteval
> > functions.
> 
> But only when it succeeds; we don't want to set it to error_mark_node if we
> aren't complaining.

Hmm, probably not.  Fixed, thanks.

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

-- >8 --
In the review of P2564:

it turned out that in order to correctly handle an example in the paper,
we should stop doing immediate evaluation in build_over_call and
bot_replace, and instead do it in cp_fold_r.  This patch does that.

Another benefit is that this is a pretty significant simplification, at
least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
doesn't compile yet).

The main drawback seems to be that cp_fold_r doesn't process
uninstantiated templates.  We still have to handle things like
"false ? foo () : 1".  To that end, I've added cp_fold_immediate, called
on dead branches in cxx_eval_conditional_expression.  Since in cxx_*
I can't rely on current_function_decl being available, I've added
another walk: a new overload for in_immediate_context that looks into
constexpr_ctx.

You'll see that I've reintroduced ADDR_EXPR_DENOTES_CALL_P here.  This
is to detect

  *()) ()
  (s.*::foo) ()

which were deemed ill-formed.

gcc/cp/ChangeLog:

* call.cc (in_immediate_context): No longer static.
(build_over_call): Set ADDR_EXPR_DENOTES_CALL_P.  Don't handle
immediate_invocation_p here.
* constexpr.cc (in_immediate_context): New overload.
(cxx_eval_call_expression): Use mce_true for DECL_IMMEDIATE_FUNCTION_P.
(cxx_eval_conditional_expression): Call cp_fold_immediate.
* cp-gimplify.cc (maybe_replace_decl): Make static.
(cp_fold_r): Expand immediate invocations.
(cp_fold_immediate_r): New.
(cp_fold_immediate): New.
* cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.
(cp_fold_immediate): Declare.
* tree.cc (bot_replace): Don't handle immediate invocations here.

libstdc++-v3/ChangeLog:

* 

[PATCH v4] c++: Move consteval folding to cp_fold_r

2023-09-13 Thread Marek Polacek via Gcc-patches
On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:
> On 9/8/23 14:24, Marek Polacek wrote:
> > +  if (!in_immediate_context ()
> > +  /* P2564: a subexpression of a manifestly constant-evaluated 
> > expression
> > +or conversion is an immediate function context.  */
> > +  && ctx->manifestly_const_eval != mce_true
> 
> I might check this first as a tiny optimization.

Done.
 
> > +  switch (TREE_CODE (stmt))
> > +{
> > +/* Unfortunately we must handle code like
> > +false ? bar () : 42
> > +   where we have to check bar too.  */
> > +case COND_EXPR:
> > +  if (cp_fold_immediate_r (_OPERAND (stmt, 1), walk_subtrees, 
> > data))
> > +   return error_mark_node;
> > +  if (TREE_OPERAND (stmt, 2)
> > + && cp_fold_immediate_r (_OPERAND (stmt, 2), walk_subtrees, data))
> > +   return error_mark_node;
> 
> Is this necessary?  Doesn't walk_tree already walk into the arms of
> COND_EXPR?

Unfortunately yes.  The cp_fold call in cp_fold_r could fold the ?: into
a constant before we see it here.  I've added a comment saying just that.

> > +  break;
> > +
> >   case PTRMEM_CST:
> > if (TREE_CODE (PTRMEM_CST_MEMBER (stmt)) == FUNCTION_DECL
> >   && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (stmt)))
> > {
> > - if (!data->pset.add (stmt))
> > + if (!data->pset.add (stmt) && (complain & tf_error))
> > error_at (PTRMEM_CST_LOCATION (stmt),
> >   "taking address of an immediate function %qD",
> >   PTRMEM_CST_MEMBER (stmt));
> >   stmt = *stmt_p = build_zero_cst (TREE_TYPE (stmt));
> 
> It looks like this will overwrite *stmt_p even if we didn't give an error.

I suppose that could result in missing errors, adjusted.  And there's no
point in setting stmt.
 
> > - break;
> > + return error_mark_node;
> > }
> > break;
> > +/* Expand immediate invocations.  */
> > +case CALL_EXPR:
> > +case AGGR_INIT_EXPR:
> > +  if (tree fn = cp_get_callee (stmt))
> > +   if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P (fn))
> > + if (tree fndecl = cp_get_fndecl_from_callee (fn, /*fold*/false))
> > +   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
> > + {
> > +   *stmt_p = stmt = cxx_constant_value (stmt, complain);
> 
> Likewise.

I think we have to keep setting *stmt_p to actually evaluate consteval
functions.  But again, no need to set stmt.

> > +   if (stmt == error_mark_node)
> > + return error_mark_node;
> > + }
> > +  break;
> > +
> >   case ADDR_EXPR:
> > if (TREE_CODE (TREE_OPERAND (stmt, 0)) == FUNCTION_DECL
> >   && DECL_IMMEDIATE_FUNCTION_P (TREE_OPERAND (stmt, 0)))
> > {
> > - error_at (EXPR_LOCATION (stmt),
> > -   "taking address of an immediate function %qD",
> > -   TREE_OPERAND (stmt, 0));
> > + if (complain & tf_error)
> > +   error_at (EXPR_LOCATION (stmt),
> > + "taking address of an immediate function %qD",
> > + TREE_OPERAND (stmt, 0));
> >   stmt = *stmt_p = build_zero_cst (TREE_TYPE (stmt));
> 
> Likewise.

Adjusted like case PTRMEM_CST.

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

-- >8 --
In the review of P2564:

it turned out that in order to correctly handle an example in the paper,
we should stop doing immediate evaluation in build_over_call and
bot_replace, and instead do it in cp_fold_r.  This patch does that.

Another benefit is that this is a pretty significant simplification, at
least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
doesn't compile yet).

The main drawback seems to be that cp_fold_r doesn't process
uninstantiated templates.  We still have to handle things like
"false ? foo () : 1".  To that end, I've added cp_fold_immediate, called
on dead branches in cxx_eval_conditional_expression.  Since in cxx_*
I can't rely on current_function_decl being available, I've added
another walk: a new overload for in_immediate_context that looks into
constexpr_ctx.

You'll see that I've reintroduced ADDR_EXPR_DENOTES_CALL_P here.  This
is to detect

  *()) ()
  (s.*::foo) ()

which were deemed ill-formed.

gcc/cp/ChangeLog:

* call.cc (in_immediate_context): No longer static.
(build_over_call): Set ADDR_EXPR_DENOTES_CALL_P.  Don't handle
immediate_invocation_p here.
* constexpr.cc (in_immediate_context): New overload.
(cxx_eval_call_expression): Use mce_true for DECL_IMMEDIATE_FUNCTION_P.
(cxx_eval_conditional_expression): Call cp_fold_immediate.
* cp-gimplify.cc (maybe_replace_decl): Make static.
(cp_fold_r): Expand immediate invocations.
(cp_fold_immediate_r): New.
(cp_fold_immediate): New.
* cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.
(cp_fold_immediate): Declare.
* tree.cc 

Re: [pushed] c++: __integer_pack with class argument [PR111357]

2023-09-12 Thread Marek Polacek via Gcc-patches
On Tue, Sep 12, 2023 at 01:27:44PM -0400, Jason Merrill via Gcc-patches wrote:
> Tested x86_64-pc-linux-gnu, applying to trunk.
> 
> -- 8< --
> 
> The argument might not already be an integer.
> 
>   PR c++/111357
> 
> gcc/cp/ChangeLog:
> 
>   * pt.cc (expand_integer_pack): Convert argument to int.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/ext/integer-pack7.C: New test.
> ---
>  gcc/cp/pt.cc |  2 ++
>  gcc/testsuite/g++.dg/ext/integer-pack7.C | 38 
>  2 files changed, 40 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/ext/integer-pack7.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 838179d5fe3..b583c11eb99 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -3793,6 +3793,8 @@ expand_integer_pack (tree call, tree args, 
> tsubst_flags_t complain,
>  }
>else
>  {
> +  hi = perform_implicit_conversion_flags (integer_type_node, hi, 
> complain,
> +   LOOKUP_IMPLICIT);

FWIW, we have perform_implicit_conversion for this.

Marek



[PATCH v3] c++: Move consteval folding to cp_fold_r

2023-09-08 Thread Marek Polacek via Gcc-patches
On Thu, Sep 07, 2023 at 02:32:51PM -0400, Jason Merrill wrote:
> On 9/7/23 11:23, Marek Polacek wrote:
> > On Tue, Sep 05, 2023 at 04:36:34PM -0400, Jason Merrill wrote:
> > > On 9/5/23 15:59, Marek Polacek wrote:
> > > > On Tue, Sep 05, 2023 at 10:52:04AM -0400, Jason Merrill wrote:
> > > > > On 9/1/23 13:23, Marek Polacek wrote:
> > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > > > 
> > > > > > -- >8 --
> > > > > > 
> > > > > > In the review of P2564:
> > > > > > 
> > > > > > it turned out that in order to correctly handle an example in the 
> > > > > > paper,
> > > > > > we should stop doing immediate evaluation in build_over_call and
> > > > > > bot_replace, and instead do it in cp_fold_r.  This patch does that.
> > > > > > 
> > > > > > Another benefit is that this is a pretty significant 
> > > > > > simplification, at
> > > > > > least in my opinion.  Also, this fixes the c++/110997 ICE (but the 
> > > > > > test
> > > > > > doesn't compile yet).
> > > > > > 
> > > > > > The main drawback seems to be that cp_fold_r doesn't process as much
> > > > > > code as we did before: uninstantiated templates
> > > > > 
> > > > > That's acceptable, it's an optional diagnostic.
> > > > > 
> > > > > > and things like "false ? foo () : 1".
> > > > > 
> > > > > This is a problem.  Maybe we want cp_fold_r to recurse into the arms 
> > > > > of a
> > > > > COND_EXPR before folding them away?  Maybe only if we know we've seen 
> > > > > an
> > > > > immediate function?
> > > > 
> > > > Unfortunately we had already thrown the dead branch away when we got to
> > > > cp_fold_r.  I wonder if we have to adjust 
> > > > cxx_eval_conditional_expression
> > > > to call cp_fold_r on the dead branch too,
> > > 
> > > Hmm, I guess so.
> > > 
> > > > perhaps with a new ff_ flag to skip the whole second switch in 
> > > > cp_fold_r?
> > > 
> > > Or factor out the immediate function handling to a separate walk function
> > > that cp_fold_r also calls?
> > 
> > I did that.
> > > > But then it's possible that the in_immediate_context checks have to 
> > > > stay.
> > > 
> > > We can just not do the walk in immediate (or mce_true) context, like we
> > > currently avoid calling cp_fold_function.
> > 
> > Right.  Unfortunately I have to check even when mce_true, consider
> > 
> >consteval int bar (int i) { if (i != 1) throw 1; return 0; }
> >constexpr int a = 0 ? bar(3) : 3;
> 
> I disagree; the call is in a manifestly constant-evaluated expression, and
> so is now considered an immediate function context, and we should accept
> that example.

Ack.  I was still living in pre-P2564 world.
 
> > > For mce_unknown I guess we'd want
> > > to set *non_constant_p instead of giving an error.
> > 
> > I did not do this because I haven't found a case where it would make
> > a difference.
> 
> I think it will given the above comment.

Correct.  For instance, in:

  consteval int bar (int i) { if (i != 1) throw 1; return 0; }

  constexpr int
  foo (bool b)
  {
return b ? bar (3) : 2;
  }

  static_assert (foo (false) == 2);

we should complain only once.  I've implemented your suggestion to set
*non_constant_p instead of giving an error for mce_unknown.

> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 0ca4370deab..397d5c7ec3f 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -2311,6 +2311,29 @@ cxx_dynamic_cast_fn_p (tree fndecl)
> >   && CP_DECL_CONTEXT (fndecl) == abi_node);
> >   }
> > +/* Return true if we are in the body of a consteval function. > +   This 
> > is in addition to in_immediate_context because that
> > +   uses current_function_decl which may not be available.  CTX is
> > +   the current constexpr context.  */
> > +
> > +static bool
> > +in_immediate_context (const constexpr_ctx *ctx)
> > +{
> > +  if (in_immediate_context ())
> > +return true;
> 
> Can't we check for mce_true here instead of looking at the call chain?

Yes.
 
> > +/* A wrapper around cp_fold_immediate_r.  */
> > +
> > +void
> > +cp_fold_immediate (tree *tp)
> > +{
> 
> Maybe return early if consteval isn't supported in the active standard?

Absolutely.

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

-- >8 --
In the review of P2564:

it turned out that in order to correctly handle an example in the paper,
we should stop doing immediate evaluation in build_over_call and
bot_replace, and instead do it in cp_fold_r.  This patch does that.

Another benefit is that this is a pretty significant simplification, at
least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
doesn't compile yet).

The main drawback seems to be that cp_fold_r doesn't process
uninstantiated templates.  We still have to handle things like
"false ? foo () : 1".  To that end, I've added cp_fold_immediate, called
on dead branches in 

[PATCH v2] c++: Move consteval folding to cp_fold_r

2023-09-07 Thread Marek Polacek via Gcc-patches
On Tue, Sep 05, 2023 at 04:36:34PM -0400, Jason Merrill wrote:
> On 9/5/23 15:59, Marek Polacek wrote:
> > On Tue, Sep 05, 2023 at 10:52:04AM -0400, Jason Merrill wrote:
> > > On 9/1/23 13:23, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > 
> > > > In the review of P2564:
> > > > 
> > > > it turned out that in order to correctly handle an example in the paper,
> > > > we should stop doing immediate evaluation in build_over_call and
> > > > bot_replace, and instead do it in cp_fold_r.  This patch does that.
> > > > 
> > > > Another benefit is that this is a pretty significant simplification, at
> > > > least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
> > > > doesn't compile yet).
> > > > 
> > > > The main drawback seems to be that cp_fold_r doesn't process as much
> > > > code as we did before: uninstantiated templates
> > > 
> > > That's acceptable, it's an optional diagnostic.
> > > 
> > > > and things like "false ? foo () : 1".
> > > 
> > > This is a problem.  Maybe we want cp_fold_r to recurse into the arms of a
> > > COND_EXPR before folding them away?  Maybe only if we know we've seen an
> > > immediate function?
> > 
> > Unfortunately we had already thrown the dead branch away when we got to
> > cp_fold_r.  I wonder if we have to adjust cxx_eval_conditional_expression
> > to call cp_fold_r on the dead branch too,
> 
> Hmm, I guess so.
> 
> > perhaps with a new ff_ flag to skip the whole second switch in cp_fold_r?
> 
> Or factor out the immediate function handling to a separate walk function
> that cp_fold_r also calls?

I did that.
 
> > But then it's possible that the in_immediate_context checks have to stay.
> 
> We can just not do the walk in immediate (or mce_true) context, like we
> currently avoid calling cp_fold_function.

Right.  Unfortunately I have to check even when mce_true, consider

  consteval int bar (int i) { if (i != 1) throw 1; return 0; }
  constexpr int a = 0 ? bar(3) : 3;

> For mce_unknown I guess we'd want
> to set *non_constant_p instead of giving an error.

I did not do this because I haven't found a case where it would make
a difference.

> This is a problem.  Maybe we want cp_fold_r to recurse into the arms of a
> COND_EXPR before folding them away?  Maybe only if we know we've seen an
> immediate function?

Hopefully resolved now.
 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 8bd5c4a47f8..af4f98b1fe1 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -3135,6 +3135,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
> > tree t,
> >   unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
> >   unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
> > + /* Make sure we fold std::is_constant_evaluated to true in an
> > +immediate function.  */
> > + if (immediate_invocation_p (fun))
> 
> I think this should just check DECL_IMMEDIATE_FUNCTION_P, the context
> doesn't matter.

Fixed.  And now I don't need to export immediate_invocation_p.
 
> > +   call_ctx.manifestly_const_eval = mce_true;
> > +
> > diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
> > index 206e791fcfd..29132aad158 100644
> > --- a/gcc/cp/cp-gimplify.cc
> > +++ b/gcc/cp/cp-gimplify.cc
> > @@ -1058,9 +1058,21 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void 
> > *data_)
> > }
> > break;
> > +/* Expand immediate invocations.  */
> > +case CALL_EXPR:
> > +case AGGR_INIT_EXPR:
> > +  if (!in_immediate_context ())
> 
> As you mentioned in your followup, we shouldn't need to check this because
> we don't call cp_fold_r in immediate context.

Fixed.

> > +   if (tree fn = cp_get_callee (stmt))
> > + if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P (fn))
> > +   if (tree fndecl = cp_get_fndecl_from_callee (fn, /*fold*/false))
> > + if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
> > +   *stmt_p = stmt = cxx_constant_value (stmt);
> > +  break;
> > +
> >   case ADDR_EXPR:
> > if (TREE_CODE (TREE_OPERAND (stmt, 0)) == FUNCTION_DECL
> > - && DECL_IMMEDIATE_FUNCTION_P (TREE_OPERAND (stmt, 0)))
> > + && DECL_IMMEDIATE_FUNCTION_P (TREE_OPERAND (stmt, 0))
> > + && !in_immediate_context ())
> 
> Likewise.

Fixed.
 
> > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
> > index 799183dc646..7dfb6de2da3 100644
> > --- a/gcc/cp/tree.cc
> > +++ b/gcc/cp/tree.cc
> > @@ -3254,7 +3254,7 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_)
> >  variables.  */
> >   static tree
> > -bot_replace (tree* t, int* walk_subtrees, void* data_)
> > +bot_replace (tree* t, int*, void* data_)
> 
> Generally we keep the parameter name as a comment like
> int */*walk_subtrees*/

I reaaally mislike that but ok, changed.

> > diff --git 

Re: [PATCH] c++: Move consteval folding to cp_fold_r

2023-09-05 Thread Marek Polacek via Gcc-patches
On Tue, Sep 05, 2023 at 10:52:04AM -0400, Jason Merrill wrote:
> On 9/1/23 13:23, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > 
> > In the review of P2564:
> > 
> > it turned out that in order to correctly handle an example in the paper,
> > we should stop doing immediate evaluation in build_over_call and
> > bot_replace, and instead do it in cp_fold_r.  This patch does that.
> > 
> > Another benefit is that this is a pretty significant simplification, at
> > least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
> > doesn't compile yet).
> > 
> > The main drawback seems to be that cp_fold_r doesn't process as much
> > code as we did before: uninstantiated templates
> 
> That's acceptable, it's an optional diagnostic.
> 
> > and things like "false ? foo () : 1".
> 
> This is a problem.  Maybe we want cp_fold_r to recurse into the arms of a
> COND_EXPR before folding them away?  Maybe only if we know we've seen an
> immediate function?

Unfortunately we had already thrown the dead branch away when we got to
cp_fold_r.  I wonder if we have to adjust cxx_eval_conditional_expression
to call cp_fold_r on the dead branch too, perhaps with a new ff_ flag
to skip the whole second switch in cp_fold_r?  But then it's possible
that the in_immediate_context checks have to stay.

[ I'll address the rest later. ]

Marek



Re: [PATCH] c++: improve verify_constant diagnostic [PR91483]

2023-09-01 Thread Marek Polacek via Gcc-patches
On Fri, Sep 01, 2023 at 08:00:01PM -0400, Marek Polacek via Gcc-patches wrote:
>if (TREE_OVERFLOW_P (t))
> diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr3.C 
> b/gcc/testsuite/g++.dg/diagnostic/constexpr3.C
> new file mode 100644
> index 000..b6e43a93664
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/constexpr3.C
> @@ -0,0 +1,32 @@
> +// { dg-do compile { target c++14 } }

I've added the missing PR c++/91483 here and in the ChangeLog in my local repo.

Marek



[PATCH] c++: improve verify_constant diagnostic [PR91483]

2023-09-01 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

When verify_constant complains, it's pretty terse.  Consider

  void test ()
  {
constexpr int i = 42;
constexpr const int *p = 
  }

where it says "'& i' is not a constant expression".  OK, but why?

With this patch, we say:

b.C:5:28: error: '& i' is not a constant expression
5 |   constexpr const int *p = 
  |^~
b.C:5:28: note: pointer to 'i' is not a constant expression
b.C:4:17: note: address of non-static constexpr variable 'i' may differ on each 
invocation of the enclosing function; add 'static' to give it a constant address
4 |   constexpr int i = 42;
  | ^
  | static

which brings g++ on par with clang++.

gcc/cp/ChangeLog:

* constexpr.cc (verify_constant_explain_r): New.
(verify_constant): Call it.

gcc/testsuite/ChangeLog:

* g++.dg/diagnostic/constexpr3.C: New test.
---
 gcc/cp/constexpr.cc  | 56 +++-
 gcc/testsuite/g++.dg/diagnostic/constexpr3.C | 32 +++
 2 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/constexpr3.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8bd5c4a47f8..6d5aed82377 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3381,6 +3381,54 @@ ok:
 }
 }
 
+/* *TP was not deemed constant by reduced_constant_expression_p.  Explain
+   why and suggest what could be done about it.  */
+
+static tree
+verify_constant_explain_r (tree *tp, int *, void *)
+{
+  bool ref_p = false;
+
+  switch (TREE_CODE (*tp))
+{
+CASE_CONVERT:
+  if (TREE_CODE (TREE_OPERAND (*tp, 0)) != ADDR_EXPR)
+   break;
+  ref_p = TYPE_REF_P (TREE_TYPE (*tp));
+  *tp = TREE_OPERAND (*tp, 0);
+  gcc_fallthrough ();
+case ADDR_EXPR:
+  {
+   tree op = TREE_OPERAND (*tp, 0);
+   if (VAR_P (op)
+   && DECL_DECLARED_CONSTEXPR_P (op)
+   && !TREE_STATIC (op)
+   /* ??? We should also say something about temporaries.  */
+   && !DECL_ARTIFICIAL (op))
+ {
+   if (ref_p)
+ inform (location_of (*tp), "reference to %qD is not a constant "
+ "expression", op);
+   else
+ inform (location_of (*tp), "pointer to %qD is not a constant "
+ "expression", op);
+   const location_t op_loc = DECL_SOURCE_LOCATION (op);
+   rich_location richloc (line_table, op_loc);
+   richloc.add_fixit_insert_before (op_loc, "static ");
+   inform (,
+   "address of non-static constexpr variable %qD may differ on 
"
+   "each invocation of the enclosing function; add % "
+   "to give it a constant address", op);
+ }
+   break;
+  }
+default:
+  break;
+}
+
+  return NULL_TREE;
+}
+
 /* Some expressions may have constant operands but are not constant
themselves, such as 1/0.  Call this function to check for that
condition.
@@ -3398,7 +3446,13 @@ verify_constant (tree t, bool allow_non_constant, bool 
*non_constant_p,
   && t != void_node)
 {
   if (!allow_non_constant)
-   error ("%q+E is not a constant expression", t);
+   {
+ auto_diagnostic_group d;
+ error_at (cp_expr_loc_or_input_loc (t),
+   "%q+E is not a constant expression", t);
+ cp_walk_tree_without_duplicates (, verify_constant_explain_r,
+  nullptr);
+   }
   *non_constant_p = true;
 }
   if (TREE_OVERFLOW_P (t))
diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr3.C 
b/gcc/testsuite/g++.dg/diagnostic/constexpr3.C
new file mode 100644
index 000..b6e43a93664
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/constexpr3.C
@@ -0,0 +1,32 @@
+// { dg-do compile { target c++14 } }
+
+struct X {
+  int const& var;
+};
+
+struct A {
+  A *ap = this;
+};
+
+constexpr A
+foo ()
+{
+  return {};
+}
+
+void
+test ()
+{
+  constexpr int i = 42; // { dg-message "may differ on each invocation" }
+
+  constexpr X x{i}; // { dg-error "not a constant expression" }
+  // { dg-message "reference to .i. is not a constant expression" "" { target 
*-*-* } .-1 }
+  constexpr const int *p =  // { dg-error "not a constant expression" }
+  // { dg-message "pointer to .i. is not a constant expression" "" { target 
*-*-* } .-1 }
+
+  constexpr A a = foo (); // { dg-error "not a constant expression" }
+  // { dg-message "pointer to .a. is not a constant expression|may differ" "" 
{ target *-*-* } .-1 }
+
+  constexpr const int *q = __builtin_launder (); // { dg-error "not a 
constant expression" }
+  // { dg-message "pointer to .i. is not a constant expression" "" { target 
*-*-* } .-1 }
+}

base-commit: 6f06152541d62ae7c8579b7d7bf552be19e15b05
-- 
2.41.0



Re: [PATCH] c++: Move consteval folding to cp_fold_r

2023-09-01 Thread Marek Polacek via Gcc-patches
On Fri, Sep 01, 2023 at 01:23:48PM -0400, Marek Polacek via Gcc-patches wrote:
> --- a/gcc/cp/cp-gimplify.cc
> +++ b/gcc/cp/cp-gimplify.cc
[...]
>  case ADDR_EXPR:
>if (TREE_CODE (TREE_OPERAND (stmt, 0)) == FUNCTION_DECL
> -   && DECL_IMMEDIATE_FUNCTION_P (TREE_OPERAND (stmt, 0)))
> +   && DECL_IMMEDIATE_FUNCTION_P (TREE_OPERAND (stmt, 0))
> +   && !in_immediate_context ())

This hunk isn't actually necessary.  I'm happy to drop it.  Or add the
in_immediate_context check into case PTRMEM_CST too.

Marek



[PATCH] c++: Move consteval folding to cp_fold_r

2023-09-01 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

In the review of P2564:

it turned out that in order to correctly handle an example in the paper,
we should stop doing immediate evaluation in build_over_call and
bot_replace, and instead do it in cp_fold_r.  This patch does that.

Another benefit is that this is a pretty significant simplification, at
least in my opinion.  Also, this fixes the c++/110997 ICE (but the test
doesn't compile yet).

The main drawback seems to be that cp_fold_r doesn't process as much
code as we did before: uninstantiated templates and things like
"false ? foo () : 1".

You'll see that I've reintroduced ADDR_EXPR_DENOTES_CALL_P here.  This
is to detect

  *()) ()
  (s.*::foo) ()

which were deemed ill-formed.

gcc/cp/ChangeLog:

* call.cc (in_immediate_context): No longer static.
(build_over_call): Set ADDR_EXPR_DENOTES_CALL_P.  Don't handle
immediate_invocation_p here.
* constexpr.cc (cxx_eval_call_expression): Use mce_true for
immediate_invocation_p.
* cp-gimplify.cc (cp_fold_r): Expand immediate invocations.
* cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.
(immediate_invocation_p): Declare.
* tree.cc (bot_replace): Don't handle immediate invocations here.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/consteval-if2.C: Add xfail.
* g++.dg/cpp2a/consteval-memfn1.C: Adjust.
* g++.dg/cpp2a/consteval11.C: Remove dg-message.
* g++.dg/cpp2a/consteval3.C: Remove dg-message and dg-error.
* g++.dg/cpp2a/consteval9.C: Remove dg-message.
* g++.dg/cpp2a/consteval32.C: New test.
* g++.dg/cpp2a/consteval33.C: New test.

libstdc++-v3/ChangeLog:

* testsuite/20_util/allocator/105975.cc: Add dg-error.
---
 gcc/cp/call.cc| 42 +++
 gcc/cp/constexpr.cc   |  5 +++
 gcc/cp/cp-gimplify.cc | 14 ++-
 gcc/cp/cp-tree.h  |  6 +++
 gcc/cp/tree.cc| 23 +-
 gcc/testsuite/g++.dg/cpp23/consteval-if2.C|  2 +-
 gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C |  7 
 gcc/testsuite/g++.dg/cpp2a/consteval11.C  | 37 
 gcc/testsuite/g++.dg/cpp2a/consteval3.C   |  3 +-
 gcc/testsuite/g++.dg/cpp2a/consteval32.C  |  4 ++
 gcc/testsuite/g++.dg/cpp2a/consteval33.C  | 34 +++
 gcc/testsuite/g++.dg/cpp2a/consteval9.C   |  2 +-
 .../testsuite/20_util/allocator/105975.cc |  2 +-
 13 files changed, 100 insertions(+), 81 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval32.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval33.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 40d9fdc0516..abdbc8fff8c 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9763,7 +9763,7 @@ in_immediate_context ()
 /* Return true if a call to FN with number of arguments NARGS
is an immediate invocation.  */
 
-static bool
+bool
 immediate_invocation_p (tree fn)
 {
   return (TREE_CODE (fn) == FUNCTION_DECL
@@ -10471,6 +10471,10 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
   fn = build_addr_func (fn, complain);
   if (fn == error_mark_node)
return error_mark_node;
+
+  /* We're actually invoking the function.  (Immediate functions get an
+& when invoking it even though the user didn't use &.)  */
+  ADDR_EXPR_DENOTES_CALL_P (fn) = true;
 }
 
   tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
@@ -10488,41 +10492,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
   if (TREE_CODE (c) == CALL_EXPR)
suppress_warning (c /* Suppress all warnings.  */);
 }
-  if (TREE_CODE (fn) == ADDR_EXPR)
-{
-  tree fndecl = STRIP_TEMPLATE (TREE_OPERAND (fn, 0));
-  if (immediate_invocation_p (fndecl))
-   {
- tree obj_arg = NULL_TREE;
- /* Undo convert_from_reference called by build_cxx_call.  */
- if (REFERENCE_REF_P (call))
-   call = TREE_OPERAND (call, 0);
- if (DECL_CONSTRUCTOR_P (fndecl))
-   obj_arg = cand->first_arg ? cand->first_arg : (*args)[0];
- if (obj_arg && is_dummy_object (obj_arg))
-   {
- call = build_cplus_new (DECL_CONTEXT (fndecl), call, complain);
- obj_arg = NULL_TREE;
-   }
- /* Look through *(const T *)  */
- else if (obj_arg && INDIRECT_REF_P (obj_arg))
-   {
- tree addr = TREE_OPERAND (obj_arg, 0);
- STRIP_NOPS (addr);
- if (TREE_CODE (addr) == ADDR_EXPR)
-   {
- tree typeo = TREE_TYPE (obj_arg);
- tree typei = TREE_TYPE (TREE_OPERAND (addr, 0));
- if (same_type_ignoring_top_level_qualifiers_p 

Re: [PATCH] c++: CWG 2359, wrong copy-init with designated init [PR91319]

2023-08-30 Thread Marek Polacek via Gcc-patches
On Tue, Aug 29, 2023 at 04:44:11PM -0400, Jason Merrill wrote:
> On 8/28/23 19:09, Marek Polacek wrote:
> > On Mon, Aug 28, 2023 at 06:27:26PM -0400, Jason Merrill wrote:
> > > On 8/25/23 12:44, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > 
> > > > This CWG clarifies that designated initializer support 
> > > > direct-initialization.
> > > > Just be careful what Note 2 in [dcl.init.aggr]/4.2 says: "If the
> > > > initialization is by designated-initializer-clause, its form determines
> > > > whether copy-initialization or direct-initialization is performed."  
> > > > Hence
> > > > this patch sets CONSTRUCTOR_IS_DIRECT_INIT only when we are dealing with
> > > > ".x{}", but not ".x = {}".
> > > > 
> > > > PR c++/91319
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * parser.cc (cp_parser_initializer_list): Set 
> > > > CONSTRUCTOR_IS_DIRECT_INIT
> > > > when the designated initializer is of the .x{} form.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp2a/desig30.C: New test.
> > > > ---
> > > >gcc/cp/parser.cc |  6 ++
> > > >gcc/testsuite/g++.dg/cpp2a/desig30.C | 22 ++
> > > >2 files changed, 28 insertions(+)
> > > >create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig30.C
> > > > 
> > > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > > > index eeb22e44fb4..b3d5c65b469 100644
> > > > --- a/gcc/cp/parser.cc
> > > > +++ b/gcc/cp/parser.cc
> > > > @@ -25718,6 +25718,7 @@ cp_parser_initializer_list (cp_parser* parser, 
> > > > bool* non_constant_p,
> > > >  tree designator;
> > > >  tree initializer;
> > > >  bool clause_non_constant_p;
> > > > +  bool direct_p = false;
> > > >  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
> > > >  /* Handle the C++20 syntax, '. id ='.  */
> > > > @@ -25740,6 +25741,8 @@ cp_parser_initializer_list (cp_parser* parser, 
> > > > bool* non_constant_p,
> > > >   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
> > > > /* Consume the `='.  */
> > > > cp_lexer_consume_token (parser->lexer);
> > > > + else
> > > > +   direct_p = true;
> > > > }
> > > >  /* Also, if the next token is an identifier and the following 
> > > > one is a
> > > >  colon, we are looking at the GNU designated-initializer
> > > > @@ -25817,6 +25820,9 @@ cp_parser_initializer_list (cp_parser* parser, 
> > > > bool* non_constant_p,
> > > >  if (clause_non_constant_p && non_constant_p)
> > > > *non_constant_p = true;
> > > > +  if (TREE_CODE (initializer) == CONSTRUCTOR)
> > > > +   CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p;
> > > 
> > > Why |= rather than = ?
> > 
> > CONSTRUCTOR_IS_DIRECT_INIT could already have been set earlier so using
> > = might wrongly clear it.  I saw this in direct-enum-init1.C.
> 
> What is setting it earlier?

cp_parser_functional_cast.  Test:

enum class C {};

template 
void
foo ()
{
  C c = { C{8} };
}

void
test ()
{
  foo<0> ();
}

The template actually matters here because then finish_compound_literal
returns {8} and not just 8 due to:

  /* If we're in a template, return the original compound literal.  */
  if (orig_cl)
return orig_cl;
 
> The patch is OK with a comment explaining that.

Ok, I'll say that CONSTRUCTOR_IS_DIRECT_INIT could have been set in
cp_parser_functional_cast so we must be careful not to clear the flag.
Thanks,

Marek



Re: RFC: Introduce -fhardened to enable security-related flags

2023-08-29 Thread Marek Polacek via Gcc-patches
On Tue, Aug 29, 2023 at 09:11:35PM +0100, Sam James via Gcc-patches wrote:
> 
> Marek Polacek via Gcc-patches  writes:
> 
> > Improving the security of software has been a major trend in the recent
> > years.  Fortunately, GCC offers a wide variety of flags that enable extra
> > hardening.  These flags aren't enabled by default, though.  And since
> > there are a lot of hardening flags, with more to come, it's been difficult
> > to keep on top of them; more so for the users of GCC who ought not to be
> > expected to keep track of all the new options.
> >
> > To alleviate some of the problems I mentioned, we thought it would
> > be useful to provide a new umbrella option that enables a reasonable set
> > of hardening flags.  What's "reasonable" in this context is not easy to
> > pin down.  Surely, there must be no ABI impact, the option cannot cause
> > severe performance issues, and, I suspect, it should not cause build
> > errors by enabling stricter compile-time errors (such as, -Wimplicit-int,
> > -Wint-conversion).  Including a controversial option in -fhardened
> > would likely cause that users would not use -fhardened at all.  It's
> > roughly akin to -Wall or -O2 -- those also enable a reasonable set of
> > options, and evolve over time, and are not kept in sync with other
> > compilers.
> >
> > Currently, -fhardened enables:
> 
> Right now, we patch the compiler in Gentoo to default to these
> (some always, some only if the user requests hardening).
> 
> It's a bit invasive (trivial, but just a bit messy) and it gets
> pretty tedious to rebase it.

Yeah, I bet.

> I'd find it really helpful to be able
> to instead default on -fhardened from a maintenance perspective.

That's good feedback.
 
> >
> >   -D_FORTIFY_SOURCE=3 (or =2 for older glibcs)
> >   -D_GLIBCXX_ASSERTIONS
> >   -ftrivial-auto-var-init=zero
> >   -fPIE  -pie  -Wl,-z,relro,-z,now
> >   -fstack-protector-strong
> >   -fstack-clash-protection
> >   -fcf-protection=full (x86 GNU/Linux only)
> >
> 
> ... and I also think it's going to be useful for people when
> debugging/developing. We can tell them to simply use -fhardened and
> then they'll know the compiler will give them the equivalent of -Wall
> in terms of sanity checks to help find problems.
> 
> It should be useful for folks who just want to slap it in their CI as
> well without keeping up with the various new developments and compiler
> features.

Yup, pretty much the intended usage.

Thanks!

Marek



Re: [PATCH v2] c++: tweaks for explicit conversion fns diagnostic

2023-08-29 Thread Marek Polacek via Gcc-patches
On Tue, Aug 29, 2023 at 04:42:33PM -0400, Jason Merrill wrote:
> On 8/28/23 19:24, Marek Polacek wrote:
> > On Fri, Aug 25, 2023 at 08:34:37PM -0400, Jason Merrill wrote:
> > > On 8/25/23 19:37, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > -- >8 --
> > > > 
> > > > 1) When saying that a conversion is erroneous because it would use
> > > > an explicit constructor, it might be nice to show where exactly
> > > > the explicit constructor is located.  For example, with this patch:
> > > > 
> > > > [...]
> > > > explicit.C:4:12: note: 'S::S(int)' declared here
> > > >   4 |   explicit S(int) { }
> > > > |^
> > > > 
> > > > 2) When a conversion doesn't work out merely because the conversion
> > > > function necessary to do the conversion couldn't be used because
> > > > it was marked explicit, it would be useful to the user to say so,
> > > > rather than just saying "cannot convert".  For example, with this patch:
> > > > 
> > > > explicit.C:13:12: error: cannot convert 'S' to 'bool' in initialization
> > > >  13 |   bool b = S{1};
> > > > |^~~~
> > > > ||
> > > > |S
> > > > explicit.C:5:12: note: explicit conversion function was not considered
> > > >   5 |   explicit operator bool() const { return true; }
> > > > |^~~~
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * call.cc (convert_like_internal): Show where the conversion 
> > > > function
> > > > was declared.
> > > > (maybe_show_nonconverting_candidate): New.
> > > > * cp-tree.h (maybe_show_nonconverting_candidate): Declare.
> > > > * typeck.cc (convert_for_assignment): Call it.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/diagnostic/explicit.C: New test.
> > > > ---
> > > >gcc/cp/call.cc | 41 
> > > > +++---
> > > >gcc/cp/cp-tree.h   |  1 +
> > > >gcc/cp/typeck.cc   |  5 +++
> > > >gcc/testsuite/g++.dg/diagnostic/explicit.C | 16 +
> > > >4 files changed, 59 insertions(+), 4 deletions(-)
> > > >create mode 100644 gcc/testsuite/g++.dg/diagnostic/explicit.C
> > > > 
> > > > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > > > index 23e458d3252..09ebcf6a115 100644
> > > > --- a/gcc/cp/call.cc
> > > > +++ b/gcc/cp/call.cc
> > > > @@ -8459,12 +8459,21 @@ convert_like_internal (conversion *convs, tree 
> > > > expr, tree fn, int argnum,
> > > > if (pedwarn (loc, 0, "converting to %qT from 
> > > > initializer list "
> > > >  "would use explicit constructor %qD",
> > > >  totype, convfn))
> > > > - inform (loc, "in C++11 and above a default 
> > > > constructor "
> > > > - "can be explicit");
> > > > + {
> > > > +   inform (loc, "in C++11 and above a default 
> > > > constructor "
> > > > +   "can be explicit");
> > > > +   inform (DECL_SOURCE_LOCATION (convfn), "%qD 
> > > > declared here",
> > > > +   convfn);
> > > 
> > > I'd swap these two informs.
> > 
> > Done.
> > > > +++ b/gcc/testsuite/g++.dg/diagnostic/explicit.C
> > > > @@ -0,0 +1,16 @@
> > > > +// { dg-do compile { target c++11 } }
> > > > +
> > > > +struct S {
> > > > +  explicit S(int) { }
> > > > +  explicit operator bool() const { return true; } // { dg-message 
> > > > "explicit conversion function was not considered" }
> > > > +  explicit operator int() const { return 42; } // { dg-message 
> > > > "explicit conversion function was not considered" }
> > > > +};
> > > > +
> > > > +void
> > > > +g ()
> > > > +{
> > > > +  S s = {1}; // { dg-error "would use explicit constructor" }
> > > > +  bool b = S{1}; // { dg-error "cannot convert .S. to .bool. in 
> > > > initialization" }
> > > > +  int i;
> > > > +  i = S{2}; // { dg-error "cannot convert .S. to .int. in assignment" }
> > > > +}
> > > 
> > > Let's also test other copy-initialization contexts: parameter passing,
> > > return, throw, aggregate member initialization.
> > 
> > Done except for throw.  To handle arg passing I moved the call to
> > maybe_show_nonconverting_candidate one line down.  I guess a testcase
> > for throw would be
> > 
> > struct T {
> >T() { } // #1
> >explicit T(const T&) { } // #2
> > };
> > 
> > void
> > g ()
> > {
> >T t{};
> >throw t;
> > }
> > 
> > but #2 isn't a viable candidate so this would take more effort to handle.
> 
> True, copy-initialization is different when the types are the same.
> 
> > We just say about #1 that "candidate expects 0 arguments, 1 provided".
> > 
> > clang++ says
> > 
> > e.C:3:12: note: explicit constructor is not a candidate
> >  3 |   explicit T(const T&) { }
> >|^
> 

RFC: Introduce -fhardened to enable security-related flags

2023-08-29 Thread Marek Polacek via Gcc-patches
Improving the security of software has been a major trend in the recent
years.  Fortunately, GCC offers a wide variety of flags that enable extra
hardening.  These flags aren't enabled by default, though.  And since
there are a lot of hardening flags, with more to come, it's been difficult
to keep on top of them; more so for the users of GCC who ought not to be
expected to keep track of all the new options.

To alleviate some of the problems I mentioned, we thought it would
be useful to provide a new umbrella option that enables a reasonable set
of hardening flags.  What's "reasonable" in this context is not easy to
pin down.  Surely, there must be no ABI impact, the option cannot cause
severe performance issues, and, I suspect, it should not cause build
errors by enabling stricter compile-time errors (such as, -Wimplicit-int,
-Wint-conversion).  Including a controversial option in -fhardened
would likely cause that users would not use -fhardened at all.  It's
roughly akin to -Wall or -O2 -- those also enable a reasonable set of
options, and evolve over time, and are not kept in sync with other
compilers.

Currently, -fhardened enables:

  -D_FORTIFY_SOURCE=3 (or =2 for older glibcs)
  -D_GLIBCXX_ASSERTIONS
  -ftrivial-auto-var-init=zero
  -fPIE  -pie  -Wl,-z,relro,-z,now
  -fstack-protector-strong
  -fstack-clash-protection
  -fcf-protection=full (x86 GNU/Linux only)

-fsanitize=undefined is specifically not enabled.  -fstrict-flex-arrays is
also liable to break a lot of code so I didn't include it.

Appended is a proof-of-concept patch.  It doesn't implement --help=hardened
yet.  A fairly crucial point is that -fhardened will not override options
that were specified on the command line (before or after -fhardened).  For
example,
 
 -D_FORTIFY_SOURCE=1 -fhardened

means that _FORTIFY_SOURCE=1 will be used.  Similarly,

  -fhardened -fstack-protector

will not enable -fstack-protector-strong.

Thoughts?

---
 gcc/c-family/c-opts.cc | 25 
 gcc/common.opt |  4 +++
 gcc/config/i386/i386-options.cc| 11 ++-
 gcc/doc/invoke.texi| 29 +-
 gcc/gcc.cc | 35 +-
 gcc/opts.cc| 15 --
 gcc/testsuite/c-c++-common/fhardened-1.S   |  6 
 gcc/testsuite/c-c++-common/fhardened-1.c   | 18 +++
 gcc/testsuite/c-c++-common/fhardened-10.c  | 10 +++
 gcc/testsuite/c-c++-common/fhardened-2.c   | 12 
 gcc/testsuite/c-c++-common/fhardened-3.c   | 12 
 gcc/testsuite/c-c++-common/fhardened-5.c   | 11 +++
 gcc/testsuite/c-c++-common/fhardened-6.c   | 11 +++
 gcc/testsuite/c-c++-common/fhardened-7.c   |  7 +
 gcc/testsuite/c-c++-common/fhardened-8.c   |  7 +
 gcc/testsuite/c-c++-common/fhardened-9.c   |  6 
 gcc/testsuite/gcc.misc-tests/help.exp  |  2 ++
 gcc/testsuite/gcc.target/i386/cf_check-6.c | 12 
 gcc/toplev.cc  |  6 
 19 files changed, 233 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-1.S
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-1.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-10.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-2.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-3.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-5.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-6.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-7.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-8.c
 create mode 100644 gcc/testsuite/c-c++-common/fhardened-9.c
 create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-6.c

diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index 4961af63de8..764714ba8a5 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -1514,6 +1514,9 @@ c_finish_options (void)
   cb_file_change (parse_in, cmd_map);
   linemap_line_start (line_table, 0, 1);
 
+  bool fortify_seen_p = false;
+  bool cxx_assert_seen_p = false;
+
   /* All command line defines must have the same location.  */
   cpp_force_token_locations (parse_in, line_table->highest_line);
   for (size_t i = 0; i < deferred_count; i++)
@@ -1531,6 +1534,28 @@ c_finish_options (void)
  else
cpp_assert (parse_in, opt->arg);
}
+
+ if (UNLIKELY (flag_hardened)
+ && (opt->code == OPT_D || opt->code == OPT_U))
+   {
+ if (!fortify_seen_p)
+   fortify_seen_p = !strncmp (opt->arg, "_FORTIFY_SOURCE", 15);
+ if (!cxx_assert_seen_p)
+   cxx_assert_seen_p = !strcmp (opt->arg, "_GLIBCXX_ASSERTIONS");
+   }
+   }
+
+  if (flag_hardened)
+   {
+ if (!fortify_seen_p && optimize > 0)
+   {
+ if (TARGET_GLIBC_MAJOR == 2 && 

[PATCH] c++: disallow constinit on functions [PR111173]

2023-08-29 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

[dcl.constinit]/1: The constinit specifier shall be applied only to a 
declaration
of a variable with static or thread storage duration.

and while we detect

  constinit int fn();

we weren't detecting

  using F = int();
  constinit F f;

PR c++/73

gcc/cp/ChangeLog:

* decl.cc (grokdeclarator): Disallow constinit on functions.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constinit19.C: New test.
---
 gcc/cp/decl.cc   | 3 +++
 gcc/testsuite/g++.dg/cpp2a/constinit19.C | 5 +
 2 files changed, 8 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constinit19.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index bea0ee92106..a0e8a24efc0 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -14639,6 +14639,9 @@ grokdeclarator (const cp_declarator *declarator,
"storage class % invalid for "
"function %qs", name);
  }
+   else if (constinit_p)
+ error_at (declspecs->locations[ds_constinit],
+   "% specifier invalid for function %qs", name);
 
 if (virt_specifiers)
   error ("virt-specifiers in %qs not allowed outside a class "
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit19.C 
b/gcc/testsuite/g++.dg/cpp2a/constinit19.C
new file mode 100644
index 000..5be610a18a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit19.C
@@ -0,0 +1,5 @@
+// PR c++/73
+// { dg-do compile { target c++20 } }
+
+using Function = int();
+constinit Function f; // { dg-error ".constinit. specifier invalid for 
function" }

base-commit: fce74ce2535aa3b7648ba82e7e61eb77d0175546
-- 
2.41.0



[PATCH v2] c++: tweaks for explicit conversion fns diagnostic

2023-08-28 Thread Marek Polacek via Gcc-patches
On Fri, Aug 25, 2023 at 08:34:37PM -0400, Jason Merrill wrote:
> On 8/25/23 19:37, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > 
> > 1) When saying that a conversion is erroneous because it would use
> > an explicit constructor, it might be nice to show where exactly
> > the explicit constructor is located.  For example, with this patch:
> > 
> > [...]
> > explicit.C:4:12: note: 'S::S(int)' declared here
> >  4 |   explicit S(int) { }
> >|^
> > 
> > 2) When a conversion doesn't work out merely because the conversion
> > function necessary to do the conversion couldn't be used because
> > it was marked explicit, it would be useful to the user to say so,
> > rather than just saying "cannot convert".  For example, with this patch:
> > 
> > explicit.C:13:12: error: cannot convert 'S' to 'bool' in initialization
> > 13 |   bool b = S{1};
> >|^~~~
> >||
> >|S
> > explicit.C:5:12: note: explicit conversion function was not considered
> >  5 |   explicit operator bool() const { return true; }
> >|^~~~
> > 
> > gcc/cp/ChangeLog:
> > 
> > * call.cc (convert_like_internal): Show where the conversion function
> > was declared.
> > (maybe_show_nonconverting_candidate): New.
> > * cp-tree.h (maybe_show_nonconverting_candidate): Declare.
> > * typeck.cc (convert_for_assignment): Call it.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/diagnostic/explicit.C: New test.
> > ---
> >   gcc/cp/call.cc | 41 +++---
> >   gcc/cp/cp-tree.h   |  1 +
> >   gcc/cp/typeck.cc   |  5 +++
> >   gcc/testsuite/g++.dg/diagnostic/explicit.C | 16 +
> >   4 files changed, 59 insertions(+), 4 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/diagnostic/explicit.C
> > 
> > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > index 23e458d3252..09ebcf6a115 100644
> > --- a/gcc/cp/call.cc
> > +++ b/gcc/cp/call.cc
> > @@ -8459,12 +8459,21 @@ convert_like_internal (conversion *convs, tree 
> > expr, tree fn, int argnum,
> > if (pedwarn (loc, 0, "converting to %qT from initializer list "
> >  "would use explicit constructor %qD",
> >  totype, convfn))
> > - inform (loc, "in C++11 and above a default constructor "
> > - "can be explicit");
> > + {
> > +   inform (loc, "in C++11 and above a default constructor "
> > +   "can be explicit");
> > +   inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
> > +   convfn);
> 
> I'd swap these two informs.

Done.
 
> > +++ b/gcc/testsuite/g++.dg/diagnostic/explicit.C
> > @@ -0,0 +1,16 @@
> > +// { dg-do compile { target c++11 } }
> > +
> > +struct S {
> > +  explicit S(int) { }
> > +  explicit operator bool() const { return true; } // { dg-message 
> > "explicit conversion function was not considered" }
> > +  explicit operator int() const { return 42; } // { dg-message "explicit 
> > conversion function was not considered" }
> > +};
> > +
> > +void
> > +g ()
> > +{
> > +  S s = {1}; // { dg-error "would use explicit constructor" }
> > +  bool b = S{1}; // { dg-error "cannot convert .S. to .bool. in 
> > initialization" }
> > +  int i;
> > +  i = S{2}; // { dg-error "cannot convert .S. to .int. in assignment" }
> > +}
> 
> Let's also test other copy-initialization contexts: parameter passing,
> return, throw, aggregate member initialization.

Done except for throw.  To handle arg passing I moved the call to
maybe_show_nonconverting_candidate one line down.  I guess a testcase
for throw would be

struct T {
  T() { } // #1
  explicit T(const T&) { } // #2
};

void
g ()
{
  T t{};
  throw t;
}

but #2 isn't a viable candidate so this would take more effort to handle.
We just say about #1 that "candidate expects 0 arguments, 1 provided".

clang++ says

e.C:3:12: note: explicit constructor is not a candidate
3 |   explicit T(const T&) { }
  |^

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

-- >8 --
1) When saying that a conversion is erroneous because it would use
an explicit constructor, it might be nice to show where exactly
the explicit constructor is located.  For example, with this patch:

[...]
explicit.C:4:12: note: 'S::S(int)' declared here
4 |   explicit S(int) { }
  |^

2) When a conversion doesn't work out merely because the conversion
function necessary to do the conversion couldn't be used because
it was marked explicit, it would be useful to the user to say so,
rather than just saying "cannot convert".  For example, with this patch:

explicit.C:13:12: error: cannot convert 'S' to 'bool' in initialization
   13 |   bool b = S{1};
  |^~~~
  |

Re: [PATCH] c++: CWG 2359, wrong copy-init with designated init [PR91319]

2023-08-28 Thread Marek Polacek via Gcc-patches
On Mon, Aug 28, 2023 at 06:27:26PM -0400, Jason Merrill wrote:
> On 8/25/23 12:44, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > 
> > This CWG clarifies that designated initializer support 
> > direct-initialization.
> > Just be careful what Note 2 in [dcl.init.aggr]/4.2 says: "If the
> > initialization is by designated-initializer-clause, its form determines
> > whether copy-initialization or direct-initialization is performed."  Hence
> > this patch sets CONSTRUCTOR_IS_DIRECT_INIT only when we are dealing with
> > ".x{}", but not ".x = {}".
> > 
> > PR c++/91319
> > 
> > gcc/cp/ChangeLog:
> > 
> > * parser.cc (cp_parser_initializer_list): Set CONSTRUCTOR_IS_DIRECT_INIT
> > when the designated initializer is of the .x{} form.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp2a/desig30.C: New test.
> > ---
> >   gcc/cp/parser.cc |  6 ++
> >   gcc/testsuite/g++.dg/cpp2a/desig30.C | 22 ++
> >   2 files changed, 28 insertions(+)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig30.C
> > 
> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > index eeb22e44fb4..b3d5c65b469 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -25718,6 +25718,7 @@ cp_parser_initializer_list (cp_parser* parser, 
> > bool* non_constant_p,
> > tree designator;
> > tree initializer;
> > bool clause_non_constant_p;
> > +  bool direct_p = false;
> > location_t loc = cp_lexer_peek_token (parser->lexer)->location;
> > /* Handle the C++20 syntax, '. id ='.  */
> > @@ -25740,6 +25741,8 @@ cp_parser_initializer_list (cp_parser* parser, 
> > bool* non_constant_p,
> >   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
> > /* Consume the `='.  */
> > cp_lexer_consume_token (parser->lexer);
> > + else
> > +   direct_p = true;
> > }
> > /* Also, if the next token is an identifier and the following one 
> > is a
> >  colon, we are looking at the GNU designated-initializer
> > @@ -25817,6 +25820,9 @@ cp_parser_initializer_list (cp_parser* parser, 
> > bool* non_constant_p,
> > if (clause_non_constant_p && non_constant_p)
> > *non_constant_p = true;
> > +  if (TREE_CODE (initializer) == CONSTRUCTOR)
> > +   CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p;
> 
> Why |= rather than = ?

CONSTRUCTOR_IS_DIRECT_INIT could already have been set earlier so using
= might wrongly clear it.  I saw this in direct-enum-init1.C.

Marek



[PATCH] c++: tweaks for explicit conversion fns diagnostic

2023-08-25 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

1) When saying that a conversion is erroneous because it would use
an explicit constructor, it might be nice to show where exactly
the explicit constructor is located.  For example, with this patch:

[...]
explicit.C:4:12: note: 'S::S(int)' declared here
4 |   explicit S(int) { }
  |^

2) When a conversion doesn't work out merely because the conversion
function necessary to do the conversion couldn't be used because
it was marked explicit, it would be useful to the user to say so,
rather than just saying "cannot convert".  For example, with this patch:

explicit.C:13:12: error: cannot convert 'S' to 'bool' in initialization
   13 |   bool b = S{1};
  |^~~~
  ||
  |S
explicit.C:5:12: note: explicit conversion function was not considered
5 |   explicit operator bool() const { return true; }
  |^~~~

gcc/cp/ChangeLog:

* call.cc (convert_like_internal): Show where the conversion function
was declared.
(maybe_show_nonconverting_candidate): New.
* cp-tree.h (maybe_show_nonconverting_candidate): Declare.
* typeck.cc (convert_for_assignment): Call it.

gcc/testsuite/ChangeLog:

* g++.dg/diagnostic/explicit.C: New test.
---
 gcc/cp/call.cc | 41 +++---
 gcc/cp/cp-tree.h   |  1 +
 gcc/cp/typeck.cc   |  5 +++
 gcc/testsuite/g++.dg/diagnostic/explicit.C | 16 +
 4 files changed, 59 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/explicit.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..09ebcf6a115 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8459,12 +8459,21 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
if (pedwarn (loc, 0, "converting to %qT from initializer list "
 "would use explicit constructor %qD",
 totype, convfn))
- inform (loc, "in C++11 and above a default constructor "
- "can be explicit");
+ {
+   inform (loc, "in C++11 and above a default constructor "
+   "can be explicit");
+   inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
+   convfn);
+ }
  }
else
- error ("converting to %qT from initializer list would use "
-"explicit constructor %qD", totype, convfn);
+ {
+   auto_diagnostic_group d;
+   error ("converting to %qT from initializer list would use "
+  "explicit constructor %qD", totype, convfn);
+   inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
+   convfn);
+ }
  }
 
/* If we're initializing from {}, it's value-initialization.  */
@@ -14323,4 +14332,28 @@ is_list_ctor (tree decl)
   return true;
 }
 
+/* We know that can_convert_arg_bad already said "no" when trying to convert
+   FROM to TO with ARG and FLAGS.  Try to figure out if it was because
+   an explicit conversion function was skipped when looking for a way to
+   perform the conversion.  At this point we've already printed an error.  */
+
+void
+maybe_show_nonconverting_candidate (tree to, tree from, tree arg, int flags)
+{
+  if (!(flags & LOOKUP_ONLYCONVERTING))
+return;
+
+  conversion_obstack_sentinel cos;
+  conversion *c = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
+  flags & ~LOOKUP_ONLYCONVERTING, tf_none);
+  if (c && !c->bad_p && c->user_conv_p)
+/* Ay, the conversion would have worked in copy-init context.  */
+for (; c; c = next_conversion (c))
+  if (c->kind == ck_user
+ && DECL_P (c->cand->fn)
+ && DECL_NONCONVERTING_P (c->cand->fn))
+   inform (DECL_SOURCE_LOCATION (c->cand->fn), "explicit conversion "
+   "function was not considered");
+}
+
 #include "gt-cp-call.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 608d6310e53..6b225ca182f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6727,6 +6727,7 @@ extern bool cp_handle_deprecated_or_unavailable (tree, 
tsubst_flags_t = tf_warni
 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);
 
 /* in class.cc */
 extern tree build_vfield_ref   (tree, tree);
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index d5c0c85ed51..bf9963db3ba 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10262,6 +10262,8 @@ convert_for_assignment (tree type, 

Re: [PATCH] c++: use conversion_obstack_sentinel throughout

2023-08-25 Thread Marek Polacek via Gcc-patches
On Fri, Aug 25, 2023 at 12:33:31PM -0400, Patrick Palka via Gcc-patches wrote:
> Boostrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?

Very nice.  LGTM.
 
> -- >8 --
> 
> This replaces manual memory management via conversion_obstack_alloc(0)
> and obstack_free with the recently added conversion_obstack_sentinel,
> and also uses the latter in build_user_type_conversion and
> build_operator_new_call.
> 
> gcc/cp/ChangeLog:
> 
>   * call.cc (build_user_type_conversion): Free allocated
>   conversions.
>   (build_converted_constant_expr_internal): Use
>   conversion_obstack_sentinel instead.
>   (perform_dguide_overload_resolution): Likewise.
>   (build_new_function_call): Likewise.
>   (build_operator_new_call): Free allocated conversions.
>   (build_op_call): Use conversion_obstack_sentinel instead.
>   (build_conditional_expr): Use conversion_obstack_sentinel
>   instead, and hoist it out to the outermost scope.
>   (build_new_op): Use conversion_obstack_sentinel instead
>   and set it up before the first goto.  Remove second unneeded goto.
>   (build_op_subscript): Use conversion_obstack_sentinel instead.
>   (ref_conv_binds_to_temporary): Likewise.
>   (build_new_method_call): Likewise.
>   (can_convert_arg): Likewise.
>   (can_convert_arg_bad): Likewise.
>   (perform_implicit_conversion_flags): Likewise.
>   (perform_direct_initialization_if_possible): Likewise.
>   (initialize_reference): Likewise.
> ---
>  gcc/cp/call.cc | 107 ++---
>  1 file changed, 22 insertions(+), 85 deletions(-)
> 
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 673ec91d60e..432ac99b4bb 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -4646,6 +4646,9 @@ build_user_type_conversion (tree totype, tree expr, int 
> flags,
>tree ret;
>  
>auto_cond_timevar tv (TV_OVERLOAD);
> +
> +  conversion_obstack_sentinel cos;
> +
>cand = build_user_type_conversion_1 (totype, expr, flags, complain);
>  
>if (cand)
> @@ -4698,15 +4701,13 @@ build_converted_constant_expr_internal (tree type, 
> tree expr,
>   int flags, tsubst_flags_t complain)
>  {
>conversion *conv;
> -  void *p;
>tree t;
>location_t loc = cp_expr_loc_or_input_loc (expr);
>  
>if (error_operand_p (expr))
>  return error_mark_node;
>  
> -  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
> -  p = conversion_obstack_alloc (0);
> +  conversion_obstack_sentinel cos;
>  
>conv = implicit_conversion (type, TREE_TYPE (expr), expr,
> /*c_cast_p=*/false, flags, complain);
> @@ -4815,9 +4816,6 @@ build_converted_constant_expr_internal (tree type, tree 
> expr,
>expr = error_mark_node;
>  }
>  
> -  /* Free all the conversions we allocated.  */
> -  obstack_free (_obstack, p);
> -
>return expr;
>  }
>  
> @@ -4985,8 +4983,7 @@ perform_dguide_overload_resolution (tree dguides, const 
> vec *args,
>  
>gcc_assert (deduction_guide_p (OVL_FIRST (dguides)));
>  
> -  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
> -  void *p = conversion_obstack_alloc (0);
> +  conversion_obstack_sentinel cos;
>  
>z_candidate *cand = perform_overload_resolution (dguides, args, 
> ,
>  _viable_p, complain);
> @@ -4999,9 +4996,6 @@ perform_dguide_overload_resolution (tree dguides, const 
> vec *args,
>else
>  result = cand->fn;
>  
> -  /* Free all the conversions we allocated.  */
> -  obstack_free (_obstack, p);
> -
>return result;
>  }
>  
> @@ -5015,7 +5009,6 @@ build_new_function_call (tree fn, vec 
> **args,
>  {
>struct z_candidate *candidates, *cand;
>bool any_viable_p;
> -  void *p;
>tree result;
>  
>if (args != NULL && *args != NULL)
> @@ -5028,8 +5021,7 @@ build_new_function_call (tree fn, vec 
> **args,
>if (flag_tm)
>  tm_malloc_replacement (fn);
>  
> -  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
> -  p = conversion_obstack_alloc (0);
> +  conversion_obstack_sentinel cos;
>  
>cand = perform_overload_resolution (fn, *args, , _viable_p,
> complain);
> @@ -5061,9 +5053,6 @@ build_new_function_call (tree fn, vec 
> **args,
> == BUILT_IN_NORMAL)
> result = coro_validate_builtin_call (result);
>  
> -  /* Free all the conversions we allocated.  */
> -  obstack_free (_obstack, p);
> -
>return result;
>  }
>  
> @@ -5108,6 +5097,8 @@ build_operator_new_call (tree fnname, vec 
> **args,
>if (*args == NULL)
>  return error_mark_node;
>  
> +  conversion_obstack_sentinel cos;
> +
>/* Based on:
>  
> [expr.new]
> @@ -5234,7 +5225,6 @@ build_op_call (tree obj, vec **args, 
> tsubst_flags_t complain)
>tree fns, convs, first_mem_arg = NULL_TREE;
>bool any_viable_p;
>tree result = NULL_TREE;
> -  void *p;
>  
>

[PATCH] c++: CWG 2359, wrong copy-init with designated init [PR91319]

2023-08-25 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

This CWG clarifies that designated initializer support direct-initialization.
Just be careful what Note 2 in [dcl.init.aggr]/4.2 says: "If the
initialization is by designated-initializer-clause, its form determines
whether copy-initialization or direct-initialization is performed."  Hence
this patch sets CONSTRUCTOR_IS_DIRECT_INIT only when we are dealing with
".x{}", but not ".x = {}".

PR c++/91319

gcc/cp/ChangeLog:

* parser.cc (cp_parser_initializer_list): Set CONSTRUCTOR_IS_DIRECT_INIT
when the designated initializer is of the .x{} form.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig30.C: New test.
---
 gcc/cp/parser.cc |  6 ++
 gcc/testsuite/g++.dg/cpp2a/desig30.C | 22 ++
 2 files changed, 28 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig30.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index eeb22e44fb4..b3d5c65b469 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -25718,6 +25718,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
   tree designator;
   tree initializer;
   bool clause_non_constant_p;
+  bool direct_p = false;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Handle the C++20 syntax, '. id ='.  */
@@ -25740,6 +25741,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
  if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
/* Consume the `='.  */
cp_lexer_consume_token (parser->lexer);
+ else
+   direct_p = true;
}
   /* Also, if the next token is an identifier and the following one is a
 colon, we are looking at the GNU designated-initializer
@@ -25817,6 +25820,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
   if (clause_non_constant_p && non_constant_p)
*non_constant_p = true;
 
+  if (TREE_CODE (initializer) == CONSTRUCTOR)
+   CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p;
+
   /* If we have an ellipsis, this is an initializer pack
 expansion.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig30.C 
b/gcc/testsuite/g++.dg/cpp2a/desig30.C
new file mode 100644
index 000..d9292df9de2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig30.C
@@ -0,0 +1,22 @@
+// PR c++/91319
+// { dg-do compile { target c++20 } }
+
+struct X {
+explicit X() { }
+};
+
+struct Aggr {
+X x;
+};
+
+Aggr
+f ()
+{
+  return Aggr{.x{}};
+}
+
+Aggr
+f2 ()
+{
+  return Aggr{.x = {}}; // { dg-error "explicit constructor" }
+}

base-commit: 54cc21eaf5f3eb7f7a508919a086f6c8bf5c4c17
-- 
2.41.0



[PATCH] c++: implement P2564, consteval needs to propagate up [PR107687]

2023-08-23 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

This patch implements P2564, described at , whereby
certain functions are promoted to consteval.  For example:

  consteval int id(int i) { return i; }

  template 
  constexpr int f(T t)
  {
return t + id(t); // id causes f to be promoted to consteval
  }

  void g(int i)
  {
f (3);
  }

now compiles.  Previously the code was ill-formed: we would complain
that 't' in 'f' is not a constant expression.  Since 'f' is now
consteval, it means that the call to id(t) is in an immediate context,
so doesn't have to produce a constant -- this is how we allow consteval
functions composition.  But making 'f' consteval also means that
the call to 'f' in 'g' must yield a constant; failure to do so results
in an error.  I made the effort to have cc1plus explain to us what's
going on.  For example, calling f(i) produces this neat diagnostic:

q.C: In function 'void g(int)':
q.C:11:5: error: call to consteval function 'f(i)' is not a constant 
expression
   11 |   f (i);
  |   ~~^~~
q.C:6:16: note: 'constexpr int f(T) [with T = int]' was promoted to an 
immediate function because its body contains an immediate-escalating expression 
'id(t)'
6 |   return t + id(t);
  |  ~~^~~

which hopefully makes it clear what's going on.

Implementing this proposal has been tricky.  One problem was delayed
instantiation: instantiating a function can set off a domino effect
where one call promotes a function to consteval but that then means
that another function should also be promoted, etc.  I previously
thought that I could get past that by implementing the propagation in
cp_gimplify_expr at which point we have already instantiated everything
via instantiate_pending_templates.  But I realized that we don't
gimplify e.g.

  static auto p = 

and so we'd never detect taking the address of a consteval function.
Therefore this patch instantiates immediate-escalating functions
beforehand.  And as usual, there were a lot of other things to
handle.  It's not just calls to consteval functions that we must
detect, we also have to look for id-expressions that denote an
immediate function.

I discovered two crashes:
, ICE-on-valid with NSDMI
, missing ; causes an ICE
which this patch doesn't address, but adds a dg-ice test for the former.

I left one FIXME in the patch because I'm unclear on how to properly fix
the modules problem.

PR c++/107687

gcc/c-family/ChangeLog:

* c-cppbuiltin.cc (c_cpp_builtins): Update __cpp_consteval.

gcc/cp/ChangeLog:

* call.cc (immediate_invocation_p): No longer static.
(immediate_escalating_function_p): New.
(maybe_promote_function_to_consteval): New.
(build_over_call): Set ADDR_EXPR_DENOTES_CALL_P.  Maybe promote
current_function_decl to consteval.
* constexpr.cc (instantiate_cx_fn_r): No longer static.
* cp-gimplify.cc (struct find_escalating_expr_t): New.
(find_escalating_expr_r): New.
(maybe_explain_promoted_consteval): New.
(maybe_escalate_decl_and_cfun): New.
(cp_fold_r) : Handle promoting functions to consteval.
: New case, handle promoting functions to consteval.
: Handle promoting functions to consteval.
* cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.
(immediate_invocation_p): Declare.
(immediate_escalating_function_p): Declare.
(maybe_promote_function_to_consteval): Declare.
(instantiate_constexpr_fns): Declare.
* typeck.cc (cp_build_addr_expr_1): SET_EXPR_LOCATION on constexpr
functions as well.

libstdc++-v3/ChangeLog:

* testsuite/20_util/integer_comparisons/greater_equal_neg.cc: Adjust
expected diagnostic.
* testsuite/20_util/integer_comparisons/greater_neg.cc: Likewise.
* testsuite/20_util/integer_comparisons/less_equal_neg.cc: Likewise.
* testsuite/20_util/optional/monadic/or_else_neg.cc: Likewise.
* testsuite/23_containers/array/creation/3_neg.cc: Likewise.
* testsuite/23_containers/span/first_neg.cc: Likewise.
* testsuite/23_containers/span/last_neg.cc: Likewise.
* testsuite/23_containers/span/subspan_neg.cc: Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-inst1.C: Add dg-error.
* g++.dg/cpp23/consteval-if10.C: Remove dg-error.
* g++.dg/cpp23/consteval-if2.C: Likewise.
* g++.dg/cpp23/feat-cxx2b.C: Adjust expected value of __cpp_consteval.
* g++.dg/cpp26/feat-cxx26.C: Likewise.
* g++.dg/cpp2a/feat-cxx2a.C: Likewise.
* g++.dg/cpp2a/consteval-prop1.C: New test.
* g++.dg/cpp2a/consteval-prop10.C: New test.
* g++.dg/cpp2a/consteval-prop11.C: New test.
* g++.dg/cpp2a/consteval-prop12.C: New test.
* g++.dg/cpp2a/consteval-prop13.C: New test.
* g++.dg/cpp2a/consteval-prop14.C: New test.
   

Re: [PATCH V4] Add warning options -W[no-]compare-distinct-pointer-types

2023-08-23 Thread Marek Polacek via Gcc-patches
On Thu, Aug 17, 2023 at 05:37:03PM +0200, Jose E. Marchesi via Gcc-patches 
wrote:
> 
> > On Thu, 17 Aug 2023, Jose E. Marchesi via Gcc-patches wrote:
> >
> >> +@opindex Wcompare-distinct-pointer-types
> >> +@item -Wcompare-distinct-pointer-types
> >
> > This @item should say @r{(C and Objective-C only)}, since the option isn't 
> > implemented for C++.  OK with that change.
> 
> Pushed with that change.
> Thanks for the prompt review!

I see the following failures:

FAIL: gcc.c-torture/compile/pr106537-1.c   -Os   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-1.c   -Os   (test for warnings, line 30)
FAIL: gcc.c-torture/compile/pr106537-1.c   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-1.c   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none   (test for warnings, line 30)
FAIL: gcc.c-torture/compile/pr106537-1.c   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-1.c   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects   (test for warnings, line 30)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O0   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O0   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O1   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O1   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O2   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O2   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O3 -g   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O3 -g   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-2.c   -Os   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -Os   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none   (test for warnings, line 28)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects   (test for warnings, line 26)
FAIL: gcc.c-torture/compile/pr106537-2.c   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects   (test for warnings, line 28)

The problem is that for ==/!=, when one of the types is void*,
build_binary_op goes to the branch attempting to warn about
comparing void* with a function pointer, and never gets to the 
-Wcompare-distinct-pointer-types warning.

Marek



Re: [committed] i386: Fix grammar typo in diagnostic

2023-08-07 Thread Marek Polacek via Gcc-patches
On Mon, Aug 07, 2023 at 10:12:35PM +0100, Jonathan Wakely via Gcc-patches wrote:
> Committed as obvious.
> 
> Less obvious (to me) is whether it's correct to say "GCC V13" here. I
> don't think we refer to a version that way anywhere else, do we?
> 
> Would "since GCC 13.1.0" be better?

x86_field_alignment uses

  inform (input_location, "the alignment of %<_Atomic %T%> "
  "fields changed in %{GCC 11.1%}",

so maybe the below should use %{GCC 13.1%}.  "GCC V13" looks unusual
to me.

> -- >8 --
> 
> gcc/ChangeLog:
> 
>   * config/i386/i386.cc (ix86_invalid_conversion): Fix grammar.
> ---
>  gcc/config/i386/i386.cc | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index 50860050049..5d57726e22c 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -22890,7 +22890,7 @@ ix86_invalid_conversion (const_tree fromtype, 
> const_tree totype)
>   warning (0, "%<__bfloat16%> is redefined from typedef % "
>   "to real %<__bf16%> since GCC V13, be careful of "
>"implicit conversion between %<__bf16%> and %; "
> -  "a explicit bitcast may be needed here");
> +  "an explicit bitcast may be needed here");
>  }
>  
>/* Conversion allowed.  */
> -- 
> 2.41.0
> 

Marek



Re: [PATCH v2] analyzer: stash values for CPython plugin [PR107646]

2023-08-02 Thread Marek Polacek via Gcc-patches
On Wed, Aug 02, 2023 at 12:59:28PM -0400, David Malcolm wrote:
> On Wed, 2023-08-02 at 12:20 -0400, Eric Feng wrote:
> 
> Hi Eric, thanks for the updated patch.
> 
> Overall, looks good to me, although I'd drop the "Exited." from the
> "sorry" message (and thus from the dg-message directive), since the
> compiler is not exiting, it's just the particular plugin that's giving
> up (but let's not hold up the patch with a "bikeshed" discussion on the
> precise wording).
> 
> If Joseph or Marek approves the C parts of the patch, this will be OK
> to push to trunk.

[...]

> > index cf82b0306d1..617111b0f0a 100644
> > --- a/gcc/c/c-parser.cc
> > +++ b/gcc/c/c-parser.cc
> > @@ -1695,6 +1695,32 @@ public:
> >  return NULL_TREE;
> >    }
> >  
> > +  tree
> > +  lookup_type_by_id (tree id) const final override
> > +  {
> > +    if (tree type_decl = lookup_name (id))
> > +  {
> > +   if (TREE_CODE (type_decl) == TYPE_DECL)
> > + {
> > +   tree record_type = TREE_TYPE (type_decl);
> > +   if (TREE_CODE (record_type) == RECORD_TYPE)
> > + return record_type;
> > + }
> > +  }

I'd drop this set of { }, like below.  OK with that adjusted, thanks.

> > +
> > +    return NULL_TREE;
> > +  }
> > +
> > +  tree
> > +  lookup_global_var_by_id (tree id) const final override
> > +  {
> > +    if (tree var_decl = lookup_name (id))
> > +  if (TREE_CODE (var_decl) == VAR_DECL)
> > +   return var_decl;
> > +
> > +    return NULL_TREE;
> > +  }
> > +
> >  private:
> >    /* Attempt to get an INTEGER_CST from MACRO.
> >   Only handle the simplest cases: where MACRO's definition is a

Marek



[PATCH] c++: parser cleanup, remove dummy arguments

2023-07-31 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

Now that cp_parser_constant_expression accepts a null non_constant_p,
we can transitively remove dummy arguments in the call chain.

Running dg.exp and counting the # of is_rvalue_constant_expression calls
from cp_parser_constant_expression:
pre-r14-2800: 2,459,145
this patch  : 1,719,454

gcc/cp/ChangeLog:

* parser.cc (cp_parser_postfix_expression): Adjust the call to
cp_parser_braced_list.
(cp_parser_postfix_open_square_expression): Likewise.
(cp_parser_new_initializer): Likewise.
(cp_parser_assignment_expression): Adjust the call to
cp_parser_initializer_clause.
(cp_parser_lambda_introducer): Adjust the call to cp_parser_initializer.
(cp_parser_range_for): Adjust the call to cp_parser_braced_list.
(cp_parser_jump_statement): Likewise.
(cp_parser_mem_initializer): Likewise.
(cp_parser_template_argument): Likewise.
(cp_parser_default_argument): Adjust the call to cp_parser_initializer.
(cp_parser_initializer): Handle null is_direct_init and non_constant_p
arguments.
(cp_parser_initializer_clause): Handle null non_constant_p argument.
(cp_parser_braced_list): Likewise.
(cp_parser_initializer_list): Likewise.
(cp_parser_member_declaration): Adjust the call to
cp_parser_initializer_clause and cp_parser_initializer.
(cp_parser_yield_expression): Adjust the call to cp_parser_braced_list.
(cp_parser_functional_cast): Likewise.
(cp_parser_late_parse_one_default_arg): Adjust the call to
cp_parser_initializer.
(cp_parser_omp_for_loop_init): Likewise.
(cp_parser_omp_declare_reduction_exprs): Likewise.
---
 gcc/cp/parser.cc | 102 +++
 1 file changed, 41 insertions(+), 61 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index b1d2e141e35..957eb705b2a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2483,11 +2483,11 @@ static tree cp_parser_default_argument
 static void cp_parser_function_body
   (cp_parser *, bool);
 static tree cp_parser_initializer
-  (cp_parser *, bool *, bool *, bool = false);
+  (cp_parser *, bool * = nullptr, bool * = nullptr, bool = false);
 static cp_expr cp_parser_initializer_clause
-  (cp_parser *, bool *);
+  (cp_parser *, bool * = nullptr);
 static cp_expr cp_parser_braced_list
-  (cp_parser*, bool*);
+  (cp_parser*, bool * = nullptr);
 static vec *cp_parser_initializer_list
   (cp_parser *, bool *, bool *);
 
@@ -7734,12 +7734,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
/* If things aren't going well, there's no need to
   keep going.  */
if (!cp_parser_error_occurred (parser))
- {
-   bool non_constant_p;
-   /* Parse the brace-enclosed initializer list.  */
-   initializer = cp_parser_braced_list (parser,
-_constant_p);
- }
+ /* Parse the brace-enclosed initializer list.  */
+ initializer = cp_parser_braced_list (parser);
/* If that worked, we're definitely looking at a
   compound-literal expression.  */
if (cp_parser_parse_definitely (parser))
@@ -8203,10 +8199,9 @@ cp_parser_postfix_open_square_expression (cp_parser 
*parser,
}
   else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- bool expr_nonconst_p;
  cp_lexer_set_source_position (parser->lexer);
  maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
- index = cp_parser_braced_list (parser, _nonconst_p);
+ index = cp_parser_braced_list (parser);
}
   else
index = cp_parser_expression (parser, NULL, /*cast_p=*/false,
@@ -9640,12 +9635,10 @@ cp_parser_new_initializer (cp_parser* parser)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 {
-  tree t;
-  bool expr_non_constant_p;
   cp_lexer_set_source_position (parser->lexer);
   maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
-  t = cp_parser_braced_list (parser, _non_constant_p);
-  CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
+  tree t = cp_parser_braced_list (parser);
+  CONSTRUCTOR_IS_DIRECT_INIT (t) = true;
   expression_list = make_tree_vector_single (t);
 }
   else
@@ -10505,11 +10498,8 @@ cp_parser_assignment_expression (cp_parser* parser, 
cp_id_kind * pidk,
= cp_parser_assignment_operator_opt (parser);
  if (assignment_operator != ERROR_MARK)
{
- bool non_constant_p;
-
  /* Parse the right-hand side of the assignment.  */
- cp_expr rhs = cp_parser_initializer_clause (parser,
- _constant_p);
+ cp_expr rhs = 

Re: [PATCH] c++: fix ICE with is_really_empty_class [PR110106]

2023-07-25 Thread Marek Polacek via Gcc-patches
On Tue, Jul 25, 2023 at 04:24:39PM -0400, Jason Merrill wrote:
> On 7/25/23 15:59, Marek Polacek wrote:
> > Something like this, then?  I see that cp_parser_initializer_clause et al
> > offer further opportunities (because they sometimes use a dummy too) but
> > this should be a good start.
> 
> Looks good.  Please do update the other callers as well, while you're
> looking at this.

Thanks.  Can I push this part first?



Re: [PATCH] c++: fix ICE with is_really_empty_class [PR110106]

2023-07-25 Thread Marek Polacek via Gcc-patches
On Fri, Jul 21, 2023 at 01:44:17PM -0400, Jason Merrill wrote:
> On 7/20/23 17:58, Marek Polacek wrote:
> > On Thu, Jul 20, 2023 at 03:51:32PM -0400, Marek Polacek wrote:
> > > On Thu, Jul 20, 2023 at 02:37:07PM -0400, Jason Merrill wrote:
> > > > On 7/20/23 14:13, Marek Polacek wrote:
> > > > > On Wed, Jul 19, 2023 at 10:11:27AM -0400, Patrick Palka wrote:
> > > > > > On Tue, 18 Jul 2023, Marek Polacek via Gcc-patches wrote:
> > > > > > 
> > > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk and 
> > > > > > > branches?
> > > > > > 
> > > > > > Looks reasonable to me.
> > > > > 
> > > > > Thanks.
> > > > > > Though I wonder if we could also fix this by not checking 
> > > > > > potentiality
> > > > > > at all in this case?  The problematic call to 
> > > > > > is_rvalue_constant_expression
> > > > > > happens from cp_parser_constant_expression with 
> > > > > > 'allow_non_constant' != 0
> > > > > > and with 'non_constant_p' being a dummy out argument that comes from
> > > > > > cp_parser_functional_cast, so the result of 
> > > > > > is_rvalue_constant_expression
> > > > > > is effectively unused in this case, and we should be able to safely 
> > > > > > elide
> > > > > > it when 'allow_non_constant && non_constant_p == nullptr'.
> > > > > 
> > > > > Sounds plausible.  I think my patch could be applied first since it
> > > > > removes a tiny bit of code, then I can hopefully remove the flag 
> > > > > below,
> > > > > then maybe go back and optimize the call to 
> > > > > is_rvalue_constant_expression.
> > > > > Does that sound sensible?
> > > > > 
> > > > > > Relatedly, ISTM the member 
> > > > > > cp_parser::non_integral_constant_expression_p
> > > > > > is also effectively unused and could be removed?
> > > > > 
> > > > > It looks that way.  Seems it's only used in 
> > > > > cp_parser_constant_expression:
> > > > > 10806   if (allow_non_constant_p)
> > > > > 10807 *non_constant_p = 
> > > > > parser->non_integral_constant_expression_p;
> > > > > but that could be easily replaced by a local var.  I'd be happy to 
> > > > > see if
> > > > > we can actually do away with it.  (I wonder why it was introduced and 
> > > > > when
> > > > > it actually stopped being useful.)
> > > > 
> > > > It was for the C++98 notion of constant-expression, which was more of a
> > > > parser-level notion, and has been supplanted by the C++11 version.  I'm
> > > > happy to remove it, and therefore remove the 
> > > > is_rvalue_constant_expression
> > > > call.
> > > 
> > > Wonderful.  I'll do that next.
> > 
> > I found a use of parser->non_integral_constant_expression_p:
> > finish_id_expression_1 can set it to true which then makes
> > a difference in cp_parser_constant_expression in C++98.  In
> > cp_parser_constant_expression we set n_i_c_e_p to false, call
> > cp_parser_assignment_expression in which finish_id_expression_1
> > sets n_i_c_e_p to true, then back in cp_parser_constant_expression
> > we skip the cxx11 block, and set *non_constant_p to true.  If I
> > remove n_i_c_e_p, we lose that.  This can be seen in init/array60.C.
> 
> Sure, we would need to use the C++11 code for C++98 mode, which is likely
> fine but is more uncertain.
> 
> It's probably simpler to just ignore n_i_c_e_p for C++11 and up, along with
> Patrick's suggestion of allowing null non_constant_p with true
> allow_non_constant_p.

Something like this, then?  I see that cp_parser_initializer_clause et al
offer further opportunities (because they sometimes use a dummy too) but
this should be a good start.

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

-- >8 --
It's pointless to call *_rvalue_constant_expression when we're not using
the result.  Also apply some drive-by cleanups.

gcc/cp/ChangeLog:

* parser.cc (cp_parser_constant_expression): Allow non_constant_p to be
nullptr even when allow_non_constant_p is true.  Don't call
_rvalue_constant_expression when not necessary.  Move local variable
declarations closer to their first use.
(cp_parser_static_assert

[PATCH] c++: clear tf_partial et al in instantiate_template [PR108960]

2023-07-25 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

In 
we concluded that we might clear all flags except tf_warning_or_error
when performing instantiate_template.

PR c++/108960

gcc/cp/ChangeLog:

* pt.cc (lookup_and_finish_template_variable): Don't clear tf_partial
here.
(instantiate_template): Reset all complain flags except
tf_warning_or_error.
---
 gcc/cp/pt.cc | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 21b08a6266a..265e2a59a52 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10396,12 +10396,6 @@ lookup_and_finish_template_variable (tree templ, tree 
targs,
   tree var = lookup_template_variable (templ, targs, complain);
   if (var == error_mark_node)
 return error_mark_node;
-  /* We may be called while doing a partial substitution, but the
- type of the variable template may be auto, in which case we
- will call do_auto_deduction in mark_used (which clears tf_partial)
- and the auto must be properly reduced at that time for the
- deduction to work.  */
-  complain &= ~tf_partial;
   var = finish_template_variable (var, complain);
   mark_used (var);
   return var;
@@ -22008,6 +22002,14 @@ instantiate_template (tree tmpl, tree orig_args, 
tsubst_flags_t complain)
   if (tmpl == error_mark_node)
 return error_mark_node;
 
+  /* The other flags are not relevant anymore here, especially tf_partial
+ shouldn't be set.  For instance, we may be called while doing a partial
+ substitution of a template variable, but the type of the variable
+ template may be auto, in which case we will call do_auto_deduction
+ in mark_used (which clears tf_partial) and the auto must be properly
+ reduced at that time for the deduction to work.  */
+  complain &= tf_warning_or_error;
+
   gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
 
   if (modules_p ())

base-commit: 6e424febfbcb27c21a7fe3a137e614765f9cf9d2
-- 
2.41.0



[PATCH v3] c++: fix ICE with constexpr ARRAY_REF [PR110382]

2023-07-25 Thread Marek Polacek via Gcc-patches
On Tue, Jul 25, 2023 at 11:15:07AM -0400, Jason Merrill wrote:
> On 7/24/23 18:37, Marek Polacek wrote:
> > On Sat, Jul 22, 2023 at 12:28:59AM -0400, Jason Merrill wrote:
> > > On 7/21/23 18:38, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > > > 
> > > > -- >8 --
> > > > 
> > > > This code in cxx_eval_array_reference has been hard to get right.
> > > > In r12-2304 I added some code; in r13-5693 I removed some of it.
> > > > 
> > > > Here the problematic line is "S s = arr[0];" which causes a crash
> > > > on the assert in verify_ctor_sanity:
> > > > 
> > > > gcc_assert (!ctx->object || !DECL_P (ctx->object)
> > > > || ctx->global->get_value (ctx->object) == ctx->ctor);
> > > > 
> > > > ctx->object is the VAR_DECL 's', which is correct here.  The second
> > > > line points to the problem: we replaced ctx->ctor in
> > > > cxx_eval_array_reference:
> > > > 
> > > > new_ctx.ctor = build_constructor (elem_type, NULL); // #1
> > > 
> > > ...and this code doesn't also clear(/set) new_ctx.object like everywhere
> > > else in constexpr.cc that sets new_ctx.ctor.  Fixing that should make the
> > > testcase work.
> > 
> > Right, but then we'd be back pre-r12-2304 or r13-5693...
> > 
> > ...except it should work to always clear the object, like below.
> > > > which I think we shouldn't have; the CONSTRUCTOR we created in
> > > > cxx_eval_constant_expression/DECL_EXPR
> > > > 
> > > > new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
> > > > 
> > > > had the right type.
> > > 
> > > Indeed, and using it rather than building a new one seems like a valid
> > > optimization for trunk.
> > Agreed, I kept it.
> > 
> > > I also notice that the DECL_EXPR code calls unshare_constructor, which
> > > should be unnecessary if init == ctx->ctor?
> > 
> > It looks like init == ctx->ctor only happens only with this new testcase.
> > I'm not sure it's worth it adding code for such a rare case?
> > > > We still need #1 though.  E.g., in constexpr-96241.C, we never
> > > > set ctx.ctor/object before calling cxx_eval_array_reference, so
> > > > we have to build a CONSTRUCTOR there.  And in constexpr-101371-2.C
> > > > we have a ctx.ctor, but it has the wrong type, so we need a new one.
> > > > 
> > > > PR c++/110382
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (cxx_eval_array_reference): Create a new 
> > > > constructor
> > > > only when we don't already have a matching one.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp1y/constexpr-110382.C: New test.
> > > > ---
> > > >gcc/cp/constexpr.cc   |  5 -
> > > >gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C | 17 +
> > > >2 files changed, 21 insertions(+), 1 deletion(-)
> > > >create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C
> > > > 
> > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > index fb94f3cefcb..518b7c7a2d5 100644
> > > > --- a/gcc/cp/constexpr.cc
> > > > +++ b/gcc/cp/constexpr.cc
> > > > @@ -4291,7 +4291,10 @@ cxx_eval_array_reference (const constexpr_ctx 
> > > > *ctx, tree t,
> > > >  else
> > > >val = build_value_init (elem_type, tf_warning_or_error);
> > > > -  if (!SCALAR_TYPE_P (elem_type))
> > > > +  if (!SCALAR_TYPE_P (elem_type)
> > > > +  /* Create a new constructor only if we don't already have one 
> > > > that
> > > > +is suitable.  */
> > > > +  && !(ctx->ctor && same_type_p (elem_type, TREE_TYPE 
> > > > (ctx->ctor
> > > 
> > > We generally use same_type_ignoring_top_level_qualifiers_p in the 
> > > constexpr
> > > code.
> > 
> > True, changed.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > For 13, I guess I should only clear the object and leave out the
> > same_type_ bit.
> > 
> > -- >8 --
> > This code in cxx_eval_array_reference has been hard to get right.
> > In r12-2304 I added some code; in r13-5693 I removed some of it.
> > 
> > Here the problematic line is "S s = arr[0];" which causes a crash
> > on the assert in verify_ctor_sanity:
> > 
> >gcc_assert (!ctx->object || !DECL_P (ctx->object)
> >|| ctx->global->get_value (ctx->object) == ctx->ctor);
> > 
> > ctx->object is the VAR_DECL 's', which is correct here.  The second
> > line points to the problem: we replaced ctx->ctor in
> > cxx_eval_array_reference:
> > 
> >new_ctx.ctor = build_constructor (elem_type, NULL); // #1
> > 
> > which I think we shouldn't have; the CONSTRUCTOR we created in
> > cxx_eval_constant_expression/DECL_EXPR
> > 
> >new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
> > 
> > had the right type.
> > 
> > We still need #1 though.  E.g., in constexpr-96241.C, we never
> > set ctx.ctor/object before calling cxx_eval_array_reference, so
> > we have to build a CONSTRUCTOR there.  And in constexpr-101371-2.C
> > we have a ctx.ctor, but it 

[PATCH v2] c++: fix ICE with constexpr ARRAY_REF [PR110382]

2023-07-24 Thread Marek Polacek via Gcc-patches
On Sat, Jul 22, 2023 at 12:28:59AM -0400, Jason Merrill wrote:
> On 7/21/23 18:38, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > 
> > -- >8 --
> > 
> > This code in cxx_eval_array_reference has been hard to get right.
> > In r12-2304 I added some code; in r13-5693 I removed some of it.
> > 
> > Here the problematic line is "S s = arr[0];" which causes a crash
> > on the assert in verify_ctor_sanity:
> > 
> >gcc_assert (!ctx->object || !DECL_P (ctx->object)
> >|| ctx->global->get_value (ctx->object) == ctx->ctor);
> > 
> > ctx->object is the VAR_DECL 's', which is correct here.  The second
> > line points to the problem: we replaced ctx->ctor in
> > cxx_eval_array_reference:
> > 
> >new_ctx.ctor = build_constructor (elem_type, NULL); // #1
> 
> ...and this code doesn't also clear(/set) new_ctx.object like everywhere
> else in constexpr.cc that sets new_ctx.ctor.  Fixing that should make the
> testcase work.

Right, but then we'd be back pre-r12-2304 or r13-5693...

...except it should work to always clear the object, like below.
 
> > which I think we shouldn't have; the CONSTRUCTOR we created in
> > cxx_eval_constant_expression/DECL_EXPR
> > 
> >new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
> > 
> > had the right type.
> 
> Indeed, and using it rather than building a new one seems like a valid
> optimization for trunk.
 
Agreed, I kept it.

> I also notice that the DECL_EXPR code calls unshare_constructor, which
> should be unnecessary if init == ctx->ctor?

It looks like init == ctx->ctor only happens only with this new testcase.
I'm not sure it's worth it adding code for such a rare case?
 
> > We still need #1 though.  E.g., in constexpr-96241.C, we never
> > set ctx.ctor/object before calling cxx_eval_array_reference, so
> > we have to build a CONSTRUCTOR there.  And in constexpr-101371-2.C
> > we have a ctx.ctor, but it has the wrong type, so we need a new one.
> > 
> > PR c++/110382
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (cxx_eval_array_reference): Create a new constructor
> > only when we don't already have a matching one.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp1y/constexpr-110382.C: New test.
> > ---
> >   gcc/cp/constexpr.cc   |  5 -
> >   gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C | 17 +
> >   2 files changed, 21 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index fb94f3cefcb..518b7c7a2d5 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -4291,7 +4291,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, 
> > tree t,
> > else
> >   val = build_value_init (elem_type, tf_warning_or_error);
> > -  if (!SCALAR_TYPE_P (elem_type))
> > +  if (!SCALAR_TYPE_P (elem_type)
> > +  /* Create a new constructor only if we don't already have one that
> > +is suitable.  */
> > +  && !(ctx->ctor && same_type_p (elem_type, TREE_TYPE (ctx->ctor
> 
> We generally use same_type_ignoring_top_level_qualifiers_p in the constexpr
> code.

True, changed.

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

For 13, I guess I should only clear the object and leave out the
same_type_ bit.

-- >8 --
This code in cxx_eval_array_reference has been hard to get right.
In r12-2304 I added some code; in r13-5693 I removed some of it.

Here the problematic line is "S s = arr[0];" which causes a crash
on the assert in verify_ctor_sanity:

  gcc_assert (!ctx->object || !DECL_P (ctx->object)
  || ctx->global->get_value (ctx->object) == ctx->ctor);

ctx->object is the VAR_DECL 's', which is correct here.  The second
line points to the problem: we replaced ctx->ctor in
cxx_eval_array_reference:

  new_ctx.ctor = build_constructor (elem_type, NULL); // #1

which I think we shouldn't have; the CONSTRUCTOR we created in
cxx_eval_constant_expression/DECL_EXPR

  new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);

had the right type.

We still need #1 though.  E.g., in constexpr-96241.C, we never
set ctx.ctor/object before calling cxx_eval_array_reference, so
we have to build a CONSTRUCTOR there.  And in constexpr-101371-2.C
we have a ctx.ctor, but it has the wrong type, so we need a new one.

We can fix the problem by always clearing the object, and, as an
optimization, only create/free a new ctor when actually needed.

PR c++/110382

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_array_reference): Create a new constructor
only when we don't already have a matching one.  Clear the object
when the type is non-scalar.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-110382.C: New test.
---
 gcc/cp/constexpr.cc   | 17 +++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C | 17 +
 2 

[PATCH] c++: fix ICE with constexpr ARRAY_REF [PR110382]

2023-07-21 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?

-- >8 --

This code in cxx_eval_array_reference has been hard to get right.
In r12-2304 I added some code; in r13-5693 I removed some of it.

Here the problematic line is "S s = arr[0];" which causes a crash
on the assert in verify_ctor_sanity:

  gcc_assert (!ctx->object || !DECL_P (ctx->object)
  || ctx->global->get_value (ctx->object) == ctx->ctor);

ctx->object is the VAR_DECL 's', which is correct here.  The second
line points to the problem: we replaced ctx->ctor in
cxx_eval_array_reference:

  new_ctx.ctor = build_constructor (elem_type, NULL); // #1

which I think we shouldn't have; the CONSTRUCTOR we created in
cxx_eval_constant_expression/DECL_EXPR

  new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);

had the right type.

We still need #1 though.  E.g., in constexpr-96241.C, we never
set ctx.ctor/object before calling cxx_eval_array_reference, so
we have to build a CONSTRUCTOR there.  And in constexpr-101371-2.C
we have a ctx.ctor, but it has the wrong type, so we need a new one.

PR c++/110382

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_array_reference): Create a new constructor
only when we don't already have a matching one.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-110382.C: New test.
---
 gcc/cp/constexpr.cc   |  5 -
 gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C | 17 +
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fb94f3cefcb..518b7c7a2d5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4291,7 +4291,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
   else
 val = build_value_init (elem_type, tf_warning_or_error);
 
-  if (!SCALAR_TYPE_P (elem_type))
+  if (!SCALAR_TYPE_P (elem_type)
+  /* Create a new constructor only if we don't already have one that
+is suitable.  */
+  && !(ctx->ctor && same_type_p (elem_type, TREE_TYPE (ctx->ctor
 {
   new_ctx = *ctx;
   new_ctx.ctor = build_constructor (elem_type, NULL);
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C
new file mode 100644
index 000..317c5ecfcd5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C
@@ -0,0 +1,17 @@
+// PR c++/110382
+// { dg-do compile { target c++14 } }
+
+struct S {
+  double a = 0;
+};
+
+constexpr double
+g ()
+{
+  S arr[1];
+  S s = arr[0];
+  (void) arr[0];
+  return s.a;
+}
+
+int main() { return  g (); }

base-commit: 87516efcbe28884c39a8c68e600d11cc91ed96c7
-- 
2.41.0



Re: [PATCH] c++: fix ICE with is_really_empty_class [PR110106]

2023-07-20 Thread Marek Polacek via Gcc-patches
On Thu, Jul 20, 2023 at 03:51:32PM -0400, Marek Polacek wrote:
> On Thu, Jul 20, 2023 at 02:37:07PM -0400, Jason Merrill wrote:
> > On 7/20/23 14:13, Marek Polacek wrote:
> > > On Wed, Jul 19, 2023 at 10:11:27AM -0400, Patrick Palka wrote:
> > > > On Tue, 18 Jul 2023, Marek Polacek via Gcc-patches wrote:
> > > > 
> > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk and 
> > > > > branches?
> > > > 
> > > > Looks reasonable to me.
> > > 
> > > Thanks.
> > > > Though I wonder if we could also fix this by not checking potentiality
> > > > at all in this case?  The problematic call to 
> > > > is_rvalue_constant_expression
> > > > happens from cp_parser_constant_expression with 'allow_non_constant' != > > > > 0
> > > > and with 'non_constant_p' being a dummy out argument that comes from
> > > > cp_parser_functional_cast, so the result of 
> > > > is_rvalue_constant_expression
> > > > is effectively unused in this case, and we should be able to safely 
> > > > elide
> > > > it when 'allow_non_constant && non_constant_p == nullptr'.
> > > 
> > > Sounds plausible.  I think my patch could be applied first since it
> > > removes a tiny bit of code, then I can hopefully remove the flag below,
> > > then maybe go back and optimize the call to is_rvalue_constant_expression.
> > > Does that sound sensible?
> > > 
> > > > Relatedly, ISTM the member cp_parser::non_integral_constant_expression_p
> > > > is also effectively unused and could be removed?
> > > 
> > > It looks that way.  Seems it's only used in cp_parser_constant_expression:
> > > 10806   if (allow_non_constant_p)
> > > 10807 *non_constant_p = parser->non_integral_constant_expression_p;
> > > but that could be easily replaced by a local var.  I'd be happy to see if
> > > we can actually do away with it.  (I wonder why it was introduced and when
> > > it actually stopped being useful.)
> > 
> > It was for the C++98 notion of constant-expression, which was more of a
> > parser-level notion, and has been supplanted by the C++11 version.  I'm
> > happy to remove it, and therefore remove the is_rvalue_constant_expression
> > call.
> 
> Wonderful.  I'll do that next.

I found a use of parser->non_integral_constant_expression_p:
finish_id_expression_1 can set it to true which then makes
a difference in cp_parser_constant_expression in C++98.  In
cp_parser_constant_expression we set n_i_c_e_p to false, call
cp_parser_assignment_expression in which finish_id_expression_1
sets n_i_c_e_p to true, then back in cp_parser_constant_expression
we skip the cxx11 block, and set *non_constant_p to true.  If I
remove n_i_c_e_p, we lose that.  This can be seen in init/array60.C.

Marek



Re: [PATCH] c++: fix ICE with is_really_empty_class [PR110106]

2023-07-20 Thread Marek Polacek via Gcc-patches
On Thu, Jul 20, 2023 at 02:37:07PM -0400, Jason Merrill wrote:
> On 7/20/23 14:13, Marek Polacek wrote:
> > On Wed, Jul 19, 2023 at 10:11:27AM -0400, Patrick Palka wrote:
> > > On Tue, 18 Jul 2023, Marek Polacek via Gcc-patches wrote:
> > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk and 
> > > > branches?
> > > 
> > > Looks reasonable to me.
> > 
> > Thanks.
> > > Though I wonder if we could also fix this by not checking potentiality
> > > at all in this case?  The problematic call to 
> > > is_rvalue_constant_expression
> > > happens from cp_parser_constant_expression with 'allow_non_constant' != 0
> > > and with 'non_constant_p' being a dummy out argument that comes from
> > > cp_parser_functional_cast, so the result of is_rvalue_constant_expression
> > > is effectively unused in this case, and we should be able to safely elide
> > > it when 'allow_non_constant && non_constant_p == nullptr'.
> > 
> > Sounds plausible.  I think my patch could be applied first since it
> > removes a tiny bit of code, then I can hopefully remove the flag below,
> > then maybe go back and optimize the call to is_rvalue_constant_expression.
> > Does that sound sensible?
> > 
> > > Relatedly, ISTM the member cp_parser::non_integral_constant_expression_p
> > > is also effectively unused and could be removed?
> > 
> > It looks that way.  Seems it's only used in cp_parser_constant_expression:
> > 10806   if (allow_non_constant_p)
> > 10807 *non_constant_p = parser->non_integral_constant_expression_p;
> > but that could be easily replaced by a local var.  I'd be happy to see if
> > we can actually do away with it.  (I wonder why it was introduced and when
> > it actually stopped being useful.)
> 
> It was for the C++98 notion of constant-expression, which was more of a
> parser-level notion, and has been supplanted by the C++11 version.  I'm
> happy to remove it, and therefore remove the is_rvalue_constant_expression
> call.

Wonderful.  I'll do that next.
 
> > > > -- >8 --
> > > > 
> > > > is_really_empty_class is liable to crash when it gets an incomplete
> > > > or dependent type.  Since r11-557, we pass the yet-uninstantiated
> > > > class type S<0> of the PARM_DECL s to is_really_empty_class -- because
> > > > of the potential_rvalue_constant_expression -> 
> > > > is_rvalue_constant_expression
> > > > change in cp_parser_constant_expression.  Here we're not parsing
> > > > a template so we did not check COMPLETE_TYPE_P as we should.
> > > > 
> > > > PR c++/110106
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (potential_constant_expression_1): Check 
> > > > COMPLETE_TYPE_P
> > > > even when !processing_template_decl.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp0x/noexcept80.C: New test.
> > > > ---
> > > >   gcc/cp/constexpr.cc |  2 +-
> > > >   gcc/testsuite/g++.dg/cpp0x/noexcept80.C | 12 
> > > >   2 files changed, 13 insertions(+), 1 deletion(-)
> > > >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept80.C
> > > > 
> > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > index 6e8f1c2b61e..1f59c5472fb 100644
> > > > --- a/gcc/cp/constexpr.cc
> > > > +++ b/gcc/cp/constexpr.cc
> > > > @@ -9116,7 +9116,7 @@ potential_constant_expression_1 (tree t, bool 
> > > > want_rval, bool strict, bool now,
> > > > if (now && want_rval)
> > > > {
> > > >   tree type = TREE_TYPE (t);
> > > > - if ((processing_template_decl && !COMPLETE_TYPE_P (type))
> > > > + if (!COMPLETE_TYPE_P (type)
> > > >   || dependent_type_p (type)
> 
> There shouldn't be a problem completing the type here, so it seems to me
> that we're missing a call to complete_type_p, at least when
> !processing_template_decl.  Probably need to move the dependent_type_p check
> up as a result.

Like so?

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

-- >8 --
is_really_empty_class is liable to crash when it gets an incomplete
or dependent type.  Since r11-557, we pass the yet-uninstantiated
class type S<0> of the PARM_DECL s to is_really_empty_class -- because
of th

Re: [PATCH] c++: fix ICE with is_really_empty_class [PR110106]

2023-07-20 Thread Marek Polacek via Gcc-patches
On Wed, Jul 19, 2023 at 10:11:27AM -0400, Patrick Palka wrote:
> On Tue, 18 Jul 2023, Marek Polacek via Gcc-patches wrote:
> 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk and branches?
> 
> Looks reasonable to me.

Thanks.
 
> Though I wonder if we could also fix this by not checking potentiality
> at all in this case?  The problematic call to is_rvalue_constant_expression
> happens from cp_parser_constant_expression with 'allow_non_constant' != 0
> and with 'non_constant_p' being a dummy out argument that comes from
> cp_parser_functional_cast, so the result of is_rvalue_constant_expression
> is effectively unused in this case, and we should be able to safely elide
> it when 'allow_non_constant && non_constant_p == nullptr'.

Sounds plausible.  I think my patch could be applied first since it
removes a tiny bit of code, then I can hopefully remove the flag below,
then maybe go back and optimize the call to is_rvalue_constant_expression.
Does that sound sensible?

> Relatedly, ISTM the member cp_parser::non_integral_constant_expression_p
> is also effectively unused and could be removed?

It looks that way.  Seems it's only used in cp_parser_constant_expression:
10806   if (allow_non_constant_p)
10807 *non_constant_p = parser->non_integral_constant_expression_p;
but that could be easily replaced by a local var.  I'd be happy to see if
we can actually do away with it.  (I wonder why it was introduced and when
it actually stopped being useful.)

Thanks,

> > 
> > -- >8 --
> > 
> > is_really_empty_class is liable to crash when it gets an incomplete
> > or dependent type.  Since r11-557, we pass the yet-uninstantiated
> > class type S<0> of the PARM_DECL s to is_really_empty_class -- because
> > of the potential_rvalue_constant_expression -> is_rvalue_constant_expression
> > change in cp_parser_constant_expression.  Here we're not parsing
> > a template so we did not check COMPLETE_TYPE_P as we should.
> > 
> > PR c++/110106
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (potential_constant_expression_1): Check COMPLETE_TYPE_P
> > even when !processing_template_decl.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/noexcept80.C: New test.
> > ---
> >  gcc/cp/constexpr.cc |  2 +-
> >  gcc/testsuite/g++.dg/cpp0x/noexcept80.C | 12 
> >  2 files changed, 13 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept80.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 6e8f1c2b61e..1f59c5472fb 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -9116,7 +9116,7 @@ potential_constant_expression_1 (tree t, bool 
> > want_rval, bool strict, bool now,
> >if (now && want_rval)
> > {
> >   tree type = TREE_TYPE (t);
> > - if ((processing_template_decl && !COMPLETE_TYPE_P (type))
> > + if (!COMPLETE_TYPE_P (type)
> >   || dependent_type_p (type)
> >   || is_really_empty_class (type, /*ignore_vptr*/false))
> > /* An empty class has no data to read.  */
> > diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept80.C 
> > b/gcc/testsuite/g++.dg/cpp0x/noexcept80.C
> > new file mode 100644
> > index 000..3e90af747e2
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept80.C
> > @@ -0,0 +1,12 @@
> > +// PR c++/110106
> > +// { dg-do compile { target c++11 } }
> > +
> > +template struct S
> > +{
> > +};
> > +
> > +struct G {
> > +  G(S<0>);
> > +};
> > +
> > +void y(S<0> s) noexcept(noexcept(G{s}));
> > 
> > base-commit: fca089e8a47314a40ad93527ba9f9d0d374b3afb
> > -- 
> > 2.41.0
> > 
> > 
> 

Marek



Re: [PATCH] testsuite: fix allocator-opt1.C FAIL with old ABI

2023-07-20 Thread Marek Polacek via Gcc-patches
On Wed, Jul 19, 2023 at 03:22:10PM -0400, Marek Polacek wrote:
> Ping.
> 
> On Mon, Jul 10, 2023 at 04:33:26PM -0400, Marek Polacek via Gcc-patches wrote:
> > Running
> > $ make check-g++ 
> > RUNTESTFLAGS='--target_board=unix\{-D_GLIBCXX_USE_CXX11_ABI=0,\} 
> > dg.exp=allocator-opt1.C'
> > yields:
> > 
> > FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++98  scan-tree-dump-times 
> > gimple "struct allocator D" 1
> > FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++14  scan-tree-dump-times 
> > gimple "struct allocator D" 1
> > FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++17  scan-tree-dump-times 
> > gimple "struct allocator D" 1
> > FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++20  scan-tree-dump-times 
> > gimple "struct allocator D" 1

I just pushed the patch after fixing it and adding a new comment:

-- >8 --

Running
$ make check-g++ 
RUNTESTFLAGS='--target_board=unix\{-D_GLIBCXX_USE_CXX11_ABI=0,\} 
dg.exp=allocator-opt1.C'
yields:

FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++98  scan-tree-dump-times gimple 
"struct allocator D" 1
FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++14  scan-tree-dump-times gimple 
"struct allocator D" 1
FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++17  scan-tree-dump-times gimple 
"struct allocator D" 1
FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++20  scan-tree-dump-times gimple 
"struct allocator D" 1

=== g++ Summary for unix/-D_GLIBCXX_USE_CXX11_ABI=0 ===

=== g++ Summary for unix ===

because in the old ABI we get two "struct allocator D".  This patch
follows r14-658 although I'm not quite sure I follow the logic there.

gcc/testsuite/ChangeLog:

* g++.dg/tree-ssa/allocator-opt1.C: Force _GLIBCXX_USE_CXX11_ABI to 1.
---
 gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C | 12 
 1 file changed, 12 insertions(+)

diff --git a/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C 
b/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
index e8394c7ad70..51c470dee37 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
@@ -5,8 +5,20 @@
 // Currently the dump doesn't print the allocator template arg in this context.
 // { dg-final { scan-tree-dump-times "struct allocator D" 1 "gimple" } }
 
+// In the pre-C++11 ABI we get two allocator variables.
+#undef _GLIBCXX_USE_CXX11_ABI
+#define _GLIBCXX_USE_CXX11_ABI 1
+
 #include 
+
+// When the library is not dual-ABI and defaults to old just compile
+// an empty TU.  NB: We test _GLIBCXX_USE_CXX11_ABI again because the
+// #include above might have undef'd _GLIBCXX_USE_CXX11_ABI.
+#if _GLIBCXX_USE_CXX11_ABI
+
 void f (const char *p)
 {
   std::string lst[] = { p, p, p, p };
 }
+
+#endif

base-commit: 506f068e7d01ad2fb107185b8fb204a0ec23785c
-- 
2.41.0



[PATCH v2] c++: fix ICE with designated initializer [PR110114]

2023-07-20 Thread Marek Polacek via Gcc-patches
On Wed, Jul 19, 2023 at 03:24:10PM -0400, Jason Merrill wrote:
> On 7/19/23 14:38, Marek Polacek wrote:
> > On Wed, Jul 19, 2023 at 02:32:15PM -0400, Patrick Palka wrote:
> > > On Wed, 19 Jul 2023, Marek Polacek wrote:
> > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > 
> > > LGTM.  It might be preferable to check COMPLETE_TYPE_P in the caller
> > > instead, so that we avoid inspecting CLASSTYPE_NON_AGGREGATE on an
> > > incomplete class type, and so that the caller doesn't "commit" to
> > > building an aggregate conversion.
> > 
> > Perhaps.  I wanted to avoid the call to build_user_type_conversion_1.
> > I could add an early return to implicit_conversion_1 but I'd have to
> > move some code around not to check COMPLETE_TYPE_P before complete_type.
> 
> Maybe return NULL for the incomplete case here, rather than just skipping
> reshape_init?
> 
>   /* Call reshape_init early to remove redundant braces.  */
>   if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)
>   && CLASS_TYPE_P (to)
>   && COMPLETE_TYPE_P (complete_type (to))
>   && !CLASSTYPE_NON_AGGREGATE (to))
> {
>   expr = reshape_init (to, expr, complain);
>   if (expr == error_mark_node)
> return NULL;
>   from = TREE_TYPE (expr);
> }
> 
> If that doesn't work, the patch is fine as-is.

It does work, with one test tweak (which I don't think is a regression):
 
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
r13-1227 added an assert checking that the index in a CONSTRUCTOR
is a FIELD_DECL.  That's a reasonable assumption but in this case
we never called reshape_init due to the type being incomplete, and
so the index remained an identifier node: get_class_binding never
got around to looking up the FIELD_DECL.

We can avoid the crash by returning early in implicit_conversion_1; we'd
return NULL anyway due to:

  if (i < CONSTRUCTOR_NELTS (ctor))
return NULL;

in build_aggr_conv.

PR c++/110114

gcc/cp/ChangeLog:

* call.cc (implicit_conversion_1): Return early if the type isn't
complete.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist100.C: Adjust expected diagnostic.
* g++.dg/cpp2a/desig28.C: New test.
* g++.dg/cpp2a/desig29.C: New test.
---
 gcc/cp/call.cc   | 19 +++
 gcc/testsuite/g++.dg/cpp0x/initlist100.C |  4 ++--
 gcc/testsuite/g++.dg/cpp2a/desig28.C | 17 +
 gcc/testsuite/g++.dg/cpp2a/desig29.C | 10 ++
 4 files changed, 40 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig28.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig29.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index b55230d98aa..673ec91d60e 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -2059,15 +2059,18 @@ implicit_conversion_1 (tree to, tree from, tree expr, 
bool c_cast_p,
   complain &= ~tf_error;
 
   /* Call reshape_init early to remove redundant braces.  */
-  if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)
-  && CLASS_TYPE_P (to)
-  && COMPLETE_TYPE_P (complete_type (to))
-  && !CLASSTYPE_NON_AGGREGATE (to))
+  if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr) && CLASS_TYPE_P (to))
 {
-  expr = reshape_init (to, expr, complain);
-  if (expr == error_mark_node)
-   return NULL;
-  from = TREE_TYPE (expr);
+  to = complete_type (to);
+  if (!COMPLETE_TYPE_P (to))
+   return nullptr;
+  if (!CLASSTYPE_NON_AGGREGATE (to))
+   {
+ expr = reshape_init (to, expr, complain);
+ if (expr == error_mark_node)
+   return nullptr;
+ from = TREE_TYPE (expr);
+   }
 }
 
   if (TYPE_REF_P (to))
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist100.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist100.C
index 9d80a004c17..6865d34a6f9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist100.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist100.C
@@ -2,9 +2,9 @@
 // { dg-do compile { target c++11 } }
 
 namespace std {
-template  class initializer_list;  // { dg-message "declaration" }
+template  class initializer_list;
 }
 
 template  struct B { B (std::initializer_list); };
 struct C { virtual int foo (); };
-struct D : C {} d { B { D {} } };  // { dg-error "incomplete|no matching" }
+struct D : C {} d { B { D {} } };  // { dg-error "no matching" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig28.C 
b/gcc/testsuite/g++.dg/cpp2a/desig28.C
new file mode 100644
index 000..b63265fea51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig28.C
@@ -0,0 +1,17 @@
+// PR c++/110114
+// { dg-do compile { target c++20 } }
+
+struct A {
+int a,b;
+};
+
+struct B;
+
+void foo(const A &) {}
+void foo(const B &) {}
+
+int
+main ()
+{
+  foo({.a=0});
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig29.C 
b/gcc/testsuite/g++.dg/cpp2a/desig29.C
new file mode 100644
index 000..bd1a82b041d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig29.C
@@ -0,0 +1,10 @@
+// PR 

[PATCH] c++: Improve printing of base classes [PR110745]

2023-07-19 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

This patch changes

  warning: missing initializer for member 'D::' 
[-Wmissing-field-initializers]

to

  warning: missing initializer for member 'D::B' [-Wmissing-field-initializers]

PR c++/110745

gcc/cp/ChangeLog:

* error.cc (dump_simple_decl): Print base class name.

gcc/testsuite/ChangeLog:

* g++.dg/diagnostic/base.C: New test.
---
 gcc/cp/error.cc|  2 ++
 gcc/testsuite/g++.dg/diagnostic/base.C | 16 
 2 files changed, 18 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/base.C

diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 31319aa9e87..8a5219a68a1 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1177,6 +1177,8 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree 
type, int flags)
 }
   else if (DECL_DECOMPOSITION_P (t))
 pp_string (pp, M_(""));
+  else if (TREE_CODE (t) == FIELD_DECL && DECL_FIELD_IS_BASE (t))
+dump_type (pp, TREE_TYPE (t), flags);
   else
 pp_string (pp, M_(""));
 
diff --git a/gcc/testsuite/g++.dg/diagnostic/base.C 
b/gcc/testsuite/g++.dg/diagnostic/base.C
new file mode 100644
index 000..1540414072e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/base.C
@@ -0,0 +1,16 @@
+// PR c++/110745
+// { dg-do compile { target c++17 } }
+// { dg-options "-Wmissing-field-initializers" }
+
+struct B { int i; };
+struct D : B {
+int x;
+int y;
+};
+
+int
+main ()
+{
+  D d = {.x=1, .y=2}; // { dg-warning "missing initializer for member .D::B." }
+  (void)d;
+}

base-commit: b1ae46bdd19fc2aaea41bc894168bdaf4799be80
-- 
2.41.0



Re: [PATCH] c++: -Wmissing-field-initializers and empty class [PR110064]

2023-07-19 Thread Marek Polacek via Gcc-patches
On Wed, Jul 19, 2023 at 03:36:49PM -0400, Jason Merrill wrote:
> On 7/19/23 15:20, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
> OK.  We might also improve the diagnostic for base classes, perhaps by
> teaching dump_simple_decl about DECL_FIELD_IS_BASE?

As in, instead of "D::" emit "D::B"?  Good idea.  I suppose
I could do that; Barry's testcase without this patch looks like a good
test case.  Thanks,

Marek



Re: [PATCH] testsuite: fix allocator-opt1.C FAIL with old ABI

2023-07-19 Thread Marek Polacek via Gcc-patches
Ping.

On Mon, Jul 10, 2023 at 04:33:26PM -0400, Marek Polacek via Gcc-patches wrote:
> Running
> $ make check-g++ 
> RUNTESTFLAGS='--target_board=unix\{-D_GLIBCXX_USE_CXX11_ABI=0,\} 
> dg.exp=allocator-opt1.C'
> yields:
> 
> FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++98  scan-tree-dump-times 
> gimple "struct allocator D" 1
> FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++14  scan-tree-dump-times 
> gimple "struct allocator D" 1
> FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++17  scan-tree-dump-times 
> gimple "struct allocator D" 1
> FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++20  scan-tree-dump-times 
> gimple "struct allocator D" 1
> 
>   === g++ Summary for unix/-D_GLIBCXX_USE_CXX11_ABI=0 ===
> 
>   === g++ Summary for unix ===
> 
> because in the old ABI we get two "struct allocator D".  This patch
> follows r14-658 although I'm not quite sure I follow the logic there.
> 
> Tested on x86_64-pc-linux-gnu, ok for trunk?
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/tree-ssa/allocator-opt1.C: Force _GLIBCXX_USE_CXX11_ABI to 1.
> ---
>  gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C | 10 ++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C 
> b/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
> index e8394c7ad70..9f13eedb604 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
> @@ -5,8 +5,18 @@
>  // Currently the dump doesn't print the allocator template arg in this 
> context.
>  // { dg-final { scan-tree-dump-times "struct allocator D" 1 "gimple" } }
>  
> +// In the pre-C++11 ABI we get two allocator variables.
> +#undef _GLIBCXX_USE_CXX11_ABI
> +#define _GLIBCXX_USE_CXX11_ABI 1
> +
> +// When the library is not dual-ABI and defaults to old just compile
> +// an empty TU
> +#if _GLIBCXX_USE_CXX11_ABI
> +
>  #include 
>  void f (const char *p)
>  {
>std::string lst[] = { p, p, p, p };
>  }
> +
> +#endif
> 
> base-commit: 2d7c95e31431a297060c94697af84f498abf97a2
> -- 
> 2.41.0
> 

Marek



[PATCH] c++: -Wmissing-field-initializers and empty class [PR110064]

2023-07-19 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

Let's suppress -Wmissing-field-initializers for empty classes.

Here I don't think I need the usual COMPLETE_TYPE_P/dependent_type_p
checks.

PR c++/110064

gcc/cp/ChangeLog:

* typeck2.cc (process_init_constructor_record): Don't emit
-Wmissing-field-initializers for empty classes.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wmissing-field-initializers-3.C: New test.
---
 gcc/cp/typeck2.cc |  3 +-
 .../warn/Wmissing-field-initializers-3.C  | 48 +++
 2 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wmissing-field-initializers-3.C

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 1c204c8612b..582a73bb053 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1874,7 +1874,8 @@ process_init_constructor_record (tree type, tree init, 
int nested, int flags,
 to zero.  */
  if ((complain & tf_warning)
  && !cp_unevaluated_operand
- && !EMPTY_CONSTRUCTOR_P (init))
+ && !EMPTY_CONSTRUCTOR_P (init)
+ && !is_really_empty_class (fldtype, /*ignore_vptr*/false))
warning (OPT_Wmissing_field_initializers,
 "missing initializer for member %qD", field);
 
diff --git a/gcc/testsuite/g++.dg/warn/Wmissing-field-initializers-3.C 
b/gcc/testsuite/g++.dg/warn/Wmissing-field-initializers-3.C
new file mode 100644
index 000..a8d75b92bd1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmissing-field-initializers-3.C
@@ -0,0 +1,48 @@
+// PR c++/110064
+// { dg-do compile { target c++17 } }
+// { dg-options "-Wmissing-field-initializers" }
+
+struct B { };
+struct D : B {
+int x;
+int y;
+};
+
+struct E {
+  int x;
+  int y;
+  B z;
+};
+
+template struct X { };
+
+template
+struct F {
+  int i;
+  int j;
+  X x;
+};
+
+int
+main ()
+{
+  D d = {.x=1, .y=2}; // { dg-bogus "missing" }
+  (void)d;
+  E e = {.x=1, .y=2}; // { dg-bogus "missing" }
+  (void)e;
+  F f = {.i=1, .j=2 }; // { dg-bogus "missing" }
+  (void)f;
+}
+
+template
+void fn ()
+{
+  F f = {.i=1, .j=2 }; // { dg-bogus "missing" }
+  (void)f;
+}
+
+void
+g ()
+{
+  fn ();
+}

base-commit: 2971ff7b1d564ac04b537d907c70e6093af70832
-- 
2.41.0



Re: [PATCH] c++: fix ICE with designated initializer [PR110114]

2023-07-19 Thread Marek Polacek via Gcc-patches
On Wed, Jul 19, 2023 at 02:32:15PM -0400, Patrick Palka wrote:
> On Wed, 19 Jul 2023, Marek Polacek wrote:
> 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
> LGTM.  It might be preferable to check COMPLETE_TYPE_P in the caller
> instead, so that we avoid inspecting CLASSTYPE_NON_AGGREGATE on an
> incomplete class type, and so that the caller doesn't "commit" to
> building an aggregate conversion.

Perhaps.  I wanted to avoid the call to build_user_type_conversion_1.
I could add an early return to implicit_conversion_1 but I'd have to
move some code around not to check COMPLETE_TYPE_P before complete_type.
 
> > 
> > -- >8 --
> > 
> > r13-1227 added an assert checking that the index in a CONSTRUCTOR
> > is a FIELD_DECL.  That's a reasonable assumption but in this case
> > we never called reshape_init due to the type being incomplete, and
> > so the index remained an identifier node: get_class_binding never
> > got around to looking up the FIELD_DECL.
> > 
> > We can avoid the crash by returning early in build_aggr_conv; we'd
> > return NULL anyway due to:
> > 
> >   if (i < CONSTRUCTOR_NELTS (ctor))
> > return NULL;
> > 
> > PR c++/110114
> > 
> > gcc/cp/ChangeLog:
> > 
> > * call.cc (build_aggr_conv): Return early if the type isn't
> > complete.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp2a/desig28.C: New test.
> > * g++.dg/cpp2a/desig29.C: New test.
> > ---
> >  gcc/cp/call.cc   |  5 +
> >  gcc/testsuite/g++.dg/cpp2a/desig28.C | 17 +
> >  gcc/testsuite/g++.dg/cpp2a/desig29.C | 10 ++
> >  3 files changed, 32 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig28.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig29.C
> > 
> > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > index b55230d98aa..0af20a81717 100644
> > --- a/gcc/cp/call.cc
> > +++ b/gcc/cp/call.cc
> > @@ -986,6 +986,11 @@ build_aggr_conv (tree type, tree ctor, int flags, 
> > tsubst_flags_t complain)
> >tree empty_ctor = NULL_TREE;
> >hash_set pset;
> >  
> > +  /* We've called complete_type on TYPE before calling this function, but
> > + perhaps it wasn't successful.  */
> > +  if (!COMPLETE_TYPE_P (type))
> > +return nullptr;
> > +
> >/* We already called reshape_init in implicit_conversion, but it might 
> > not
> >   have done anything in the case of parenthesized aggr init.  */
> >  
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/desig28.C 
> > b/gcc/testsuite/g++.dg/cpp2a/desig28.C
> > new file mode 100644
> > index 000..b63265fea51
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/desig28.C
> > @@ -0,0 +1,17 @@
> > +// PR c++/110114
> > +// { dg-do compile { target c++20 } }
> > +
> > +struct A {
> > +int a,b;
> > +};
> > +
> > +struct B;
> > +
> > +void foo(const A &) {}
> > +void foo(const B &) {}
> > +
> > +int
> > +main ()
> > +{
> > +  foo({.a=0});
> > +}
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/desig29.C 
> > b/gcc/testsuite/g++.dg/cpp2a/desig29.C
> > new file mode 100644
> > index 000..bd1a82b041d
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/desig29.C
> > @@ -0,0 +1,10 @@
> > +// PR c++/110114
> > +// { dg-do compile { target c++20 } }
> > +
> > +struct B;
> > +
> > +void foo(const B &) {}
> > +
> > +int main() {
> > +foo({.a=0}); // { dg-error "invalid" }
> > +}
> > 
> > base-commit: 2971ff7b1d564ac04b537d907c70e6093af70832
> > -- 
> > 2.41.0
> > 
> > 
> 

Marek



[PATCH] c++: fix ICE with designated initializer [PR110114]

2023-07-19 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --

r13-1227 added an assert checking that the index in a CONSTRUCTOR
is a FIELD_DECL.  That's a reasonable assumption but in this case
we never called reshape_init due to the type being incomplete, and
so the index remained an identifier node: get_class_binding never
got around to looking up the FIELD_DECL.

We can avoid the crash by returning early in build_aggr_conv; we'd
return NULL anyway due to:

  if (i < CONSTRUCTOR_NELTS (ctor))
return NULL;

PR c++/110114

gcc/cp/ChangeLog:

* call.cc (build_aggr_conv): Return early if the type isn't
complete.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig28.C: New test.
* g++.dg/cpp2a/desig29.C: New test.
---
 gcc/cp/call.cc   |  5 +
 gcc/testsuite/g++.dg/cpp2a/desig28.C | 17 +
 gcc/testsuite/g++.dg/cpp2a/desig29.C | 10 ++
 3 files changed, 32 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig28.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig29.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index b55230d98aa..0af20a81717 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -986,6 +986,11 @@ build_aggr_conv (tree type, tree ctor, int flags, 
tsubst_flags_t complain)
   tree empty_ctor = NULL_TREE;
   hash_set pset;
 
+  /* We've called complete_type on TYPE before calling this function, but
+ perhaps it wasn't successful.  */
+  if (!COMPLETE_TYPE_P (type))
+return nullptr;
+
   /* We already called reshape_init in implicit_conversion, but it might not
  have done anything in the case of parenthesized aggr init.  */
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig28.C 
b/gcc/testsuite/g++.dg/cpp2a/desig28.C
new file mode 100644
index 000..b63265fea51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig28.C
@@ -0,0 +1,17 @@
+// PR c++/110114
+// { dg-do compile { target c++20 } }
+
+struct A {
+int a,b;
+};
+
+struct B;
+
+void foo(const A &) {}
+void foo(const B &) {}
+
+int
+main ()
+{
+  foo({.a=0});
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig29.C 
b/gcc/testsuite/g++.dg/cpp2a/desig29.C
new file mode 100644
index 000..bd1a82b041d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig29.C
@@ -0,0 +1,10 @@
+// PR c++/110114
+// { dg-do compile { target c++20 } }
+
+struct B;
+
+void foo(const B &) {}
+
+int main() {
+foo({.a=0}); // { dg-error "invalid" }
+}

base-commit: 2971ff7b1d564ac04b537d907c70e6093af70832
-- 
2.41.0



[PATCH] c++: fix ICE with is_really_empty_class [PR110106]

2023-07-18 Thread Marek Polacek via Gcc-patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk and branches?

-- >8 --

is_really_empty_class is liable to crash when it gets an incomplete
or dependent type.  Since r11-557, we pass the yet-uninstantiated
class type S<0> of the PARM_DECL s to is_really_empty_class -- because
of the potential_rvalue_constant_expression -> is_rvalue_constant_expression
change in cp_parser_constant_expression.  Here we're not parsing
a template so we did not check COMPLETE_TYPE_P as we should.

PR c++/110106

gcc/cp/ChangeLog:

* constexpr.cc (potential_constant_expression_1): Check COMPLETE_TYPE_P
even when !processing_template_decl.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 6e8f1c2b61e..1f59c5472fb 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9116,7 +9116,7 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
   if (now && want_rval)
{
  tree type = TREE_TYPE (t);
- if ((processing_template_decl && !COMPLETE_TYPE_P (type))
+ if (!COMPLETE_TYPE_P (type)
  || dependent_type_p (type)
  || is_really_empty_class (type, /*ignore_vptr*/false))
/* An empty class has no data to read.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept80.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept80.C
new file mode 100644
index 000..3e90af747e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept80.C
@@ -0,0 +1,12 @@
+// PR c++/110106
+// { dg-do compile { target c++11 } }
+
+template struct S
+{
+};
+
+struct G {
+  G(S<0>);
+};
+
+void y(S<0> s) noexcept(noexcept(G{s}));

base-commit: fca089e8a47314a40ad93527ba9f9d0d374b3afb
-- 
2.41.0



[pushed] c++: Add tests for P2621, no UB in lexer [PR110340]

2023-07-18 Thread Marek Polacek via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

C++26 P2621 removes UB in the lexer and either makes the construct valid
or ill-formed.  We're already handling this correctly so this patch only
adds tests.

PR c++/110340

gcc/testsuite/ChangeLog:

* g++.dg/cpp/string-4.C: New test.
* g++.dg/cpp/ucn-2.C: New test.
---
 gcc/testsuite/g++.dg/cpp/string-4.C |  6 ++
 gcc/testsuite/g++.dg/cpp/ucn-2.C| 15 +++
 2 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp/string-4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp/ucn-2.C

diff --git a/gcc/testsuite/g++.dg/cpp/string-4.C 
b/gcc/testsuite/g++.dg/cpp/string-4.C
new file mode 100644
index 000..37d0388413c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/string-4.C
@@ -0,0 +1,6 @@
+// P2621R2 - UB? In My Lexer?
+// { dg-do compile }
+
+// [lex.phases] If a U+0027 APOSTROPHE or a U+0022 QUOTATION
+// MARK matches the last category, the program is ill-formed.
+const char * foo=" // { dg-error "terminating|expected" }
diff --git a/gcc/testsuite/g++.dg/cpp/ucn-2.C b/gcc/testsuite/g++.dg/cpp/ucn-2.C
new file mode 100644
index 000..c5583e06dd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/ucn-2.C
@@ -0,0 +1,15 @@
+// P2621R2 - UB? In My Lexer?
+// { dg-do compile }
+
+// Line splicing can form a universal-character-name [lex.charset].
+int \\
+u\
+0\
+3\
+9\
+1 = 0;
+
+// [cpp.concat] Concatenation can form a universal-character-name.
+#define CONCAT(x,y) x##y
+
+int CONCAT(\,u0393)=0;

base-commit: 05fc7db93452841280ddc5cdf71b33498ed576dc
-- 
2.41.0



[PATCH v2] c++: wrong error with static constexpr var in tmpl [PR109876]

2023-07-13 Thread Marek Polacek via Gcc-patches
On Fri, May 26, 2023 at 09:47:10PM -0400, Jason Merrill wrote:
> On 5/26/23 19:18, Marek Polacek wrote:
> > Since r8-509, we'll no longer create a static temporary var for
> > the initializer '{ 1, 2 }' for num in the attached test because
> > the code in finish_compound_literal is now guarded by
> > '&& fcl_context == fcl_c99' but it's fcl_functional here.  This
> > causes us to reject num as non-constant when evaluating it in
> > a template.
> > 
> > Jason's idea was to treat num as value-dependent even though it
> > actually isn't.  This patch implements that suggestion.
> > 
> > The is_really_empty_class check is sort of non-obvious but the
> > comment should explain why I added it.
> > 
> > Co-authored-by: Jason Merrill 
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > PR c++/109876
> > 
> > gcc/cp/ChangeLog:
> > 
> > * pt.cc (value_dependent_expression_p) : Treat a
> > constexpr-declared non-constant variable as value-dependent.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/constexpr-template12.C: New test.
> > * g++.dg/cpp1z/constexpr-template1.C: New test.
> > ---
> >   gcc/cp/pt.cc  | 12 ++
> >   .../g++.dg/cpp0x/constexpr-template12.C   | 38 +++
> >   .../g++.dg/cpp1z/constexpr-template1.C| 25 
> >   3 files changed, 75 insertions(+)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-template12.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-template1.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 7fb3e75bceb..38fd8070705 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -27969,6 +27969,18 @@ value_dependent_expression_p (tree expression)
> > else if (TYPE_REF_P (TREE_TYPE (expression)))
> > /* FIXME cp_finish_decl doesn't fold reference initializers.  */
> > return true;
> > +  /* We have a constexpr variable and we're processing a template.  
> > When
> > +there's lifetime extension involved (for which finish_compound_literal
> > +used to create a temporary), we'll not be able to evaluate the
> > +variable until instantiating, so pretend it's value-dependent.  */
> > +  else if (DECL_DECLARED_CONSTEXPR_P (expression)
> > +  && !TREE_CONSTANT (expression)
> > +  /* When there's nothing to initialize, we'll never mark the
> > + VAR_DECL TREE_CONSTANT, therefore it would remain
> > + value-dependent and we wouldn't instantiate.  */
 
Sorry it's taken so long to get back to this.

> Interesting.  Can we change that (i.e. mark it TREE_CONSTANT) rather than
> work around it here?

I think we can.  Maybe as in the below:

-- >8 --
Since r8-509, we'll no longer create a static temporary var for
the initializer '{ 1, 2 }' for num in the attached test because
the code in finish_compound_literal is now guarded by
'&& fcl_context == fcl_c99' but it's fcl_functional here.  This
causes us to reject num as non-constant when evaluating it in
a template.

Jason's idea was to treat num as value-dependent even though it
actually isn't.  This patch implements that suggestion.

We weren't marking objects whose type is an empty class type
constant.  This patch changes that so that v_d_e_p doesn't need
to check is_really_empty_class.

Co-authored-by: Jason Merrill 

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

PR c++/109876

gcc/cp/ChangeLog:

* decl.cc (cp_finish_decl): Set TREE_CONSTANT when initializing
an object of empty class type.
* pt.cc (value_dependent_expression_p) : Treat a
constexpr-declared non-constant variable as value-dependent.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-template12.C: New test.
* g++.dg/cpp1z/constexpr-template1.C: New test.
* g++.dg/cpp1z/constexpr-template2.C: New test.
---
 gcc/cp/decl.cc| 13 +--
 gcc/cp/pt.cc  |  7 
 .../g++.dg/cpp0x/constexpr-template12.C   | 38 +++
 .../g++.dg/cpp1z/constexpr-template1.C| 25 
 .../g++.dg/cpp1z/constexpr-template2.C| 25 
 5 files changed, 105 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-template12.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-template1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-template2.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 60f107d50c4..792ab330dd0 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8200,7 +8200,6 @@ void
 cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
tree asmspec_tree, int flags)
 {
-  tree type;
   vec *cleanups = NULL;
   const char *asmspec = NULL;
   int was_readonly = 0;
@@ -8220,7 +8219,7 @@ cp_finish_decl (tree decl, tree init, bool 
init_const_expr_p,
   /* Parameters are handled by store_parm_decls, not 

Re: [pushed] c++: C++26 constexpr cast from void* [PR110344]

2023-07-12 Thread Marek Polacek via Gcc-patches
On Tue, Jun 27, 2023 at 11:29:34PM -0400, Jason Merrill via Gcc-patches wrote:
> Tested x86_64-pc-linux-gnu, applying to trunk.
> 
> -- 8< --
> 
> P2768 allows static_cast from void* to ob* in constant evaluation if the
> pointer does in fact point to an object of the appropriate type.
> cxx_fold_indirect_ref already does the work of finding such an object if it
> happens to be a subobject rather than the outermost object at that address,
> as in constexpr-voidptr2.C.

This patch seems to have broken a lot of tests when running with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26.  cpp0x/constexpr-cast2.C
probably just needs not to expect certain errors in C++26, and
cpp2a/constexpr-new*.C may need code to handle  (?).
 
>   P2768
>   PR c++/110344
> 
> gcc/c-family/ChangeLog:
> 
>   * c-cppbuiltin.cc (c_cpp_builtins): Update __cpp_constexpr.
> 
> gcc/cp/ChangeLog:
> 
>   * constexpr.cc (cxx_eval_constant_expression): In C++26, allow cast
>   from void* to the type of a pointed-to object.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/cpp26/constexpr-voidptr1.C: New test.
>   * g++.dg/cpp26/constexpr-voidptr2.C: New test.
>   * g++.dg/cpp26/feat-cxx26.C: New test.
> ---
>  gcc/c-family/c-cppbuiltin.cc  |   8 +-
>  gcc/cp/constexpr.cc   |  11 +
>  .../g++.dg/cpp26/constexpr-voidptr1.C |  35 +
>  .../g++.dg/cpp26/constexpr-voidptr2.C |  15 +
>  gcc/testsuite/g++.dg/cpp26/feat-cxx26.C   | 597 ++
>  5 files changed, 665 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp26/constexpr-voidptr2.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
> 
> diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
> index 5d64625fcd7..6bd4c1261a7 100644
> --- a/gcc/c-family/c-cppbuiltin.cc
> +++ b/gcc/c-family/c-cppbuiltin.cc
> @@ -1075,12 +1075,18 @@ c_cpp_builtins (cpp_reader *pfile)
> cpp_define (pfile, "__cpp_size_t_suffix=202011L");
> cpp_define (pfile, "__cpp_if_consteval=202106L");
> cpp_define (pfile, "__cpp_auto_cast=202110L");
> -   cpp_define (pfile, "__cpp_constexpr=202211L");
> +   if (cxx_dialect <= cxx23)
> + cpp_define (pfile, "__cpp_constexpr=202211L");
> cpp_define (pfile, "__cpp_multidimensional_subscript=202211L");
> cpp_define (pfile, "__cpp_named_character_escapes=202207L");
> cpp_define (pfile, "__cpp_static_call_operator=202207L");
> cpp_define (pfile, "__cpp_implicit_move=202207L");
>   }
> +  if (cxx_dialect > cxx23)
> + {
> +   /* Set feature test macros for C++26.  */
> +   cpp_define (pfile, "__cpp_constexpr=202306L");
> + }
>if (flag_concepts)
>  {
> if (cxx_dialect >= cxx20)
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 432b3a275e8..cca0435bafc 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -7681,6 +7681,17 @@ cxx_eval_constant_expression (const constexpr_ctx 
> *ctx, tree t,
>   && !is_std_construct_at (ctx->call)
>   && !is_std_allocator_allocate (ctx->call))
> {
> + /* P2738 (C++26): a conversion from a prvalue P of type "pointer to
> +cv void" to a pointer-to-object type T unless P points to an
> +object whose type is similar to T.  */
> + if (cxx_dialect > cxx23)
> +   if (tree ob
> +   = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), op))
> + {
> +   r = build1 (ADDR_EXPR, type, ob);
> +   break;
> + }
> +
>   /* Likewise, don't error when casting from void* when OP is
>   uninit and similar.  */
>   tree sop = tree_strip_nop_conversions (op);
> diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C 
> b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C
> new file mode 100644
> index 000..ce0ccbef5f9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C
> @@ -0,0 +1,35 @@
> +// PR c++/110344
> +// { dg-do compile { target c++26 } }
> +
> +#include 
> +struct Sheep {
> +  constexpr std::string_view speak() const noexcept { return "Baa"; }
> +};
> +struct Cow {
> +  constexpr std::string_view speak() const noexcept { return "Mooo"; }
> +};
> +class Animal_View {
> +private:
> +  const void *animal;
> +  std::string_view (*speak_function)(const void *);
> +public:
> +  template 
> +  constexpr Animal_View(const Animal )
> +: animal{}, speak_function{[](const void *object) {
> +return static_cast *>(object)->speak();
> +  }} {}
> +  constexpr std::string_view speak() const noexcept {
> +return speak_function(animal);
> +  }
> +};
> +// This is the key bit here. This is a single concrete function
> +// that can take anything that happens to have the 

[PATCH] testsuite: fix allocator-opt1.C FAIL with old ABI

2023-07-10 Thread Marek Polacek via Gcc-patches
Running
$ make check-g++ 
RUNTESTFLAGS='--target_board=unix\{-D_GLIBCXX_USE_CXX11_ABI=0,\} 
dg.exp=allocator-opt1.C'
yields:

FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++98  scan-tree-dump-times gimple 
"struct allocator D" 1
FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++14  scan-tree-dump-times gimple 
"struct allocator D" 1
FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++17  scan-tree-dump-times gimple 
"struct allocator D" 1
FAIL: g++.dg/tree-ssa/allocator-opt1.C  -std=c++20  scan-tree-dump-times gimple 
"struct allocator D" 1

=== g++ Summary for unix/-D_GLIBCXX_USE_CXX11_ABI=0 ===

=== g++ Summary for unix ===

because in the old ABI we get two "struct allocator D".  This patch
follows r14-658 although I'm not quite sure I follow the logic there.

Tested on x86_64-pc-linux-gnu, ok for trunk?

gcc/testsuite/ChangeLog:

* g++.dg/tree-ssa/allocator-opt1.C: Force _GLIBCXX_USE_CXX11_ABI to 1.
---
 gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C 
b/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
index e8394c7ad70..9f13eedb604 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/allocator-opt1.C
@@ -5,8 +5,18 @@
 // Currently the dump doesn't print the allocator template arg in this context.
 // { dg-final { scan-tree-dump-times "struct allocator D" 1 "gimple" } }
 
+// In the pre-C++11 ABI we get two allocator variables.
+#undef _GLIBCXX_USE_CXX11_ABI
+#define _GLIBCXX_USE_CXX11_ABI 1
+
+// When the library is not dual-ABI and defaults to old just compile
+// an empty TU
+#if _GLIBCXX_USE_CXX11_ABI
+
 #include 
 void f (const char *p)
 {
   std::string lst[] = { p, p, p, p };
 }
+
+#endif

base-commit: 2d7c95e31431a297060c94697af84f498abf97a2
-- 
2.41.0



[PATCH] testsuite: fix dwarf2/utf-1.C with DWARF4

2023-07-05 Thread Marek Polacek via Gcc-patches
Running
$ make check-c++ RUNTESTFLAGS='--target_board=unix\{-gdwarf-5,-gdwarf-4\} 
dwarf2.exp=utf-1.C'
shows
FAIL: g++.dg/debug/dwarf2/utf-1.C  -std=gnu++20  scan-assembler-times 
DW_AT_encoding \\(0x10\\) 3
because with -gdwarf-4 the output is:

  .byte   0x10# DW_AT_encoding

but with -gdwarf-5 the output is the expected:

# DW_AT_encoding (0x10)

The difference is caused by the DWARF5 optimize_implicit_const
optimization:


I suppose we could do what testsuite/rust/debug/chartype.rs does
and just run the test with -gdwarf-4.

Tested on x86_64-pc-linux-gnu, ok for trunk?

gcc/testsuite/ChangeLog:

* g++.dg/debug/dwarf2/utf-1.C: Use -gdwarf-4.  Adjust expected
output.
---
 gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C 
b/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C
index 43b354f1bb5..0ce4d8727d6 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C
@@ -1,8 +1,13 @@
 // { dg-do compile { target c++20 } }
-// { dg-options { -gdwarf -dA } }
+// { dg-options { -gdwarf-4 -dA } }
 
 // Test that all three use DW_ATE_UTF.
-// { dg-final { scan-assembler-times {DW_AT_encoding \(0x10\)} 3 } }
+// This test uses -gdwarf-4 since in DWARF5 optimize_implicit_const
+// would optimize the output from:
+//   .byte   0x10# DW_AT_encoding
+// into:
+//   # DW_AT_encoding (0x10)
+// { dg-final { scan-assembler-times "0x10\[ \t]\[^\n\r]* DW_AT_encoding" 3 } }
 
 char8_t c8;
 char16_t c16;

base-commit: be240fc6acc9714e66afbfbe6dc193844bfcba05
-- 
2.41.0



Re: [PATCH] i386: add -fno-stack-protector to two tests

2023-06-29 Thread Marek Polacek via Gcc-patches
On Fri, Jun 30, 2023 at 04:11:44AM +0800, Xi Ruoyao wrote:
> On Fri, 2023-06-30 at 04:08 +0800, Xi Ruoyao wrote:
> > On Thu, 2023-06-29 at 16:01 -0400, Marek Polacek via Gcc-patches wrote:
> > > These tests fail when the testsuite is executed with -fstack-
> > > protector-strong.
> > > To avoid this, this patch adds -fno-stack-protector to dg-options.
> > > 
> > > Tested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > LGTM, we've noticed these two failures in Linux From Scratch [1].  But
> > this is not an approval because I'm not a maintainer.

Thanks.

> And can we backport them to gcc-13 branch too?  These two tests were
> added in the cycle of GCC 13, so we could consider the failures
> "regression".

Yeah, it would be good for Fedora gcc as well.  I'll put the patch in 13
as well.
 
Marek



[PATCH] i386: add -fno-stack-protector to two tests

2023-06-29 Thread Marek Polacek via Gcc-patches
These tests fail when the testsuite is executed with -fstack-protector-strong.
To avoid this, this patch adds -fno-stack-protector to dg-options.

Tested on x86_64-pc-linux-gnu, ok for trunk?

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr104610.c: Use -fno-stack-protector.
* gcc.target/i386/pr69482-1.c: Likewise.
---
 gcc/testsuite/gcc.target/i386/pr104610.c  | 2 +-
 gcc/testsuite/gcc.target/i386/pr69482-1.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.target/i386/pr104610.c 
b/gcc/testsuite/gcc.target/i386/pr104610.c
index fe39cbe5b8a..5173fc8898c 100644
--- a/gcc/testsuite/gcc.target/i386/pr104610.c
+++ b/gcc/testsuite/gcc.target/i386/pr104610.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -mavx -mmove-max=256 -mstore-max=256" } */
+/* { dg-options "-O2 -mavx -mmove-max=256 -mstore-max=256 
-fno-stack-protector" } */
 /* { dg-final { scan-assembler-times {(?n)vptest.*ymm} 1 } } */
 /* { dg-final { scan-assembler-times {sete} 1 } } */
 /* { dg-final { scan-assembler-not {(?n)je.*L[0-9]} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr69482-1.c 
b/gcc/testsuite/gcc.target/i386/pr69482-1.c
index f192261b104..99bb6ad5a37 100644
--- a/gcc/testsuite/gcc.target/i386/pr69482-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr69482-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O3" } */
+/* { dg-options "-O3 -fno-stack-protector" } */
 
 static inline void memset_s(void* s, int n) {
   volatile unsigned char * p = s;

base-commit: 070a6bf0bdc6761ad77ac97404c98f00a7007d54
-- 
2.41.0



[PATCH] testsuite: Use -fno-report-bug in gcc.dg/plugin/

2023-06-29 Thread Marek Polacek via Gcc-patches
Certain downstream compilers (for example, in Fedora) default to
-freport-bug.  The extra output breaks the following tests.  We can use
-fno-report-bug to fix that.  Patch verified with:

$ make check RUNTESTFLAGS='--target_board=unix\{,-freport-bug\} plugin.exp'

Tested x86_64-pc-linux-gnu, ok for trunk/13?

gcc/testsuite/ChangeLog:

* gcc.dg/plugin/crash-test-ice-sarif.c: Use -fno-report-bug.  Adjust
scan-sarif-file.
* gcc.dg/plugin/crash-test-ice-stderr.c: Use -fno-report-bug.
* gcc.dg/plugin/crash-test-write-though-null-sarif.c: Use
-fno-report-bug.  Adjust scan-sarif-file.
* gcc.dg/plugin/crash-test-write-though-null-stderr.c: Use
-fno-report-bug.
---
 gcc/testsuite/gcc.dg/plugin/crash-test-ice-sarif.c | 3 ++-
 gcc/testsuite/gcc.dg/plugin/crash-test-ice-stderr.c| 1 +
 .../gcc.dg/plugin/crash-test-write-though-null-sarif.c | 3 ++-
 .../gcc.dg/plugin/crash-test-write-though-null-stderr.c| 1 +
 4 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/plugin/crash-test-ice-sarif.c 
b/gcc/testsuite/gcc.dg/plugin/crash-test-ice-sarif.c
index 3b773a9a84c..84a4347a17e 100644
--- a/gcc/testsuite/gcc.dg/plugin/crash-test-ice-sarif.c
+++ b/gcc/testsuite/gcc.dg/plugin/crash-test-ice-sarif.c
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-fdiagnostics-format=sarif-file" } */
+/* { dg-additional-options "-fno-report-bug" } */
 
 extern void inject_ice (void);
 
@@ -56,7 +57,7 @@ void test_inject_ice (void)
  { dg-final { scan-sarif-file "\"contextRegion\": " } }
  { dg-final { scan-sarif-file "\"artifactLocation\": " } }
  { dg-final { scan-sarif-file "\"region\": " } }
-   { dg-final { scan-sarif-file "\"startLine\": 8" } }
+   { dg-final { scan-sarif-file "\"startLine\": 9" } }
{ dg-final { scan-sarif-file "\"startColumn\": 3" } }
{ dg-final { scan-sarif-file "\"endColumn\": 16" } }
  { dg-final { scan-sarif-file "\"message\": " } }
diff --git a/gcc/testsuite/gcc.dg/plugin/crash-test-ice-stderr.c 
b/gcc/testsuite/gcc.dg/plugin/crash-test-ice-stderr.c
index cee701b135c..0064d3bc447 100644
--- a/gcc/testsuite/gcc.dg/plugin/crash-test-ice-stderr.c
+++ b/gcc/testsuite/gcc.dg/plugin/crash-test-ice-stderr.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-additional-options "-fno-report-bug" } */
 
 extern void inject_ice (void);
 
diff --git a/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-sarif.c 
b/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-sarif.c
index 57caa20155f..83b38d2ffb5 100644
--- a/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-sarif.c
+++ b/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-sarif.c
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-fdiagnostics-format=sarif-file" } */
+/* { dg-additional-options "-fno-report-bug" } */
 
 extern void inject_write_through_null (void);
 
@@ -56,7 +57,7 @@ void test_inject_write_through_null (void)
  { dg-final { scan-sarif-file "\"contextRegion\": " } }
  { dg-final { scan-sarif-file "\"artifactLocation\": " } }
  { dg-final { scan-sarif-file "\"region\": " } }
-   { dg-final { scan-sarif-file "\"startLine\": 8" } }
+   { dg-final { scan-sarif-file "\"startLine\": 9" } }
{ dg-final { scan-sarif-file "\"startColumn\": 3" } }
{ dg-final { scan-sarif-file "\"endColumn\": 31" } }
  { dg-final { scan-sarif-file "\"message\": " } }
diff --git a/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-stderr.c 
b/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-stderr.c
index 7b43e423633..a9a211a3b1f 100644
--- a/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-stderr.c
+++ b/gcc/testsuite/gcc.dg/plugin/crash-test-write-though-null-stderr.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-additional-options "-fno-report-bug" } */
 
 extern void inject_write_through_null (void);
 

base-commit: 070a6bf0bdc6761ad77ac97404c98f00a7007d54
-- 
2.41.0



Re: [PATCH] configure: Implement --enable-host-bind-now

2023-06-29 Thread Marek Polacek via Gcc-patches
On Thu, Jun 29, 2023 at 05:58:22PM +0200, Martin Jambor wrote:
> Hi,
> 
> On Tue, Jun 27 2023, Marek Polacek wrote:
> > On Tue, Jun 27, 2023 at 01:39:16PM +0200, Martin Jambor wrote:
> >> Hello,
> >> 
> >> On Tue, May 16 2023, Marek Polacek via Gcc-patches wrote:
> >> > As promised in the --enable-host-pie patch, this patch adds another
> >> > configure option, --enable-host-bind-now, which adds -z now when linking
> >> > the compiler executables in order to extend hardening.  BIND_NOW with 
> >> > RELRO
> >> > allows the GOT to be marked RO; this prevents GOT modification attacks.
> >> >
> >> > This option does not affect linking of target libraries; you can use
> >> > LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now to enable RELRO/BIND_NOW.
> >> >
> >> > With this patch:
> >> > $ readelf -Wd cc1{,plus} | grep FLAGS
> >> >  0x001e (FLAGS)  BIND_NOW
> >> >  0x6ffb (FLAGS_1)Flags: NOW PIE
> >> >  0x001e (FLAGS)  BIND_NOW
> >> >  0x6ffb (FLAGS_1)Flags: NOW PIE
> >> >
> >> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >> >
> >> > c++tools/ChangeLog:
> >> >
> >> >  * configure.ac (--enable-host-bind-now): New check.
> >> >  * configure: Regenerate.
> >> >
> >> > gcc/ChangeLog:
> >> >
> >> >  * configure.ac (--enable-host-bind-now): New check.  Add
> >> >  -Wl,-z,now to LD_PICFLAG if --enable-host-bind-now.
> >> >  * configure: Regenerate.
> >> >  * doc/install.texi: Document --enable-host-bind-now.
> >> >
> >> > lto-plugin/ChangeLog:
> >> >
> >> >  * configure.ac (--enable-host-bind-now): New check.  Link with
> >> >  -z,now.
> >> >  * configure: Regenerate.
> >> 
> >> Our reconfiguration checking script complains about a missing hunk in
> >> lto-plugin/Makefile.in:
> >> 
> >> diff --git a/lto-plugin/Makefile.in b/lto-plugin/Makefile.in
> >> index cb568e1e09f..f6f5b020ff5 100644
> >> --- a/lto-plugin/Makefile.in
> >> +++ b/lto-plugin/Makefile.in
> >> @@ -298,6 +298,7 @@ datadir = @datadir@
> >>  datarootdir = @datarootdir@
> >>  docdir = @docdir@
> >>  dvidir = @dvidir@
> >> +enable_host_bind_now = @enable_host_bind_now@
> >>  exec_prefix = @exec_prefix@
> >>  gcc_build_dir = @gcc_build_dir@
> >>  get_gcc_base_ver = @get_gcc_base_ver@
> >> 
> >> 
> >> I am somewhat puzzled why the line is not missing in any of the other
> >> Makefile.in files.  Can you please check whether that is the only thing
> >> that is missing (assuming it is actually missing)?
> >
> > Arg, once again, I'm sorry.  I don't know how this happened.  It would
> > be trivial to fix it but since
> >
> > commit 4a48a38fa99f067b8f3a3d1a5dc7a1e602db351f
> > Author: Eric Botcazou 
> > Date:   Wed Jun 21 18:19:36 2023 +0200
> >
> > ada: Fix build of GNAT tools
> >
> > the build with Ada included fails with --enable-host-pie.  So that needs
> > to be fixed first.
> >
> > Eric, I'm not asking you to fix that, but I'm curious, what did the
> > commit above fix?  The patch looks correct; I'm just puzzled why I
> > hadn't seen any build failures.
> >
> > The --enable-host-pie patch has been a nightmare :(.
> >
> 
> No worries, I can see how these things can easily get difficult.
> 
> Unfortunately I won't have time to actually look at this in the next 2-3
> weeks, so I am inclined to just trust the verification script (which
> essentially runs autoconf/automake everywhere and then expects no diff)
> and commit the one-line change.  What do you think, does that make sense
> (even without looking at why other Makefile.in files did not change)?

Yes please, go ahead with the one line change meanwhile.  Thanks!

I've opened PR110467 for the build problem.

Marek



Re: [PATCH] c++: unpropagated CONSTRUCTOR_MUTABLE_POISON [PR110463]

2023-06-29 Thread Marek Polacek via Gcc-patches
On Thu, Jun 29, 2023 at 11:22:55AM -0400, Patrick Palka via Gcc-patches wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk/13?
> 
> -- >8 --
> 
> cp_fold is neglecting to propagate CONSTRUCTOR_MUTABLE_POISON when folding
> a CONSTRUCTOR initializer, which for the below testcase causes us to fail
> to reject a mutable member access of a constexpr variable during constexpr
> evaluation.

LGTM.
 
>   PR c++/110463
> 
> gcc/cp/ChangeLog:
> 
>   * cp-gimplify.cc (cp_fold) : Propagate
>   CONSTRUCTOR_MUTABLE_POISON.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/cpp0x/constexpr-mutable6.C: New test.
> ---
>  gcc/cp/cp-gimplify.cc  |  2 ++
>  .../g++.dg/cpp0x/constexpr-mutable6.C  | 18 ++
>  2 files changed, 20 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-mutable6.C
> 
> diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
> index 853b1e44236..f5734197774 100644
> --- a/gcc/cp/cp-gimplify.cc
> +++ b/gcc/cp/cp-gimplify.cc
> @@ -3079,6 +3079,8 @@ cp_fold (tree x, fold_flags_t flags)
>   x = build_constructor (TREE_TYPE (x), nelts);
>   CONSTRUCTOR_PLACEHOLDER_BOUNDARY (x)
> = CONSTRUCTOR_PLACEHOLDER_BOUNDARY (org_x);
> + CONSTRUCTOR_MUTABLE_POISON (x)
> +   = CONSTRUCTOR_MUTABLE_POISON (org_x);
> }
>   if (VECTOR_TYPE_P (TREE_TYPE (x)))
> x = fold (x);
> diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable6.C 
> b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable6.C
> new file mode 100644
> index 000..2c946e388ab
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable6.C
> @@ -0,0 +1,18 @@
> +// PR c++/110463
> +// { dg-do compile { target c++11 } }
> +
> +struct U {
> +  mutable int x = 1;
> +};
> +
> +struct V {
> +  mutable int y = 1+1;
> +};
> +
> +int main() {
> +  constexpr U u = {};
> +  constexpr int x = u.x; // { dg-error "mutable" }
> +
> +  constexpr V v = {};
> +  constexpr int y = v.y; // { dg-error "mutable" }
> +}
> -- 
> 2.41.0.199.ga9e066fa63
> 

Marek



Re: [PATCH] configure: Implement --enable-host-bind-now

2023-06-27 Thread Marek Polacek via Gcc-patches
On Tue, Jun 27, 2023 at 01:39:16PM +0200, Martin Jambor wrote:
> Hello,
> 
> On Tue, May 16 2023, Marek Polacek via Gcc-patches wrote:
> > As promised in the --enable-host-pie patch, this patch adds another
> > configure option, --enable-host-bind-now, which adds -z now when linking
> > the compiler executables in order to extend hardening.  BIND_NOW with RELRO
> > allows the GOT to be marked RO; this prevents GOT modification attacks.
> >
> > This option does not affect linking of target libraries; you can use
> > LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now to enable RELRO/BIND_NOW.
> >
> > With this patch:
> > $ readelf -Wd cc1{,plus} | grep FLAGS
> >  0x001e (FLAGS)  BIND_NOW
> >  0x6ffb (FLAGS_1)Flags: NOW PIE
> >  0x001e (FLAGS)  BIND_NOW
> >  0x6ffb (FLAGS_1)Flags: NOW PIE
> >
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > c++tools/ChangeLog:
> >
> > * configure.ac (--enable-host-bind-now): New check.
> > * configure: Regenerate.
> >
> > gcc/ChangeLog:
> >
> > * configure.ac (--enable-host-bind-now): New check.  Add
> > -Wl,-z,now to LD_PICFLAG if --enable-host-bind-now.
> > * configure: Regenerate.
> > * doc/install.texi: Document --enable-host-bind-now.
> >
> > lto-plugin/ChangeLog:
> >
> > * configure.ac (--enable-host-bind-now): New check.  Link with
> > -z,now.
> > * configure: Regenerate.
> 
> Our reconfiguration checking script complains about a missing hunk in
> lto-plugin/Makefile.in:
> 
> diff --git a/lto-plugin/Makefile.in b/lto-plugin/Makefile.in
> index cb568e1e09f..f6f5b020ff5 100644
> --- a/lto-plugin/Makefile.in
> +++ b/lto-plugin/Makefile.in
> @@ -298,6 +298,7 @@ datadir = @datadir@
>  datarootdir = @datarootdir@
>  docdir = @docdir@
>  dvidir = @dvidir@
> +enable_host_bind_now = @enable_host_bind_now@
>  exec_prefix = @exec_prefix@
>  gcc_build_dir = @gcc_build_dir@
>  get_gcc_base_ver = @get_gcc_base_ver@
> 
> 
> I am somewhat puzzled why the line is not missing in any of the other
> Makefile.in files.  Can you please check whether that is the only thing
> that is missing (assuming it is actually missing)?

Arg, once again, I'm sorry.  I don't know how this happened.  It would
be trivial to fix it but since

commit 4a48a38fa99f067b8f3a3d1a5dc7a1e602db351f
Author: Eric Botcazou 
Date:   Wed Jun 21 18:19:36 2023 +0200

ada: Fix build of GNAT tools

the build with Ada included fails with --enable-host-pie.  So that needs
to be fixed first.

Eric, I'm not asking you to fix that, but I'm curious, what did the
commit above fix?  The patch looks correct; I'm just puzzled why I
hadn't seen any build failures.

The --enable-host-pie patch has been a nightmare :(.

Marek



[PATCH] c++: fix error reporting routines re-entered ICE [PR110175]

2023-06-23 Thread Marek Polacek via Gcc-patches
Here we get the "error reporting routines re-entered" ICE because
of an unguarded use of warning_at.  While at it, I added a check
for a warning_at just above it.

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

PR c++/110175

gcc/cp/ChangeLog:

* typeck.cc (cp_build_unary_op): Check tf_warning before warning.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/decltype-110175.C: New test.
---
 gcc/cp/typeck.cc | 5 +++--
 gcc/testsuite/g++.dg/cpp0x/decltype-110175.C | 6 ++
 2 files changed, 9 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-110175.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index da591dafc8f..859b133a18d 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -7561,7 +7561,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool 
noconvert,
/* [depr.volatile.type] "Postfix ++ and -- expressions and
   prefix ++ and -- expressions of volatile-qualified arithmetic
   and pointer types are deprecated."  */
-   if (TREE_THIS_VOLATILE (arg) || CP_TYPE_VOLATILE_P (TREE_TYPE (arg)))
+   if ((TREE_THIS_VOLATILE (arg) || CP_TYPE_VOLATILE_P (TREE_TYPE (arg)))
+   && (complain & tf_warning))
  warning_at (location, OPT_Wvolatile,
  "%qs expression of %-qualified type is "
  "deprecated",
@@ -7592,7 +7593,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool 
noconvert,
return error_mark_node;
  }
/* Otherwise, [depr.incr.bool] says this is deprecated.  */
-   else
+   else if (complain & tf_warning)
  warning_at (location, OPT_Wdeprecated,
  "use of an operand of type %qT "
  "in % is deprecated",
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-110175.C 
b/gcc/testsuite/g++.dg/cpp0x/decltype-110175.C
new file mode 100644
index 000..39643cafcf8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-110175.C
@@ -0,0 +1,6 @@
+// PR c++/110175
+// { dg-do compile { target c++11 } }
+
+template auto f(T t) -> decltype(++t) { return t; } // { dg-warning 
"reference" "" { target c++14_down } }
+void f(...) {}
+void g() { f(true); }

base-commit: 5388a43f6a3f348929292998bd6d0c1da6f006de
-- 
2.41.0



[PATCH v2] c++: Add support for -std={c,gnu}++2{c,6}

2023-06-23 Thread Marek Polacek via Gcc-patches
On Fri, Jun 23, 2023 at 10:58:54AM -0400, Jason Merrill wrote:
> On 6/22/23 20:25, Marek Polacek wrote:
> > It seems prudent to add C++26 now that the first C++26 papers have been
> > approved.  I followed commit r11-6920 as well as r8-3237.
> > 
> > I was puzzled to see that -std=c++23 was marked Undocumented but
> > -std=c++2b wasn't.  I think it should be the other way round, like
> > the earlier modes.
> 
> I was leaving -std=c++23 undocumented until C++23 was finalized, which it
> now effectively is, so this change is good.  Speaking of which, it looks
> like the final value for __cplusplus for C++23 is 202302L.
 
Ok.  I've updated the code to reflect that.

> But similarly, I'd like to leave -std=c++26 undocumented for now.

Done.

> > As for __cplusplus, I've arbitrarily chosen 202600L:
> 
> Our previous convention has been the year after the previous standard, so
> let's use 202400L.
 
Done.

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

-- >8 --
It seems prudent to add C++26 now that the first C++26 papers have been
approved.  I followed commit r11-6920 as well as r8-3237.

Since C++23 is essentially finished and its __cplusplus value has
settled to 202302L, I've updated cpp_init_builtins and marked
-std=c++2b Undocumented and made -std=c++23 no longer Undocumented.

As for __cplusplus, I've chosen 202400L:

  $ xg++ -std=c++26 -dM -E -x c++ - < /dev/null | grep cplusplus
  #define __cplusplus 202400L

I've verified the patch with a simple test, exercising the new
directives.  Don't forget to update your GXX_TESTSUITE_STDS!

This patch does not add -Wc++26-extensions.

gcc/c-family/ChangeLog:

* c-common.h (cxx_dialect): Add cxx26 as a dialect.
* c-opts.cc (set_std_cxx26): New.
(c_common_handle_option): Set options when -std={c,gnu}++2{c,6} is
enabled.
(c_common_post_options): Adjust comments.
* c.opt: Add options for -std=c++26, std=c++2c, -std=gnu++26,
and -std=gnu++2c.
(std=c++2b): Mark as Undocumented.
(std=c++23): No longer Undocumented.

gcc/ChangeLog:

* doc/cpp.texi (__cplusplus): Document value for -std=c++26 and
-std=gnu++26.  Document that for C++23, its value is 202302L.
* doc/invoke.texi: Document -std=c++26 and -std=gnu++26.
* dwarf2out.cc (highest_c_language): Handle GNU C++26.
(gen_compile_unit_die): Likewise.

libcpp/ChangeLog:

* include/cpplib.h (c_lang): Add CXX26 and GNUCXX26.
* init.cc (lang_defaults): Add rows for CXX26 and GNUCXX26.
(cpp_init_builtins): Set __cplusplus to 202400L for C++26.
Set __cplusplus to 202302L for C++23.

gcc/testsuite/ChangeLog:

* lib/target-supports.exp (check_effective_target_c++23): Return
1 also if check_effective_target_c++26.
(check_effective_target_c++23_down): New.
(check_effective_target_c++26_only): New.
(check_effective_target_c++26): New.
* g++.dg/cpp23/cplusplus.C: Adjust expected value.
* g++.dg/cpp26/cplusplus.C: New test.
---
 gcc/c-family/c-common.h|  4 +++-
 gcc/c-family/c-opts.cc | 28 +++-
 gcc/c-family/c.opt | 24 +
 gcc/doc/cpp.texi   |  7 +++---
 gcc/doc/invoke.texi| 12 +++
 gcc/dwarf2out.cc   |  5 -
 gcc/testsuite/g++.dg/cpp23/cplusplus.C |  2 +-
 gcc/testsuite/g++.dg/cpp26/cplusplus.C |  3 +++
 gcc/testsuite/lib/target-supports.exp  | 30 +-
 libcpp/include/cpplib.h|  2 +-
 libcpp/init.cc | 13 +++
 11 files changed, 113 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp26/cplusplus.C

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 336a09f4a40..b5ef5ff6b2c 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -740,7 +740,9 @@ enum cxx_dialect {
   /* C++20 */
   cxx20,
   /* C++23 */
-  cxx23
+  cxx23,
+  /* C++26 */
+  cxx26
 };
 
 /* The C++ dialect being used. C++98 is the default.  */
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index c68a2a27469..af19140e382 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -111,6 +111,7 @@ static void set_std_cxx14 (int);
 static void set_std_cxx17 (int);
 static void set_std_cxx20 (int);
 static void set_std_cxx23 (int);
+static void set_std_cxx26 (int);
 static void set_std_c89 (int, int);
 static void set_std_c99 (int);
 static void set_std_c11 (int);
@@ -663,6 +664,12 @@ c_common_handle_option (size_t scode, const char *arg, 
HOST_WIDE_INT value,
set_std_cxx23 (code == OPT_std_c__23 /* ISO */);
   break;
 
+case OPT_std_c__26:
+case OPT_std_gnu__26:
+  if (!preprocessing_asm_p)
+   set_std_cxx26 (code == OPT_std_c__26 /* ISO */);
+  break;
+
 case OPT_std_c90:
 case OPT_std_iso9899_199409:
   if 

[PATCH] c++: Add support for -std={c,gnu}++2{c,6}

2023-06-22 Thread Marek Polacek via Gcc-patches
It seems prudent to add C++26 now that the first C++26 papers have been
approved.  I followed commit r11-6920 as well as r8-3237.

I was puzzled to see that -std=c++23 was marked Undocumented but
-std=c++2b wasn't.  I think it should be the other way round, like
the earlier modes.

As for __cplusplus, I've arbitrarily chosen 202600L:

  $ xg++ -std=c++26 -dM -E -x c++ - < /dev/null | grep cplusplus
  #define __cplusplus 202600L

I've verified the patch with a simple test, exercising the new
directives.  Don't forget to update your GXX_TESTSUITE_STDS!

This patch does not add -Wc++26-extensions.

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

gcc/c-family/ChangeLog:

* c-common.h (cxx_dialect): Add cxx26 as a dialect.
* c-opts.cc (set_std_cxx26): New.
(c_common_handle_option): Set options when -std={c,gnu}++2{c,6} is
enabled.
(c_common_post_options): Adjust comments.
* c.opt: Add options for -std=c++26, std=c++2c, -std=gnu++26,
and -std=gnu++2c.
(std=c++2b): Mark as Undocumented.
(std=c++23): No longer Undocumented.

gcc/ChangeLog:

* doc/cpp.texi (__cplusplus): Document value for -std=c++26 and
-std=gnu++26.
* doc/invoke.texi: Document -std=c++26 and -std=gnu++26.
* dwarf2out.cc (highest_c_language): Handle GNU C++26.
(gen_compile_unit_die): Likewise.

libcpp/ChangeLog:

* include/cpplib.h (c_lang): Add CXX26 and GNUCXX26.
* init.cc (lang_defaults): Add rows for CXX26 and GNUCXX26.
(cpp_init_builtins): Set __cplusplus to 202600L for C++26.

gcc/testsuite/ChangeLog:

* lib/target-supports.exp (check_effective_target_c++23): Return
1 also if check_effective_target_c++26.
(check_effective_target_c++23_down): New.
(check_effective_target_c++26_only): New.
(check_effective_target_c++26): New.
* g++.dg/cpp26/cplusplus.C: New test.
---
 gcc/c-family/c-common.h|  4 +++-
 gcc/c-family/c-opts.cc | 28 +++-
 gcc/c-family/c.opt | 24 +
 gcc/doc/cpp.texi   |  5 +
 gcc/doc/invoke.texi| 12 +++
 gcc/dwarf2out.cc   |  5 -
 gcc/testsuite/g++.dg/cpp26/cplusplus.C |  5 +
 gcc/testsuite/lib/target-supports.exp  | 30 +-
 libcpp/include/cpplib.h|  2 +-
 libcpp/init.cc | 13 ---
 10 files changed, 116 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp26/cplusplus.C

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 336a09f4a40..b5ef5ff6b2c 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -740,7 +740,9 @@ enum cxx_dialect {
   /* C++20 */
   cxx20,
   /* C++23 */
-  cxx23
+  cxx23,
+  /* C++26 */
+  cxx26
 };
 
 /* The C++ dialect being used. C++98 is the default.  */
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index c68a2a27469..af19140e382 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -111,6 +111,7 @@ static void set_std_cxx14 (int);
 static void set_std_cxx17 (int);
 static void set_std_cxx20 (int);
 static void set_std_cxx23 (int);
+static void set_std_cxx26 (int);
 static void set_std_c89 (int, int);
 static void set_std_c99 (int);
 static void set_std_c11 (int);
@@ -663,6 +664,12 @@ c_common_handle_option (size_t scode, const char *arg, 
HOST_WIDE_INT value,
set_std_cxx23 (code == OPT_std_c__23 /* ISO */);
   break;
 
+case OPT_std_c__26:
+case OPT_std_gnu__26:
+  if (!preprocessing_asm_p)
+   set_std_cxx26 (code == OPT_std_c__26 /* ISO */);
+  break;
+
 case OPT_std_c90:
 case OPT_std_iso9899_199409:
   if (!preprocessing_asm_p)
@@ -1032,7 +1039,8 @@ c_common_post_options (const char **pfilename)
warn_narrowing = 1;
 
   /* Unless -f{,no-}ext-numeric-literals has been used explicitly,
-for -std=c++{11,14,17,20,23} default to -fno-ext-numeric-literals.  */
+for -std=c++{11,14,17,20,23,26} default to
+-fno-ext-numeric-literals.  */
   if (flag_iso && !OPTION_SET_P (flag_ext_numeric_literals))
cpp_opts->ext_numeric_literals = 0;
 }
@@ -1820,6 +1828,24 @@ set_std_cxx23 (int iso)
   lang_hooks.name = "GNU C++23";
 }
 
+/* Set the C++ 2026 standard (without GNU extensions if ISO).  */
+static void
+set_std_cxx26 (int iso)
+{
+  cpp_set_lang (parse_in, iso ? CLK_CXX26: CLK_GNUCXX26);
+  flag_no_gnu_keywords = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_iso = iso;
+  /* C++26 includes the C11 standard library.  */
+  flag_isoc94 = 1;
+  flag_isoc99 = 1;
+  flag_isoc11 = 1;
+  /* C++26 includes coroutines.  */
+  flag_coroutines = true;
+  cxx_dialect = cxx26;
+  lang_hooks.name = "GNU C++26";
+}
+
 /* Args to -d specify what to dump.  Silently ignore
unrecognized options; they may be aimed at 

Re: PING: Re: [PATCH] c++: provide #include hint for missing includes [PR110164]

2023-06-22 Thread Marek Polacek via Gcc-patches
On Wed, Jun 21, 2023 at 04:44:00PM -0400, David Malcolm via Gcc-patches wrote:
> I'd like to ping this C++ FE patch for review:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-June/621779.html

Not an approval, but LGTM, though some nits below:
 
> On Wed, 2023-06-14 at 20:28 -0400, David Malcolm wrote:
> > PR c++/110164 notes that in cases where we have a forward decl
> > of a std library type such as:
> > 
> > std::array x;
> > 
> > we omit this diagnostic:
> > 
> > error: aggregate ‘std::array x’ has incomplete type and cannot be 
> > defined
> > 
> > This patch adds this hint to the diagnostic:
> > 
> > note: ‘std::array’ is defined in header ‘’; this is probably fixable 
> > by adding ‘#include ’
> > 
> > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> > OK for trunk?
> > 
> > gcc/cp/ChangeLog:
> > PR c++/110164
> > * cp-name-hint.h (maybe_suggest_missing_header): New decl.
> > * decl.cc: Define INCLUDE_MEMORY.  Add include of
> > "cp/cp-name-hint.h".
> > (start_decl_1): Call maybe_suggest_missing_header.
> > * name-lookup.cc (maybe_suggest_missing_header): Remove "static".
> > 
> > gcc/testsuite/ChangeLog:
> > PR c++/110164
> > * g++.dg/missing-header-pr110164.C: New test.
> > ---
> >  gcc/cp/cp-name-hint.h  |  3 +++
> >  gcc/cp/decl.cc | 10 ++
> >  gcc/cp/name-lookup.cc  |  2 +-
> >  gcc/testsuite/g++.dg/missing-header-pr110164.C | 10 ++
> >  4 files changed, 24 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/g++.dg/missing-header-pr110164.C
> > 
> > diff --git a/gcc/cp/cp-name-hint.h b/gcc/cp/cp-name-hint.h
> > index bfa7c53c8f6..e2387e23d1f 100644
> > --- a/gcc/cp/cp-name-hint.h
> > +++ b/gcc/cp/cp-name-hint.h
> > @@ -32,6 +32,9 @@ along with GCC; see the file COPYING3.  If not see
> >  
> >  extern name_hint suggest_alternatives_for (location_t, tree, bool);
> >  extern name_hint suggest_alternatives_in_other_namespaces (location_t, 
> > tree);
> > +extern name_hint maybe_suggest_missing_header (location_t location,
> > +  tree name,
> > +  tree scope);

The enclosing decls omit the parameter names; if you do that, it may
fit on one line.

> >  extern name_hint suggest_alternative_in_explicit_scope (location_t, tree, 
> > tree);
> >  extern name_hint suggest_alternative_in_scoped_enum (tree, tree);
> >  
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index a672e4844f1..504b08ec250 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >     line numbers.  For example, the CONST_DECLs for enum values.  */
> >  
> >  #include "config.h"
> > +#define INCLUDE_MEMORY
> >  #include "system.h"
> >  #include "coretypes.h"
> >  #include "target.h"
> > @@ -46,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "c-family/c-objc.h"
> >  #include "c-family/c-pragma.h"
> >  #include "c-family/c-ubsan.h"
> > +#include "cp/cp-name-hint.h"
> >  #include "debug.h"
> >  #include "plugin.h"
> >  #include "builtins.h"
> > @@ -5995,7 +5997,11 @@ start_decl_1 (tree decl, bool initialized)
> > ;   /* An auto type is ok.  */
> >    else if (TREE_CODE (type) != ARRAY_TYPE)
> > {
> > + auto_diagnostic_group d;
> >   error ("variable %q#D has initializer but incomplete type", decl);
> > + maybe_suggest_missing_header (input_location,
> > +   TYPE_IDENTIFIER (type),
> > +   TYPE_CONTEXT (type));

Maybe CP_TYPE_CONTEXT?

> >   type = TREE_TYPE (decl) = error_mark_node;
> > }
> >    else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type
> > @@ -6011,8 +6017,12 @@ start_decl_1 (tree decl, bool initialized)
> > gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (type));
> >    else
> > {
> > + auto_diagnostic_group d;
> >   error ("aggregate %q#D has incomplete type and cannot be defined",
> >  decl);
> > + maybe_suggest_missing_header (input_location,
> > +   TYPE_IDENTIFIER (type),
> > +   TYPE_CONTEXT (type));

Here as well.

> >   /* Change the type so that assemble_variable will give
> >  DECL an rtl we can live with: (mem (const_int 0)).  */
> >   type = TREE_TYPE (decl) = error_mark_node;
> > diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
> > index 6ac58a35b56..917b481c163 100644
> > --- a/gcc/cp/name-lookup.cc
> > +++ b/gcc/cp/name-lookup.cc
> > @@ -6796,7 +6796,7 @@ maybe_suggest_missing_std_header (location_t 
> > location, tree name)
> >     for NAME within SCOPE at LOCATION, or an empty name_hint if this isn't

[wwwdocs] cxx-status: Add C++26 papers (Spring 2023, Varna)

2023-06-21 Thread Marek Polacek via Gcc-patches
First C++26 papers started to trickle in.  Update our docs accordingly.

We don't have -std=c++2c/-std=c++26/-std=gnu++2c/-std=gnu++26 yet, but
I should have a patch for it by the end of this week.

W3C validated.  Pushed.

commit 9c66e33761140358d350c5fb2d1638f6afdaead4
Author: Marek Polacek 
Date:   Wed Jun 21 12:41:25 2023 -0400

cxx-status: Add C++26 papers (Spring 2023, Varna)

diff --git a/htdocs/projects/cxx-status.html b/htdocs/projects/cxx-status.html
index 675fbcd0..99387540 100644
--- a/htdocs/projects/cxx-status.html
+++ b/htdocs/projects/cxx-status.html
@@ -20,6 +20,7 @@
 C++17
 C++20
 C++23
+C++26
 Technical Specifications
   
   
@@ -32,6 +33,99 @@
Implementation Status section of the Libstdc++ manual.
   
 
+  C++26 Support in GCC
+
+  GCC has experimental support for the next revision of the C++
+  standard, which is expected to be published in 2026.
+
+
+
+
+  C++26 Language Features
+
+  
+
+  Language Feature
+  Proposal
+  Available in GCC?
+  SD-6 Feature Test
+
+
+
+   Remove undefined behavior from lexing 
+  https://wg21.link/P2621R2;>P2621R2 (DR) 
+   https://gcc.gnu.org/PR110340;>No
+   
+
+
+   Making non-encodable string literals ill-formed 
+  https://wg21.link/P1854R4;>P1854R4  (DR) 
+   https://gcc.gnu.org/PR110341;>No
+   
+
+
+   Unevaluated strings 
+   https://wg21.link/P2361R6;>P2361R6
+   https://gcc.gnu.org/PR110342;>No
+   
+
+
+   Add @, $, and ` to the basic character set 
+   https://wg21.link/P2558R2;>P2558R2
+   https://gcc.gnu.org/PR110343;>No
+   
+
+
+   constexpr cast from void* 
+   https://wg21.link/P2738R1;>P2738R1
+   https://gcc.gnu.org/PR110344;>No
+   
+
+
+   On the ignorability of standard attributes 
+  https://wg21.link/P2552R3;>P2552R3 (DR) 
+   https://gcc.gnu.org/PR110345;>No
+   
+
+
+   Static storage for braced initializers 
+  https://wg21.link/P2752R3;>P2752R3 (DR) 
+   https://gcc.gnu.org/PR110346;>No
+   
+
+
+   User-generated static_assert messages 
+   https://wg21.link/P2741R3;>P2741R3
+   https://gcc.gnu.org/PR110348;>No
+   
+
+
+   Placeholder variables with no name 
+   https://wg21.link/P2169R4;>P2169R4
+   https://gcc.gnu.org/PR110349;>No
+   
+
+
+  
+
   C++23 Support in GCC
 
   GCC has experimental support for the next revision of the C++



Re: [PATCH v3] configure: Implement --enable-host-pie

2023-06-16 Thread Marek Polacek via Gcc-patches
On Fri, Jun 16, 2023 at 12:26:23PM +0200, Martin Jambor wrote:
> Hello,
> 
> On Thu, Jun 15 2023, Marek Polacek via Gcc-patches wrote:
> > On Mon, Jun 05, 2023 at 09:06:43PM -0600, Jeff Law wrote:
> >> 
> >> 
> >> On 6/5/23 10:18, Marek Polacek via Gcc-patches wrote:
> >> > Ping.  Anyone have any further comments?
> >> Given this was approved before, but got reverted due to issues (which have
> >> since been addressed) -- I think you might as well go forward and sooner
> >> rather than later so that we can catch fallout earlier.
> >
> > Thanks, pushed now, after rebasing, adjusting the patch for
> > r14-1385, and testing with and without --enable-host-pie on
> > both Debian and Fedora.
> >
> > If something comes up and I can't fix it quickly enough, I'll
> > have to revert the patch.  We'll see.
> >
> 
> The script that regularly checks that the checked-in autotools-generated
> files are in sync now complain about the following diff.  Unless someone
> stops me because I overlooked something or for some other reason, I will
> commit it later on as obvious.

Please, go ahead.
 
> I wonder where the "line" differences come from, perhaps you added a
> comment after running autoconf/automake/...?  The zlib/Makefile.in hunks

Arg, I think I must've messed up the #lines when rebasing though I don't
know what went wrong with zlib/Makefile.in.  But I don't think the latter
will actually make any difference.

> like something we should have, though, even if I did not check whether
> it makes any difference in practice.  And I want the checking script to
> shut up too ;-)

Thanks and sorry.

> Thanks,
> 
> Martin
> 
> 
> diff --git a/gcc/configure b/gcc/configure
> index a4563a9cade..f7b4b283ca2 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -19847,7 +19847,7 @@ else
>lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>lt_status=$lt_dlunknown
>cat > conftest.$ac_ext <<_LT_EOF
> -#line 19848 "configure"
> +#line 19850 "configure"
>  #include "confdefs.h"
>  
>  #if HAVE_DLFCN_H
> @@ -19953,7 +19953,7 @@ else
>lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>lt_status=$lt_dlunknown
>cat > conftest.$ac_ext <<_LT_EOF
> -#line 19954 "configure"
> +#line 19956 "configure"
>  #include "confdefs.h"
>  
>  #if HAVE_DLFCN_H
> diff --git a/zlib/Makefile.in b/zlib/Makefile.in
> index 3f5102d1b87..80fe3b69116 100644
> --- a/zlib/Makefile.in
> +++ b/zlib/Makefile.in
> @@ -353,6 +353,8 @@ datadir = @datadir@
>  datarootdir = @datarootdir@
>  docdir = @docdir@
>  dvidir = @dvidir@
> +enable_host_pie = @enable_host_pie@
> +enable_host_shared = @enable_host_shared@
>  exec_prefix = @exec_prefix@
>  host = @host@
>  host_alias = @host_alias@
> diff --git a/zlib/configure b/zlib/configure
> index 77be6c284e3..9308866a636 100755
> --- a/zlib/configure
> +++ b/zlib/configure
> @@ -10763,7 +10763,7 @@ else
>lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>lt_status=$lt_dlunknown
>cat > conftest.$ac_ext <<_LT_EOF
> -#line 10778 "configure"
> +#line 10766 "configure"
>  #include "confdefs.h"
>  
>  #if HAVE_DLFCN_H
> @@ -10869,7 +10869,7 @@ else
>lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>lt_status=$lt_dlunknown
>cat > conftest.$ac_ext <<_LT_EOF
> -#line 10884 "configure"
> +#line 10872 "configure"
>  #include "confdefs.h"
>  
>  #if HAVE_DLFCN_H
> 

Marek



Re: [PATCH v3] configure: Implement --enable-host-pie

2023-06-15 Thread Marek Polacek via Gcc-patches
On Mon, Jun 05, 2023 at 09:06:43PM -0600, Jeff Law wrote:
> 
> 
> On 6/5/23 10:18, Marek Polacek via Gcc-patches wrote:
> > Ping.  Anyone have any further comments?
> Given this was approved before, but got reverted due to issues (which have
> since been addressed) -- I think you might as well go forward and sooner
> rather than later so that we can catch fallout earlier.

Thanks, pushed now, after rebasing, adjusting the patch for
r14-1385, and testing with and without --enable-host-pie on
both Debian and Fedora.

If something comes up and I can't fix it quickly enough, I'll
have to revert the patch.  We'll see.

Marek



[wwwdocs] cxx-dr-status: Update from C++ Core Language Issue TOC, Revision 111

2023-06-12 Thread Marek Polacek via Gcc-patches
A biiig update with 100 new DRs.

Also updated to reflect that DR 976 has been implemented.

W3C validated.  Pushed.

commit d558d0a4f3407696d3f2ed868926a09a289e032e
Author: Marek Polacek 
Date:   Mon Jun 12 20:06:34 2023 -0400

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

diff --git a/htdocs/projects/cxx-dr-status.html 
b/htdocs/projects/cxx-dr-status.html
index d87466a3..d9255328 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
-  109 (https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html;>here).
+  111 (https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html;>here).
 
   
 
@@ -274,7 +274,7 @@
 
 
   https://wg21.link/cwg36;>36
-  DRWP
+  CD6
   using-declarations in multiple-declaration contexts
   ?
   
@@ -792,7 +792,7 @@
 
 
   https://wg21.link/cwg110;>110
-  DRWP
+  CD6
   Can template functions and classes be declared in the same 
scope?
   ?
   
@@ -988,7 +988,7 @@
 
 
   https://wg21.link/cwg138;>138
-  DRWP
+  CD6
   Friend declaration name lookup
   ?
   
@@ -1210,11 +1210,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg170;>170
-  open
+  tentatively ready
   Pointer-to-member conversions
-  -
+  ?
   
 
 
@@ -1359,7 +1359,7 @@
 
 
   https://wg21.link/cwg191;>191
-  DRWP
+  CD6
   Name lookup does not handle complex nesting
   ?
   
@@ -1810,7 +1810,7 @@
 
 
   https://wg21.link/cwg255;>255
-  DRWP
+  CD6
   Placement deallocation functions and lookup ambiguity
   ?
   
@@ -1922,7 +1922,7 @@
 
 
   https://wg21.link/cwg271;>271
-  DRWP
+  CD6
   Explicit instantiation and template argument deduction
   ?
   
@@ -1978,7 +1978,7 @@
 
 
   https://wg21.link/cwg279;>279
-  DRWP
+  CD6
   Correspondence of "names for linkage purposes"
   ?
   
@@ -2391,7 +2391,7 @@
 
 
   https://wg21.link/cwg338;>338
-  DRWP
+  CD6
   Enumerator name with linkage used as class name in other translation 
unit
   ?
   
@@ -2545,7 +2545,7 @@
 
 
   https://wg21.link/cwg360;>360
-  DRWP
+  CD6
   Using-declaration that reduces access
   ?
   
@@ -2727,7 +2727,7 @@
 
 
   https://wg21.link/cwg386;>386
-  DRWP
+  CD6
   Friend declaration of name brought in by 
using-declaration
   ?
   
@@ -2818,7 +2818,7 @@
 
 
   https://wg21.link/cwg399;>399
-  DRWP
+  CD6
   Destructor lookup redux
   ?
   https://gcc.gnu.org/PR28985;>PR28985,
@@ -2861,7 +2861,7 @@
 
 
   https://wg21.link/cwg405;>405
-  DRWP
+  CD6
   Unqualified function name lookup
   ?
   
@@ -2903,7 +2903,7 @@
 
 
   https://wg21.link/cwg411;>411
-  WP
+  CD6
   Use of universal-character-name in character versus string 
literals
   ?
   
@@ -2952,7 +2952,7 @@
 
 
   https://wg21.link/cwg418;>418
-  DRWP
+  CD6
   Imperfect wording on error on multiple default arguments on a called 
function
   ?
   
@@ -3211,9 +3211,9 @@
 
 
   https://wg21.link/cwg455;>455
-  open
+  NAD
   Partial ordering and non-deduced arguments
-  -
+  N/A
   
 
 
@@ -3778,7 +3778,7 @@
 
 
   https://wg21.link/cwg536;>536
-  DRWP
+  CD6
   Problems in the description of id-expressions
   ?
   
@@ -3904,7 +3904,7 @@
 
 
   https://wg21.link/cwg554;>554
-  DRWP
+  CD6
   Definition of "declarative region" and "scope"
   ?
   
@@ -3960,14 +3960,14 @@
 
 
   https://wg21.link/cwg562;>562
-  DRWP
+  CD6
   qualified-ids in non-expression contexts
   ?
   
 
 
   https://wg21.link/cwg563;>563
-  DRWP
+  CD6
   Linkage specification for objects
   ?
   https://gcc.gnu.org/PR28389;>PR28389
@@ -4072,9 +4072,9 @@
 
 
   https://wg21.link/cwg578;>578
-  review
+  CD6
   Phase 1 replacement of characters with 
universal-character-names
-  -
+  ?
   
 
 
@@ -4226,7 +4226,7 @@
 
 
   https://wg21.link/cwg600;>600
-  DRWP
+  CD6
   Does access control apply to members or to names?
   ?
   
@@ -4275,7 +4275,7 @@
 
 
   https://wg21.link/cwg607;>607
-  DRWP
+  CD6
   Lookup of mem-initializer-ids
   ?
   
@@ -5239,11 +5239,11 @@
   ?
   
 
-
+
   https://wg21.link/cwg745;>745
-  open
+  C++23
   Effect of ill-formedness resulting from #error
-  

[PATCH] doc: Clarification for -Wmissing-field-initializers

2023-06-08 Thread Marek Polacek via Gcc-patches
The manual is incorrect in saying that the option does not warn
about designated initializers, which it does in C++.  Whether the
divergence in behavior is desirable is another thing, but let's
at least make the manual match the reality.

PR c/39589
PR c++/96868

gcc/ChangeLog:

* doc/invoke.texi: Clarify that -Wmissing-field-initializers doesn't
warn about designated initializers in C only.
---
 gcc/doc/invoke.texi | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6d08229ce40..0870f7aff93 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9591,8 +9591,9 @@ struct s @{ int f, g, h; @};
 struct s x = @{ 3, 4 @};
 @end smallexample
 
-This option does not warn about designated initializers, so the following
-modification does not trigger a warning:
+@c It's unclear if this behavior is desirable.  See PR39589 and PR96868.
+In C this option does not warn about designated initializers, so the
+following modification does not trigger a warning:
 
 @smallexample
 struct s @{ int f, g, h; @};

base-commit: 1379ae33e05c28d705f3c69a3f6c774bf6e83136
-- 
2.40.1



[PATCH] c++: wrong error with static constexpr var in tmpl [PR109876]

2023-05-26 Thread Marek Polacek via Gcc-patches
Since r8-509, we'll no longer create a static temporary var for
the initializer '{ 1, 2 }' for num in the attached test because
the code in finish_compound_literal is now guarded by
'&& fcl_context == fcl_c99' but it's fcl_functional here.  This
causes us to reject num as non-constant when evaluating it in
a template.

Jason's idea was to treat num as value-dependent even though it
actually isn't.  This patch implements that suggestion.

The is_really_empty_class check is sort of non-obvious but the
comment should explain why I added it.

Co-authored-by: Jason Merrill 

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

PR c++/109876

gcc/cp/ChangeLog:

* pt.cc (value_dependent_expression_p) : Treat a
constexpr-declared non-constant variable as value-dependent.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-template12.C: New test.
* g++.dg/cpp1z/constexpr-template1.C: New test.
---
 gcc/cp/pt.cc  | 12 ++
 .../g++.dg/cpp0x/constexpr-template12.C   | 38 +++
 .../g++.dg/cpp1z/constexpr-template1.C| 25 
 3 files changed, 75 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-template12.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-template1.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 7fb3e75bceb..38fd8070705 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27969,6 +27969,18 @@ value_dependent_expression_p (tree expression)
   else if (TYPE_REF_P (TREE_TYPE (expression)))
/* FIXME cp_finish_decl doesn't fold reference initializers.  */
return true;
+  /* We have a constexpr variable and we're processing a template.  When
+there's lifetime extension involved (for which finish_compound_literal
+used to create a temporary), we'll not be able to evaluate the
+variable until instantiating, so pretend it's value-dependent.  */
+  else if (DECL_DECLARED_CONSTEXPR_P (expression)
+  && !TREE_CONSTANT (expression)
+  /* When there's nothing to initialize, we'll never mark the
+ VAR_DECL TREE_CONSTANT, therefore it would remain
+ value-dependent and we wouldn't instantiate.  */
+  && !is_really_empty_class (TREE_TYPE (expression),
+ /*ignore_vptr*/false))
+   return true;
   return false;
 
 case DYNAMIC_CAST_EXPR:
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template12.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-template12.C
new file mode 100644
index 000..a9e065320c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template12.C
@@ -0,0 +1,38 @@
+// PR c++/109876
+// { dg-do compile { target c++11 } }
+
+using size_t = decltype(sizeof 0);
+
+namespace std {
+template  struct initializer_list {
+  const int *_M_array;
+  size_t _M_len;
+  constexpr size_t size() const { return _M_len; }
+};
+} // namespace std
+
+constexpr std::initializer_list gnum{2};
+
+template  struct Array {};
+template  void g()
+{
+  static constexpr std::initializer_list num{2};
+  static_assert(num.size(), "");
+  Array ctx;
+
+  constexpr Array<1> num1{};
+}
+
+template 
+struct Foo
+{
+  static constexpr std::initializer_list num = { 1, 2 };
+  static_assert(num.size(), "");
+  Array ctx;
+};
+
+void
+f (Foo<5>)
+{
+  g<0>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-template1.C 
b/gcc/testsuite/g++.dg/cpp1z/constexpr-template1.C
new file mode 100644
index 000..58be046fd36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-template1.C
@@ -0,0 +1,25 @@
+// PR c++/109876
+// { dg-do compile { target c++17 } }
+
+struct Foo {};
+template  struct X {};
+
+void g()
+{
+  static constexpr Foo foo;
+  X x;
+}
+
+template
+void f()
+{
+  static constexpr Foo foo;
+  X x;
+}
+
+void
+h ()
+{
+  f<0>();
+  f<1>();
+}

base-commit: 8d6bd830f5f9c939e8565c0341a0c6c588834484
-- 
2.40.1



[PATCH] c++: -Wdangling-reference not suppressed in template [PR109774]

2023-05-16 Thread Marek Polacek via Gcc-patches
In check_return_expr, we suppress the -Wdangling-reference warning when
we're sure it would be a false positive.  It wasn't working in a
template, though, because the suppress_warning call was never reached.

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

PR c++/109774

gcc/cp/ChangeLog:

* typeck.cc (check_return_expr): In a template, return only after
suppressing -Wdangling-reference.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wdangling-reference13.C: New test.
---
 gcc/cp/typeck.cc  |  6 ++---
 .../g++.dg/warn/Wdangling-reference13.C   | 23 +++
 2 files changed, 26 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference13.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 53ac925a092..c225c4e2423 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11236,9 +11236,6 @@ check_return_expr (tree retval, bool *no_warning)
 build_zero_cst (TREE_TYPE (retval)));
 }
 
-  if (processing_template_decl)
-return saved_retval;
-
   /* A naive attempt to reduce the number of -Wdangling-reference false
  positives: if we know that this function can return a variable with
  static storage duration rather than one of its parameters, suppress
@@ -11250,6 +11247,9 @@ check_return_expr (tree retval, bool *no_warning)
   && TREE_STATIC (bare_retval))
 suppress_warning (current_function_decl, OPT_Wdangling_reference);
 
+  if (processing_template_decl)
+return saved_retval;
+
   /* Actually copy the value returned into the appropriate location.  */
   if (retval && retval != result)
 {
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference13.C 
b/gcc/testsuite/g++.dg/warn/Wdangling-reference13.C
new file mode 100644
index 000..bc09fbae22b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference13.C
@@ -0,0 +1,23 @@
+// PR c++/109774
+// { dg-do compile }
+// { dg-options "-Wdangling-reference" }
+
+int y;
+
+template
+int& get(const char& )
+{
+return y;
+}
+
+int& get2(const char&)
+{
+return y;
+}
+
+int stuff(void)
+{
+const int  = get(0); // { dg-bogus "dangling reference" }
+const int  = get2(0); // { dg-bogus "dangling reference" }
+return h+k;
+}

base-commit: 94a311abf783de754f0f1b2d4c1f00a9788e795b
-- 
2.40.1



[PATCH] configure: Implement --enable-host-bind-now

2023-05-16 Thread Marek Polacek via Gcc-patches
As promised in the --enable-host-pie patch, this patch adds another
configure option, --enable-host-bind-now, which adds -z now when linking
the compiler executables in order to extend hardening.  BIND_NOW with RELRO
allows the GOT to be marked RO; this prevents GOT modification attacks.

This option does not affect linking of target libraries; you can use
LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now to enable RELRO/BIND_NOW.

With this patch:
$ readelf -Wd cc1{,plus} | grep FLAGS
 0x001e (FLAGS)  BIND_NOW
 0x6ffb (FLAGS_1)Flags: NOW PIE
 0x001e (FLAGS)  BIND_NOW
 0x6ffb (FLAGS_1)Flags: NOW PIE

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

c++tools/ChangeLog:

* configure.ac (--enable-host-bind-now): New check.
* configure: Regenerate.

gcc/ChangeLog:

* configure.ac (--enable-host-bind-now): New check.  Add
-Wl,-z,now to LD_PICFLAG if --enable-host-bind-now.
* configure: Regenerate.
* doc/install.texi: Document --enable-host-bind-now.

lto-plugin/ChangeLog:

* configure.ac (--enable-host-bind-now): New check.  Link with
-z,now.
* configure: Regenerate.

diff --git a/c++tools/configure b/c++tools/configure
index 88087009383..006efe07b35 100755
--- a/c++tools/configure
+++ b/c++tools/configure
@@ -628,6 +628,7 @@ EGREP
 GREP
 CXXCPP
 LD_PICFLAG
+enable_host_bind_now
 PICFLAG
 MAINTAINER
 CXX_AUX_TOOLS
@@ -702,6 +703,7 @@ enable_maintainer_mode
 enable_checking
 enable_default_pie
 enable_host_pie
+enable_host_bind_now
 with_gcc_major_version_only
 '
   ac_precious_vars='build_alias
@@ -1336,6 +1338,7 @@ Optional Features:
   yes,no,all,none,release.
   --enable-default-pieenable Position Independent Executable as default
   --enable-host-pie   build host code as PIE
+  --enable-host-bind-now  link host code as BIND_NOW
 
 Optional Packages:
   --with-PACKAGE[=ARG]use PACKAGE [ARG=yes]
@@ -3007,6 +3010,14 @@ fi
 
 
 
+# Enable --enable-host-bind-now
+# Check whether --enable-host-bind-now was given.
+if test "${enable_host_bind_now+set}" = set; then :
+  enableval=$enable_host_bind_now; LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"
+fi
+
+
+
 
 # Check if O_CLOEXEC is defined by fcntl
 
diff --git a/c++tools/configure.ac b/c++tools/configure.ac
index 44dfaccbbfa..c2a16601425 100644
--- a/c++tools/configure.ac
+++ b/c++tools/configure.ac
@@ -110,6 +110,13 @@ AC_ARG_ENABLE(host-pie,
[build host code as PIE])],
 [PICFLAG=-fPIE; LD_PICFLAG=-pie], [])
 AC_SUBST(PICFLAG)
+
+# Enable --enable-host-bind-now
+AC_ARG_ENABLE(host-bind-now,
+[AS_HELP_STRING([--enable-host-bind-now],
+   [link host code as BIND_NOW])],
+[LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"], [])
+AC_SUBST(enable_host_bind_now)
 AC_SUBST(LD_PICFLAG)
 
 # Check if O_CLOEXEC is defined by fcntl
diff --git a/gcc/configure b/gcc/configure
index 629446ecf3b..6d847c60024 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -635,6 +635,7 @@ CET_HOST_FLAGS
 LD_PICFLAG
 PICFLAG
 enable_default_pie
+enable_host_bind_now
 enable_host_pie
 enable_host_shared
 enable_plugin
@@ -1031,6 +1032,7 @@ enable_version_specific_runtime_libs
 enable_plugin
 enable_host_shared
 enable_host_pie
+enable_host_bind_now
 enable_libquadmath_support
 with_linker_hash_style
 with_diagnostics_color
@@ -1794,6 +1796,7 @@ Optional Features:
   --enable-plugin enable plugin support
   --enable-host-sharedbuild host code as shared libraries
   --enable-host-pie   build host code as PIE
+  --enable-host-bind-now  link host code as BIND_NOW
   --disable-libquadmath-support
   disable libquadmath support for Fortran
   --enable-default-pieenable Position Independent Executable as default
@@ -19852,7 +19855,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19867 "configure"
+#line 19870 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19958,7 +19961,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19973 "configure"
+#line 19976 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -32105,6 +32108,14 @@ fi
 
 
 
+# Enable --enable-host-bind-now
+# Check whether --enable-host-bind-now was given.
+if test "${enable_host_bind_now+set}" = set; then :
+  enableval=$enable_host_bind_now;
+fi
+
+
+
 # Check whether --enable-libquadmath-support was given.
 if test "${enable_libquadmath_support+set}" = set; then :
   enableval=$enable_libquadmath_support; ENABLE_LIBQUADMATH_SUPPORT=$enableval
@@ -32291,6 +32302,8 @@ else
   PICFLAG=
 fi
 
+
+
 if test x$enable_host_pie = xyes; then
   LD_PICFLAG=-pie
 elif test x$gcc_cv_no_pie = xyes; then
@@ -32299,6 +32312,9 @@ else
   LD_PICFLAG=
 fi
 
+if test x$enable_host_bind_now = xyes; then
+  

Re: [PATCH] configure: Implement --enable-host-pie

2023-05-16 Thread Marek Polacek via Gcc-patches
Ping.

On Tue, May 09, 2023 at 03:41:58PM -0400, Marek Polacek via Gcc-patches wrote:
> [ This is my third attempt to add this configure option.  The first
> version was approved but it came too late in the development cycle.
> The second version was also approved, but I had to revert it:
> <https://gcc.gnu.org/pipermail/gcc-patches/2022-November/607082.html>.
> I've fixed the problem (by moving $(PICFLAG) from INTERNAL_CFLAGS to
> ALL_COMPILERFLAGS).  Another change is that since r13-4536 I no longer
> need to touch Makefile.def, so this patch is simplified. ]
> 
> This patch implements the --enable-host-pie configure option which
> makes the compiler executables PIE.  This can be used to enhance
> protection against ROP attacks, and can be viewed as part of a wider
> trend to harden binaries.
> 
> It is similar to the option --enable-host-shared, except that --e-h-s
> won't add -shared to the linker flags whereas --e-h-p will add -pie.
> It is different from --enable-default-pie because that option just
> adds an implicit -fPIE/-pie when the compiler is invoked, but the
> compiler itself isn't PIE.
> 
> Since r12-5768-gfe7c3ecf, PCH works well with PIE, so there are no PCH
> regressions.
> 
> When building the compiler, the build process may use various in-tree
> libraries; these need to be built with -fPIE so that it's possible to
> use them when building a PIE.  For instance, when --with-included-gettext
> is in effect, intl object files must be compiled with -fPIE.  Similarly,
> when building in-tree gmp, isl, mpfr and mpc, they must be compiled with
> -fPIE.
> 
> With this patch and --enable-host-pie used to configure gcc:
> 
> $ file gcc/cc1{,plus,obj} gcc/f951 gcc/lto1 gcc/cpp
> gcc/cc1: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
> 3.2.0, with debug_info, not stripped
> gcc/cc1plus: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
> 3.2.0, with debug_info, not stripped
> gcc/f951:ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
> 3.2.0, with debug_info, not stripped
> gcc/cc1obj:  ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
> 3.2.0, with debug_info, not stripped
> gcc/lto1:ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
> 3.2.0, with debug_info, not stripped
> gcc/cpp: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
> 3.2.0, with debug_info, not stripped
> 
> I plan to add an option to link with -Wl,-z,now.
> 
> Bootstrapped on x86_64-pc-linux-gnu with --with-included-gettext
> --enable-host-pie as well as without --enable-host-pie.  Also tested
> on a Debian system where the system gcc was configured with
> --enable-default-pie.
> 
> ChangeLog:
> 
>   * configure.ac (--enable-host-pie): New check.  Set PICFLAG after this
>   check.
>   * configure: Regenerate.
> 
> c++tools/ChangeLog:
> 
>   * Makefile.in: Rename PIEFLAG to PICFLAG.  Set LD_PICFLAG.  Use it.
>   Use pic/libiberty.a if PICFLAG is set.
>   * configure.ac (--enable-default-pie): Set PICFLAG instead of PIEFLAG.
>   (--enable-host-pie): New check.
>   * configure: Regenerate.
> 
> fixincludes/ChangeLog:
> 
>   * Makefile.in: Set and use PICFLAG and LD_PICFLAG.  Use the "pic"
>   build of libiberty if PICFLAG is set.
>   * configure.ac:
>   * configure: Regenerate.
> 
> gcc/ChangeLog:
> 
>   * Makefile.in: Set LD_PICFLAG.  Use it.  Set enable_host_pie.
>   Remove NO_PIE_CFLAGS and NO_PIE_FLAG.  Pass LD_PICFLAG to
>   ALL_LINKERFLAGS.  Use the "pic" build of libiberty if --enable-host-pie.
>   * configure.ac (--enable-host-shared): Don't set PICFLAG here.
>   (--enable-host-pie): New check.  Set PICFLAG and LD_PICFLAG after this
>   check.
>   * configure: Regenerate.
>   * doc/install.texi: Document --enable-host-pie.
> 
> gcc/d/ChangeLog:
> 
>   * Make-lang.in: Remove NO_PIE_CFLAGS.
> 
> intl/ChangeLog:
> 
>   * Makefile.in: Use @PICFLAG@ in COMPILE as well.
>   * configure.ac (--enable-host-shared): Don't set PICFLAG here.
>   (--enable-host-pie): New check.  Set PICFLAG after this check.
>   * configure: Regenerate.
> 
> libcody/ChangeLog

[PATCH v2] c++: wrong std::is_convertible with cv-qual fn [PR109680]

2023-05-10 Thread Marek Polacek via Gcc-patches
On Wed, May 03, 2023 at 03:37:03PM -0400, Jason Merrill wrote:
> On 5/2/23 19:10, Marek Polacek wrote:
> > This PR points out that std::is_convertible has given the wrong answer
> > in
> > 
> >static_assert (!std::is_convertible_v , "");
> > 
> > since r13-2822 implemented __is_{,nothrow_}convertible.
> > 
> > std::is_convertible uses the imaginary
> > 
> >To test() { return std::declval(); }
> > 
> > to do its job.  Here, From is 'int () const'.  std::declval is defined as:
> > 
> >template
> >typename std::add_rvalue_reference::type declval() noexcept;
> > 
> > std::add_rvalue_reference is defined as "If T is a function type that
> > has no cv- or ref- qualifier or an object type, provides a member typedef
> > type which is T&&, otherwise type is T."
> > 
> > In our case, T is cv-qualified, so the result is T, so we end up with
> > 
> >int () const declval() noexcept;
> > 
> > which is invalid.  In other words, this is pretty much like:
> > 
> >using T = int () const;
> >T fn1(); // bad, fn returning a fn
> >T& fn2(); // bad, cannot declare reference to qualified function type
> >T* fn3(); // bad, cannot declare pointer to qualified function type
> > 
> >using U = int ();
> >U fn4(); // bad, fn returning a fn
> >U& fn5(); // OK
> >U* fn6(); // OK
> > 
> > I think is_convertible_helper needs to simulate std::declval better.
> > I wouldn't be surprised if other type traits needed a similar fix.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13?
> > 
> > I've tested the new test with G++12 and clang++ as well (with
> > std::is_convertible).
> > 
> > PR c++/109680
> > 
> > gcc/cp/ChangeLog:
> > 
> > * method.cc (is_convertible_helper): Correct simulating std::declval.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/ext/is_convertible6.C: New test.
> > ---
> >   gcc/cp/method.cc   | 20 
> >   gcc/testsuite/g++.dg/ext/is_convertible6.C | 16 
> >   2 files changed, 36 insertions(+)
> >   create mode 100644 gcc/testsuite/g++.dg/ext/is_convertible6.C
> > 
> > diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
> > index 00eae56eb5b..38eb7520312 100644
> > --- a/gcc/cp/method.cc
> > +++ b/gcc/cp/method.cc
> > @@ -2245,6 +2245,26 @@ is_convertible_helper (tree from, tree to)
> >   {
> > if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
> >   return integer_one_node;
> > +  /* std::is_{,nothrow_}convertible test whether the imaginary function
> > + definition
> > +
> > +   To test() { return std::declval(); }
> > +
> > + is well-formed.  A function can't return a function...  */
> > +  if (FUNC_OR_METHOD_TYPE_P (to)
> > +  /* ...neither can From be a function with cv-/ref-qualifiers:
> > +std::declval is defined as
> > +
> > + template
> > + typename std::add_rvalue_reference::type declval() noexcept;
> > +
> > +   and std::add_rvalue_reference yields T when T is a function with
> > +   cv- or ref-qualifiers, making the definition ill-formed.
> > +   ??? Should we check this in other uses of build_stub_object too?  */
> 
> Probably we want a build_trait_object that wraps build_stub_object with
> these extra checks, or does something that exercises more of the normal
> code, maybe by tsubsting into T (U&&) with { to, from }?

I did the former.  We only have the To type when processing
__is_convertible, so I think that can't be part of the declval
function, which takes another type, From.  IOW, if we want to factor
declval out, build_trait_object will take only one type.  Eh, that
still sounds confusing.  But the patch is simple.

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

-- >8 --
This PR points out that std::is_convertible has given the wrong answer
in

  static_assert (!std::is_convertible_v , "");

since r13-2822 implemented __is_{,nothrow_}convertible.

std::is_convertible uses the imaginary

  To test() { return std::declval(); }

to do its job.  Here, From is 'int () const'.  std::declval is defined as:

  template
  typename std::add_rvalue_reference::type declval() noexcept;

std::add_rvalue_reference is defined as "If T is a function type that
has no cv- or ref- qualifier or an object type, provides a member typedef
type which is T&&, otherwise type is T."

In our case, T is cv-qualified, so the result is T, so we end up with

  int () const declval() noexcept;

which is invalid.  In other words, this is pretty much like:

  using T = int () const;
  T fn1(); // bad, fn returning a fn
  T& fn2(); // bad, cannot declare reference to qualified function type
  T* fn3(); // bad, cannot declare pointer to qualified function type

  using U = int ();
  U fn4(); // bad, fn returning a fn
  U& fn5(); // OK
  U* fn6(); // OK

I think is_convertible_helper needs to simulate std::declval better.
To that end, I'm introducing build_trait_object, to be used where
a declval is needed.

PR c++/109680

gcc/cp/ChangeLog:

   

[PATCH] configure: Implement --enable-host-pie

2023-05-09 Thread Marek Polacek via Gcc-patches
[ This is my third attempt to add this configure option.  The first
version was approved but it came too late in the development cycle.
The second version was also approved, but I had to revert it:
.
I've fixed the problem (by moving $(PICFLAG) from INTERNAL_CFLAGS to
ALL_COMPILERFLAGS).  Another change is that since r13-4536 I no longer
need to touch Makefile.def, so this patch is simplified. ]

This patch implements the --enable-host-pie configure option which
makes the compiler executables PIE.  This can be used to enhance
protection against ROP attacks, and can be viewed as part of a wider
trend to harden binaries.

It is similar to the option --enable-host-shared, except that --e-h-s
won't add -shared to the linker flags whereas --e-h-p will add -pie.
It is different from --enable-default-pie because that option just
adds an implicit -fPIE/-pie when the compiler is invoked, but the
compiler itself isn't PIE.

Since r12-5768-gfe7c3ecf, PCH works well with PIE, so there are no PCH
regressions.

When building the compiler, the build process may use various in-tree
libraries; these need to be built with -fPIE so that it's possible to
use them when building a PIE.  For instance, when --with-included-gettext
is in effect, intl object files must be compiled with -fPIE.  Similarly,
when building in-tree gmp, isl, mpfr and mpc, they must be compiled with
-fPIE.

With this patch and --enable-host-pie used to configure gcc:

$ file gcc/cc1{,plus,obj} gcc/f951 gcc/lto1 gcc/cpp
gcc/cc1: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, with debug_info, not stripped
gcc/cc1plus: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, with debug_info, not stripped
gcc/f951:ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, with debug_info, not stripped
gcc/cc1obj:  ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, with debug_info, not stripped
gcc/lto1:ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, with debug_info, not stripped
gcc/cpp: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, with debug_info, not stripped

I plan to add an option to link with -Wl,-z,now.

Bootstrapped on x86_64-pc-linux-gnu with --with-included-gettext
--enable-host-pie as well as without --enable-host-pie.  Also tested
on a Debian system where the system gcc was configured with
--enable-default-pie.

ChangeLog:

* configure.ac (--enable-host-pie): New check.  Set PICFLAG after this
check.
* configure: Regenerate.

c++tools/ChangeLog:

* Makefile.in: Rename PIEFLAG to PICFLAG.  Set LD_PICFLAG.  Use it.
Use pic/libiberty.a if PICFLAG is set.
* configure.ac (--enable-default-pie): Set PICFLAG instead of PIEFLAG.
(--enable-host-pie): New check.
* configure: Regenerate.

fixincludes/ChangeLog:

* Makefile.in: Set and use PICFLAG and LD_PICFLAG.  Use the "pic"
build of libiberty if PICFLAG is set.
* configure.ac:
* configure: Regenerate.

gcc/ChangeLog:

* Makefile.in: Set LD_PICFLAG.  Use it.  Set enable_host_pie.
Remove NO_PIE_CFLAGS and NO_PIE_FLAG.  Pass LD_PICFLAG to
ALL_LINKERFLAGS.  Use the "pic" build of libiberty if --enable-host-pie.
* configure.ac (--enable-host-shared): Don't set PICFLAG here.
(--enable-host-pie): New check.  Set PICFLAG and LD_PICFLAG after this
check.
* configure: Regenerate.
* doc/install.texi: Document --enable-host-pie.

gcc/d/ChangeLog:

* Make-lang.in: Remove NO_PIE_CFLAGS.

intl/ChangeLog:

* Makefile.in: Use @PICFLAG@ in COMPILE as well.
* configure.ac (--enable-host-shared): Don't set PICFLAG here.
(--enable-host-pie): New check.  Set PICFLAG after this check.
* configure: Regenerate.

libcody/ChangeLog:

* Makefile.in: Pass LD_PICFLAG to LDFLAGS.
* configure.ac (--enable-host-shared): Don't set PICFLAG here.
(--enable-host-pie): New check.  Set PICFLAG and LD_PICFLAG after this
check.
* configure: Regenerate.

libcpp/ChangeLog:

* configure.ac (--enable-host-shared): Don't set PICFLAG here.
(--enable-host-pie): New check.  Set PICFLAG after this check.
* configure: Regenerate.

libdecnumber/ChangeLog:

* configure.ac (--enable-host-shared): Don't set PICFLAG here.
(--enable-host-pie): 

[PATCH] c++: wrong std::is_convertible with cv-qual fn [PR109680]

2023-05-02 Thread Marek Polacek via Gcc-patches
This PR points out that std::is_convertible has given the wrong answer
in

  static_assert (!std::is_convertible_v , "");

since r13-2822 implemented __is_{,nothrow_}convertible.

std::is_convertible uses the imaginary

  To test() { return std::declval(); }

to do its job.  Here, From is 'int () const'.  std::declval is defined as:

  template
  typename std::add_rvalue_reference::type declval() noexcept;

std::add_rvalue_reference is defined as "If T is a function type that
has no cv- or ref- qualifier or an object type, provides a member typedef
type which is T&&, otherwise type is T."

In our case, T is cv-qualified, so the result is T, so we end up with

  int () const declval() noexcept;

which is invalid.  In other words, this is pretty much like:

  using T = int () const;
  T fn1(); // bad, fn returning a fn
  T& fn2(); // bad, cannot declare reference to qualified function type
  T* fn3(); // bad, cannot declare pointer to qualified function type

  using U = int ();
  U fn4(); // bad, fn returning a fn
  U& fn5(); // OK
  U* fn6(); // OK

I think is_convertible_helper needs to simulate std::declval better.
I wouldn't be surprised if other type traits needed a similar fix.

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

I've tested the new test with G++12 and clang++ as well (with
std::is_convertible).

PR c++/109680

gcc/cp/ChangeLog:

* method.cc (is_convertible_helper): Correct simulating std::declval.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_convertible6.C: New test.
---
 gcc/cp/method.cc   | 20 
 gcc/testsuite/g++.dg/ext/is_convertible6.C | 16 
 2 files changed, 36 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_convertible6.C

diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 00eae56eb5b..38eb7520312 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2245,6 +2245,26 @@ is_convertible_helper (tree from, tree to)
 {
   if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
 return integer_one_node;
+  /* std::is_{,nothrow_}convertible test whether the imaginary function
+ definition
+
+   To test() { return std::declval(); }
+
+ is well-formed.  A function can't return a function...  */
+  if (FUNC_OR_METHOD_TYPE_P (to)
+  /* ...neither can From be a function with cv-/ref-qualifiers:
+std::declval is defined as
+
+ template
+ typename std::add_rvalue_reference::type declval() noexcept;
+
+   and std::add_rvalue_reference yields T when T is a function with
+   cv- or ref-qualifiers, making the definition ill-formed.
+   ??? Should we check this in other uses of build_stub_object too?  */
+  || (FUNC_OR_METHOD_TYPE_P (from)
+ && (type_memfn_quals (from) != TYPE_UNQUALIFIED
+ || type_memfn_rqual (from) != REF_QUAL_NONE)))
+return error_mark_node;
   cp_unevaluated u;
   tree expr = build_stub_object (from);
   deferring_access_check_sentinel acs (dk_no_deferred);
diff --git a/gcc/testsuite/g++.dg/ext/is_convertible6.C 
b/gcc/testsuite/g++.dg/ext/is_convertible6.C
new file mode 100644
index 000..180582663e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_convertible6.C
@@ -0,0 +1,16 @@
+// PR c++/109680
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_convertible(int () const, int (*)()));
+SA(!__is_convertible(int (*)(), int () const));
+
+SA( __is_convertible(int (), int (*)()));
+SA(!__is_convertible(int (*)(), int ()));
+
+SA( __is_convertible(int (int), int (*) (int)));
+SA(!__is_convertible(int (*) (int), int (int)));
+
+SA(!__is_convertible(int (int) const, int (*) (int)));
+SA(!__is_convertible(int (*) (int), int (int) const));

base-commit: 33020780a9699f1146eeed61783cec89fde337a0
-- 
2.40.1



[PATCH] c++: Move -Wdangling-reference to -Wextra [PR109642]

2023-05-01 Thread Marek Polacek via Gcc-patches
Sadly, -Wdangling-reference generates false positives for std::span-like
user classes, and it seems imprudent to attempt to improve the heuristic
in GCC 13.  Let's move the warning to -Wextra, that will hopefully
reduce the number of false positives the users have been seeing with 13.

I'm leaving the warning in -Wall in 14 where I think I can write code
to detect std::span-like classes.

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

PR c++/109642
PR c++/109640
PR c++/109671

gcc/c-family/ChangeLog:

* c.opt (Wdangling-reference): Move from -Wall to -Wextra.

gcc/ChangeLog:

* doc/invoke.texi: Document that -Wdangling-reference is
enabled by -Wextra.
---
 gcc/c-family/c.opt  | 2 +-
 gcc/doc/invoke.texi | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index cddeece..a75038930ae 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -560,7 +560,7 @@ C ObjC C++ ObjC++ Joined RejectNegative UInteger 
Var(warn_dangling_pointer) Warn
 Warn for uses of pointers to auto variables whose lifetime has ended.
 
 Wdangling-reference
-C++ ObjC++ Var(warn_dangling_reference) Warning LangEnabledBy(C++ ObjC++, Wall)
+C++ ObjC++ Var(warn_dangling_reference) Warning LangEnabledBy(C++ ObjC++, 
Wextra)
 Warn when a reference is bound to a temporary whose lifetime has ended.
 
 Wdate-time
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a38547f53e5..36ed1591440 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3781,7 +3781,7 @@ where @code{std::minmax} returns @code{std::pair}, and
 both references dangle after the end of the full expression that contains
 the call to @code{std::minmax}.
 
-This warning is enabled by @option{-Wall}.
+This warning is enabled by @option{-Wextra}.
 
 @opindex Wdelete-non-virtual-dtor
 @opindex Wno-delete-non-virtual-dtor
@@ -6126,6 +6126,7 @@ name is still supported, but the newer name is more 
descriptive.)
 
 @gccoptlist{-Wclobbered
 -Wcast-function-type
+-Wdangling-reference @r{(C++ only)}
 -Wdeprecated-copy @r{(C++ only)}
 -Wempty-body
 -Wenum-conversion @r{(C only)}
-- 
2.40.1



[pushed] ubsan: ubsan_maybe_instrument_array_ref tweak

2023-05-01 Thread Marek Polacek via Gcc-patches
In 
we discussed that the copy_node in ubsan_maybe_instrument_array_ref
is redundant, but also that it'd be best to postpone the optimization
to GCC 14.  So I'm making that change now.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/c-family/ChangeLog:

* c-ubsan.cc (ubsan_maybe_instrument_array_ref): Don't copy_node.
---
 gcc/c-family/c-ubsan.cc | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc
index c3ae515306c..cfb7cbf389c 100644
--- a/gcc/c-family/c-ubsan.cc
+++ b/gcc/c-family/c-ubsan.cc
@@ -505,12 +505,8 @@ ubsan_maybe_instrument_array_ref (tree *expr_p, bool 
ignore_off_by_one)
   tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, ,
ignore_off_by_one);
   if (e != NULL_TREE)
-   {
- tree t = copy_node (*expr_p);
- TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
-   e, op1);
- *expr_p = t;
-   }
+   TREE_OPERAND (*expr_p, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
+   e, op1);
 }
 }
 

base-commit: 07c52d1eec9671af92b7ce977b469f13a87887ad
-- 
2.40.1



Re: [PATCH] doc: Describe behaviour of enums with fixed underlying type

2023-04-27 Thread Marek Polacek via Gcc-patches
On Thu, Apr 27, 2023 at 12:16:34PM +0100, Jonathan Wakely via Gcc-patches wrote:
> C2x adds the ability to give an enumeration type a fixed underlying
> type, as C++ already has. The -fshort-enums option alters the compiler's
> choice of underlying type, but when it's fixed the compiler can't
> choose.
> 
> Similarly for C++ -fstrict-enums has no effect with a fixed underlying
> type, because every value of the underlying type is a valid value of the
> enumeration type.
> 
> This caused confusion recently: https://gcc.gnu.org/PR109532
> 
> OK for trunk?

LGTM.
 
> -- >8 --
> 
> gcc/ChangeLog:
> 
>   * doc/invoke.texi (Code Gen Options): Note that -fshort-enums
>   is ignored for a fixed underlying type.
>   (C++ Dialect Options): Likewise for -fstrict-enums.
> ---
>  gcc/doc/invoke.texi | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 2f40c58b21c..0f91464f8c0 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -3495,6 +3495,8 @@ defined in the C++ standard; basically, a value that 
> can be
>  represented in the minimum number of bits needed to represent all the
>  enumerators).  This assumption may not be valid if the program uses a
>  cast to convert an arbitrary integer value to the enumerated type.
> +This option has no effect for an enumeration type with a fixed underlying
> +type.
>  
>  @opindex fstrong-eval-order
>  @item -fstrong-eval-order
> @@ -18303,6 +18305,8 @@ Use it to conform to a non-default application binary 
> interface.
>  Allocate to an @code{enum} type only as many bytes as it needs for the
>  declared range of possible values.  Specifically, the @code{enum} type
>  is equivalent to the smallest integer type that has enough room.
> +This option has no effect for an enumeration type with a fixed underlying
> +type.
>  
>  @strong{Warning:} the @option{-fshort-enums} switch causes GCC to generate
>  code that is not binary compatible with code generated without that switch.
> -- 
> 2.40.0
> 

Marek



Re: [PATCH] c: Avoid -Wenum-int-mismatch warning for redeclaration of builtin acc_on_device [PR107041]

2023-04-20 Thread Marek Polacek via Gcc-patches
On Thu, Apr 20, 2023 at 07:24:29PM +0200, Jakub Jelinek wrote:
> On Thu, Apr 20, 2023 at 12:48:57PM -0400, Marek Polacek wrote:
> > > -  else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL)
> > > +  else if (enum_and_int_p
> > > +&& TREE_CODE (newdecl) != TYPE_DECL
> > > +/* Don't warn about about acc_on_device builtin redeclaration,
> > 
> > "built-in"
> > 
> > > +   the builtin is declared with int rather than enum because
> > 
> > "built-in"
> 
> Changing.
> > 
> > > +   the enum isn't intrinsic.  */
> > > +&& !(TREE_CODE (olddecl) == FUNCTION_DECL
> > > + && fndecl_built_in_p (olddecl, BUILT_IN_ACC_ON_DEVICE)
> > > + && !C_DECL_DECLARED_BUILTIN (olddecl)))
> > 
> > What do you think about adding an (UN)LIKELY here?  This seems a rather
> > very special case.  On the other hand we're not on a hot path here so it
> > hardly matters.
> 
> If anything, I'd add it either as UNLIKELY (enum_and_int_p) because that
> whole thing is unlikely,

Might could as well.

> or add UNLIKELY (flag_openacc) && before this
> acc_on_device stuff (but then users of -fopenacc might complain that it is
> likely for them).

Ok.

Marek



Re: [PATCH] c: Avoid -Wenum-int-mismatch warning for redeclaration of builtin acc_on_device [PR107041]

2023-04-20 Thread Marek Polacek via Gcc-patches
On Wed, Apr 19, 2023 at 11:02:53AM +0200, Jakub Jelinek wrote:
> Hi!
> 
> The new -Wenum-int-mismatch warning triggers with -Wsystem-headers in
> , for obvious reasons the builtin acc_on_device uses int
> type argument rather than enum which isn't defined yet when the builtin
> is created, while the OpenACC spec requires it to have acc_device_t
> enum argument.  The header makes sure it has int underlying type by using
> negative and __INT_MAX__ enumerators.
> 
> I've tried to make the builtin typegeneric or just varargs, but that
> changes behavior e.g. when one calls it with some C++ class which has
> cast operator to acc_device_t, so the following patch instead disables
> the warning for this builtin.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
> and 13.2?
> 
> 2023-04-19  Jakub Jelinek  
> 
>   PR c/107041
>   * c-decl.cc (diagnose_mismatched_decls): Avoid -Wenum-int-mismatch
>   warning on acc_on_device declaration.
> 
>   * gcc.dg/goacc/pr107041.c: New test.
> 
> --- gcc/c/c-decl.cc.jj2023-03-10 10:10:17.918387120 +0100
> +++ gcc/c/c-decl.cc   2023-04-18 10:29:33.340793562 +0200
> @@ -2219,7 +2219,14 @@ diagnose_mismatched_decls (tree newdecl,
>  }
>/* Warn about enum/integer type mismatches.  They are compatible types
>   (C2X 6.7.2.2/5), but may pose portability problems.  */
> -  else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL)
> +  else if (enum_and_int_p
> +&& TREE_CODE (newdecl) != TYPE_DECL
> +/* Don't warn about about acc_on_device builtin redeclaration,

"built-in"

> +   the builtin is declared with int rather than enum because

"built-in"

> +   the enum isn't intrinsic.  */
> +&& !(TREE_CODE (olddecl) == FUNCTION_DECL
> + && fndecl_built_in_p (olddecl, BUILT_IN_ACC_ON_DEVICE)
> + && !C_DECL_DECLARED_BUILTIN (olddecl)))

What do you think about adding an (UN)LIKELY here?  This seems a rather
very special case.  On the other hand we're not on a hot path here so it
hardly matters.

OK either way, thanks.

>  warned = warning_at (DECL_SOURCE_LOCATION (newdecl),
>OPT_Wenum_int_mismatch,
>"conflicting types for %q+D due to enum/integer "
> --- gcc/testsuite/gcc.dg/goacc/pr107041.c.jj  2023-04-18 10:18:07.039754258 
> +0200
> +++ gcc/testsuite/gcc.dg/goacc/pr107041.c 2023-04-18 10:17:21.252418797 
> +0200
> @@ -0,0 +1,23 @@
> +/* PR c/107041 */
> +/* { dg-do compile } */
> +/* { dg-additional-options "-Wenum-int-mismatch" } */
> +
> +typedef enum acc_device_t {
> +  acc_device_current = -1,
> +  acc_device_none = 0,
> +  acc_device_default = 1,
> +  acc_device_host = 2,
> +  acc_device_not_host = 4,
> +  acc_device_nvidia = 5,
> +  acc_device_radeon = 8,
> +  _ACC_highest = __INT_MAX__
> +} acc_device_t;
> +
> +int acc_on_device (acc_device_t);/* { dg-bogus "conflicting 
> types for 'acc_on_device' due to enum/integer mismatch; have 
> 'int\\\(acc_device_t\\\)'" } */
> +int acc_on_device (acc_device_t);
> +
> +int
> +foo (void)
> +{
> +  return acc_on_device (acc_device_host);
> +}
> 
>   Jakub
> 

Marek



Re: [PATCH] sanitizer: missing signed integer overflow errors [PR109107]

2023-03-27 Thread Marek Polacek via Gcc-patches
Ping.

On Tue, Mar 14, 2023 at 06:50:26PM -0400, Marek Polacek via Gcc-patches wrote:
> Here we're failing to detect a signed overflow with -O because match.pd,
> since r8-1516, transforms
> 
>   c = (a + 1) - (int) (short int) b;
> 
> into
> 
>   c = (int) ((unsigned int) a + 4294946117);
> 
> wrongly eliding the overflow.  This kind of problems is usually
> avoided by using TYPE_OVERFLOW_SANITIZED in the appropriate place.
> The first match.pd hunk in the patch fixes it.  I've constructed
> a testcase for each of the surrounding cases as well.  Then I
> noticed that fold_binary_loc/associate has the same problem, so I've
> added a TYPE_OVERFLOW_SANITIZED there as well (it may be too coarse,
> sorry).  Then I found yet another problem, but instead of fixing it
> now I've opened 109134.  I could probably go on and find a dozen more.
> 
> Is this worth doing?
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
>   PR sanitizer/109107
> 
> gcc/ChangeLog:
> 
>   * fold-const.cc (fold_binary_loc): Use TYPE_OVERFLOW_SANITIZED
>   when associating.
>   * match.pd: Use TYPE_OVERFLOW_SANITIZED.
> 
> gcc/testsuite/ChangeLog:
> 
>   * c-c++-common/ubsan/pr109107-2.c: New test.
>   * c-c++-common/ubsan/pr109107-3.c: New test.
>   * c-c++-common/ubsan/pr109107-4.c: New test.
>   * c-c++-common/ubsan/pr109107.c: New test.
> ---
>  gcc/fold-const.cc |  3 ++-
>  gcc/match.pd  |  6 ++---
>  gcc/testsuite/c-c++-common/ubsan/pr109107-2.c | 24 ++
>  gcc/testsuite/c-c++-common/ubsan/pr109107-3.c | 25 +++
>  gcc/testsuite/c-c++-common/ubsan/pr109107-4.c | 24 ++
>  gcc/testsuite/c-c++-common/ubsan/pr109107.c   | 23 +
>  6 files changed, 101 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107-2.c
>  create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107-3.c
>  create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107-4.c
>  create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107.c
> 
> diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> index 02a24c5fe65..8d3308a34e9 100644
> --- a/gcc/fold-const.cc
> +++ b/gcc/fold-const.cc
> @@ -11319,7 +11319,8 @@ fold_binary_loc (location_t loc, enum tree_code code, 
> tree type,
>And, we need to make sure type is not saturating.  */
>  
>if ((! FLOAT_TYPE_P (type) || flag_associative_math)
> -   && !TYPE_SATURATING (type))
> +   && !TYPE_SATURATING (type)
> +   && !TYPE_OVERFLOW_SANITIZED (type))
>   {
> tree var0, minus_var0, con0, minus_con0, lit0, minus_lit0;
> tree var1, minus_var1, con1, minus_con1, lit1, minus_lit1;
> diff --git a/gcc/match.pd b/gcc/match.pd
> index e352bd422f5..98bca9ea388 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -2933,7 +2933,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> /* If the constant operation overflows we cannot do the transform
> directly as we would introduce undefined overflow, for example
> with (a - 1) + INT_MIN.  */
> -   (if (types_match (type, @0))
> +   (if (types_match (type, @0) && !TYPE_OVERFLOW_SANITIZED (type))
>   (with { tree cst = const_binop (outer_op == inner_op
>   ? PLUS_EXPR : MINUS_EXPR,
>   type, @1, @2); }
> @@ -2964,7 +2964,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
> || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
>(view_convert (minus (outer_op @1 (view_convert @2)) @0))
> -  (if (types_match (type, @0))
> +  (if (types_match (type, @0) && !TYPE_OVERFLOW_SANITIZED (type))
> (with { tree cst = const_binop (outer_op, type, @1, @2); }
>   (if (cst && !TREE_OVERFLOW (cst))
>(minus { cst; } @0
> @@ -2983,7 +2983,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
>|| TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
>   (view_convert (plus @0 (minus (view_convert @1) @2)))
> - (if (types_match (type, @0))
> + (if (types_match (type, @0) && !TYPE_OVERFLOW_SANITIZED (type))
>(with { tree cst = const_binop (MINUS_EXPR, type, @1, @2); }
> (if (cst && !TREE_OVERFLOW (cst))
>   (plus { cst; } @0)))
> diff --git a/gcc/testsuite/c-c++-common/ubsan/pr109107-2.c 
> b/gcc/testsuite/c-c++-common/ubsan/pr109107-2.c
> new file mode 100644
> index 000..eb440b58dd8
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/ubsan/pr10910

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

2023-03-20 Thread Marek Polacek via Gcc-patches
On Sat, Mar 18, 2023 at 08:35:36AM -0400, Jason Merrill wrote:
> On 3/17/23 16:29, Marek Polacek wrote:
> > Based on ,
> > it seems like we should treat *any* class with a reference member
> > as a reference wrapper.  This simplifies the code so I'm happy to
> > make that change.
> > 
> > The patch, however, does not suppress the warning in
> > 
> >int i = 42;
> >auto const& v = std::get<0>(std::tuple(i));
> 
> Why not?  tuple has an int& member, doesn't it?  Do we need to look
> into bases as well?

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

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

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

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

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

PR c++/107532

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c52a09b9be2..429170e43ea 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13783,8 +13783,31 @@ std_pair_ref_ref_p (tree t)
 
 /* Return true if a class CTYPE is either std::reference_wrapper or
std::ref_view, or a reference wrapper class.  We consider a class
-   a reference wrapper class if it has a reference member and a
-   constructor taking the same reference type.  */
+   a reference wrapper class if it has a reference member.  We no
+   longer check that it has a constructor taking the same reference type
+   since that approach still generated too many false positives.  */
+
+static bool
+class_has_reference_member_p (tree t)
+{
+  for (tree fields = TYPE_FIELDS (t);
+   fields;
+   fields = DECL_CHAIN (fields))
+if (TREE_CODE (fields) == FIELD_DECL
+   && !DECL_ARTIFICIAL (fields)
+   && TYPE_REF_P (TREE_TYPE (fields)))
+  return true;
+  return false;
+}
+
+/* A wrapper for the above suitable as a callback for dfs_walk_once.  */
+
+static tree
+class_has_reference_member_p_r (tree binfo, void *)
+{
+  return (class_has_reference_member_p (BINFO_TYPE (binfo))
+ ? integer_one_node : NULL_TREE);
+}
 
 static bool
 reference_like_class_p (tree ctype)
@@ -13800,31 +13823,19 @@ reference_like_class_p (tree ctype)
   if (decl_in_std_namespace_p (tdecl))
 {
   tree name = DECL_NAME (tdecl);
-  return (name
- && (id_equal (name, "reference_wrapper")
- || id_equal (name, "span")
- || id_equal (name, "ref_view")));
-}
-  for (tree fields = TYPE_FIELDS (ctype);
-   fields;
-   fields = DECL_CHAIN (fields))
-{
-  if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
-   continue;
-  tree type = TREE_TYPE (fields);
-  if (!TYPE_REF_P (type))
-   continue;
-  /* OK, the field is a reference member.  Do we have a constructor
-taking its type?  */
-  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype)))
-   {
- tree args = FUNCTION_FIRST_USER_PARMTYPE (fn);
- if (args
- && same_type_p (TREE_VALUE (args), type)
- && TREE_CHAIN (args) == void_list_node)
-   return true;
-   }
+  if (name
+ && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "span")
+ || id_equal (name, "ref_view")))
+   return true;
 }
+
+  /* Some classes, such as std::tuple, have the reference member in its
+ (non-direct) base class.  */
+  if (dfs_walk_once (TYPE_BINFO (ctype), class_has_reference_member_p_r,
+nullptr, nullptr))
+return true;
+
   return false;
 }
 
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C 
b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
new file mode 100644
index 000..667618e7196
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
@@ -0,0 +1,23 @@
+// PR c++/107532
+// { dg-do compile { 

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

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

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

PR c++/109159

gcc/cp/ChangeLog:

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

libstdc++-v3/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c01e7b82457..c52a09b9be2 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -3612,7 +3612,9 @@ add_template_candidate_real (struct z_candidate 
**candidates, tree tmpl,
   /* Now the explicit specifier might have been deduced; check if this
  declaration is explicit.  If it is and we're ignoring non-converting
  constructors, don't add this function to the set of candidates.  */
-  if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn))
+  if (((flags & (LOOKUP_ONLYCONVERTING|LOOKUP_LIST_INIT_CTOR))
+   == LOOKUP_ONLYCONVERTING)
+  && DECL_NONCONVERTING_P (fn))
 return NULL;
 
   if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit16.C 
b/gcc/testsuite/g++.dg/cpp0x/explicit16.C
new file mode 100644
index 000..bb5a823aee6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit16.C
@@ -0,0 +1,18 @@
+// PR c++/109159
+// { dg-do compile { target c++11 } }
+
+struct A {
+  A(float) {}
+  template
+  explicit A(U) {}
+};
+
+void f(A t)
+{
+  t = {1}; // { dg-error "explicit constructor" }
+  t = 1;
+  A a1{1};
+  A a2 = {1}; // { dg-error "explicit constructor" }
+  A a3 = 1;
+  A a4(1);
+}
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc 
b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
index e875f0cbcd2..d550e9c604b 100644
--- a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -37,7 +37,7 @@ struct ExplicitDefaultDefault
 
 std::pair f1() {return {1,2};}
 
-std::pair f2() {return {1,2};} // { dg-error "could not 
convert" }
+std::pair f2() {return {1,2};} // { dg-error "explicit 
constructor" }
 
 std::pair f3() {return std::pair{1,2};}
 
@@ -52,7 +52,7 @@ std::pair v0{1,2};
 
 std::pair v1{1,2};
 
-std::pair v2 = {1,2}; // { dg-error "could not convert" }
+std::pair v2 = {1,2}; // { dg-error "explicit constructor" 
}
 
 std::pair v3{std::pair{1,2}};
 
@@ -99,7 +99,7 @@ void test_arg_passing()
 {
   f6(v0); // { dg-error "could not convert" }
   f6(v1);
-  f6({1,2}); // { dg-error "could not convert" }
+  f6({1,2}); // { dg-error "explicit constructor" }
   f6(std::pair{});
   f6(std::pair{}); // { dg-error "could not convert" }
   f7(v0);
@@ -130,6 +130,6 @@ std::pair v14{nullptr, MoveOnly{}};
 std::pair v15{MoveOnly{}, nullptr};
 
 std::pair v16 =
-  {nullptr, MoveOnly{}}; // { dg-error "could not convert" }
+  {nullptr, MoveOnly{}}; // { dg-error "explicit constructor" }
 std::pair v17 =
-  {MoveOnly{}, nullptr}; // { dg-error "could not convert" }
+  {MoveOnly{}, nullptr}; // { dg-error "explicit constructor" }
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc 
b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
index 820ddef30b4..3352dd15f7d 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -45,11 +45,11 @@ std::tuple f1b() {return {1,2};}
 std::tuple f1c() {return {1,2,3};}
 
 std::tuple f2_a()
-{return {1};} // { dg-error "could not convert" }
+{return {1};} // { dg-error "explicit constructor" }
 std::tuple f2_b()
-{return {1,2};} // { dg-error "could not convert" }
+{return {1,2};} // { dg-error "explicit constructor" }
 std::tuple f2_c()
-{return {1,2,3};} // { dg-error "could not 

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

2023-03-17 Thread Marek Polacek via Gcc-patches
Based on ,
it seems like we should treat *any* class with a reference member
as a reference wrapper.  This simplifies the code so I'm happy to
make that change.

The patch, however, does not suppress the warning in

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

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

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

PR c++/107532

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c01e7b82457..00d56a157b6 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13781,8 +13781,9 @@ std_pair_ref_ref_p (tree t)
 
 /* Return true if a class CTYPE is either std::reference_wrapper or
std::ref_view, or a reference wrapper class.  We consider a class
-   a reference wrapper class if it has a reference member and a
-   constructor taking the same reference type.  */
+   a reference wrapper class if it has a reference member.  We no
+   longer check that it has a constructor taking the same reference type
+   since that approach still generated too many false positives.  */
 
 static bool
 reference_like_class_p (tree ctype)
@@ -13798,31 +13799,19 @@ reference_like_class_p (tree ctype)
   if (decl_in_std_namespace_p (tdecl))
 {
   tree name = DECL_NAME (tdecl);
-  return (name
- && (id_equal (name, "reference_wrapper")
- || id_equal (name, "span")
- || id_equal (name, "ref_view")));
+  if (name
+ && (id_equal (name, "reference_wrapper")
+ || id_equal (name, "span")
+ || id_equal (name, "ref_view")))
+   return true;
 }
   for (tree fields = TYPE_FIELDS (ctype);
fields;
fields = DECL_CHAIN (fields))
-{
-  if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
-   continue;
-  tree type = TREE_TYPE (fields);
-  if (!TYPE_REF_P (type))
-   continue;
-  /* OK, the field is a reference member.  Do we have a constructor
-taking its type?  */
-  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype)))
-   {
- tree args = FUNCTION_FIRST_USER_PARMTYPE (fn);
- if (args
- && same_type_p (TREE_VALUE (args), type)
- && TREE_CHAIN (args) == void_list_node)
-   return true;
-   }
-}
+if (TREE_CODE (fields) == FIELD_DECL
+   && !DECL_ARTIFICIAL (fields)
+   && TYPE_REF_P (TREE_TYPE (fields)))
+  return true;
   return false;
 }
 
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C 
b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
new file mode 100644
index 000..667618e7196
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C
@@ -0,0 +1,23 @@
+// PR c++/107532
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wdangling-reference" }
+
+struct R
+{
+int& r;
+int& get() { return r; }
+int&& rget() { return static_cast(r); }
+};
+
+int main()
+{
+int i = 42;
+int& l = R{i}.get(); // { dg-bogus "dangling reference" }
+int const& cl = R{i}.get(); // { dg-bogus "dangling reference" }
+int&& r = R{i}.rget(); // { dg-bogus "dangling reference" }
+int const&& cr = R{i}.rget(); // { dg-bogus "dangling reference" }
+(void) l;
+(void) r;
+(void) cr;
+(void) cl;
+}

base-commit: ae7190e345a8d80310835cb83b3b41ef2aeb0d37
-- 
2.39.2



Re: [PATCH] c, ubsan: Instrument even shortened divisions [PR109151]

2023-03-17 Thread Marek Polacek via Gcc-patches
On Fri, Mar 17, 2023 at 09:14:04AM +0100, Jakub Jelinek wrote:
> Hi!
> 
> On the following testcase, the C FE decides to shorten the division because
> it has a guarantee that INT_MIN / -1 division won't be encountered, the
> first operand is widened from narrower unsigned and/or the second operand is
> a constant other than all ones (in this case both are true).
> The problem is that the narrower type in this case is _Bool and
> ubsan_instrument_division only instruments it if op0's type is INTEGER_TYPE
> or REAL_TYPE.  Strangely this doesn't happen in C++ FE.

I was curious.  The difference is because C++ passes this

(gdb) pge op0
(int) (short int) (VIEW_CONVERT_EXPR(d) == 1 | VIEW_CONVERT_EXPR(d) > 
9)

to shorten_binary_op while C passes:

(gdb) pge op0
(int) (<<< Unknown tree: c_maybe_const_expr
  
  d >>> == 1 || <<< Unknown tree: c_maybe_const_expr
  
  d >>> > 9)

so when we remove the '(int)' cast, we have different types underneath,
either short or bool.

In C, the BIT_IOR_EXPR -> TRUTH_OR_EXPR change is because we call c_convert ->
convert_to_integer -> do_narrow.
In C++, we never called do_narrow so shorten_binary_op gets the original tree.

Anyway, thanks for the patch.

Marek



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

2023-03-15 Thread Marek Polacek via Gcc-patches
On Wed, Mar 15, 2023 at 12:48:27PM -0400, Jason Merrill wrote:
> On 3/15/23 10:37, Marek Polacek wrote:
> > On Fri, Mar 10, 2023 at 01:47:46PM -0500, Jason Merrill wrote:
> > > On 3/10/23 11:17, Marek Polacek wrote:
> > > > We crash here since r10-3661, the store_init_value hunk in particular.
> > > > Before, we called cp_fully_fold_init, so e.g.
> > > > 
> > > > {.str=VIEW_CONVERT_EXPR("")}
> > > > 
> > > > was folded into
> > > > 
> > > > {.str=""}
> > > > 
> > > > but now we don't fold and keep the VCE around, and it causes trouble in
> > > > cxx_eval_store_expression: in the !refs->is_empty () loop we descend on
> > > > .str's initializer but since it's wrapped in a VCE, we skip the 
> > > > STRING_CST
> > > > check and then crash on the CONSTRUCTOR_NO_CLEARING.
> > > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?
> > > > 
> > > > PR c++/107280
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (cxx_eval_store_expression): Strip location 
> > > > wrappers.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp1z/constexpr-lambda28.C: New test.
> > > > ---
> > > >gcc/cp/constexpr.cc |  3 ++-
> > > >gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C | 15 +++
> > > >2 files changed, 17 insertions(+), 1 deletion(-)
> > > >create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C
> > > > 
> > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > index 8683c00596a..abf6ee560c5 100644
> > > > --- a/gcc/cp/constexpr.cc
> > > > +++ b/gcc/cp/constexpr.cc
> > > > @@ -6033,7 +6033,8 @@ cxx_eval_store_expression (const constexpr_ctx 
> > > > *ctx, tree t,
> > > >   *valp = build_constructor (type, NULL);
> > > >   CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
> > > > }
> > > > -  else if (TREE_CODE (*valp) == STRING_CST)
> > > > +  else if (STRIP_ANY_LOCATION_WRAPPER (*valp),
> > > > +  TREE_CODE (*valp) == STRING_CST)
> > > 
> > > Seems like this is stripping the location wrapper when we try to modify 
> > > the
> > > string; I think we want to strip it earlier, when we first initialize the
> > > array member.
> > 
> > Hmm, I suppose we don't want to do the stripping too early.  I could
> > have put it in get_nsdmi, for instance, but maybe here is good as well?
> 
> I guess I was thinking more around the time when the value is imported into
> constant evaluation, i.e. this chunk of cxx_eval_constant_expression:
> 
> > if (tree init = DECL_INITIAL (r))
> >   {
> > init = cxx_eval_constant_expression (ctx, init, vc_prvalue,
> >  non_constant_p, 
> > overflow_p);
> > /* Don't share a CONSTRUCTOR that might be changed.  */
> > init = unshare_constructor (init);
> > /* Remember that a constant object's constructor has already
> > run.  */
> > if (CLASS_TYPE_P (TREE_TYPE (r))
> > && CP_TYPE_CONST_P (TREE_TYPE (r)))
> >   TREE_READONLY (init) = true;
> > ctx->global->put_value (r, init);
> >   }

Ah, that wouldn't fix the problem as far as I can tell -- here init is
the whole constructor: {.str=VIEW_CONVERT_EXPR("")} so we'd
not have a way to strip the inner init.
 
> Feel free to pursue that approach or go ahead and push your first patch,
> whichever you prefer.

The original patch it is, then.  Thanks.

Marek



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

2023-03-15 Thread Marek Polacek via Gcc-patches
On Fri, Mar 10, 2023 at 01:47:46PM -0500, Jason Merrill wrote:
> On 3/10/23 11:17, Marek Polacek wrote:
> > We crash here since r10-3661, the store_init_value hunk in particular.
> > Before, we called cp_fully_fold_init, so e.g.
> > 
> >{.str=VIEW_CONVERT_EXPR("")}
> > 
> > was folded into
> > 
> >{.str=""}
> > 
> > but now we don't fold and keep the VCE around, and it causes trouble in
> > cxx_eval_store_expression: in the !refs->is_empty () loop we descend on
> > .str's initializer but since it's wrapped in a VCE, we skip the STRING_CST
> > check and then crash on the CONSTRUCTOR_NO_CLEARING.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?
> > 
> > PR c++/107280
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (cxx_eval_store_expression): Strip location wrappers.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp1z/constexpr-lambda28.C: New test.
> > ---
> >   gcc/cp/constexpr.cc |  3 ++-
> >   gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C | 15 +++
> >   2 files changed, 17 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 8683c00596a..abf6ee560c5 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -6033,7 +6033,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, 
> > tree t,
> >   *valp = build_constructor (type, NULL);
> >   CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
> > }
> > -  else if (TREE_CODE (*valp) == STRING_CST)
> > +  else if (STRIP_ANY_LOCATION_WRAPPER (*valp),
> > +  TREE_CODE (*valp) == STRING_CST)
> 
> Seems like this is stripping the location wrapper when we try to modify the
> string; I think we want to strip it earlier, when we first initialize the
> array member.

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

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

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

  {.str=VIEW_CONVERT_EXPR("")}

was folded into

  {.str=""}

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

PR c++/107280

gcc/cp/ChangeLog:

* typeck2.cc (process_init_constructor_record): Strip location wrappers.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index c56b69164e2..d0984910ce4 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1889,6 +1889,7 @@ process_init_constructor_record (tree type, tree init, 
int nested, int flags,
  CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init) = 1;
  CONSTRUCTOR_PLACEHOLDER_BOUNDARY (next) = 0;
}
+  STRIP_ANY_LOCATION_WRAPPER (next);
   CONSTRUCTOR_APPEND_ELT (v, field, next);
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C 
b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C
new file mode 100644
index 000..aafbfddd8b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C
@@ -0,0 +1,15 @@
+// PR c++/107280
+// { dg-do compile { target c++17 } }
+
+struct string {
+  char str[8] = "";
+};
+template  constexpr void
+test ()
+{
+  string str{};
+  auto append = [&](const char *s) { *str.str = *s; };
+  append("");
+}
+
+static_assert ((test(), true), "");

base-commit: 40c1352c5a4530350012d6a922435cf491663daa
-- 
2.39.2



[PATCH] sanitizer: missing signed integer overflow errors [PR109107]

2023-03-14 Thread Marek Polacek via Gcc-patches
Here we're failing to detect a signed overflow with -O because match.pd,
since r8-1516, transforms

  c = (a + 1) - (int) (short int) b;

into

  c = (int) ((unsigned int) a + 4294946117);

wrongly eliding the overflow.  This kind of problems is usually
avoided by using TYPE_OVERFLOW_SANITIZED in the appropriate place.
The first match.pd hunk in the patch fixes it.  I've constructed
a testcase for each of the surrounding cases as well.  Then I
noticed that fold_binary_loc/associate has the same problem, so I've
added a TYPE_OVERFLOW_SANITIZED there as well (it may be too coarse,
sorry).  Then I found yet another problem, but instead of fixing it
now I've opened 109134.  I could probably go on and find a dozen more.

Is this worth doing?

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

PR sanitizer/109107

gcc/ChangeLog:

* fold-const.cc (fold_binary_loc): Use TYPE_OVERFLOW_SANITIZED
when associating.
* match.pd: Use TYPE_OVERFLOW_SANITIZED.

gcc/testsuite/ChangeLog:

* c-c++-common/ubsan/pr109107-2.c: New test.
* c-c++-common/ubsan/pr109107-3.c: New test.
* c-c++-common/ubsan/pr109107-4.c: New test.
* c-c++-common/ubsan/pr109107.c: New test.
---
 gcc/fold-const.cc |  3 ++-
 gcc/match.pd  |  6 ++---
 gcc/testsuite/c-c++-common/ubsan/pr109107-2.c | 24 ++
 gcc/testsuite/c-c++-common/ubsan/pr109107-3.c | 25 +++
 gcc/testsuite/c-c++-common/ubsan/pr109107-4.c | 24 ++
 gcc/testsuite/c-c++-common/ubsan/pr109107.c   | 23 +
 6 files changed, 101 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107-2.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107-3.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107-4.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/pr109107.c

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 02a24c5fe65..8d3308a34e9 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -11319,7 +11319,8 @@ fold_binary_loc (location_t loc, enum tree_code code, 
tree type,
 And, we need to make sure type is not saturating.  */
 
   if ((! FLOAT_TYPE_P (type) || flag_associative_math)
- && !TYPE_SATURATING (type))
+ && !TYPE_SATURATING (type)
+ && !TYPE_OVERFLOW_SANITIZED (type))
{
  tree var0, minus_var0, con0, minus_con0, lit0, minus_lit0;
  tree var1, minus_var1, con1, minus_con1, lit1, minus_lit1;
diff --git a/gcc/match.pd b/gcc/match.pd
index e352bd422f5..98bca9ea388 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2933,7 +2933,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* If the constant operation overflows we cannot do the transform
  directly as we would introduce undefined overflow, for example
  with (a - 1) + INT_MIN.  */
-   (if (types_match (type, @0))
+   (if (types_match (type, @0) && !TYPE_OVERFLOW_SANITIZED (type))
(with { tree cst = const_binop (outer_op == inner_op
? PLUS_EXPR : MINUS_EXPR,
type, @1, @2); }
@@ -2964,7 +2964,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
  || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
   (view_convert (minus (outer_op @1 (view_convert @2)) @0))
-  (if (types_match (type, @0))
+  (if (types_match (type, @0) && !TYPE_OVERFLOW_SANITIZED (type))
(with { tree cst = const_binop (outer_op, type, @1, @2); }
(if (cst && !TREE_OVERFLOW (cst))
 (minus { cst; } @0
@@ -2983,7 +2983,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
 || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
  (view_convert (plus @0 (minus (view_convert @1) @2)))
- (if (types_match (type, @0))
+ (if (types_match (type, @0) && !TYPE_OVERFLOW_SANITIZED (type))
   (with { tree cst = const_binop (MINUS_EXPR, type, @1, @2); }
(if (cst && !TREE_OVERFLOW (cst))
(plus { cst; } @0)))
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr109107-2.c 
b/gcc/testsuite/c-c++-common/ubsan/pr109107-2.c
new file mode 100644
index 000..eb440b58dd8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/pr109107-2.c
@@ -0,0 +1,24 @@
+/* PR sanitizer/109107 */
+/* { dg-do run { target int32 } } */
+/* { dg-options "-fsanitize=signed-integer-overflow" } */
+
+#define INT_MIN (-__INT_MAX__ - 1)
+int a = INT_MIN;
+const int b = 676540;
+
+__attribute__((noipa)) int
+foo ()
+{
+  int c = a - 1 + (int) (short) b;
+  return c;
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+/* { dg-output "signed integer overflow: -2147483648 - 1 cannot be represented 
in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: 2147483647 \\+ 21180 cannot 
be represented in type 'int'" } */

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

2023-03-10 Thread Marek Polacek via Gcc-patches
std::span is a view and therefore should be treated as a reference
wrapper class for the purposes of -Wdangling-reference.  I'm not sure
there's a pattern that we could check for.

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

PR c++/107532

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

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

base-commit: 20d790aa3ea5b0d240032cab997b8e0938cac62c
-- 
2.39.2



Re: [PATCH v2] ubsan: missed -fsanitize=bounds for compound ops [PR108060]

2023-03-10 Thread Marek Polacek via Gcc-patches
On Fri, Mar 10, 2023 at 07:07:36PM +0100, Jakub Jelinek wrote:
> On Thu, Mar 09, 2023 at 07:44:53PM -0500, Marek Polacek wrote:
> > On Thu, Mar 09, 2023 at 09:44:49AM +0100, Jakub Jelinek wrote:
> > > On Thu, Mar 09, 2023 at 08:12:47AM +, Richard Biener wrote:
> > > > I think this is a reasonable way to address the regression, so OK.
> > > 
> > > It is true that both C and C++ (including c++14_down and c++17 and later
> > > where the latter have different ordering rules) evaluate the lhs of
> > > MODIFY_EXPR after rhs, so conceptually this patch makes sense.
> > 
> > Thank you both for taking a look.
> > 
> > > But I wonder why we do in ubsan_maybe_instrument_array_ref:
> > >   if (e != NULL_TREE)
> > > {
> > >   tree t = copy_node (*expr_p);
> > >   TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
> > > e, op1);
> > >   *expr_p = t;
> > > }
> > > rather than modification of the ARRAY_REF's operand in place.  If we
> > > did that, we wouldn't really care about the order, shared tree would
> > > be instrumented once, with SAVE_EXPR in there making sure we don't
> > > compute that multiple times.  Is that because the 2 copies could
> > > have side-effects and we do want to evaluate those multiple times?
> > 
> > I'd assumed that that was the point of the copy_node.  But now that
> > I'm actually experimenting with it, I can't trigger any problems
> > without the copy_node.  So maybe we can use the following patch, which
> > also adds a new test, bounds-21.c, to check that side-effects are
> > evaluated correctly.  I didn't bother writing a description for this
> > patch yet because I sort of think we should apply both patches at the
> > same time.  
> 
> Perhaps it would be safer to apply for GCC 13 just your first patch
> and maybe the testsuite coverage from this one and defer this change
> for GCC 14?

That sounds good, I'll push the original patch with the new test now.
Thanks.
 
> > Regtested on x86_64-pc-linux-gnu.
> > 
> > -- >8 --
> > PR sanitizer/108060
> > PR sanitizer/109050
> > 
> > gcc/c-family/ChangeLog:
> > 
> > * c-ubsan.cc (ubsan_maybe_instrument_array_ref): Don't copy_node.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * c-c++-common/ubsan/bounds-17.c: New test.
> > * c-c++-common/ubsan/bounds-18.c: New test.
> > * c-c++-common/ubsan/bounds-19.c: New test.
> > * c-c++-common/ubsan/bounds-20.c: New test.
> > * c-c++-common/ubsan/bounds-21.c: New test.
> 
>   Jakub
> 

Marek



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

2023-03-10 Thread Marek Polacek via Gcc-patches
We crash here since r10-3661, the store_init_value hunk in particular.
Before, we called cp_fully_fold_init, so e.g.

  {.str=VIEW_CONVERT_EXPR("")}

was folded into

  {.str=""}

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

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

PR c++/107280

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8683c00596a..abf6ee560c5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6033,7 +6033,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
  *valp = build_constructor (type, NULL);
  CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
}
-  else if (TREE_CODE (*valp) == STRING_CST)
+  else if (STRIP_ANY_LOCATION_WRAPPER (*valp),
+  TREE_CODE (*valp) == STRING_CST)
{
  /* An array was initialized with a string constant, and now
 we're writing into one of its elements.  Explode the
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C 
b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C
new file mode 100644
index 000..aafbfddd8b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda28.C
@@ -0,0 +1,15 @@
+// PR c++/107280
+// { dg-do compile { target c++17 } }
+
+struct string {
+  char str[8] = "";
+};
+template  constexpr void
+test ()
+{
+  string str{};
+  auto append = [&](const char *s) { *str.str = *s; };
+  append("");
+}
+
+static_assert ((test(), true), "");

base-commit: 2b2340e236c0bba8aaca358ea25a5accd8249fbd
-- 
2.39.2



[PATCH v2] ubsan: missed -fsanitize=bounds for compound ops [PR108060]

2023-03-09 Thread Marek Polacek via Gcc-patches
On Thu, Mar 09, 2023 at 09:44:49AM +0100, Jakub Jelinek wrote:
> On Thu, Mar 09, 2023 at 08:12:47AM +, Richard Biener wrote:
> > I think this is a reasonable way to address the regression, so OK.
> 
> It is true that both C and C++ (including c++14_down and c++17 and later
> where the latter have different ordering rules) evaluate the lhs of
> MODIFY_EXPR after rhs, so conceptually this patch makes sense.

Thank you both for taking a look.

> But I wonder why we do in ubsan_maybe_instrument_array_ref:
>   if (e != NULL_TREE)
> {
>   tree t = copy_node (*expr_p);
>   TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
> e, op1);
>   *expr_p = t;
> }
> rather than modification of the ARRAY_REF's operand in place.  If we
> did that, we wouldn't really care about the order, shared tree would
> be instrumented once, with SAVE_EXPR in there making sure we don't
> compute that multiple times.  Is that because the 2 copies could
> have side-effects and we do want to evaluate those multiple times?

I'd assumed that that was the point of the copy_node.  But now that
I'm actually experimenting with it, I can't trigger any problems
without the copy_node.  So maybe we can use the following patch, which
also adds a new test, bounds-21.c, to check that side-effects are
evaluated correctly.  I didn't bother writing a description for this
patch yet because I sort of think we should apply both patches at the
same time.  


Regtested on x86_64-pc-linux-gnu.

-- >8 --
PR sanitizer/108060
PR sanitizer/109050

gcc/c-family/ChangeLog:

* c-ubsan.cc (ubsan_maybe_instrument_array_ref): Don't copy_node.

gcc/testsuite/ChangeLog:

* c-c++-common/ubsan/bounds-17.c: New test.
* c-c++-common/ubsan/bounds-18.c: New test.
* c-c++-common/ubsan/bounds-19.c: New test.
* c-c++-common/ubsan/bounds-20.c: New test.
* c-c++-common/ubsan/bounds-21.c: New test.
---
 gcc/c-family/c-ubsan.cc  |  8 ++--
 gcc/testsuite/c-c++-common/ubsan/bounds-17.c | 17 +
 gcc/testsuite/c-c++-common/ubsan/bounds-18.c | 17 +
 gcc/testsuite/c-c++-common/ubsan/bounds-19.c | 20 
 gcc/testsuite/c-c++-common/ubsan/bounds-20.c | 16 
 gcc/testsuite/c-c++-common/ubsan/bounds-21.c | 18 ++
 6 files changed, 90 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-17.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-18.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-19.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-20.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-21.c

diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc
index 3e24198d7bb..8ce6421b61a 100644
--- a/gcc/c-family/c-ubsan.cc
+++ b/gcc/c-family/c-ubsan.cc
@@ -505,12 +505,8 @@ ubsan_maybe_instrument_array_ref (tree *expr_p, bool 
ignore_off_by_one)
   tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, ,
ignore_off_by_one);
   if (e != NULL_TREE)
-   {
- tree t = copy_node (*expr_p);
- TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
-   e, op1);
- *expr_p = t;
-   }
+   TREE_OPERAND (*expr_p, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
+   e, op1);
 }
 }
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-17.c 
b/gcc/testsuite/c-c++-common/ubsan/bounds-17.c
new file mode 100644
index 000..b727e3235b8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-17.c
@@ -0,0 +1,17 @@
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int c;
+
+int
+main ()
+{
+  int b = -32768;
+  a[b] |= c;
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-18.c 
b/gcc/testsuite/c-c++-common/ubsan/bounds-18.c
new file mode 100644
index 000..556abc0e1c0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-18.c
@@ -0,0 +1,17 @@
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int c;
+
+int
+main ()
+{
+  int b = -32768;
+  a[b] = a[b] | c;
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-19.c 
b/gcc/testsuite/c-c++-common/ubsan/bounds-19.c
new file mode 100644
index 000..54217ae399f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-19.c
@@ -0,0 +1,20 @@
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options 

[PATCH] ubsan: missed -fsanitize=bounds for compound ops [PR108060]

2023-03-08 Thread Marek Polacek via Gcc-patches
In this PR we are dealing with a missing .UBSAN_BOUNDS, so the
out-of-bounds access in the test makes the program crash before
a UBSan diagnostic was emitted.  In C and C++, c_genericize gets

  a[b] = a[b] | c;

but in C, both a[b] are one identical shared tree (not in C++ because
cp_fold/ARRAY_REF created two same but not identical trees).  Since
ubsan_walk_array_refs_r keeps a pset, in C we produce

  a[.UBSAN_BOUNDS (0B, SAVE_EXPR , 8);, SAVE_EXPR ;] = a[b] | c;

because the LHS is walked before the RHS.

Since r7-1900, we gimplify the RHS before the LHS.  So the statement above
gets gimplified into

_1 = a[b];
c.0_2 = c;
b.1 = b;
.UBSAN_BOUNDS (0B, b.1, 8);

With this patch we produce:

  a[b] = a[.UBSAN_BOUNDS (0B, SAVE_EXPR , 8);, SAVE_EXPR ;] | c;

which gets gimplified into:

b.0 = b;
.UBSAN_BOUNDS (0B, b.0, 8);
_1 = a[b.0];

therefore we emit a runtime error before making the bad array access.

I think it's OK that only the RHS gets a .UBSAN_BOUNDS, as in few lines
above: the instrumented array access dominates the array access on the
LHS, and I've verified that

  b = 0;
  a[b] = (a[b], b = -32768, a[0] | c);

works as expected: the inner a[b] is OK but we do emit an error for the
a[b] on the LHS.

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

PR sanitizer/108060
PR sanitizer/109050

gcc/c-family/ChangeLog:

* c-gimplify.cc (ubsan_walk_array_refs_r): For a MODIFY_EXPR, instrument
the RHS before the LHS.

gcc/testsuite/ChangeLog:

* c-c++-common/ubsan/bounds-17.c: New test.
* c-c++-common/ubsan/bounds-18.c: New test.
* c-c++-common/ubsan/bounds-19.c: New test.
* c-c++-common/ubsan/bounds-20.c: New test.
---
 gcc/c-family/c-gimplify.cc   | 12 
 gcc/testsuite/c-c++-common/ubsan/bounds-17.c | 17 +
 gcc/testsuite/c-c++-common/ubsan/bounds-18.c | 17 +
 gcc/testsuite/c-c++-common/ubsan/bounds-19.c | 20 
 gcc/testsuite/c-c++-common/ubsan/bounds-20.c | 16 
 5 files changed, 82 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-17.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-18.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-19.c
 create mode 100644 gcc/testsuite/c-c++-common/ubsan/bounds-20.c

diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
index 74b276b2b26..ef5c7d919fc 100644
--- a/gcc/c-family/c-gimplify.cc
+++ b/gcc/c-family/c-gimplify.cc
@@ -106,6 +106,18 @@ ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, 
void *data)
 }
   else if (TREE_CODE (*tp) == ARRAY_REF)
 ubsan_maybe_instrument_array_ref (tp, false);
+  else if (TREE_CODE (*tp) == MODIFY_EXPR)
+{
+  /* Since r7-1900, we gimplify RHS before LHS.  Consider
+  a[b] |= c;
+wherein we can have a single shared tree a[b] in both LHS and RHS.
+If we only instrument the LHS and the access is invalid, the program
+could crash before emitting a UBSan error.  So instrument the RHS
+first.  */
+  *walk_subtrees = 0;
+  walk_tree (_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
+  walk_tree (_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
+}
   return NULL_TREE;
 }
 
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-17.c 
b/gcc/testsuite/c-c++-common/ubsan/bounds-17.c
new file mode 100644
index 000..b727e3235b8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-17.c
@@ -0,0 +1,17 @@
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int c;
+
+int
+main ()
+{
+  int b = -32768;
+  a[b] |= c;
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-18.c 
b/gcc/testsuite/c-c++-common/ubsan/bounds-18.c
new file mode 100644
index 000..556abc0e1c0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-18.c
@@ -0,0 +1,17 @@
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int c;
+
+int
+main ()
+{
+  int b = -32768;
+  a[b] = a[b] | c;
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-19.c 
b/gcc/testsuite/c-c++-common/ubsan/bounds-19.c
new file mode 100644
index 000..54217ae399f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-19.c
@@ -0,0 +1,20 @@
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int a2[18];
+int c;
+
+int
+main ()
+{
+  int b = 0;
+  a[0] = (a2[b], b = -32768, a[0] | c);
+  b = 0;

Re: [PATCH] [RFC] RAII auto_mpfr and autp_mpz

2023-03-07 Thread Marek Polacek via Gcc-patches
On Tue, Mar 07, 2023 at 09:54:08PM +, Jonathan Wakely via Gcc-patches wrote:
> On Tue, 7 Mar 2023 at 21:52, Alexander Monakov wrote:
> >
> >
> > On Tue, 7 Mar 2023, Jonathan Wakely wrote:
> >
> > > > Shouldn't this use the idiom suggested in ansidecl.h, i.e.
> > > >
> > > >   private:
> > > > DISABLE_COPY_AND_ASSIGN (auto_mpfr);
> > >
> > >
> > > Why? A macro like that (or a base class like boost::noncopyable) has
> > > some value in a code base that wants to work for both C++03 and C++11
> > > (or later). But in GCC we know we have C++11 now, so we can just
> > > delete members. I don't see what the macro adds.
> >
> > Evidently it's possible to forget to delete one of the members, as
> > showcased in this very thread.
> 
> But easily caught by review.
> 
> > The idiom is also slightly easier to read.
> 
> That's a matter of opinion, I prefer the idiomatic C++ code to a SHOUTY MACRO.

FWIW, I'd also prefer to see the explicit =deletes rather than having to
go look up what exactly the macro does.

Marek



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

2023-03-07 Thread Marek Polacek via Gcc-patches
On Tue, Mar 07, 2023 at 09:53:28AM -0500, Jason Merrill wrote:
> On 3/6/23 17:01, Marek Polacek wrote:
> > On Mon, Mar 06, 2023 at 11:12:56AM -0500, Jason Merrill wrote:
> > > On 3/3/23 12:51, Marek Polacek wrote:
> > > > Similarly to PR107938, this also started with r11-557, whereby 
> > > > cp_finish_decl
> > > > can call check_initializer even in a template for a constexpr 
> > > > initializer.
> > > > 
> > > > Here we are rejecting
> > > > 
> > > > extern const Q q;
> > > > 
> > > > template
> > > > constexpr auto p = q(0);
> > > > 
> > > > even though q has a constexpr operator().  It's deemed non-const by
> > > > decl_maybe_constant_var_p because even though 'q' is const it is not
> > > > of integral/enum type.  I think the fix is for p_c_e to treat q(0) as
> > > > potentially-constant, as below.
> > > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12?
> > > > 
> > > > PR c++/107939
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (is_constexpr_function_object): New.
> > > > (potential_constant_expression_1): Treat an object with 
> > > > constexpr
> > > > operator() as potentially-constant.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp1y/var-templ74.C: Remove dg-error.
> > > > * g++.dg/cpp1y/var-templ77.C: New test.
> > > > ---
> > > >gcc/cp/constexpr.cc  | 23 ++-
> > > >gcc/testsuite/g++.dg/cpp1y/var-templ74.C |  2 +-
> > > >gcc/testsuite/g++.dg/cpp1y/var-templ77.C | 14 ++
> > > >3 files changed, 37 insertions(+), 2 deletions(-)
> > > >create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ77.C
> > > > 
> > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > index acf9847a4d1..7d786f332b4 100644
> > > > --- a/gcc/cp/constexpr.cc
> > > > +++ b/gcc/cp/constexpr.cc
> > > > @@ -8929,6 +8929,24 @@ check_for_return_continue (tree *tp, int 
> > > > *walk_subtrees, void *data)
> > > >  return NULL_TREE;
> > > >}
> > > > +/* Return true iff TYPE is a class with constexpr operator().  */
> > > > +
> > > > +static bool
> > > > +is_constexpr_function_object (tree type)
> > > > +{
> > > > +  if (!CLASS_TYPE_P (type))
> > > > +return false;
> > > > +
> > > > +  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
> > > > +if (TREE_CODE (f) == FUNCTION_DECL
> > > > +   && DECL_OVERLOADED_OPERATOR_P (f)
> > > > +   && DECL_OVERLOADED_OPERATOR_IS (f, CALL_EXPR)
> > > > +   && DECL_DECLARED_CONSTEXPR_P (f))
> > > > +  return true;
> > > > +
> > > > +  return false;
> > > > +}
> > > > +
> > > >/* Return true if T denotes a potentially constant expression.  Issue
> > > >   diagnostic as appropriate under control of FLAGS.  If WANT_RVAL 
> > > > is true,
> > > >   an lvalue-rvalue conversion is implied.  If NOW is true, we want 
> > > > to
> > > > @@ -9160,7 +9178,10 @@ potential_constant_expression_1 (tree t, bool 
> > > > want_rval, bool strict, bool now,
> > > >   }
> > > > else if (fun)
> > > >  {
> > > > -   if (RECUR (fun, rval))
> > > > +   if (VAR_P (fun)
> > > > +   && is_constexpr_function_object (TREE_TYPE (fun)))
> > > > + /* Could be an object with constexpr operator().  */;
> > > 
> > > I guess if fun is not a function pointer, we don't know if we're using it 
> > > as
> > > an lvalue or rvalue
> > 
> > Presumably the operator function could return this, making it an lvalue?
> > I'm not sure I'm really clear on this.
> 
> I mean just calling the operator uses the variable as an lvalue, by passing
> its address as 'this'.

Ah yeah, right.  Unless there's the && ref-qual etc.
 
> > > , so we want to pass 'any' for want_rval, which should
> > > make this work;
> > 
> > Yes, want_rval==false means that p_c_e/VAR_DECL will not issue the
> > hard error.
> > 
> > > I don't think we need to be specific about constexpr op(),
> > > as a constexpr conversion operator to fn* could also do the trick.
> > 
> > Ah, those surrogate classes.  I couldn't reproduce the problem with
> > them, though I'm adding a test for it anyway.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
> OK, thanks.

Thanks.

Marek



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

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

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

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
 
   /* We used to shortcut trivial constructor/op= here, but nowadays
  we can only get a trivial function here with -fno-elide-constructors.  */
-  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);
 
   bool non_constant_args = false;
   new_call.bindings
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
new file mode 100644
index 000..16db8eb79ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
@@ -0,0 +1,9 @@
+// PR c++/109030
+// { dg-do compile { target c++11 } }
+
+struct foo { };
+
+struct __as_receiver {
+  foo empty_env;
+};
+void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }

base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902
-- 
2.39.2



  1   2   3   4   5   6   7   8   9   10   >