[PATCH v2] c++: Catch indirect change of active union member in constexpr [PR101631]

2023-09-17 Thread Nathaniel Shead via Gcc-patches
Ping for https://gcc.gnu.org/pipermail/gcc-patches/2023-September/629084.html

-- >8 --

This patch adds checks for attempting to change the active member of a
union by methods other than a member access expression.

To be able to properly distinguish `*(&u.a) = ` from `u.a = `, this
patch redoes the solution for c++/59950 to avoid extranneous *&; it
seems that the only case that needed the workaround was when copying
empty classes.

Additionally, this patch ensures that constructors for a union field
mark that field as the active member before entering the call itself;
this ensures that modifications of the field within the constructor's
body don't cause false positives (as these will not appear to be member
access expressions). This means that we no longer need to start the
lifetime of empty union members after the constructor body completes.

PR c++/101631

gcc/cp/ChangeLog:

* call.cc (build_over_call): Fold more indirect refs for trivial
assignment op.
* class.cc (type_has_non_deleted_trivial_default_ctor): Create.
* constexpr.cc (cxx_eval_call_expression): Start lifetime of
union member before entering constructor.
(cxx_eval_store_expression): Check for accessing inactive union
member indirectly.
* cp-tree.h (type_has_non_deleted_trivial_default_ctor):
Forward declare.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-union2.C: New test.
* g++.dg/cpp2a/constexpr-union3.C: New test.
* g++.dg/cpp2a/constexpr-union4.C: New test.
* g++.dg/cpp2a/constexpr-union5.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/call.cc|  11 +-
 gcc/cp/class.cc   |   8 ++
 gcc/cp/constexpr.cc   | 105 --
 gcc/cp/cp-tree.h  |   1 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union2.C |  30 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C |  45 
 gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C |  29 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C |  55 +
 8 files changed, 246 insertions(+), 38 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..3372c88f182 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10358,10 +10358,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
   && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR)
   && trivial_fn_p (fn))
 {
-  /* Don't use cp_build_fold_indirect_ref, op= returns an lvalue even if
-the object argument isn't one.  */
-  tree to = cp_build_indirect_ref (input_location, argarray[0],
-  RO_ARROW, complain);
+  tree to = cp_build_fold_indirect_ref (argarray[0]);
   tree type = TREE_TYPE (to);
   tree as_base = CLASSTYPE_AS_BASE (type);
   tree arg = argarray[1];
@@ -10369,7 +10366,11 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
 
   if (is_really_empty_class (type, /*ignore_vptr*/true))
{
- /* Avoid copying empty classes.  */
+ /* Avoid copying empty classes, but ensure op= returns an lvalue even
+if the object argument isn't one. This isn't needed in other cases
+since MODIFY_EXPR is always considered an lvalue.  */
+ to = cp_build_addr_expr (to, tf_none);
+ to = cp_build_indirect_ref (input_location, to, RO_ARROW, complain);
  val = build2 (COMPOUND_EXPR, type, arg, to);
  suppress_warning (val, OPT_Wunused);
}
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 778759237dc..43898dabbe7 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5651,6 +5651,14 @@ type_has_virtual_destructor (tree type)
   return (dtor && DECL_VIRTUAL_P (dtor));
 }
 
+/* True iff class TYPE has a non-deleted trivial default
+   constructor.  */
+
+bool type_has_non_deleted_trivial_default_ctor (tree type)
+{
+  return TYPE_HAS_TRIVIAL_DFLT (type) && locate_ctor (type);
+}
+
 /* Returns true iff T, a class, has a move-assignment or
move-constructor.  Does not lazily declare either.
If USER_P is false, any move function will do.  If it is true, the
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8bd5c4a47f8..b82e87be974 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3141,40 +3141,34 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
tree t,
cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/false,
  non_constant_p, overflow_p);
 
+ /* If this is a constructor, we are beginning the lifetime of the
+object 

Re: [PATCH v4 2/3] c++: Improve constexpr error for dangling local variables [PR110619]

2023-07-21 Thread Nathaniel Shead via Gcc-patches
On Fri, Jul 21, 2023 at 05:44:51PM -0400, Jason Merrill wrote:
> On 7/21/23 01:39, Nathaniel Shead wrote:
> > On Thu, Jul 20, 2023 at 11:46:47AM -0400, Jason Merrill wrote:
> > > On 7/20/23 05:36, Nathaniel Shead wrote:
> > > > Currently, when typeck discovers that a return statement will refer to a
> > > > local variable it rewrites to return a null pointer. This causes the
> > > > error messages for using the return value in a constant expression to be
> > > > unhelpful, especially for reference return values.
> > > > 
> > > > This patch removes this "optimisation".
> > > 
> > > This isn't an optimization, it's for safety, removing a way for an 
> > > attacker
> > > to get a handle on other data on the stack (CWE-562).
> > > 
> > > But I agree that we need to preserve some element of UB for constexpr
> > > evaluation to see.
> > > 
> > > Perhaps we want to move this transformation to cp_maybe_instrument_return,
> > > so it happens after maybe_save_constexpr_fundef?
> > 
> > Hm, OK. I can try giving this a go. I guess I should move the entire
> > maybe_warn_about_returning_address_of_local function to cp-gimplify.cc
> > to be able to detect this? Or is there a better way of marking that a
> > return expression will return a reference to a local for this
> > transformation? (I guess I can't use whether the warning has been
> > surpressed or not because the warning might not be enabled at all.)
> 
> You could use a TREE_LANG_FLAG, looks like none of them are used on
> RETURN_EXPR.
> 
> > It looks like this warning is raised also by diag_return_locals in
> > gimple-ssa-isolate-paths, should the transformation also be made here?
> 
> Looks like it already is, in warn_return_addr_local:
> 
> >   tree zero = build_zero_cst (TREE_TYPE (val));
> >   gimple_return_set_retval (return_stmt, zero);
> >   update_stmt (return_stmt);
> 
> ...but, weirdly, only with -fisolate-erroneous-paths-*, even though it isn't
> isolating anything.  Perhaps there should be another flag for this.
> 

I see, thanks. From this I've found that my above patch isn't sufficient
anyway, as compiling with -O2 causes the warning to appear twice as the
suppression I did wasn't sufficient. As such I'll exclude this patch
from the next revision since it's not actually necessary for the problem
I was trying to solve, and I'll work on trying to solve this properly
a bit later.

> > I note that the otherwise very similar -Wdangling-pointer warning
> > doesn't do this transformation either, should that also be something I
> > look into fixing here?
> 
> With that same flag, perhaps.  I wonder if it would make sense to remove the
> isolate-paths handling of locals in favor of the dangling-pointer handling?
> I don't know either file much at all.
> 
> Jason
> 


Re: [PATCH v4 3/3] c++: Improve location information in constant evaluation

2023-07-21 Thread Nathaniel Shead via Gcc-patches
On Fri, Jul 21, 2023 at 3:00 AM Jason Merrill  wrote:
>
> On 7/20/23 05:37, Nathaniel Shead wrote:
> > This patch updates 'input_location' during constant evaluation to ensure
> > that errors in subexpressions that lack location information still
> > provide accurate diagnostics.
> >
> > By itself this change causes some small regressions in diagnostic
> > quality for circumstances where errors used 'input_location' but the
> > location of the parent subexpression doesn't make sense, so this patch
> > also includes a couple of other small diagnostic improvements to improve
> > the most egregious cases.
> >
> > gcc/cp/ChangeLog:
> >
> >   * constexpr.cc (modifying_const_object_error): Find the source
> >   location of the const object's declaration.
> >   (cxx_eval_store_expression): Fall back to the location of the
> >   target object when evaluating initialiser.
>
> I'm skeptical about this workaround being an improvement in general.
> Reverting it, there only seems to be a difference for constexpr-89285.C,
> which seems fine; we see the location as the first line of the class, as
> usual for implicitly declared constructors.
>
> Showing the DMI location might be an improvement, but I think it would
> be better to make that change in perform_member_init so it applies to
> runtime as well.

Makes sense, I'll get rid of it.

> >   (cxx_eval_constant_expression): Update input_location to the location
> >   of the currently evaluated expression, if possible.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * testsuite/25_algorithms/equal/constexpr_neg.cc: Update diagnostic
> >   locations.
> >   * testsuite/26_numerics/gcd/105844.cc: Likewise.
> >   * testsuite/26_numerics/lcm/105844.cc: Likewise.
> >
> > gcc/testsuite/ChangeLog:
> >
> >   * g++.dg/cpp0x/constexpr-48089.C: Update diagnostic locations.
> >   * g++.dg/cpp0x/constexpr-70323.C: Likewise.
> >   * g++.dg/cpp0x/constexpr-70323a.C: Likewise.
> >   * g++.dg/cpp0x/constexpr-delete2.C: Likewise.
> >   * g++.dg/cpp0x/constexpr-diag3.C: Likewise.
> >   * g++.dg/cpp0x/constexpr-ice20.C: Likewise.
> >   * g++.dg/cpp0x/constexpr-recursion.C: Likewise.
> >   * g++.dg/cpp0x/overflow1.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-89285.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-89481.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-lifetime1.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-lifetime2.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-lifetime3.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-lifetime4.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-lifetime5.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const14.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const16.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const18.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const19.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const21.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const22.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const3.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const4.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-tracking-const7.C: Likewise.
> >   * g++.dg/cpp1y/constexpr-union5.C: Likewise.
> >   * g++.dg/cpp1y/pr68180.C: Likewise.
> >   * g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
> >   * g++.dg/cpp1z/constexpr-lambda8.C: Likewise.
> >   * g++.dg/cpp2a/bit-cast11.C: Likewise.
> >   * g++.dg/cpp2a/bit-cast12.C: Likewise.
> >   * g++.dg/cpp2a/bit-cast14.C: Likewise.
> >   * g++.dg/cpp2a/constexpr-98122.C: Likewise.
> >   * g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
> >   * g++.dg/cpp2a/constexpr-init1.C: Likewise.
> >   * g++.dg/cpp2a/constexpr-new12.C: Likewise.
> >   * g++.dg/cpp2a/constexpr-new3.C: Likewise.
> >   * g++.dg/cpp2a/constinit10.C: Likewise.
> >   * g++.dg/cpp2a/is-corresponding-member4.C: Likewise.
> >   * g++.dg/ext/constexpr-vla2.C: Likewise.
> >   * g++.dg/ext/constexpr-vla3.C: Likewise.
> >   * g++.dg/ubsan/pr63956.C: Likewise.
> >
> > Signed-off-by: Nathaniel Shead 
> > ---
> >   gcc/cp/constexpr.cc   | 46 ++-
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 ++--
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |  8 ++--
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |  8 ++--
> >   .../g++.dg/cpp0x/constexpr-delete2.C  |  5 +-
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  1 +
> >   .../g++.dg/cpp0x/constexpr-recursion.C|  6 +--
> >   gcc/testsuite/g++.dg/cpp0x/overflow1.C|  2 +-
> >   gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |  5 +-
> >   gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
> >   .../g++.dg/cpp1y/constexpr-lifetime1.C|  1 +
> >   .../g++.dg/cpp1y/constexpr-lifetime2.C|  4 +-
> >   .../g++.dg/cpp1y/conste

Re: [PATCH v4 1/3] c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]

2023-07-21 Thread Nathaniel Shead via Gcc-patches
On Thu, Jul 20, 2023 at 10:42:29AM -0400, Jason Merrill wrote:
> On 7/20/23 05:35, Nathaniel Shead wrote:
> > This adds rudimentary lifetime tracking in C++ constexpr contexts,
> > allowing the compiler to report errors with using values after their
> > backing has gone out of scope. We don't yet handle other ways of
> > accessing values outside their lifetime (e.g. following explicit
> > destructor calls).
> 
> Incidentally, much of that should be straightforward to handle by no longer
> ignoring clobbers here:
> 
> > case MODIFY_EXPR:
> >   if (cxx_dialect < cxx14)
> > goto fail;
> >   if (!RECUR (TREE_OPERAND (t, 0), any))
> > return false;
> >   /* Just ignore clobbers.  */
> >   if (TREE_CLOBBER_P (TREE_OPERAND (t, 1)))
> > return true;
> 
> Assignment from a clobber represents end of lifetime to the middle-end. This
> can be a follow-up patch.

Thanks, this is very helpful to know. I'll keep this in mind.

> > @@ -7051,10 +7065,17 @@ cxx_eval_constant_expression (const constexpr_ctx 
> > *ctx, tree t,
> > return ctx->ctor;
> > if (VAR_P (t))
> > if (tree v = ctx->global->get_value (t))
> > -   {
> > - r = v;
> > - break;
> > -   }
> > + {
> > +   r = v;
> > +   break;
> > + }
> > +  if (ctx->global->is_outside_lifetime (t))
> > +   {
> > + if (!ctx->quiet)
> > +   outside_lifetime_error (loc, t);
> > + *non_constant_p = true;
> > + break;
> > +   }
> 
> Shouldn't this new check also be under the if (VAR_P (t))?  A CONST_DECL
> can't go out of scope.
> 
> Jason
> 

Yup you're right; I didn't properly read the documentation on what a
CONST_DECL was and misunderstood. I'll fix this up for the next version.


[PATCH v5 0/3] c++: Track lifetimes in constant evaluation [PR70331, ...]

2023-07-22 Thread Nathaniel Shead via Gcc-patches
This is an update of the patch series at
https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625050.html

Changes since v4:

- Reordered patches to be more independent from each other (they don't need 
  to keep updating the new tests)
- Removed workaround for better locations in cxx_eval_store_expression
- Don't bother checking lifetime for CONST_DECLs
- Rewrite patch for dangling pointers to keep the transformation to
  `return (&x, nullptr)`, but only perform it when genericising. It turns out
  that implementing this wasn't as hard as I thought it might be, at least for
  this specific case.

Thanks very much for all the reviews and comments so far!

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

Nathaniel Shead (3):
  c++: Improve location information in constant evaluation
  c++: Prevent dangling pointers from becoming nullptr in constexpr
[PR110619]
  c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]

 gcc/cp/constexpr.cc   | 159 +-
 gcc/cp/cp-gimplify.cc |  23 ++-
 gcc/cp/cp-tree.h  |   8 +-
 gcc/cp/semantics.cc   |   4 +-
 gcc/cp/typeck.cc  |   9 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |   8 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |   8 +-
 .../g++.dg/cpp0x/constexpr-delete2.C  |   5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   1 +
 .../g++.dg/cpp0x/constexpr-recursion.C|   6 +-
 gcc/testsuite/g++.dg/cpp0x/overflow1.C|   2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |   5 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime6.C|  15 ++
 .../g++.dg/cpp1y/constexpr-tracking-const14.C |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const16.C |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const18.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const19.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const21.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const22.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const3.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const4.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const7.C  |   3 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda8.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/constinit10.C  |   5 +-
 .../g++.dg/cpp2a/is-corresponding-member4.C   |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |  23 +--
 .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
 .../testsuite/26_numerics/gcd/105844.cc   |  10 +-
 .../testsuite/26_numerics/lcm/105844.cc   |  14 +-
 51 files changed, 361 insertions(+), 168 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C

-- 
2.41.0



[PATCH v5 1/3] c++: Improve location information in constant evaluation

2023-07-22 Thread Nathaniel Shead via Gcc-patches
This patch updates 'input_location' during constant evaluation to ensure
that errors in subexpressions that lack location information still
provide accurate diagnostics.

By itself this change causes some small regressions in diagnostic
quality for circumstances where errors used 'input_location' but the
location of the parent subexpression doesn't make sense, so this patch
also includes a small diagnostic improvement to fix the most egregious
case.

gcc/cp/ChangeLog:

* constexpr.cc (modifying_const_object_error): Find the source
location of the const object's declaration.
(cxx_eval_constant_expression): Update input_location to the location
of the currently evaluated expression, if possible.

libstdc++-v3/ChangeLog:

* testsuite/25_algorithms/equal/constexpr_neg.cc: Update diagnostic
locations.
* testsuite/26_numerics/gcd/105844.cc: Likewise.
* testsuite/26_numerics/lcm/105844.cc: Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-48089.C: Update diagnostic locations.
* g++.dg/cpp0x/constexpr-70323.C: Likewise.
* g++.dg/cpp0x/constexpr-70323a.C: Likewise.
* g++.dg/cpp0x/constexpr-delete2.C: Likewise.
* g++.dg/cpp0x/constexpr-diag3.C: Likewise.
* g++.dg/cpp0x/constexpr-ice20.C: Likewise.
* g++.dg/cpp0x/constexpr-recursion.C: Likewise.
* g++.dg/cpp0x/overflow1.C: Likewise.
* g++.dg/cpp1y/constexpr-89285.C: Likewise.
* g++.dg/cpp1y/constexpr-89481.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const14.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const16.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const18.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const19.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const21.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const22.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const3.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const4.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const7.C: Likewise.
* g++.dg/cpp1y/constexpr-union5.C: Likewise.
* g++.dg/cpp1y/pr68180.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda8.C: Likewise.
* g++.dg/cpp2a/bit-cast11.C: Likewise.
* g++.dg/cpp2a/bit-cast12.C: Likewise.
* g++.dg/cpp2a/bit-cast14.C: Likewise.
* g++.dg/cpp2a/constexpr-98122.C: Likewise.
* g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
* g++.dg/cpp2a/constexpr-init1.C: Likewise.
* g++.dg/cpp2a/constexpr-new12.C: Likewise.
* g++.dg/cpp2a/constexpr-new3.C: Likewise.
* g++.dg/cpp2a/constinit10.C: Likewise.
* g++.dg/cpp2a/is-corresponding-member4.C: Likewise.
* g++.dg/ext/constexpr-vla2.C: Likewise.
* g++.dg/ext/constexpr-vla3.C: Likewise.
* g++.dg/ubsan/pr63956.C: Likewise.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 31 ++-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 +++---
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |  8 ++---
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |  8 ++---
 .../g++.dg/cpp0x/constexpr-delete2.C  |  5 +--
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  1 +
 .../g++.dg/cpp0x/constexpr-recursion.C|  6 ++--
 gcc/testsuite/g++.dg/cpp0x/overflow1.C|  2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |  5 +--
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const14.C |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const16.C |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const18.C |  4 +--
 .../g++.dg/cpp1y/constexpr-tracking-const19.C |  4 +--
 .../g++.dg/cpp1y/constexpr-tracking-const21.C |  4 +--
 .../g++.dg/cpp1y/constexpr-tracking-const22.C |  4 +--
 .../g++.dg/cpp1y/constexpr-tracking-const3.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const4.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const7.C  |  3 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |  4 +--
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |  4 +--
 .../g++.dg/cpp1z/constexpr-lambda6.C  |  4 +--
 .../g++.dg/cpp1z/constexpr-lambda8.C  |  5 ++-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   | 10 +++---
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   | 10 +++---
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   | 14 -
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |  4 +--
 .../g++.dg/cpp2a/constexpr-dynamic17.C|  5 ++-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |  5 ++-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |  6 ++--
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   | 10 +++---
 gcc/testsuite/g++.dg/cpp2a/constinit10.C  |  5 ++-
 .../g++.dg/cpp2a/is-corresponding-member4.C   |  4 +--
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |  4 +--
 gcc/testsu

[PATCH v5 2/3] c++: Prevent dangling pointers from becoming nullptr in constexpr [PR110619]

2023-07-22 Thread Nathaniel Shead via Gcc-patches
Currently, when typeck discovers that a return statement will refer to a
local variable it rewrites to return a null pointer. This causes the
error messages for using the return value in a constant expression to be
unhelpful, especially for reference return values, and is also a visible
change to otherwise valid code (as in the linked PR).

The transformation is nonetheless important, however, both as a safety
guard against attackers being able to gain a handle to other data on the
stack, and to prevent duplicate warnings from later null-dereference
warning passes.

As such, this patch just delays the transformation until cp_genericize,
after constexpr function definitions have been generated.

PR c++/110619

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_genericize_r): Transform RETURN_EXPRs to
not return dangling pointers.
* cp-tree.h (RETURN_EXPR_LOCAL_ADDR_P): New flag.
(check_return_expr): Add a new parameter.
* semantics.cc (finish_return_stmt): Set flag on RETURN_EXPR
when referring to dangling pointer.
* typeck.cc (check_return_expr): Disable transformation of
dangling pointers, instead pass this information to caller.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-110619.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/cp-gimplify.cc | 23 ---
 gcc/cp/cp-tree.h  |  8 ++-
 gcc/cp/semantics.cc   |  4 +++-
 gcc/cp/typeck.cc  |  9 
 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C | 10 
 5 files changed, 45 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index f5734197774..0a5d6300aca 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1336,9 +1336,26 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void 
*data)
   break;
 
 case RETURN_EXPR:
-  if (TREE_OPERAND (stmt, 0) && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
-   /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
-   *walk_subtrees = 0;
+  if (TREE_OPERAND (stmt, 0))
+   {
+ if (is_invisiref_parm (TREE_OPERAND (stmt, 0)))
+   /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. 
 */
+   *walk_subtrees = 0;
+ if (RETURN_EXPR_LOCAL_ADDR_P (stmt))
+   {
+ /* Don't return the address of a local variable.  */
+ tree *p = &TREE_OPERAND (stmt, 0);
+ while (TREE_CODE (*p) == COMPOUND_EXPR)
+   p = &TREE_OPERAND (*p, 0);
+ if (TREE_CODE (*p) == INIT_EXPR)
+   {
+ tree op = TREE_OPERAND (*p, 1);
+ tree new_op = build2 (COMPOUND_EXPR, TREE_TYPE (op), op,
+   build_zero_cst (TREE_TYPE (op)));
+ TREE_OPERAND (*p, 1) = new_op;
+   }
+   }
+   }
   break;
 
 case OMP_CLAUSE:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3de0e154c12..e0c181d9aef 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -447,6 +447,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
   INIT_EXPR_NRV_P (in INIT_EXPR)
   ATOMIC_CONSTR_MAP_INSTANTIATED_P (in ATOMIC_CONSTR)
   contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT)
+  RETURN_EXPR_LOCAL_ADDR_P (in RETURN_EXPR)
1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)
   TI_PENDING_TEMPLATE_FLAG.
   TEMPLATE_PARMS_FOR_INLINE.
@@ -4071,6 +4072,11 @@ struct GTY(()) lang_decl {
   (LANG_DECL_FN_CHECK (FUNCTION_DECL_CHECK (NODE)) \
->u.saved_auto_return_type)
 
+/* In a RETURN_EXPR, whether the expression refers to the address
+   of a local variable.  */
+#define RETURN_EXPR_LOCAL_ADDR_P(NODE) \
+  TREE_LANG_FLAG_0 (RETURN_EXPR_CHECK (NODE))
+
 /* True if NODE is an implicit INDIRECT_REF from convert_from_reference.  */
 #define REFERENCE_REF_P(NODE)  \
   (INDIRECT_REF_P (NODE)   \
@@ -8139,7 +8145,7 @@ extern tree composite_pointer_type(const 
op_location_t &,
 tsubst_flags_t);
 extern tree merge_types(tree, tree);
 extern tree strip_array_domain (tree);
-extern tree check_return_expr  (tree, bool *);
+extern tree check_return_expr  (tree, bool *, bool *);
 extern tree spaceship_type (tree, tsubst_flags_t = 
tf_warning_or_error);
 extern tree genericize_spaceship   (location_t, tree, tree, tree);
 extern tree cp_build_binary_op  (const op_location_t &,
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..720521b7f1a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -1240

[PATCH v5 3/3] c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]

2023-07-22 Thread Nathaniel Shead via Gcc-patches
This adds rudimentary lifetime tracking in C++ constexpr contexts,
allowing the compiler to report errors with using values after their
backing has gone out of scope. We don't yet handle other ways of
accessing values outside their lifetime (e.g. following explicit
destructor calls).

PR c++/96630
PR c++/98675
PR c++/70331

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx::is_outside_lifetime): New
function.
(constexpr_global_ctx::get_value): Don't return expired values.
(constexpr_global_ctx::get_value_ptr): Likewise.
(constexpr_global_ctx::remove_value): Mark value outside
lifetime.
(outside_lifetime_error): New function.
(cxx_eval_call_expression): No longer track save_exprs.
(cxx_eval_loop_expr): Likewise.
(cxx_eval_constant_expression): Add checks for outside lifetime
values. Remove local variables at end of bind exprs, and
temporaries after cleanup points.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime1.C: New test.
* g++.dg/cpp1y/constexpr-lifetime2.C: New test.
* g++.dg/cpp1y/constexpr-lifetime3.C: New test.
* g++.dg/cpp1y/constexpr-lifetime4.C: New test.
* g++.dg/cpp1y/constexpr-lifetime5.C: New test.
* g++.dg/cpp1y/constexpr-lifetime6.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 128 --
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime6.C|  15 ++
 7 files changed, 169 insertions(+), 42 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 2bf2458c3cd..0ab77dcaf62 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1148,7 +1148,8 @@ enum constexpr_switch_state {
 
 class constexpr_global_ctx {
   /* Values for any temporaries or local variables within the
- constant-expression. */
+ constant-expression. Objects outside their lifetime have
+ value 'void_node'.  */
   hash_map values;
 public:
   /* Number of cxx_eval_constant_expression calls (except skipped ones,
@@ -1170,17 +1171,28 @@ public:
 : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr),
   heap_dealloc_count (0) {}
 
+  bool is_outside_lifetime (tree t)
+  {
+if (tree *p = values.get (t))
+  if (*p == void_node)
+   return true;
+return false;
+  }
  tree get_value (tree t)
   {
 if (tree *p = values.get (t))
-  return *p;
+  if (*p != void_node)
+   return *p;
 return NULL_TREE;
   }
   tree *get_value_ptr (tree t)
   {
 if (modifiable && !modifiable->contains (t))
   return nullptr;
-return values.get (t);
+if (tree *p = values.get (t))
+  if (*p != void_node)
+   return p;
+return nullptr;
   }
   void put_value (tree t, tree v)
   {
@@ -1188,7 +1200,13 @@ public:
 if (!already_in_map && modifiable)
   modifiable->add (t);
   }
-  void remove_value (tree t) { values.remove (t); }
+  void remove_value (tree t)
+  {
+if (DECL_P (t))
+  values.put (t, void_node);
+else
+  values.remove (t);
+  }
 };
 
 /* Helper class for constexpr_global_ctx.  In some cases we want to avoid
@@ -3111,12 +3129,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  gcc_assert (!DECL_BY_REFERENCE (res));
  ctx->global->put_value (res, NULL_TREE);
 
- /* Track the callee's evaluated SAVE_EXPRs and TARGET_EXPRs so that
-we can forget their values after the call.  */
- constexpr_ctx ctx_with_save_exprs = *ctx;
- auto_vec save_exprs;
- ctx_with_save_exprs.save_exprs = &save_exprs;
- ctx_with_save_exprs.call = &new_call;
+ /* Remember the current call we're evaluating.  */
+ constexpr_ctx call_ctx = *ctx;
+ call_ctx.call = &new_call;
  unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
  unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
 
@@ -3127,7 +3142,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  non_constant_p, overflow_p);
 
  tree jump_target = NULL_TREE;
- cxx_eval_constant_expression (&ctx_with_save_exprs, body,
+ cxx_eval_constant_expressi

[PATCH] c++: Report invalid id-expression in decltype [PR100482]

2023-08-07 Thread Nathaniel Shead via Gcc-patches
Ping for https://gcc.gnu.org/pipermail/gcc-patches/2023-June/622681.html.

-- 8< --

This patch ensures that any errors raised by finish_id_expression when
parsing a decltype expression are properly reported, rather than
potentially going ignored and causing invalid code to be accepted.

We can also now remove the separate check for templates without args as
this is also checked for in finish_id_expression.

PR c++/100482

gcc/cp/ChangeLog:

* parser.cc (cp_parser_decltype_expr): Report errors raised by
finish_id_expression.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/decltype-100482.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/parser.cc | 22 ++--
 gcc/testsuite/g++.dg/cpp0x/decltype-100482.C | 12 +++
 2 files changed, 23 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-100482.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index dd3665c8ccf..990f2034f54 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -16508,10 +16508,6 @@ cp_parser_decltype_expr (cp_parser *parser,
expr = cp_parser_lookup_name_simple (parser, expr,
 id_expr_start_token->location);
 
-  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)
-   /* A template without args is not a complete id-expression.  */
-   expr = error_mark_node;
-
   if (expr
   && expr != error_mark_node
   && TREE_CODE (expr) != TYPE_DECL
@@ -16532,13 +16528,17 @@ cp_parser_decltype_expr (cp_parser *parser,
&error_msg,
   id_expr_start_token->location));
 
-  if (expr == error_mark_node)
-/* We found an id-expression, but it was something that we
-   should not have found. This is an error, not something
-   we can recover from, so note that we found an
-   id-expression and we'll recover as gracefully as
-   possible.  */
-id_expression_or_member_access_p = true;
+ if (error_msg)
+   {
+ /* We found an id-expression, but it was something that we
+should not have found. This is an error, not something
+we can recover from, so report the error we found and
+we'll recover as gracefully as possible.  */
+ cp_parser_parse_definitely (parser);
+ cp_parser_error (parser, error_msg);
+ id_expression_or_member_access_p = true;
+ return error_mark_node;
+   }
 }
 
   if (expr
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C 
b/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
new file mode 100644
index 000..3df9c8496d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
@@ -0,0 +1,12 @@
+// PR c++/100482
+// { dg-do compile { target c++11 } }
+
+namespace N {}
+decltype(std) x;   // { dg-error "expected primary-expression" }
+
+struct S {};
+decltype(S) y;  // { dg-error "argument to .decltype. must be an expression" }
+
+template 
+struct U {};
+decltype(U) z;  // { dg-error "missing template arguments" }
-- 
2.41.0



[PATCH] c++: Report invalid id-expression in decltype [PR100482]

2023-08-07 Thread Nathaniel Shead via Gcc-patches
Sorry, noticed I provided the wrong version of the test. Here is the
correct version (not relying on 'namespace std' being implicitly
defined). Bootstrapped + regtested on x86_64-pc-linux-gnu.

-- 8< --

This patch ensures that any errors raised by finish_id_expression when
parsing a decltype expression are properly reported, rather than
potentially going ignored and causing invalid code to be accepted.

We can also now remove the separate check for templates without args as
this is also checked for in finish_id_expression.

PR c++/100482

gcc/cp/ChangeLog:

* parser.cc (cp_parser_decltype_expr): Report errors raised by
finish_id_expression.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/decltype-100482.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/parser.cc | 22 ++--
 gcc/testsuite/g++.dg/cpp0x/decltype-100482.C | 12 +++
 2 files changed, 23 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-100482.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d7ef5b34d42..119a14d03b9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -16506,10 +16506,6 @@ cp_parser_decltype_expr (cp_parser *parser,
expr = cp_parser_lookup_name_simple (parser, expr,
 id_expr_start_token->location);
 
-  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)
-   /* A template without args is not a complete id-expression.  */
-   expr = error_mark_node;
-
   if (expr
   && expr != error_mark_node
   && TREE_CODE (expr) != TYPE_DECL
@@ -16530,13 +16526,17 @@ cp_parser_decltype_expr (cp_parser *parser,
&error_msg,
   id_expr_start_token->location));
 
-  if (expr == error_mark_node)
-/* We found an id-expression, but it was something that we
-   should not have found. This is an error, not something
-   we can recover from, so note that we found an
-   id-expression and we'll recover as gracefully as
-   possible.  */
-id_expression_or_member_access_p = true;
+ if (error_msg)
+   {
+ /* We found an id-expression, but it was something that we
+should not have found. This is an error, not something
+we can recover from, so report the error we found and
+we'll recover as gracefully as possible.  */
+ cp_parser_parse_definitely (parser);
+ cp_parser_error (parser, error_msg);
+ id_expression_or_member_access_p = true;
+ return error_mark_node;
+   }
 }
 
   if (expr
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C 
b/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
new file mode 100644
index 000..1df8b162743
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
@@ -0,0 +1,12 @@
+// PR c++/100482
+// { dg-do compile { target c++11 } }
+
+namespace N {}
+decltype(N) x;   // { dg-error "expected primary-expression" }
+
+struct S {};
+decltype(S) y;  // { dg-error "argument to .decltype. must be an expression" }
+
+template 
+struct U {};
+decltype(U) z;  // { dg-error "missing template arguments" }
-- 
2.41.0



[PATCH] c++: Check for indirect change of active union member in constexpr [PR101631]

2023-08-29 Thread Nathaniel Shead via Gcc-patches
This is an attempt to improve the constexpr machinery's handling of
union lifetime by catching more cases that cause UB. Is this approach
OK? 

I'd also like some feedback on a couple of pain points with this
implementation; in particular, is there a good way to detect if a type
has a non-deleted trivial constructor? I've used 'is_trivially_xible' in
this patch, but that also checks for a trivial destructor which by my
reading of [class.union.general]p5 is possibly incorrect. Checking for a
trivial default constructor doesn't seem too hard but I couldn't find a
good way of checking if that constructor is deleted.

I'm also generally unsatisfied with the additional complexity with the
third 'refs' argument in 'cxx_eval_store_expression' being pushed and
popped; would it be better to replace this with a vector of some
specific structure type for the data that needs to be passed on?

I've also just realised that empty unions are not well handled by this
patch either, but that seems to be a more general issue (see PR111226
I've just opened) so I'm leaving that be for now.

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

-- 8< --

This patch adds checks for attempting to change the active member of a
union by methods other than a member access expression.

To be able to properly distinguish `*(&u.a) = ` from `u.a = `, this
patch redoes the solution for PR59950 to avoid extranneous *&; it seems
that the only case that needed the workaround for the PR was the copying
empty class case.

Additionally, this patch ensures that constructors for a union field
mark that field as the active member before entering the call itself;
this ensures that modifications of the field within the construction
body don't cause false positives (as these will not appear to be member
access expressions). This means that we no longer need to start the
lifetime of empty union members after the constructor body either.

PR c++/101631

gcc/cp/ChangeLog:

* call.cc (build_over_call): Fold indirect refs for trivial
assignment operators when possible.
* constexpr.cc (cxx_eval_call_expression): Start lifetime of
union member before entering constructor call.
(cxx_eval_store_expression): Check for accessing incorrect union
member indirectly.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-union2.C: New test.
* g++.dg/cpp2a/constexpr-union3.C: New test.
* g++.dg/cpp2a/constexpr-union4.C: New test.
* g++.dg/cpp2a/constexpr-union5.C: New test.

Signed-Off-By: Nathaniel Shead 
---
 gcc/cp/call.cc|  10 +-
 gcc/cp/constexpr.cc   | 103 --
 gcc/testsuite/g++.dg/cpp2a/constexpr-union2.C |  30 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C |  42 +++
 gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C |  29 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C |  46 
 6 files changed, 223 insertions(+), 37 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..cb85e9a6694 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10358,10 +10358,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
   && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR)
   && trivial_fn_p (fn))
 {
-  /* Don't use cp_build_fold_indirect_ref, op= returns an lvalue even if
-the object argument isn't one.  */
-  tree to = cp_build_indirect_ref (input_location, argarray[0],
-  RO_ARROW, complain);
+  tree to = cp_build_fold_indirect_ref (argarray[0]);
   tree type = TREE_TYPE (to);
   tree as_base = CLASSTYPE_AS_BASE (type);
   tree arg = argarray[1];
@@ -10369,6 +10366,11 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
 
   if (is_really_empty_class (type, /*ignore_vptr*/true))
{
+ /* Ensure op= returns an lvalue even if the object argument isn't one.
+This isn't needed in other cases since MODIFY_EXPR is always
+considered an lvalue.  */
+ to = cp_build_addr_expr (to, tf_none);
+ to = cp_build_indirect_ref (input_location, to, RO_ARROW, complain);
  /* Avoid copying empty classes.  */
  val = build2 (COMPOUND_EXPR, type, arg, to);
  suppress_warning (val, OPT_Wunused);
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8bd5c4a47f8..811534586da 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3141,40 +3141,34 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
tree t,
cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/false,
  

[PATCH v2] c++: Catch indirect change of active union member in constexpr [PR101631]

2023-09-01 Thread Nathaniel Shead via Gcc-patches
On Wed, Aug 30, 2023 at 04:28:18PM -0400, Jason Merrill wrote:
> On 8/29/23 09:35, Nathaniel Shead wrote:
> > This is an attempt to improve the constexpr machinery's handling of
> > union lifetime by catching more cases that cause UB. Is this approach
> > OK?
> > 
> > I'd also like some feedback on a couple of pain points with this
> > implementation; in particular, is there a good way to detect if a type
> > has a non-deleted trivial constructor? I've used 'is_trivially_xible' in
> > this patch, but that also checks for a trivial destructor which by my
> > reading of [class.union.general]p5 is possibly incorrect. Checking for a
> > trivial default constructor doesn't seem too hard but I couldn't find a
> > good way of checking if that constructor is deleted.
> 
> I guess the simplest would be
> 
> (TYPE_HAS_TRIVIAL_DFLT (t) && locate_ctor (t))
> 
> because locate_ctor returns null for a deleted default ctor.  It would be
> good to make this a separate predicate.
> 
> > I'm also generally unsatisfied with the additional complexity with the
> > third 'refs' argument in 'cxx_eval_store_expression' being pushed and
> > popped; would it be better to replace this with a vector of some
> > specific structure type for the data that needs to be passed on?
> 
> Perhaps, but what you have here is fine.  Another possibility would be to
> just have a vec of the refs and extract the index from the ref later as
> needed.
> 
> Jason
> 

Thanks for the feedback. I've kept the refs as-is for now. I've also
cleaned up a couple of other typos I'd had with comments and diagnostics.

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

-- 8< --

This patch adds checks for attempting to change the active member of a
union by methods other than a member access expression.

To be able to properly distinguish `*(&u.a) = ` from `u.a = `, this
patch redoes the solution for c++/59950 to avoid extranneous *&; it
seems that the only case that needed the workaround was when copying
empty classes.

Additionally, this patch ensures that constructors for a union field
mark that field as the active member before entering the call itself;
this ensures that modifications of the field within the constructor's
body don't cause false positives (as these will not appear to be member
access expressions). This means that we no longer need to start the
lifetime of empty union members after the constructor body completes.

PR c++/101631

gcc/cp/ChangeLog:

* call.cc (build_over_call): Fold more indirect refs for trivial
assignment op.
* class.cc (type_has_non_deleted_trivial_default_ctor): Create.
* constexpr.cc (cxx_eval_call_expression): Start lifetime of
union member before entering constructor.
(cxx_eval_store_expression): Check for accessing inactive union
member indirectly.
* cp-tree.h (type_has_non_deleted_trivial_default_ctor):
Forward declare.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-union2.C: New test.
* g++.dg/cpp2a/constexpr-union3.C: New test.
* g++.dg/cpp2a/constexpr-union4.C: New test.
* g++.dg/cpp2a/constexpr-union5.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/call.cc|  11 +-
 gcc/cp/class.cc   |   8 ++
 gcc/cp/constexpr.cc   | 105 --
 gcc/cp/cp-tree.h  |   1 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union2.C |  30 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C |  45 
 gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C |  29 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C |  55 +
 8 files changed, 246 insertions(+), 38 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..3372c88f182 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10358,10 +10358,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
   && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR)
   && trivial_fn_p (fn))
 {
-  /* Don't use cp_build_fold_indirect_ref, op= returns an lvalue even if
-the object argument isn't one.  */
-  tree to = cp_build_indirect_ref (input_location, argarray[0],
-  RO_ARROW, complain);
+  tree to = cp_build_fold_indirect_ref (argarray[0]);
   tree type = TREE_TYPE (to);
   tree as_base = CLASSTYPE_AS_BASE (type);
   tree arg = argarray[1];
@@ -10369,7 +10366,11 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
 
   if (is_really_empty_class (type, /*ignore_vptr*/true))
{
- /* Avoid copying empty classes.  */
+   

[PATCH v2 0/3] c++: Track lifetimes in constant evaluation [PR70331,...]

2023-06-13 Thread Nathaniel Shead via Gcc-patches
(Another) ping. I also have some more changes on top of this patch set
as well if this looks good as it is.

https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614811.html

Thanks!

On Wed, Mar 29, 2023 at 01:32:55PM +1100, Nathaniel Shead wrote:
> This is an update of the patch series at
> https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614759.html
> 
> The main change is modifying the first patch to store the "expired" flag
> in the C++-specific lang_decl_base struct instead of tree_decl_common.
> The second and third patches to improve diagnostic locations are
> otherwise unchanged.
> 
> Bootstrapped and regression tested on x86_64 linux.
> 
> Nathaniel
> 
> ---
> 
> Nathaniel Shead (3):
>   c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]
>   c++: Improve constexpr error for dangling local variables
>   c++: Improve location information in constexpr evaluation
> 
>  gcc/cp/constexpr.cc   | 152 --
>  gcc/cp/cp-tree.h  |  10 +-
>  gcc/cp/module.cc  |   2 +
>  gcc/cp/semantics.cc   |   5 +-
>  gcc/cp/typeck.cc  |   5 +-
>  gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
>  gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
>  gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   2 +-
>  gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
>  .../g++.dg/cpp1y/constexpr-lifetime1.C|  14 ++
>  .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
>  .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
>  .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
>  .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
>  gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
>  gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
>  .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
>  gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
>  gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
>  gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
>  .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
>  gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
>  gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
>  gcc/testsuite/g++.dg/ubsan/pr63956.C  |   4 +-
>  .../g++.dg/warn/Wreturn-local-addr-6.C|   3 -
>  .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
>  30 files changed, 246 insertions(+), 112 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
> 
> -- 
> 2.34.1
> 


[PATCH] c++: Report invalid id-expression in decltype [PR100482]

2023-06-13 Thread Nathaniel Shead via Gcc-patches
(Another) ping.

On Sun, Apr 30, 2023 at 12:00:05PM +1000, Nathaniel Shead wrote:
> This patch ensures that any errors raised by finish_id_expression when
> parsing a decltype expression are properly reported, rather than
> potentially going ignored and causing invalid code to be accepted.
> 
> We can also now remove the separate check for templates without args as
> this is also checked for in finish_id_expression.
> 
>   PR 100482
> 
> gcc/cp/ChangeLog:
> 
>   * parser.cc (cp_parser_decltype_expr): Report errors raised by
>   finish_id_expression.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/pr100482.C: New test.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/parser.cc| 22 +++---
>  gcc/testsuite/g++.dg/pr100482.C | 11 +++
>  2 files changed, 22 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/pr100482.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index e5f032f2330..20ebcdc3cfd 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -16508,10 +16508,6 @@ cp_parser_decltype_expr (cp_parser *parser,
>   expr = cp_parser_lookup_name_simple (parser, expr,
>id_expr_start_token->location);
>  
> -  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)
> - /* A template without args is not a complete id-expression.  */
> - expr = error_mark_node;
> -
>if (expr
>&& expr != error_mark_node
>&& TREE_CODE (expr) != TYPE_DECL
> @@ -16532,13 +16528,17 @@ cp_parser_decltype_expr (cp_parser *parser,
> &error_msg,
>  id_expr_start_token->location));
>  
> -  if (expr == error_mark_node)
> -/* We found an id-expression, but it was something that we
> -   should not have found. This is an error, not something
> -   we can recover from, so note that we found an
> -   id-expression and we'll recover as gracefully as
> -   possible.  */
> -id_expression_or_member_access_p = true;
> +   if (error_msg)
> + {
> +   /* We found an id-expression, but it was something that we
> +  should not have found. This is an error, not something
> +  we can recover from, so report the error we found and
> +  we'll recover as gracefully as possible.  */
> +   cp_parser_parse_definitely (parser);
> +   cp_parser_error (parser, error_msg);
> +   id_expression_or_member_access_p = true;
> +   return error_mark_node;
> + }
>  }
>  
>if (expr
> diff --git a/gcc/testsuite/g++.dg/pr100482.C b/gcc/testsuite/g++.dg/pr100482.C
> new file mode 100644
> index 000..dcf6722fda5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr100482.C
> @@ -0,0 +1,11 @@
> +// { dg-do compile { target c++11 } }
> +
> +namespace N {}
> +decltype(std) x;   // { dg-error "expected primary-expression" }
> +
> +struct S {};
> +decltype(S) y;  // { dg-error "argument to .decltype. must be an expression" 
> }
> +
> +template 
> +struct U {};
> +decltype(U) z;  // { dg-error "missing template arguments" }
> -- 
> 2.40.0
> 


[PATCH] c++: Fix ICE with parameter pack of decltype(auto) [PR103497]

2023-06-13 Thread Nathaniel Shead via Gcc-patches
(Another) ping.

https://gcc.gnu.org/pipermail/gcc-patches/2023-April/616465.html

On Sat, Apr 22, 2023 at 04:25:13PM +1000, Nathaniel Shead wrote:
> Bootstrapped and tested on x86_64-pc-linux-gnu.
> 
> -- 8< --
> 
> This patch raises an error early when the decltype(auto) specifier is
> used as a parameter of a function. This prevents any issues with an
> unexpected tree type later on when performing the call.
> 
>   PR 103497
> 
> gcc/cp/ChangeLog:
> 
>   * parser.cc (cp_parser_simple_type_specifier): Add check for
>   decltype(auto) as function parameter.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/pr103497.C: New test.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/parser.cc| 10 ++
>  gcc/testsuite/g++.dg/pr103497.C |  7 +++
>  2 files changed, 17 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/pr103497.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index e5f032f2330..1415e07e152 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -19884,6 +19884,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
>&& cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
>  {
>type = saved_checks_value (token->u.tree_check_value);
> +  /* Within a function parameter declaration, decltype(auto) is always an
> +  error.  */
> +  if (parser->auto_is_implicit_function_template_parm_p
> +   && TREE_CODE (type) == TEMPLATE_TYPE_PARM
> +   && AUTO_IS_DECLTYPE (type))
> + {
> +   error_at (token->location,
> + "cannot declare a parameter with %");
> +   type = error_mark_node;
> + }
>if (decl_specs)
>   {
> cp_parser_set_decl_spec_type (decl_specs, type,
> diff --git a/gcc/testsuite/g++.dg/pr103497.C b/gcc/testsuite/g++.dg/pr103497.C
> new file mode 100644
> index 000..bcd421c2907
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr103497.C
> @@ -0,0 +1,7 @@
> +// { dg-do compile { target c++14 } }
> +
> +void foo(decltype(auto)... args);  // { dg-error "parameter with 
> .decltype.auto..|no parameter packs" }
> +
> +int main() {
> +  foo();
> +}
> -- 
> 2.34.1
> 


Re: [PATCH] c++: Fix ICE with parameter pack of decltype(auto) [PR103497]

2023-06-24 Thread Nathaniel Shead via Gcc-patches
On Fri, Jun 23, 2023 at 11:59:51AM -0400, Patrick Palka wrote:
> Hi,
> 
> On Sat, 22 Apr 2023, Nathaniel Shead via Gcc-patches wrote:
> 
> > Bootstrapped and tested on x86_64-pc-linux-gnu.
> > 
> > -- 8< --
> > 
> > This patch raises an error early when the decltype(auto) specifier is
> > used as a parameter of a function. This prevents any issues with an
> > unexpected tree type later on when performing the call.
> 
> Thanks very much for the patch!  Some minor comments below.
> 
> > 
> > PR 103497
> 
> We should include the bug component name when referring to the PR in the
> commit message (i.e. PR c++/103497) so that upon pushing the patch the
> post-commit hook automatically adds a comment to the PR reffering to the
> commit.  I could be wrong but AFAIK the hook only performs this when the
> component name is included.

Thanks for the review! Fixed.

> > 
> > gcc/cp/ChangeLog:
> > 
> > * parser.cc (cp_parser_simple_type_specifier): Add check for
> > decltype(auto) as function parameter.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/pr103497.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  gcc/cp/parser.cc| 10 ++
> >  gcc/testsuite/g++.dg/pr103497.C |  7 +++
> >  2 files changed, 17 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/pr103497.C
> > 
> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > index e5f032f2330..1415e07e152 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -19884,6 +19884,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
> >&& cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
> >  {
> >type = saved_checks_value (token->u.tree_check_value);
> > +  /* Within a function parameter declaration, decltype(auto) is always 
> > an
> > +error.  */
> > +  if (parser->auto_is_implicit_function_template_parm_p
> > + && TREE_CODE (type) == TEMPLATE_TYPE_PARM
> 
> We could check is_auto (type) here instead, to avoid any confusion with
> checking AUTO_IS_DECLTYPE for a non-auto TEMPLATE_TYPE_PARM.
> 
> > + && AUTO_IS_DECLTYPE (type))
> > +   {
> > + error_at (token->location,
> > +   "cannot declare a parameter with %");
> > + type = error_mark_node;
> > +   }
> >if (decl_specs)
> > {
> >   cp_parser_set_decl_spec_type (decl_specs, type,
> > diff --git a/gcc/testsuite/g++.dg/pr103497.C 
> > b/gcc/testsuite/g++.dg/pr103497.C
> > new file mode 100644
> > index 000..bcd421c2907
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/pr103497.C
> > @@ -0,0 +1,7 @@
> > +// { dg-do compile { target c++14 } }
> > +
> > +void foo(decltype(auto)... args);  // { dg-error "parameter with 
> > .decltype.auto..|no parameter packs" }
> 
> I noticed for
> 
>   void foo(decltype(auto) arg);
> 
> we already issue an identical error from grokdeclarator.  Perhaps we could
> instead extend the error handling there to detect decltype(auto)... as well,
> rather than adding new error handling in cp_parser_simple_type_specifier?

Ah thanks, I didn't notice this; this simplifies the change a fair bit.
How about this patch instead?

Regtested on x86_64-pc-linux-gnu.

-- 8< --

This patch ensures that checks for usages of 'auto' in function
parameters also consider parameter packs, since 'type_uses_auto' does
not seem to consider this case.

PR c++/103497

gcc/cp/ChangeLog:

* decl.cc (grokdeclarator): Check for decltype(auto) in
parameter pack.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/decl.cc| 3 +++
 gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C | 8 
 2 files changed, 11 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 60f107d50c4..aaf691fce68 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -14044,6 +14044,9 @@ grokdeclarator (const cp_declarator *declarator,
error ("cannot use %<::%> in parameter declaration");
 
   tree auto_node = type_uses_auto (type);
+  if (!auto_node && parameter_pack_p)
+   auto_node = type_uses_auto (PACK_EXPANSION_PATTERN (type));
+
   if (auto_node && !(cxx_dialect >= cxx17 && template_parm_flag))
{
  if (cxx_dialect >= cxx14)
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C 
b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
new file mode 100644
index 000..cedd661710c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C
@@ -0,0 +1,8 @@
+// PR c++/103497
+// { dg-do compile { target c++14 } }
+
+void foo(decltype(auto)... args);  // { dg-error "cannot declare a parameter 
with .decltype.auto.." }
+
+int main() {
+  foo();
+}
-- 
2.41.0



Re: [PATCH] c++: Report invalid id-expression in decltype [PR100482]

2023-06-24 Thread Nathaniel Shead via Gcc-patches
On Fri, Jun 23, 2023 at 12:15:32PM -0400, Patrick Palka wrote:
> On Sun, 30 Apr 2023, Nathaniel Shead via Gcc-patches wrote:
> 
> > This patch ensures that any errors raised by finish_id_expression when
> > parsing a decltype expression are properly reported, rather than
> > potentially going ignored and causing invalid code to be accepted.
> > 
> > We can also now remove the separate check for templates without args as
> > this is also checked for in finish_id_expression.
> > 
> > PR 100482
> > 
> > gcc/cp/ChangeLog:
> > 
> > * parser.cc (cp_parser_decltype_expr): Report errors raised by
> > finish_id_expression.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/pr100482.C: New test.
> 
> LGTM.  Some minor comments about the new testcase below:
> 
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  gcc/cp/parser.cc| 22 +++---
> >  gcc/testsuite/g++.dg/pr100482.C | 11 +++
> >  2 files changed, 22 insertions(+), 11 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/pr100482.C
> > 
> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > index e5f032f2330..20ebcdc3cfd 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -16508,10 +16508,6 @@ cp_parser_decltype_expr (cp_parser *parser,
> > expr = cp_parser_lookup_name_simple (parser, expr,
> >  id_expr_start_token->location);
> >  
> > -  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)
> > -   /* A template without args is not a complete id-expression.  */
> > -   expr = error_mark_node;
> > -
> >if (expr
> >&& expr != error_mark_node
> >&& TREE_CODE (expr) != TYPE_DECL
> > @@ -16532,13 +16528,17 @@ cp_parser_decltype_expr (cp_parser *parser,
> > &error_msg,
> >id_expr_start_token->location));
> >  
> > -  if (expr == error_mark_node)
> > -/* We found an id-expression, but it was something that we
> > -   should not have found. This is an error, not something
> > -   we can recover from, so note that we found an
> > -   id-expression and we'll recover as gracefully as
> > -   possible.  */
> > -id_expression_or_member_access_p = true;
> > + if (error_msg)
> > +   {
> > + /* We found an id-expression, but it was something that we
> > +should not have found. This is an error, not something
> > +we can recover from, so report the error we found and
> > +we'll recover as gracefully as possible.  */
> > + cp_parser_parse_definitely (parser);
> > + cp_parser_error (parser, error_msg);
> > + id_expression_or_member_access_p = true;
> > + return error_mark_node;
> > +   }
> >  }
> >  
> >if (expr
> > diff --git a/gcc/testsuite/g++.dg/pr100482.C 
> > b/gcc/testsuite/g++.dg/pr100482.C
> > new file mode 100644
> > index 000..dcf6722fda5
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/pr100482.C
> 
> We generally prefer to organize tests according to the language dialect
> they apply to and the langugae construct that they're primarily testing.
> In this case we could name the test e.g.
> 
>   gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
> 
> > @@ -0,0 +1,11 @@
> > +// { dg-do compile { target c++10 } }
> 
> We also usually mention the PR number in the test as a comment:
> 
> // PR c++/100482
> 
> One benefit of doing so is that the git alias 'git gcc-commit-mklog'
> (https://gcc.gnu.org/gitwrite.html#vendor) will then automatically
> include the PR number in the commit message template.
> 
> > +
> > +namespace N {}
> > +decltype(std) x;   // { dg-error "expected primary-expression" }
> > +
> > +struct S {};
> > +decltype(S) y;  // { dg-error "argument to .decltype. must be an 
> > expression" }
> > +
> > +template 
> > +struct U {};
> > +decltype(U) z;  // { dg-error "missing template arguments" }
> > -- 
> > 2.40.0
> > 
> > 
> 

Thanks for the comments. I've fixed the test, does this look OK?

-- 8< --

This patch ensures that any errors raised by finish_id_expression when
parsing a decltype expression are properly reported, rather than
potentially going ignored and causing invalid code to be accepted.

Re: [PATCH v2 1/3] c++: Track lifetimes in constant evaluation [PR70331, PR96630, PR98675]

2023-06-24 Thread Nathaniel Shead via Gcc-patches
On Fri, Jun 23, 2023 at 12:43:21PM -0400, Patrick Palka wrote:
> On Wed, 29 Mar 2023, Nathaniel Shead via Gcc-patches wrote:
> 
> > This adds rudimentary lifetime tracking in C++ constexpr contexts,
> > allowing the compiler to report errors with using values after their
> > backing has gone out of scope. We don't yet handle other ways of ending
> > lifetimes (e.g. explicit destructor calls).
> 
> Awesome!
> 
> > 
> > PR c++/96630
> > PR c++/98675
> > PR c++/70331
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (constexpr_global_ctx::put_value): Mark value as
> > in lifetime.
> > (constexpr_global_ctx::remove_value): Mark value as expired.
> > (cxx_eval_call_expression): Remove comment that is no longer
> > applicable.
> > (non_const_var_error): Add check for expired values.
> > (cxx_eval_constant_expression): Add checks for expired values. Forget
> > local variables at end of bind expressions. Forget temporaries at end
> > of cleanup points.
> > * cp-tree.h (struct lang_decl_base): New flag to track expired values
> > in constant evaluation.
> > (DECL_EXPIRED_P): Access the new flag.
> > (SET_DECL_EXPIRED_P): Modify the new flag.
> > * module.cc (trees_out::lang_decl_bools): Write out the new flag.
> > (trees_in::lang_decl_bools): Read in the new flag.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/constexpr-ice20.C: Update error raised by test.
> > * g++.dg/cpp1y/constexpr-lifetime1.C: New test.
> > * g++.dg/cpp1y/constexpr-lifetime2.C: New test.
> > * g++.dg/cpp1y/constexpr-lifetime3.C: New test.
> > * g++.dg/cpp1y/constexpr-lifetime4.C: New test.
> > * g++.dg/cpp1y/constexpr-lifetime5.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  gcc/cp/constexpr.cc   | 69 +++
> >  gcc/cp/cp-tree.h  | 10 ++-
> >  gcc/cp/module.cc  |  2 +
> >  gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  2 +-
> >  .../g++.dg/cpp1y/constexpr-lifetime1.C| 13 
> >  .../g++.dg/cpp1y/constexpr-lifetime2.C| 20 ++
> >  .../g++.dg/cpp1y/constexpr-lifetime3.C| 13 
> >  .../g++.dg/cpp1y/constexpr-lifetime4.C| 11 +++
> >  .../g++.dg/cpp1y/constexpr-lifetime5.C| 11 +++
> >  9 files changed, 137 insertions(+), 14 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 3de60cfd0f8..bdbc12144a7 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -1185,10 +1185,22 @@ public:
> >void put_value (tree t, tree v)
> >{
> >  bool already_in_map = values.put (t, v);
> > +if (!already_in_map && DECL_P (t))
> > +  {
> > +   if (!DECL_LANG_SPECIFIC (t))
> > + retrofit_lang_decl (t);
> > +   if (DECL_LANG_SPECIFIC (t))
> > + SET_DECL_EXPIRED_P (t, false);
> > +  }
> 
> Since this new flag would only be used only during constexpr evaluation,
> could we instead use an on-the-side hash_set in constexpr_global_ctx for
> tracking expired-ness?  That way we won't have to allocate a
> DECL_LANG_SPECIFIC structure for decls that lack it, and won't have to
> worry about the flag in other parts of the compiler.

I've tried this but I haven't been able to get it to work well. The main
issue I'm running into is the caching of function calls in constant
evaluation. For example, consider the following:

constexpr const double& test() {
  const double& local = 3.0;
  return local;
}

constexpr int foo(const double&) { return 5; }

constexpr int a = foo(test());
static_assert(test() == 3.0);

When constant-evaluating 'a', we evaluate 'test()'. It returns a value
that ends its lifetime immediately, so we mark this in 'ctx->global' as
expired. However, 'foo()' never actually evaluates this expired value,
so the initialisation of 'a' succeeds.

However, then when the static assertion attempts to constant evaluate a
second time, the result of 'test' has already been cached, and we jus

[PATCH] c++: Fix ICE with parameter pack of decltype(auto) [PR103497]

2023-06-30 Thread Nathaniel Shead via Gcc-patches
On Thu, Jun 29, 2023 at 01:43:07PM -0400, Jason Merrill wrote:
> On 6/24/23 09:24, Nathaniel Shead wrote:
> > On Fri, Jun 23, 2023 at 11:59:51AM -0400, Patrick Palka wrote:
> > > Hi,
> > > 
> > > On Sat, 22 Apr 2023, Nathaniel Shead via Gcc-patches wrote:
> > > 
> > > > Bootstrapped and tested on x86_64-pc-linux-gnu.
> > > > 
> > > > -- 8< --
> > > > 
> > > > This patch raises an error early when the decltype(auto) specifier is
> > > > used as a parameter of a function. This prevents any issues with an
> > > > unexpected tree type later on when performing the call.
> > > 
> > > Thanks very much for the patch!  Some minor comments below.
> > > 
> > > > 
> > > > PR 103497
> > > 
> > > We should include the bug component name when referring to the PR in the
> > > commit message (i.e. PR c++/103497) so that upon pushing the patch the
> > > post-commit hook automatically adds a comment to the PR reffering to the
> > > commit.  I could be wrong but AFAIK the hook only performs this when the
> > > component name is included.
> > 
> > Thanks for the review! Fixed.
> > 
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * parser.cc (cp_parser_simple_type_specifier): Add check for
> > > > decltype(auto) as function parameter.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/pr103497.C: New test.
> > > > 
> > > > Signed-off-by: Nathaniel Shead 
> > > > ---
> > > >   gcc/cp/parser.cc| 10 ++
> > > >   gcc/testsuite/g++.dg/pr103497.C |  7 +++
> > > >   2 files changed, 17 insertions(+)
> > > >   create mode 100644 gcc/testsuite/g++.dg/pr103497.C
> > > > 
> > > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > > > index e5f032f2330..1415e07e152 100644
> > > > --- a/gcc/cp/parser.cc
> > > > +++ b/gcc/cp/parser.cc
> > > > @@ -19884,6 +19884,16 @@ cp_parser_simple_type_specifier (cp_parser* 
> > > > parser,
> > > > && cp_lexer_peek_nth_token (parser->lexer, 2)->type != 
> > > > CPP_SCOPE)
> > > >   {
> > > > type = saved_checks_value (token->u.tree_check_value);
> > > > +  /* Within a function parameter declaration, decltype(auto) is 
> > > > always an
> > > > +error.  */
> > > > +  if (parser->auto_is_implicit_function_template_parm_p
> > > > + && TREE_CODE (type) == TEMPLATE_TYPE_PARM
> > > 
> > > We could check is_auto (type) here instead, to avoid any confusion with
> > > checking AUTO_IS_DECLTYPE for a non-auto TEMPLATE_TYPE_PARM.
> > > 
> > > > + && AUTO_IS_DECLTYPE (type))
> > > > +   {
> > > > + error_at (token->location,
> > > > +   "cannot declare a parameter with 
> > > > %");
> > > > + type = error_mark_node;
> > > > +   }
> > > > if (decl_specs)
> > > > {
> > > >   cp_parser_set_decl_spec_type (decl_specs, type,
> > > > diff --git a/gcc/testsuite/g++.dg/pr103497.C 
> > > > b/gcc/testsuite/g++.dg/pr103497.C
> > > > new file mode 100644
> > > > index 000..bcd421c2907
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/g++.dg/pr103497.C
> > > > @@ -0,0 +1,7 @@
> > > > +// { dg-do compile { target c++14 } }
> > > > +
> > > > +void foo(decltype(auto)... args);  // { dg-error "parameter with 
> > > > .decltype.auto..|no parameter packs" }
> > > 
> > > I noticed for
> > > 
> > >void foo(decltype(auto) arg);
> > > 
> > > we already issue an identical error from grokdeclarator.  Perhaps we could
> > > instead extend the error handling there to detect decltype(auto)... as 
> > > well,
> > > rather than adding new error handling in cp_parser_simple_type_specifier?
> > 
> > Ah thanks, I didn't notice this; this simplifies the change a fair bit.
> > How about this patch instead?
> > 
> > Regtested on x86_64-pc-linux-gnu.
> > 
> > -- 8< --
> > 
> > This patch ensures that checks for usages of 'auto&#x

Re: [PATCH v2 1/3] c++: Track lifetimes in constant evaluation [PR70331, PR96630, PR98675]

2023-06-30 Thread Nathaniel Shead via Gcc-patches
On Mon, Jun 26, 2023 at 03:37:32PM -0400, Patrick Palka wrote:
> On Sun, 25 Jun 2023, Nathaniel Shead wrote:
> 
> > On Fri, Jun 23, 2023 at 12:43:21PM -0400, Patrick Palka wrote:
> > > On Wed, 29 Mar 2023, Nathaniel Shead via Gcc-patches wrote:
> > > 
> > > > This adds rudimentary lifetime tracking in C++ constexpr contexts,
> > > > allowing the compiler to report errors with using values after their
> > > > backing has gone out of scope. We don't yet handle other ways of ending
> > > > lifetimes (e.g. explicit destructor calls).
> > > 
> > > Awesome!
> > > 
> > > > 
> > > > PR c++/96630
> > > > PR c++/98675
> > > > PR c++/70331
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (constexpr_global_ctx::put_value): Mark value as
> > > > in lifetime.
> > > > (constexpr_global_ctx::remove_value): Mark value as expired.
> > > > (cxx_eval_call_expression): Remove comment that is no longer
> > > > applicable.
> > > > (non_const_var_error): Add check for expired values.
> > > > (cxx_eval_constant_expression): Add checks for expired values. 
> > > > Forget
> > > > local variables at end of bind expressions. Forget temporaries 
> > > > at end
> > > > of cleanup points.
> > > > * cp-tree.h (struct lang_decl_base): New flag to track expired 
> > > > values
> > > > in constant evaluation.
> > > > (DECL_EXPIRED_P): Access the new flag.
> > > > (SET_DECL_EXPIRED_P): Modify the new flag.
> > > > * module.cc (trees_out::lang_decl_bools): Write out the new 
> > > > flag.
> > > > (trees_in::lang_decl_bools): Read in the new flag.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp0x/constexpr-ice20.C: Update error raised by test.
> > > > * g++.dg/cpp1y/constexpr-lifetime1.C: New test.
> > > > * g++.dg/cpp1y/constexpr-lifetime2.C: New test.
> > > > * g++.dg/cpp1y/constexpr-lifetime3.C: New test.
> > > > * g++.dg/cpp1y/constexpr-lifetime4.C: New test.
> > > > * g++.dg/cpp1y/constexpr-lifetime5.C: New test.
> > > > 
> > > > Signed-off-by: Nathaniel Shead 
> > > > ---
> > > >  gcc/cp/constexpr.cc   | 69 +++
> > > >  gcc/cp/cp-tree.h  | 10 ++-
> > > >  gcc/cp/module.cc  |  2 +
> > > >  gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  2 +-
> > > >  .../g++.dg/cpp1y/constexpr-lifetime1.C| 13 
> > > >  .../g++.dg/cpp1y/constexpr-lifetime2.C| 20 ++
> > > >  .../g++.dg/cpp1y/constexpr-lifetime3.C| 13 
> > > >  .../g++.dg/cpp1y/constexpr-lifetime4.C| 11 +++
> > > >  .../g++.dg/cpp1y/constexpr-lifetime5.C| 11 +++
> > > >  9 files changed, 137 insertions(+), 14 deletions(-)
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
> > > > 
> > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > index 3de60cfd0f8..bdbc12144a7 100644
> > > > --- a/gcc/cp/constexpr.cc
> > > > +++ b/gcc/cp/constexpr.cc
> > > > @@ -1185,10 +1185,22 @@ public:
> > > >void put_value (tree t, tree v)
> > > >{
> > > >  bool already_in_map = values.put (t, v);
> > > > +if (!already_in_map && DECL_P (t))
> > > > +  {
> > > > +   if (!DECL_LANG_SPECIFIC (t))
> > > > + retrofit_lang_decl (t);
> > > > +   if (DECL_LANG_SPECIFIC (t))
> > > > + SET_DECL_EXPIRED_P (t, false);
> > > > +  }
> > > 
> > > Since this new flag would only be used only during constexpr evaluation,
> > > could we instead use an on-the-side hash_set in constexpr_global_ctx for
> >

[PATCH v2 3/3] c++: Improve location information in constexpr evaluation

2023-06-30 Thread Nathaniel Shead via Gcc-patches
On Fri, Jun 23, 2023 at 01:09:14PM -0400, Patrick Palka wrote:
> On Wed, 29 Mar 2023, Nathaniel Shead via Gcc-patches wrote:
> 
> > This patch caches the current expression's location information in the
> > constexpr_global_ctx struct, which allows subexpressions that have lost
> > location information to still provide accurate diagnostics. Also
> > rewrites a number of 'error' calls as 'error_at' to provide more
> > specific location information.
> > 
> > The primary effect of this change is that many errors within evaluation
> > of a constexpr function will now point at the offending expression (with
> > expansion tracing information) rather than just the outermost call.
> 
> This seems like a great improvement!
> 
> In other parts of the frontend, e.g. during substitution from
> tsubst_expr or tsubst_copy_and_build, we do something similar by
> setting/restoring input_location directly.  (We've since added the RAII
> class iloc_sentinel for this.)  I wonder if that'd be preferable here?

I didn't consider that; I've given it a try and I think it's nicer.
Doing it this way also updated a number of 'error' calls that I hadn't
fixed up in this version; generally this meant nicer error messages, but
I had to override it for a couple of cases where I felt the errors it
raised were worse (by adding context that made no sense).

I'm still bootstrapping/regtesting but I'll send out an updated version
of this sometime tomorrow when it's done. Thanks!

> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (constexpr_global_ctx): New field for cached
> > tree location, defaulting to input_location.
> > (cxx_eval_internal_function): Fall back to ctx->global->loc
> > rather than input_location.
> > (modifying_const_object_error): Likewise.
> > (cxx_eval_dynamic_cast_fn): Likewise.
> > (eval_and_check_array_index): Likewise.
> > (cxx_eval_array_reference): Likewise.
> > (cxx_eval_bit_field_ref): Likewise.
> > (cxx_eval_component_reference): Likewise.
> > (cxx_eval_indirect_ref): Likewise.
> > (cxx_eval_store_expression): Likewise.
> > (cxx_eval_increment_expression): Likewise.
> > (cxx_eval_loop_expr): Likewise.
> > (cxx_eval_binary_expression): Likewise.
> > (cxx_eval_constant_expression): Cache location of trees for use
> > in errors, and prefer it instead of input_location.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/constexpr-48089.C: Updated diagnostic locations.
> > * g++.dg/cpp0x/constexpr-diag3.C: Likewise.
> > * g++.dg/cpp0x/constexpr-ice20.C: Likewise.
> > * g++.dg/cpp1y/constexpr-89481.C: Likewise.
> > * g++.dg/cpp1y/constexpr-lifetime1.C: Likewise.
> > * g++.dg/cpp1y/constexpr-lifetime2.C: Likewise.
> > * g++.dg/cpp1y/constexpr-lifetime3.C: Likewise.
> > * g++.dg/cpp1y/constexpr-lifetime4.C: Likewise.
> > * g++.dg/cpp1y/constexpr-lifetime5.C: Likewise.
> > * g++.dg/cpp1y/constexpr-union5.C: Likewise.
> > * g++.dg/cpp1y/pr68180.C: Likewise.
> > * g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
> > * g++.dg/cpp2a/bit-cast11.C: Likewise.
> > * g++.dg/cpp2a/bit-cast12.C: Likewise.
> > * g++.dg/cpp2a/bit-cast14.C: Likewise.
> > * g++.dg/cpp2a/constexpr-98122.C: Likewise.
> > * g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
> > * g++.dg/cpp2a/constexpr-init1.C: Likewise.
> > * g++.dg/cpp2a/constexpr-new12.C: Likewise.
> > * g++.dg/cpp2a/constexpr-new3.C: Likewise.
> > * g++.dg/ext/constexpr-vla2.C: Likewise.
> > * g++.dg/ext/constexpr-vla3.C: Likewise.
> > * g++.dg/ubsan/pr63956.C: Likewise.
> > 
> > libstdc++/ChangeLog:
> > 
> > * testsuite/25_algorithms/equal/constexpr_neg.cc: Updated
> > diagnostics locations.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  gcc/cp/constexpr.cc   | 83 +++
> >  gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 +--
> >  gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
> >  gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  4 +-
> >  gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
> >  .../g++.dg/cpp1y/constexpr-lifetime1.C|  1 +
> >  .../g++.dg/cpp1y/constexpr-lifetime2.C|  4 +-
> >  .../g++.dg/cpp1y/constexpr-lifetime3.C|  4 +-
> >  .../g++.dg/cpp1y/constexpr-lifetime4.C|  2 +-
> >  .../g++.dg/cpp1y/constexpr-lifetime5.C|  4 +-
> >  gcc/testsuite/g++.dg/cpp1y/c

[PATCH v3 0/3] c++: Track lifetimes in constant evaluation [PR70331,...]

2023-06-30 Thread Nathaniel Shead via Gcc-patches
This is an update of the patch series at
https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614811.html

Changes since v2:

- Use a separate 'hash_set' to track expired variables instead of
  adding a flag to 'lang_decl_base'.
- Use 'iloc_sentinel' to propagate location information down to
  subexpressions instead of manually saving and falling back to a
  parent expression's location.
- Update more tests with improved error location information.

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

---

Nathaniel Shead (3):
  c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]
  c++: Improve constexpr error for dangling local variables
  c++: Improve location information in constant evaluation

 gcc/cp/constexpr.cc   | 158 +++---
 gcc/cp/semantics.cc   |   5 +-
 gcc/cp/typeck.cc  |   5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |   8 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |   8 +-
 .../g++.dg/cpp0x/constexpr-delete2.C  |   5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   1 +
 .../g++.dg/cpp0x/constexpr-recursion.C|   6 +-
 gcc/testsuite/g++.dg/cpp0x/overflow1.C|   2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |   5 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  14 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 .../g++.dg/cpp1y/constexpr-tracking-const14.C |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const16.C |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const18.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const19.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const21.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const22.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const3.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const4.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const7.C  |   3 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda8.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/constinit10.C  |   5 +-
 .../g++.dg/cpp2a/is-corresponding-member4.C   |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |  23 +--
 .../g++.dg/warn/Wreturn-local-addr-6.C|   3 -
 .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
 .../testsuite/26_numerics/gcd/105844.cc   |  10 +-
 .../testsuite/26_numerics/lcm/105844.cc   |  14 +-
 48 files changed, 330 insertions(+), 143 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C

-- 
2.41.0



[PATCH v3 1/3] c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]

2023-06-30 Thread Nathaniel Shead via Gcc-patches
This adds rudimentary lifetime tracking in C++ constexpr contexts,
allowing the compiler to report errors with using values after their
backing has gone out of scope. We don't yet handle other ways of
accessing values outside their lifetime (e.g. following explicit
destructor calls).

PR c++/96630
PR c++/98675
PR c++/70331

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx::remove_value): Mark value as
outside lifetime.
(find_expired_values): New function.
(outside_lifetime_error): New function.
(cxx_eval_call_expression): Don't cache calls that return references to
values outside their lifetime.
(cxx_eval_constant_expression): Add checks for out-of-lifetime values.
Forget local variables at end of bind expressions, and temporaries
after cleanup points.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime1.C: New test.
* g++.dg/cpp1y/constexpr-lifetime2.C: New test.
* g++.dg/cpp1y/constexpr-lifetime3.C: New test.
* g++.dg/cpp1y/constexpr-lifetime4.C: New test.
* g++.dg/cpp1y/constexpr-lifetime5.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 112 ++
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 6 files changed, 160 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index cca0435bafc..bc59b4aab67 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1165,6 +1165,8 @@ public:
   hash_set *modifiable;
   /* Number of heap VAR_DECL deallocations.  */
   unsigned heap_dealloc_count;
+  /* Values that are not within their lifetime.  */
+  hash_set outside_lifetime;
   /* Constructor.  */
   constexpr_global_ctx ()
 : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr),
@@ -1188,7 +1190,12 @@ public:
 if (!already_in_map && modifiable)
   modifiable->add (t);
   }
-  void remove_value (tree t) { values.remove (t); }
+  void remove_value (tree t)
+  {
+if (DECL_P (t))
+  outside_lifetime.add (t);
+values.remove (t);
+  }
 };
 
 /* Helper class for constexpr_global_ctx.  In some cases we want to avoid
@@ -2509,6 +2516,22 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree 
call,
   return cp_build_addr_expr (obj, complain);
 }
 
+/* Look for expired values in the expression *TP, called through
+   cp_walk_tree.  DATA is ctx->global->outside_lifetime.  */
+
+static tree
+find_expired_values (tree *tp, int *walk_subtrees, void *data)
+{
+  hash_set *outside_lifetime = (hash_set *) data;
+
+  if (TYPE_P (*tp))
+*walk_subtrees = 0;
+  else if (outside_lifetime->contains (*tp))
+return *tp;
+
+  return NULL_TREE;
+}
+
 /* Data structure used by replace_decl and replace_decl_r.  */
 
 struct replace_decl_data
@@ -3160,10 +3183,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  for (tree save_expr : save_exprs)
ctx->global->remove_value (save_expr);
 
- /* Remove the parms/result from the values map.  Is it worth
-bothering to do this when the map itself is only live for
-one constexpr evaluation?  If so, maybe also clear out
-other vars from call, maybe in BIND_EXPR handling?  */
+ /* Remove the parms/result from the values map.  */
  ctx->global->remove_value (res);
  for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
ctx->global->remove_value (parm);
@@ -3210,13 +3230,20 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
tree t,
cacheable = false;
}
 
-   /* Rewrite all occurrences of the function's RESULT_DECL with the
-  current object under construction.  */
-   if (!*non_constant_p && ctx->object
-   && CLASS_TYPE_P (TREE_TYPE (res))
-   && !is_empty_class (TREE_TYPE (res)))
- if (replace_decl (&result, res, ctx->object))
-   cacheable = false;
+ /* Also don't cache a call if we return a pointer to an expired
+value.  */
+ if (cacheable && (cp_walk_tree_without_duplicates
+   (&result, find_expired_values,
+&ctx->global->outside_lifetime)))
+   cacheable = false;
+
+ /* Rewrite all occurrences of the function's RESULT

[PATCH v3 2/3] c++: Improve constexpr error for dangling local variables

2023-06-30 Thread Nathaniel Shead via Gcc-patches
Currently, when typeck discovers that a return statement will refer to a
local variable it rewrites to return a null pointer. This causes the
error messages for using the return value in a constant expression to be
unhelpful, especially for reference return values.

This patch removes this "optimisation". Relying on this raises a warning
by default and causes UB anyway, so there should be no issue in doing
so. We also suppress additional warnings from later passes that detect
this as a dangling pointer, since we've already indicated this anyway.

gcc/cp/ChangeLog:

* semantics.cc (finish_return_stmt): Suppress dangling pointer
reporting on return statement if already reported.
* typeck.cc (check_return_expr): Don't set return expression to
zero for dangling addresses.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime5.C: Test reported message is
correct.
* g++.dg/warn/Wreturn-local-addr-6.C: Remove check for return
value optimisation.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/semantics.cc  | 5 -
 gcc/cp/typeck.cc | 5 +++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C | 4 ++--
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C | 3 ---
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..107407de513 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -1260,7 +1260,10 @@ finish_return_stmt (tree expr)
 
   r = build_stmt (input_location, RETURN_EXPR, expr);
   if (no_warning)
-suppress_warning (r, OPT_Wreturn_type);
+{
+  suppress_warning (r, OPT_Wreturn_type);
+  suppress_warning (r, OPT_Wdangling_pointer_);
+}
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
 
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 859b133a18d..47233b3b717 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11273,8 +11273,9 @@ check_return_expr (tree retval, bool *no_warning)
   else if (!processing_template_decl
   && maybe_warn_about_returning_address_of_local (retval, loc)
   && INDIRECT_TYPE_P (valtype))
-   retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
-build_zero_cst (TREE_TYPE (retval)));
+   /* Suppress the Wdangling-pointer warning in the return statement
+  that would otherwise occur.  */
+   *no_warning = true;
 }
 
   /* A naive attempt to reduce the number of -Wdangling-reference false
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
index a4bc71d890a..ad3ef579f63 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
@@ -1,11 +1,11 @@
 // { dg-do compile { target c++14 } }
 // { dg-options "-Wno-return-local-addr" }
 
-constexpr const int& id(int x) { return x; }
+constexpr const int& id(int x) { return x; }  // { dg-message "note: declared 
here" }
 
 constexpr bool test() {
   const int& y = id(3);
   return y == 3;
 }
 
-constexpr bool x = test();  // { dg-error "" }
+constexpr bool x = test();  // { dg-error "accessing object outside its 
lifetime" }
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C 
b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
index fae8b7e766f..ec8e241d83e 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
@@ -24,6 +24,3 @@ return_addr_local_as_intref (void)
 
   return (const intptr_t&)a;   // { dg-warning "\\\[-Wreturn-local-addr]" } */
 }
-
-/* Verify that the return value has been replaced with zero:
-  { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
-- 
2.41.0



[PATCH v3 3/3] c++: Improve location information in constant evaluation

2023-06-30 Thread Nathaniel Shead via Gcc-patches
This patch updates 'input_location' during constant evaluation to ensure
that errors in subexpressions that lack location information still
provide accurate diagnostics.

By itself this change causes some small regressions in diagnostic
quality for circumstances where errors used 'input_location' but the
location of the parent subexpression doesn't make sense, so this patch
also includes a couple of other small diagnostic improvements to improve
the most egregious cases.

gcc/cp/ChangeLog:

* constexpr.cc (modifying_const_object_error): Find the source
location of the const object's declaration.
(cxx_eval_store_expression): Fall back to the location of the
target object when evaluating initialiser.
(cxx_eval_constant_expression): Update input_location to the location
of the currently evaluated expression.

libstdc++-v3/ChangeLog:

* testsuite/25_algorithms/equal/constexpr_neg.cc: Update diagnostic
locations.
* testsuite/26_numerics/gcd/105844.cc: Likewise.
* testsuite/26_numerics/lcm/105844.cc: Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-48089.C: Update diagnostic locations.
* g++.dg/cpp0x/constexpr-70323.C: Likewise.
* g++.dg/cpp0x/constexpr-70323a.C: Likewise.
* g++.dg/cpp0x/constexpr-delete2.C: Likewise.
* g++.dg/cpp0x/constexpr-diag3.C: Likewise.
* g++.dg/cpp0x/constexpr-ice20.C: Likewise.
* g++.dg/cpp0x/constexpr-recursion.C: Likewise.
* g++.dg/cpp0x/overflow1.C: Likewise.
* g++.dg/cpp1y/constexpr-89285.C: Likewise.
* g++.dg/cpp1y/constexpr-89481.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime1.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime2.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime3.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime4.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime5.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const14.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const16.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const18.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const19.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const21.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const22.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const3.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const4.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const7.C: Likewise.
* g++.dg/cpp1y/constexpr-union5.C: Likewise.
* g++.dg/cpp1y/pr68180.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda8.C: Likewise.
* g++.dg/cpp2a/bit-cast11.C: Likewise.
* g++.dg/cpp2a/bit-cast12.C: Likewise.
* g++.dg/cpp2a/bit-cast14.C: Likewise.
* g++.dg/cpp2a/constexpr-98122.C: Likewise.
* g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
* g++.dg/cpp2a/constexpr-init1.C: Likewise.
* g++.dg/cpp2a/constexpr-new12.C: Likewise.
* g++.dg/cpp2a/constexpr-new3.C: Likewise.
* g++.dg/cpp2a/constinit10.C: Likewise.
* g++.dg/cpp2a/is-corresponding-member4.C: Likewise.
* g++.dg/ext/constexpr-vla2.C: Likewise.
* g++.dg/ext/constexpr-vla3.C: Likewise.
* g++.dg/ubsan/pr63956.C: Likewise.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 46 ++-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 ++--
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |  8 ++--
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |  8 ++--
 .../g++.dg/cpp0x/constexpr-delete2.C  |  5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  1 +
 .../g++.dg/cpp0x/constexpr-recursion.C|  6 +--
 gcc/testsuite/g++.dg/cpp0x/overflow1.C|  2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |  5 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  1 +
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  2 +-
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const14.C |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const16.C |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const18.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const19.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const21.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const22.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const3.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const4.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const7.C  |  3 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |  4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |  4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |  4 +-
 .../g++.dg/cpp1z/constexpr-l

Re: [PATCH v3 1/3] c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]

2023-07-16 Thread Nathaniel Shead via Gcc-patches
On Fri, Jul 14, 2023 at 11:16:58AM -0400, Jason Merrill wrote:
> On 6/30/23 23:28, Nathaniel Shead via Gcc-patches wrote:
> > This adds rudimentary lifetime tracking in C++ constexpr contexts,
> 
> Thanks!
> 
> I'm not seeing either a copyright assignment or DCO certification for you;
> please see https://gcc.gnu.org/contribute.html#legal for more information.
> 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index cca0435bafc..bc59b4aab67 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -1188,7 +1190,12 @@ public:
> >   if (!already_in_map && modifiable)
> > modifiable->add (t);
> > }
> > -  void remove_value (tree t) { values.remove (t); }
> > +  void remove_value (tree t)
> > +  {
> > +if (DECL_P (t))
> > +  outside_lifetime.add (t);
> > +values.remove (t);
> 
> What if, instead of removing the variable from one hash table and adding it
> to another, we change the value to, say, void_node?

I have another patch I'm working on after this which does seem to
require the overlapping tables to properly catch uses of aggregates
while they are still being constructed (i.e. before their lifetime has
begun), as part of PR c++/109518. In that case the 'values' map contains
the CONSTRUCTOR node for the aggregate, but it also needs to be in
'outside_lifetime'. I could also explore solving this another way
however if you prefer.

(I also have vague dreams of at some point making this a map to the
location that the object was destroyed for more context in the error
messages, but I'm not yet sure if that's feasible or will actually be
all that helpful so I'm happy to forgo that.)

> > + /* Also don't cache a call if we return a pointer to an expired
> > +value.  */
> > + if (cacheable && (cp_walk_tree_without_duplicates
> > +   (&result, find_expired_values,
> > +&ctx->global->outside_lifetime)))
> > +   cacheable = false;
> 
> I think we need to reconsider cacheability in general; I think we only want
> to cache calls that are themselves valid constant expressions, in that the
> return value is a "permitted result of a constant expression"
> (https://eel.is/c++draft/expr.const#13).  A pointer to an automatic variable
> is not, whether or not it is currently within its lifetime.
> 
> That is, only cacheable if reduced_constant_expression_p (result).
> 
> I'm experimenting with this now, you don't need to mess with it.

Thanks! I agree, that sounds a lot nicer; I definitely ran into caching
problems in a few different ways when I was developing this patch, and
this approach sounds like it would have avoided that.

> > @@ -7085,7 +7138,7 @@ cxx_eval_constant_expression (const constexpr_ctx 
> > *ctx, tree t,
> >   case PARM_DECL:
> > if (lval && !TYPE_REF_P (TREE_TYPE (t)))
> > /* glvalue use.  */;
> > -  else if (tree v = ctx->global->get_value (r))
> > +  else if (tree v = ctx->global->get_value (t))
> 
> I agree with this change, but it doesn't have any actual effect, right? I'll
> go ahead and apply it separately.

Yup, it was just a drive-by cleanup I made while trying to understand
this part of the code. Thanks.

> > @@ -7328,17 +7386,28 @@ cxx_eval_constant_expression (const constexpr_ctx 
> > *ctx, tree t,
> > auto_vec cleanups;
> > vec *prev_cleanups = ctx->global->cleanups;
> > ctx->global->cleanups = &cleanups;
> > -   r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
> > +
> > +   auto_vec save_exprs;
> 
> Now that we're going to track temporaries for each full-expression, I think
> we shouldn't also need to track them for loops and calls.

Good point, I didn't think about that. I'm now bootstrapping/regtesting
a modification of this patch that removes the tracking in loops and
calls, but an initial run of the dg.exp testsuite is promising. It also
fixes an issue I just noticed where I don't actually check lifetimes of
empty types.

I'll send out a new version when that finishes.


[PATCH v4 0/3] c++: Track lifetimes in constant evaluation [PR70331, ...]

2023-07-20 Thread Nathaniel Shead via Gcc-patches
This is an update of the patch series at
https://gcc.gnu.org/pipermail/gcc-patches/2023-July/623375.html

Changes since v3:

- Use void_node in values map to indicate out-of-lifetime instead of a separate
  hash set
- Remove tracking of temporaries for loops and calls
- Fix missed checks for uses of empty classes outside lifetime and associated
  test
- Add reference to PR c++/110619 for the second patch, and corresponding new
  test case

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

Nathaniel Shead (3):
  c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]
  c++: Improve constexpr error for dangling local variables [PR110619]
  c++: Improve location information in constant evaluation

 gcc/cp/constexpr.cc   | 178 +-
 gcc/cp/semantics.cc   |   5 +-
 gcc/cp/typeck.cc  |   5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |   8 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |   8 +-
 .../g++.dg/cpp0x/constexpr-delete2.C  |   5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   1 +
 .../g++.dg/cpp0x/constexpr-recursion.C|   6 +-
 gcc/testsuite/g++.dg/cpp0x/overflow1.C|   2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C |  10 +
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |   5 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  14 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 ++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime6.C|  15 ++
 .../g++.dg/cpp1y/constexpr-tracking-const14.C |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const16.C |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const18.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const19.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const21.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const22.C |   4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const3.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const4.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const7.C  |   3 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda8.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/constinit10.C  |   5 +-
 .../g++.dg/cpp2a/is-corresponding-member4.C   |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |  23 +--
 .../g++.dg/warn/Wreturn-local-addr-6.C|   3 -
 .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
 .../testsuite/26_numerics/gcd/105844.cc   |  10 +-
 .../testsuite/26_numerics/lcm/105844.cc   |  14 +-
 50 files changed, 350 insertions(+), 168 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C

-- 
2.41.0



[PATCH v4 1/3] c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]

2023-07-20 Thread Nathaniel Shead via Gcc-patches
This adds rudimentary lifetime tracking in C++ constexpr contexts,
allowing the compiler to report errors with using values after their
backing has gone out of scope. We don't yet handle other ways of
accessing values outside their lifetime (e.g. following explicit
destructor calls).

PR c++/96630
PR c++/98675
PR c++/70331

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx::is_outside_lifetime): New
function.
(constexpr_global_ctx::get_value): Don't return expired values.
(constexpr_global_ctx::get_value_ptr): Likewise.
(constexpr_global_ctx::remove_value): Mark value outside
lifetime.
(outside_lifetime_error): New function.
(cxx_eval_call_expression): No longer track save_exprs.
(cxx_eval_loop_expr): Likewise.
(cxx_eval_constant_expression): Add checks for outside lifetime
values. Remove local variables at end of bind exprs, and
temporaries after cleanup points.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime1.C: New test.
* g++.dg/cpp1y/constexpr-lifetime2.C: New test.
* g++.dg/cpp1y/constexpr-lifetime3.C: New test.
* g++.dg/cpp1y/constexpr-lifetime4.C: New test.
* g++.dg/cpp1y/constexpr-lifetime5.C: New test.
* g++.dg/cpp1y/constexpr-lifetime6.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 132 --
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime6.C|  15 ++
 7 files changed, 170 insertions(+), 45 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 6e8f1c2b61e..cd4424bcb44 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1148,7 +1148,8 @@ enum constexpr_switch_state {
 
 class constexpr_global_ctx {
   /* Values for any temporaries or local variables within the
- constant-expression. */
+ constant-expression. Objects outside their lifetime have
+ value 'void_node'.  */
   hash_map values;
 public:
   /* Number of cxx_eval_constant_expression calls (except skipped ones,
@@ -1170,17 +1171,28 @@ public:
 : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr),
   heap_dealloc_count (0) {}
 
+  bool is_outside_lifetime (tree t)
+  {
+if (tree *p = values.get(t))
+  if (*p == void_node)
+   return true;
+return false;
+  }
  tree get_value (tree t)
   {
 if (tree *p = values.get (t))
-  return *p;
+  if (*p != void_node)
+   return *p;
 return NULL_TREE;
   }
   tree *get_value_ptr (tree t)
   {
 if (modifiable && !modifiable->contains (t))
   return nullptr;
-return values.get (t);
+if (tree *p = values.get (t))
+  if (*p != void_node)
+   return p;
+return nullptr;
   }
   void put_value (tree t, tree v)
   {
@@ -1188,7 +1200,13 @@ public:
 if (!already_in_map && modifiable)
   modifiable->add (t);
   }
-  void remove_value (tree t) { values.remove (t); }
+  void remove_value (tree t)
+  {
+if (DECL_P (t))
+  values.put (t, void_node);
+else
+  values.remove (t);
+  }
 };
 
 /* Helper class for constexpr_global_ctx.  In some cases we want to avoid
@@ -3085,12 +3103,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  gcc_assert (!DECL_BY_REFERENCE (res));
  ctx->global->put_value (res, NULL_TREE);
 
- /* Track the callee's evaluated SAVE_EXPRs and TARGET_EXPRs so that
-we can forget their values after the call.  */
- constexpr_ctx ctx_with_save_exprs = *ctx;
- auto_vec save_exprs;
- ctx_with_save_exprs.save_exprs = &save_exprs;
- ctx_with_save_exprs.call = &new_call;
+ /* Remember the current call we're evaluating.  */
+ constexpr_ctx call_ctx = *ctx;
+ call_ctx.call = &new_call;
  unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
  unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
 
@@ -3101,7 +3116,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  non_constant_p, overflow_p);
 
  tree jump_target = NULL_TREE;
- cxx_eval_constant_expression (&ctx_with_save_exprs, body,
+ cxx_eval_constant_expressio

[PATCH v4 2/3] c++: Improve constexpr error for dangling local variables [PR110619]

2023-07-20 Thread Nathaniel Shead via Gcc-patches
Currently, when typeck discovers that a return statement will refer to a
local variable it rewrites to return a null pointer. This causes the
error messages for using the return value in a constant expression to be
unhelpful, especially for reference return values.

This patch removes this "optimisation". Relying on this raises a warning
by default and causes UB anyway, so there should be no issue in doing
so. We also suppress additional warnings from later passes that detect
this as a dangling pointer, since we've already indicated this anyway.

PR c++/110619

gcc/cp/ChangeLog:

* semantics.cc (finish_return_stmt): Suppress dangling pointer
reporting on return statement if already reported.
* typeck.cc (check_return_expr): Don't set return expression to
zero for dangling addresses.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime5.C: Test reported message is
correct.
* g++.dg/cpp1y/constexpr-lifetime6.C: Likewise.
* g++.dg/cpp1y/constexpr-110619.C: New test.
* g++.dg/warn/Wreturn-local-addr-6.C: Remove check for return
value optimisation.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/semantics.cc  |  5 -
 gcc/cp/typeck.cc |  5 +++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C| 10 ++
 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C |  4 ++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C |  8 
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C |  3 ---
 6 files changed, 23 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..107407de513 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -1260,7 +1260,10 @@ finish_return_stmt (tree expr)
 
   r = build_stmt (input_location, RETURN_EXPR, expr);
   if (no_warning)
-suppress_warning (r, OPT_Wreturn_type);
+{
+  suppress_warning (r, OPT_Wreturn_type);
+  suppress_warning (r, OPT_Wdangling_pointer_);
+}
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
 
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 859b133a18d..47233b3b717 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11273,8 +11273,9 @@ check_return_expr (tree retval, bool *no_warning)
   else if (!processing_template_decl
   && maybe_warn_about_returning_address_of_local (retval, loc)
   && INDIRECT_TYPE_P (valtype))
-   retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
-build_zero_cst (TREE_TYPE (retval)));
+   /* Suppress the Wdangling-pointer warning in the return statement
+  that would otherwise occur.  */
+   *no_warning = true;
 }
 
   /* A naive attempt to reduce the number of -Wdangling-reference false
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
new file mode 100644
index 000..cca13302238
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++14 } }
+// { dg-options "-Wno-return-local-addr" }
+// PR c++/110619
+
+constexpr auto f() {
+int i = 0;
+return &i;
+};
+
+static_assert( f() != nullptr );
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
index a4bc71d890a..ad3ef579f63 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
@@ -1,11 +1,11 @@
 // { dg-do compile { target c++14 } }
 // { dg-options "-Wno-return-local-addr" }
 
-constexpr const int& id(int x) { return x; }
+constexpr const int& id(int x) { return x; }  // { dg-message "note: declared 
here" }
 
 constexpr bool test() {
   const int& y = id(3);
   return y == 3;
 }
 
-constexpr bool x = test();  // { dg-error "" }
+constexpr bool x = test();  // { dg-error "accessing object outside its 
lifetime" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C
index f358aff4490..b81e89af79c 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C
@@ -4,12 +4,12 @@
 struct Empty {};
 
 constexpr const Empty& empty() {
-  return Empty{};
+  return Empty{};  // { dg-message "note: declared here" }
 }
 
-constexpr const Empty& empty_parm(Empty e) {
+constexpr const Empty& empty_parm(Empty e) {  // { dg-message "note: declared 
here" }
   return e;
 }
 
-constexpr Empty a = empty();  // { dg-error "" }
-constexpr Empty b = empty_parm({});  // { dg-error "" }
+constexpr Empty a = empty();  // { dg-error "accessing object outside its 
lifetime" }
+constexpr Empty b = empty_parm({});  // { dg-error "accessing object outside 
its lifetime" }
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C 
b/gcc/testsuite/g+

[PATCH v4 3/3] c++: Improve location information in constant evaluation

2023-07-20 Thread Nathaniel Shead via Gcc-patches
This patch updates 'input_location' during constant evaluation to ensure
that errors in subexpressions that lack location information still
provide accurate diagnostics.

By itself this change causes some small regressions in diagnostic
quality for circumstances where errors used 'input_location' but the
location of the parent subexpression doesn't make sense, so this patch
also includes a couple of other small diagnostic improvements to improve
the most egregious cases.

gcc/cp/ChangeLog:

* constexpr.cc (modifying_const_object_error): Find the source
location of the const object's declaration.
(cxx_eval_store_expression): Fall back to the location of the
target object when evaluating initialiser.
(cxx_eval_constant_expression): Update input_location to the location
of the currently evaluated expression, if possible.

libstdc++-v3/ChangeLog:

* testsuite/25_algorithms/equal/constexpr_neg.cc: Update diagnostic
locations.
* testsuite/26_numerics/gcd/105844.cc: Likewise.
* testsuite/26_numerics/lcm/105844.cc: Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-48089.C: Update diagnostic locations.
* g++.dg/cpp0x/constexpr-70323.C: Likewise.
* g++.dg/cpp0x/constexpr-70323a.C: Likewise.
* g++.dg/cpp0x/constexpr-delete2.C: Likewise.
* g++.dg/cpp0x/constexpr-diag3.C: Likewise.
* g++.dg/cpp0x/constexpr-ice20.C: Likewise.
* g++.dg/cpp0x/constexpr-recursion.C: Likewise.
* g++.dg/cpp0x/overflow1.C: Likewise.
* g++.dg/cpp1y/constexpr-89285.C: Likewise.
* g++.dg/cpp1y/constexpr-89481.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime1.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime2.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime3.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime4.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime5.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const14.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const16.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const18.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const19.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const21.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const22.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const3.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const4.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const7.C: Likewise.
* g++.dg/cpp1y/constexpr-union5.C: Likewise.
* g++.dg/cpp1y/pr68180.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda8.C: Likewise.
* g++.dg/cpp2a/bit-cast11.C: Likewise.
* g++.dg/cpp2a/bit-cast12.C: Likewise.
* g++.dg/cpp2a/bit-cast14.C: Likewise.
* g++.dg/cpp2a/constexpr-98122.C: Likewise.
* g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
* g++.dg/cpp2a/constexpr-init1.C: Likewise.
* g++.dg/cpp2a/constexpr-new12.C: Likewise.
* g++.dg/cpp2a/constexpr-new3.C: Likewise.
* g++.dg/cpp2a/constinit10.C: Likewise.
* g++.dg/cpp2a/is-corresponding-member4.C: Likewise.
* g++.dg/ext/constexpr-vla2.C: Likewise.
* g++.dg/ext/constexpr-vla3.C: Likewise.
* g++.dg/ubsan/pr63956.C: Likewise.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 46 ++-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 ++--
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C  |  8 ++--
 gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C |  8 ++--
 .../g++.dg/cpp0x/constexpr-delete2.C  |  5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  1 +
 .../g++.dg/cpp0x/constexpr-recursion.C|  6 +--
 gcc/testsuite/g++.dg/cpp0x/overflow1.C|  2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |  5 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  1 +
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  2 +-
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const14.C |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const16.C |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const18.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const19.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const21.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const22.C |  4 +-
 .../g++.dg/cpp1y/constexpr-tracking-const3.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const4.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-tracking-const7.C  |  3 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |  4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |  4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |  4 +-
 .../g++.dg/cpp1

Re: [PATCH v4 2/3] c++: Improve constexpr error for dangling local variables [PR110619]

2023-07-20 Thread Nathaniel Shead via Gcc-patches
On Thu, Jul 20, 2023 at 11:46:47AM -0400, Jason Merrill wrote:
> On 7/20/23 05:36, Nathaniel Shead wrote:
> > Currently, when typeck discovers that a return statement will refer to a
> > local variable it rewrites to return a null pointer. This causes the
> > error messages for using the return value in a constant expression to be
> > unhelpful, especially for reference return values.
> > 
> > This patch removes this "optimisation".
> 
> This isn't an optimization, it's for safety, removing a way for an attacker
> to get a handle on other data on the stack (CWE-562).
> 
> But I agree that we need to preserve some element of UB for constexpr
> evaluation to see.
> 
> Perhaps we want to move this transformation to cp_maybe_instrument_return,
> so it happens after maybe_save_constexpr_fundef?

Hm, OK. I can try giving this a go. I guess I should move the entire
maybe_warn_about_returning_address_of_local function to cp-gimplify.cc
to be able to detect this? Or is there a better way of marking that a
return expression will return a reference to a local for this
transformation? (I guess I can't use whether the warning has been
surpressed or not because the warning might not be enabled at all.)

It looks like this warning is raised also by diag_return_locals in
gimple-ssa-isolate-paths, should the transformation also be made here?

I note that the otherwise very similar -Wdangling-pointer warning
doesn't do this transformation either, should that also be something I
look into fixing here?

> > Relying on this raises a warning
> > by default and causes UB anyway, so there should be no issue in doing
> > so. We also suppress additional warnings from later passes that detect
> > this as a dangling pointer, since we've already indicated this anyway.
> > 
> > PR c++/110619
> > 
> > gcc/cp/ChangeLog:
> > 
> > * semantics.cc (finish_return_stmt): Suppress dangling pointer
> > reporting on return statement if already reported.
> > * typeck.cc (check_return_expr): Don't set return expression to
> > zero for dangling addresses.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp1y/constexpr-lifetime5.C: Test reported message is
> > correct.
> > * g++.dg/cpp1y/constexpr-lifetime6.C: Likewise.
> > * g++.dg/cpp1y/constexpr-110619.C: New test.
> > * g++.dg/warn/Wreturn-local-addr-6.C: Remove check for return
> > value optimisation.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >   gcc/cp/semantics.cc  |  5 -
> >   gcc/cp/typeck.cc |  5 +++--
> >   gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C| 10 ++
> >   gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C |  4 ++--
> >   gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime6.C |  8 
> >   gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C |  3 ---
> >   6 files changed, 23 insertions(+), 12 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
> > 
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 8fb47fd179e..107407de513 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -1260,7 +1260,10 @@ finish_return_stmt (tree expr)
> > r = build_stmt (input_location, RETURN_EXPR, expr);
> > if (no_warning)
> > -suppress_warning (r, OPT_Wreturn_type);
> > +{
> > +  suppress_warning (r, OPT_Wreturn_type);
> > +  suppress_warning (r, OPT_Wdangling_pointer_);
> > +}
> > r = maybe_cleanup_point_expr_void (r);
> > r = add_stmt (r);
> > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> > index 859b133a18d..47233b3b717 100644
> > --- a/gcc/cp/typeck.cc
> > +++ b/gcc/cp/typeck.cc
> > @@ -11273,8 +11273,9 @@ check_return_expr (tree retval, bool *no_warning)
> > else if (!processing_template_decl
> >&& maybe_warn_about_returning_address_of_local (retval, loc)
> >&& INDIRECT_TYPE_P (valtype))
> > -   retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
> > -build_zero_cst (TREE_TYPE (retval)));
> > +   /* Suppress the Wdangling-pointer warning in the return statement
> > +  that would otherwise occur.  */
> > +   *no_warning = true;
> >   }
> > /* A naive attempt to reduce the number of -Wdangling-reference false
> > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C 
> > b/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
> > new file mode 100644
> > index 000..cca13302238
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C
> > @@ -0,0 +1,10 @@
> > +// { dg-do compile { target c++14 } }
> > +// { dg-options "-Wno-return-local-addr" }
> > +// PR c++/110619
> > +
> > +constexpr auto f() {
> > +int i = 0;
> > +return &i;
> > +};
> > +
> > +static_assert( f() != nullptr );
> > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C 
> > b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
> > index a4bc71d890a..ad3ef579f63 100644
> > --- a/gcc/testsuite/g+

Re: [Ping][PATCH] libstdc++: Add missing functions to [PR79700]

2023-05-17 Thread Nathaniel Shead via Gcc-patches
Now that GCC13.1 is released is it ok to merge? Thanks!

On Tue, Apr 18, 2023 at 6:48 PM Jonathan Wakely  wrote:
>
> On Mon, 17 Apr 2023 at 09:11, Nathaniel Shead  
> wrote:
> >
> > Hi, just checking whether there were any issues with this patch?
> > https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612386.html
> >
> > Otherwise I assume it won't be in GCC13.
>
> That's right, it's too large and invasive a change to get into GCC 13
> when only submitted in February, sorry. I'll merge it to trunk once
> GCC 13.1 is released though.
>


Re: [Ping][PATCH] libstdc++: Add missing functions to [PR79700]

2023-05-17 Thread Nathaniel Shead via Gcc-patches
On Wed, May 17, 2023 at 10:05:59AM +0100, Jonathan Wakely wrote:
> On Wed, 17 May 2023 at 09:37, Nathaniel Shead wrote:
> 
> > Now that GCC13.1 is released is it ok to merge? Thanks!
> >
> 
> Yes, I've been testing this locally, but I think it needs more work (sorry!)
> 
> Looking at it again, I'm not sure why I asked for the additional tests
> because if they fail, it's a problem in libc, and there's nothing we can
> actually do about it in libstdc++. We certainly do want std::expl(0.0L) to
> return the same thing as std::exp(0.0L), but if it doesn't, we'll just have
> a libstdc++ test failure caused by a bug in libc. But you wrote the test
> now, so let's keep it. If we get failures for the test it will allow us to
> inform the relevant libc maintainers that they have a bug.

Sounds good.

> Also, since you're contributing this under the DCO terms the new test
> should not have the FSF copyright header, unless it's a derived work of an
> existing test with that header (and in that case it should retain the dates
> from the copied test). I don't actually bother putting the copyright and
> license header on new tests these days. There's nothing in that test that
> is novel or interesting, and I think it's arguably not useful or meaningful
> to consider it copyrighted.

Makes sense, I was just copying from other tests in the directory. I'll
keep this in mind for the future, thanks!

> Finally, and most importantly, the new using-declarations in  are
> not guarded by any autoconf macro. That will break targets without full C99
>  support, e.g. djgpp declares acosf but not acosl, so the new
> "using acosl;" would be a hard error as soon as  is included (and
> might even prevent GCC building on that target). So I think we need a new
> autoconf check for the existence of those functions. I'm in the process of
> reworking the autoconf macros for  (due to PR 109818), which is why
> I didn't address it for this patch yet.

Ah, I see; yes, that would be a problem. I'm not very familiar with
autoconf, so thanks for working this out. Let me know when you've done
that if there's anything else I should do for this patch.

> >
> > On Tue, Apr 18, 2023 at 6:48 PM Jonathan Wakely 
> > wrote:
> > >
> > > On Mon, 17 Apr 2023 at 09:11, Nathaniel Shead 
> > wrote:
> > > >
> > > > Hi, just checking whether there were any issues with this patch?
> > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612386.html
> > > >
> > > > Otherwise I assume it won't be in GCC13.
> > >
> > > That's right, it's too large and invasive a change to get into GCC 13
> > > when only submitted in February, sorry. I'll merge it to trunk once
> > > GCC 13.1 is released though.
> > >
> >
> >


ping: [PATCH] c++: Fix ICE with parameter pack of decltype(auto) [PR103497]

2023-05-27 Thread Nathaniel Shead via Gcc-patches
Ping: https://gcc.gnu.org/pipermail/gcc-patches/2023-April/616465.html

On Sat, Apr 22, 2023 at 04:25:13PM +1000, Nathaniel Shead wrote:
> Bootstrapped and tested on x86_64-pc-linux-gnu.
> 
> -- 8< --
> 
> This patch raises an error early when the decltype(auto) specifier is
> used as a parameter of a function. This prevents any issues with an
> unexpected tree type later on when performing the call.
> 
>   PR 103497
> 
> gcc/cp/ChangeLog:
> 
>   * parser.cc (cp_parser_simple_type_specifier): Add check for
>   decltype(auto) as function parameter.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/pr103497.C: New test.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/parser.cc| 10 ++
>  gcc/testsuite/g++.dg/pr103497.C |  7 +++
>  2 files changed, 17 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/pr103497.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index e5f032f2330..1415e07e152 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -19884,6 +19884,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
>&& cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
>  {
>type = saved_checks_value (token->u.tree_check_value);
> +  /* Within a function parameter declaration, decltype(auto) is always an
> +  error.  */
> +  if (parser->auto_is_implicit_function_template_parm_p
> +   && TREE_CODE (type) == TEMPLATE_TYPE_PARM
> +   && AUTO_IS_DECLTYPE (type))
> + {
> +   error_at (token->location,
> + "cannot declare a parameter with %");
> +   type = error_mark_node;
> + }
>if (decl_specs)
>   {
> cp_parser_set_decl_spec_type (decl_specs, type,
> diff --git a/gcc/testsuite/g++.dg/pr103497.C b/gcc/testsuite/g++.dg/pr103497.C
> new file mode 100644
> index 000..bcd421c2907
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr103497.C
> @@ -0,0 +1,7 @@
> +// { dg-do compile { target c++14 } }
> +
> +void foo(decltype(auto)... args);  // { dg-error "parameter with 
> .decltype.auto..|no parameter packs" }
> +
> +int main() {
> +  foo();
> +}
> -- 
> 2.34.1
> 


ping: [PATCH] c++: Report invalid id-expression in decltype [PR100482]

2023-05-27 Thread Nathaniel Shead via Gcc-patches
Ping: https://gcc.gnu.org/pipermail/gcc-patches/2023-April/617145.html

Also it looks like I forgot to mention, but this patch was bootstrapped
and regtested on x86_64-pc-linux-gnu.

On Sun, Apr 30, 2023 at 12:00:05PM +1000, Nathaniel Shead wrote:
> This patch ensures that any errors raised by finish_id_expression when
> parsing a decltype expression are properly reported, rather than
> potentially going ignored and causing invalid code to be accepted.
> 
> We can also now remove the separate check for templates without args as
> this is also checked for in finish_id_expression.
> 
>   PR 100482
> 
> gcc/cp/ChangeLog:
> 
>   * parser.cc (cp_parser_decltype_expr): Report errors raised by
>   finish_id_expression.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/pr100482.C: New test.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/parser.cc| 22 +++---
>  gcc/testsuite/g++.dg/pr100482.C | 11 +++
>  2 files changed, 22 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/pr100482.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index e5f032f2330..20ebcdc3cfd 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -16508,10 +16508,6 @@ cp_parser_decltype_expr (cp_parser *parser,
>   expr = cp_parser_lookup_name_simple (parser, expr,
>id_expr_start_token->location);
>  
> -  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)
> - /* A template without args is not a complete id-expression.  */
> - expr = error_mark_node;
> -
>if (expr
>&& expr != error_mark_node
>&& TREE_CODE (expr) != TYPE_DECL
> @@ -16532,13 +16528,17 @@ cp_parser_decltype_expr (cp_parser *parser,
> &error_msg,
>  id_expr_start_token->location));
>  
> -  if (expr == error_mark_node)
> -/* We found an id-expression, but it was something that we
> -   should not have found. This is an error, not something
> -   we can recover from, so note that we found an
> -   id-expression and we'll recover as gracefully as
> -   possible.  */
> -id_expression_or_member_access_p = true;
> +   if (error_msg)
> + {
> +   /* We found an id-expression, but it was something that we
> +  should not have found. This is an error, not something
> +  we can recover from, so report the error we found and
> +  we'll recover as gracefully as possible.  */
> +   cp_parser_parse_definitely (parser);
> +   cp_parser_error (parser, error_msg);
> +   id_expression_or_member_access_p = true;
> +   return error_mark_node;
> + }
>  }
>  
>if (expr
> diff --git a/gcc/testsuite/g++.dg/pr100482.C b/gcc/testsuite/g++.dg/pr100482.C
> new file mode 100644
> index 000..dcf6722fda5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr100482.C
> @@ -0,0 +1,11 @@
> +// { dg-do compile { target c++11 } }
> +
> +namespace N {}
> +decltype(std) x;   // { dg-error "expected primary-expression" }
> +
> +struct S {};
> +decltype(S) y;  // { dg-error "argument to .decltype. must be an expression" 
> }
> +
> +template 
> +struct U {};
> +decltype(U) z;  // { dg-error "missing template arguments" }
> -- 
> 2.40.0
> 


[PATCH 3/3] c++: Improve location information in constexpr evaluation

2023-03-28 Thread Nathaniel Shead via Gcc-patches
This patch caches the current expression's location information in the
constexpr_global_ctx struct, which allows subexpressions that have lost
location information to still provide accurate diagnostics. Also
rewrites a number of  'error' calls as 'error_at' to provide more
specific location information.

The primary effect of this change is that many errors within evaluation
of a constexpr function will now point at the offending expression (with
expansion tracing information) rather than just the outermost call.

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx): New field for cached
tree location, defaulting to input_location.
(cxx_eval_internal_function): Fall back to ctx->global->loc
rather than input_location.
(modifying_const_object_error): Likewise.
(cxx_eval_dynamic_cast_fn): Likewise.
(eval_and_check_array_index): Likewise.
(cxx_eval_array_reference): Likewise.
(cxx_eval_bit_field_ref): Likewise.
(cxx_eval_component_reference): Likewise.
(cxx_eval_indirect_ref): Likewise.
(cxx_eval_store_expression): Likewise.
(cxx_eval_increment_expression): Likewise.
(cxx_eval_loop_expr): Likewise.
(cxx_eval_binary_expression): Likewise.
(cxx_eval_constant_expression): Cache location of trees for use
in errors, and prefer it instead of input_location.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-48089.C: Updated diagnostic locations.
* g++.dg/cpp0x/constexpr-diag3.C: Likewise.
* g++.dg/cpp0x/constexpr-ice20.C: Likewise.
* g++.dg/cpp1y/constexpr-89481.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime1.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime2.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime3.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime4.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime5.C: Likewise.
* g++.dg/cpp1y/constexpr-union5.C: Likewise.
* g++.dg/cpp1y/pr68180.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
* g++.dg/cpp2a/bit-cast11.C: Likewise.
* g++.dg/cpp2a/bit-cast12.C: Likewise.
* g++.dg/cpp2a/bit-cast14.C: Likewise.
* g++.dg/cpp2a/constexpr-98122.C: Likewise.
* g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
* g++.dg/cpp2a/constexpr-init1.C: Likewise.
* g++.dg/cpp2a/constexpr-new12.C: Likewise.
* g++.dg/cpp2a/constexpr-new3.C: Likewise.
* g++.dg/ext/constexpr-vla2.C: Likewise.
* g++.dg/ext/constexpr-vla3.C: Likewise.
* g++.dg/ubsan/pr63956.C: Likewise.

libstdc++/ChangeLog:

* testsuite/25_algorithms/equal/constexpr_neg.cc: Updated
diagnostics locations.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 83 +++
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 +--
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  4 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  1 +
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  2 +-
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  4 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |  4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |  4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |  4 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   | 10 +--
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   | 10 +--
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   | 14 ++--
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |  4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|  5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |  5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |  6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   | 10 +--
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |  4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |  4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |  4 +-
 .../25_algorithms/equal/constexpr_neg.cc  |  7 +-
 25 files changed, 111 insertions(+), 101 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 28e3f891fb8..31884220b4e 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1165,10 +1165,12 @@ public:
   hash_set *modifiable;
   /* Number of heap VAR_DECL deallocations.  */
   unsigned heap_dealloc_count;
+  /* Current location in case subtree has no location information.  */
+  location_t loc;
   /* Constructor.  */
   constexpr_global_ctx ()
 : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr),
-  heap_dealloc_count (0) {}
+  heap_dealloc_count (0), loc (input_location) {}
 
  tree get_value (tree t)
   {
@@ -2108,7 +2110,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, 
tree t,
 
 default:
   if (!ctx->quiet)
-  

[PATCH 0/3] Track lifetimes in constant evaluation [PR70331,...]

2023-03-28 Thread Nathaniel Shead via Gcc-patches
The first patch fixes PR70331, PR96630, and PR98675 regarding
constexpr evaluation not correctly diagnosing uses of dangling
references and pointers. The following two patches clean up and improve
some of the errors that are generated by this change, but aren't
strictly necessary.

This is my first change to the frontend, so any feedback is welcome. In
particular, I'm not sure if the way I went about the fix was correct:
for simplicity and efficiency's sake I added a new flag to
tree_decl_common, but this feels somewhat overkill for what is otherwise
a very locally useful property. 

Another option here would be to add a new lookup table to
constexpr_global_ctx which tracks what decls are in lifetime, but I
expect that to negatively impact performance. I haven't done any
benchmarks on this however.

Bootstrapped and regression tested on x86_64 linux.

---

Nathaniel Shead (3):
  c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]
  c++: Improve constexpr error for dangling local variables
  c++: Improve location information in constexpr evaluation

 gcc/cp/constexpr.cc   | 149 --
 gcc/cp/module.cc  |   2 +
 gcc/cp/semantics.cc   |   5 +-
 gcc/cp/typeck.cc  |   5 +-
 gcc/print-tree.cc |   4 +
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  14 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |   4 +-
 .../g++.dg/warn/Wreturn-local-addr-6.C|   3 -
 gcc/tree-core.h   |   5 +-
 gcc/tree.h|   6 +
 .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
 32 files changed, 247 insertions(+), 113 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C

-- 
2.34.1



[PATCH 1/3] c++: Track lifetimes in constant evaluation [PR70331, PR96630, PR98675]

2023-03-28 Thread Nathaniel Shead via Gcc-patches
This adds rudimentary lifetime tracking in C++ constexpr contexts,
allowing the compiler to report errors with using values after their
backing has gone out of scope. We don't yet handle other ways of ending
lifetimes (e.g. explicit destructor calls).

PR c++/70331
PR c++/96630
PR c++/98675

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx::put_value): Mark value as
in lifetime.
(constexpr_global_ctx::remove_value): Mark value as expired.
(cxx_eval_call_expression): Remove comment that is no longer
applicable.
(non_const_var_error): Add check for expired values.
(cxx_eval_constant_expression): Add checks for expired values.
Forget local variables at end of bind expressions. Forget
temporaries at end of cleanup points.
* module.cc (trees_out::core_bools): Write out the new flag.
(trees_in::core_bools): Read in the new flag.

gcc/ChangeLog:

* tree-core.h (struct tree_decl_common): New flag to check if
value lifetime has expired.
* tree.h (DECL_EXPIRED): Access the new flag.
* print-tree.cc (print_node): Print the new flag.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-ice20.C: Update error raised by test.
* g++.dg/cpp1y/constexpr-lifetime1.C: New test.
* g++.dg/cpp1y/constexpr-lifetime2.C: New test.
* g++.dg/cpp1y/constexpr-lifetime3.C: New test.
* g++.dg/cpp1y/constexpr-lifetime4.C: New test.
* g++.dg/cpp1y/constexpr-lifetime5.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 66 +++
 gcc/cp/module.cc  |  2 +
 gcc/print-tree.cc |  4 ++
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  2 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C| 13 
 .../g++.dg/cpp1y/constexpr-lifetime2.C| 20 ++
 .../g++.dg/cpp1y/constexpr-lifetime3.C| 13 
 .../g++.dg/cpp1y/constexpr-lifetime4.C| 11 
 .../g++.dg/cpp1y/constexpr-lifetime5.C| 11 
 gcc/tree-core.h   |  5 +-
 gcc/tree.h|  6 ++
 11 files changed, 138 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 3de60cfd0f8..28e3f891fb8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1185,10 +1185,17 @@ public:
   void put_value (tree t, tree v)
   {
 bool already_in_map = values.put (t, v);
+if (!already_in_map && DECL_P (t))
+  DECL_EXPIRED (t) = false;
 if (!already_in_map && modifiable)
   modifiable->add (t);
   }
-  void remove_value (tree t) { values.remove (t); }
+  void remove_value (tree t)
+  {
+if (DECL_P (t))
+  DECL_EXPIRED (t) = true;
+values.remove (t);
+  }
 };
 
 /* Helper class for constexpr_global_ctx.  In some cases we want to avoid
@@ -3157,10 +3164,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  for (tree save_expr : save_exprs)
ctx->global->remove_value (save_expr);
 
- /* Remove the parms/result from the values map.  Is it worth
-bothering to do this when the map itself is only live for
-one constexpr evaluation?  If so, maybe also clear out
-other vars from call, maybe in BIND_EXPR handling?  */
+ /* Remove the parms/result from the values map.  */
  ctx->global->remove_value (res);
  for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
ctx->global->remove_value (parm);
@@ -5708,6 +5712,13 @@ non_const_var_error (location_t loc, tree r, bool 
fundef_p)
inform (DECL_SOURCE_LOCATION (r), "allocated here");
   return;
 }
+  if (DECL_EXPIRED (r))
+{
+  if (constexpr_error (loc, fundef_p, "accessing object outside its "
+  "lifetime"))
+   inform (DECL_SOURCE_LOCATION (r), "declared here");
+  return;
+}
   if (!constexpr_error (loc, fundef_p, "the value of %qD is not usable in "
"a constant expression", r))
 return;
@@ -6995,7 +7006,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
   else
{
  if (!ctx->quiet)
-   error ("%qE is not a constant expression", t);
+   non_const_var_error (loc, t, /*fundef_p*/false);
  *non_constant_p = true;
}
   break;
@@ -7048,6 +7059,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
  r = build_constructor (TREE_TYPE (t), NULL);
  TREE_CONSTANT (r) = 

[PATCH 2/3] c++: Improve constexpr error for dangling local variables

2023-03-28 Thread Nathaniel Shead via Gcc-patches
Currently, when typeck discovers that a return statement will refer to a
local variable it rewrites to return a null pointer. This causes the
error messages for using the return value in a constant expression to be
unhelpful, especially for reference return values.

This patch removes this "optimisation". Relying on this raises a warning
by default and causes UB anyway, so there should be no issue in doing
so. We also suppress additional warnings from later passes that detect
this as a dangling pointer, since we've already indicated this anyway.

gcc/cp/ChangeLog:

* semantics.cc (finish_return_stmt): Suppress dangling pointer
reporting on return statement if already reported.
* typeck.cc (check_return_expr): Don't set return expression to
zero for dangling addresses.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime5.C: Test reported message is
correct.
* g++.dg/warn/Wreturn-local-addr-6.C: Remove check for return
value optimisation.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/semantics.cc  | 5 -
 gcc/cp/typeck.cc | 5 +++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C | 4 ++--
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C | 3 ---
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 87c2e8a7111..14b4b7f4ce1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -1246,7 +1246,10 @@ finish_return_stmt (tree expr)
 
   r = build_stmt (input_location, RETURN_EXPR, expr);
   if (no_warning)
-suppress_warning (r, OPT_Wreturn_type);
+{
+  suppress_warning (r, OPT_Wreturn_type);
+  suppress_warning (r, OPT_Wdangling_pointer_);
+}
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
 
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index afb956087ce..a7d642e2029 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11235,8 +11235,9 @@ check_return_expr (tree retval, bool *no_warning)
   else if (!processing_template_decl
   && maybe_warn_about_returning_address_of_local (retval, loc)
   && INDIRECT_TYPE_P (valtype))
-   retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
-build_zero_cst (TREE_TYPE (retval)));
+   /* Suppress the Wdangling-pointer warning in the return statement
+  that would otherwise occur.  */
+   *no_warning = true;
 }
 
   if (processing_template_decl)
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
index a4bc71d890a..ad3ef579f63 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
@@ -1,11 +1,11 @@
 // { dg-do compile { target c++14 } }
 // { dg-options "-Wno-return-local-addr" }
 
-constexpr const int& id(int x) { return x; }
+constexpr const int& id(int x) { return x; }  // { dg-message "note: declared 
here" }
 
 constexpr bool test() {
   const int& y = id(3);
   return y == 3;
 }
 
-constexpr bool x = test();  // { dg-error "" }
+constexpr bool x = test();  // { dg-error "accessing object outside its 
lifetime" }
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C 
b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
index fae8b7e766f..ec8e241d83e 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
@@ -24,6 +24,3 @@ return_addr_local_as_intref (void)
 
   return (const intptr_t&)a;   // { dg-warning "\\\[-Wreturn-local-addr]" } */
 }
-
-/* Verify that the return value has been replaced with zero:
-  { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
-- 
2.34.1



Re: [PATCH 1/3] c++: Track lifetimes in constant evaluation [PR70331, PR96630, PR98675]

2023-03-28 Thread Nathaniel Shead via Gcc-patches
On Tue, Mar 28, 2023 at 10:50 PM Jakub Jelinek  wrote:
>
> On Tue, Mar 28, 2023 at 10:32:28PM +1100, Nathaniel Shead via Gcc-patches 
> wrote:
> >   * tree-core.h (struct tree_decl_common): New flag to check if
> > value lifetime has expired.
> >   * tree.h (DECL_EXPIRED): Access the new flag.
> >   * print-tree.cc (print_node): Print the new flag.
> > --- a/gcc/tree-core.h
> > +++ b/gcc/tree-core.h
> > @@ -1834,7 +1834,10 @@ struct GTY(()) tree_decl_common {
> >/* In FIELD_DECL, this is DECL_NOT_FLEXARRAY.  */
> >unsigned int decl_not_flexarray : 1;
> >
> > -  /* 13 bits unused.  */
> > +  /* In VAR_DECL, PARM_DECL, or RESULT_DECL, this is DECL_EXPIRED.  */
> > +  unsigned int decl_expired_flag : 1;
> > +
> > +  /* 12 bits unused.  */
> >
> >/* UID for points-to sets, stable over copying from inlining.  */
> >unsigned int pt_uid;
> > --- a/gcc/tree.h
> > +++ b/gcc/tree.h
> > @@ -2697,6 +2697,12 @@ extern tree vector_element_bits_tree (const_tree);
> > ??? Need to figure out some way to check this isn't a PARM_DECL.  */
> >  #define DECL_INITIAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.initial)
> >
> > +/* Used in a VAR_DECL, PARM_DECL, or RESULT_DECL to indicate whether
> > +   this declaration is currently in lifetime for constant evaluation
> > +   purposes.  */
> > +#define DECL_EXPIRED(NODE) \
> > +  (DECL_COMMON_CHECK(NODE)->decl_common.decl_expired_flag)
> > +
> >  /* Holds the size of the datum, in bits, as a tree expression.
> > Need not be constant and may be null.  May be less than TYPE_SIZE
> > for a C++ FIELD_DECL representing a base class subobject with its
>
> While it is true that tree_decl_common has some spare bits, this support
> is for an implementation detail of the C++ FE and as such, I think it is
> highly preferred to use some bit in the lang specific data structures
> rather than wasting bits that we could need later on for things that will
> be needed in the middle-end.
> struct lang_decl_base I think also has 12 spare bits...
>
> Rest I'll defer to C++ maintainers (also whether this is appropriate now
> or should be deferred for GCC 14 stage1).
>
> Jakub
>

Thanks, I didn't notice that there were lang specific data structures;
I'll take a look at using that instead.

>From my point of view I was expecting this would be too late for GCC13
(especially since it should only affect already invalid code, and the
risk of false positives), but I'm happy either way.


[PATCH v2 2/3] c++: Improve constexpr error for dangling local variables

2023-03-28 Thread Nathaniel Shead via Gcc-patches
Currently, when typeck discovers that a return statement will refer to a
local variable it rewrites to return a null pointer. This causes the
error messages for using the return value in a constant expression to be
unhelpful, especially for reference return values.

This patch removes this "optimisation". Relying on this raises a warning
by default and causes UB anyway, so there should be no issue in doing
so. We also suppress additional warnings from later passes that detect
this as a dangling pointer, since we've already indicated this anyway.

gcc/cp/ChangeLog:

* semantics.cc (finish_return_stmt): Suppress dangling pointer
reporting on return statement if already reported.
* typeck.cc (check_return_expr): Don't set return expression to
zero for dangling addresses.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-lifetime5.C: Test reported message is
correct.
* g++.dg/warn/Wreturn-local-addr-6.C: Remove check for return
value optimisation.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/semantics.cc  | 5 -
 gcc/cp/typeck.cc | 5 +++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C | 4 ++--
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C | 3 ---
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 87c2e8a7111..14b4b7f4ce1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -1246,7 +1246,10 @@ finish_return_stmt (tree expr)
 
   r = build_stmt (input_location, RETURN_EXPR, expr);
   if (no_warning)
-suppress_warning (r, OPT_Wreturn_type);
+{
+  suppress_warning (r, OPT_Wreturn_type);
+  suppress_warning (r, OPT_Wdangling_pointer_);
+}
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
 
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index afb956087ce..a7d642e2029 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11235,8 +11235,9 @@ check_return_expr (tree retval, bool *no_warning)
   else if (!processing_template_decl
   && maybe_warn_about_returning_address_of_local (retval, loc)
   && INDIRECT_TYPE_P (valtype))
-   retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
-build_zero_cst (TREE_TYPE (retval)));
+   /* Suppress the Wdangling-pointer warning in the return statement
+  that would otherwise occur.  */
+   *no_warning = true;
 }
 
   if (processing_template_decl)
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
index a4bc71d890a..ad3ef579f63 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
@@ -1,11 +1,11 @@
 // { dg-do compile { target c++14 } }
 // { dg-options "-Wno-return-local-addr" }
 
-constexpr const int& id(int x) { return x; }
+constexpr const int& id(int x) { return x; }  // { dg-message "note: declared 
here" }
 
 constexpr bool test() {
   const int& y = id(3);
   return y == 3;
 }
 
-constexpr bool x = test();  // { dg-error "" }
+constexpr bool x = test();  // { dg-error "accessing object outside its 
lifetime" }
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C 
b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
index fae8b7e766f..ec8e241d83e 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
@@ -24,6 +24,3 @@ return_addr_local_as_intref (void)
 
   return (const intptr_t&)a;   // { dg-warning "\\\[-Wreturn-local-addr]" } */
 }
-
-/* Verify that the return value has been replaced with zero:
-  { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
-- 
2.34.1



[PATCH v2 0/3] c++: Track lifetimes in constant evaluation [PR70331, ...]

2023-03-28 Thread Nathaniel Shead via Gcc-patches
This is an update of the patch series at
https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614759.html

The main change is modifying the first patch to store the "expired" flag
in the C++-specific lang_decl_base struct instead of tree_decl_common.
The second and third patches to improve diagnostic locations are
otherwise unchanged.

Bootstrapped and regression tested on x86_64 linux.

Nathaniel

---

Nathaniel Shead (3):
  c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]
  c++: Improve constexpr error for dangling local variables
  c++: Improve location information in constexpr evaluation

 gcc/cp/constexpr.cc   | 152 --
 gcc/cp/cp-tree.h  |  10 +-
 gcc/cp/module.cc  |   2 +
 gcc/cp/semantics.cc   |   5 +-
 gcc/cp/typeck.cc  |   5 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  14 ++
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |   4 +-
 .../g++.dg/warn/Wreturn-local-addr-6.C|   3 -
 .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
 30 files changed, 246 insertions(+), 112 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C

-- 
2.34.1



[PATCH v2 1/3] c++: Track lifetimes in constant evaluation [PR70331, PR96630, PR98675]

2023-03-28 Thread Nathaniel Shead via Gcc-patches
This adds rudimentary lifetime tracking in C++ constexpr contexts,
allowing the compiler to report errors with using values after their
backing has gone out of scope. We don't yet handle other ways of ending
lifetimes (e.g. explicit destructor calls).

PR c++/96630
PR c++/98675
PR c++/70331

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx::put_value): Mark value as
in lifetime.
(constexpr_global_ctx::remove_value): Mark value as expired.
(cxx_eval_call_expression): Remove comment that is no longer
applicable.
(non_const_var_error): Add check for expired values.
(cxx_eval_constant_expression): Add checks for expired values. Forget
local variables at end of bind expressions. Forget temporaries at end
of cleanup points.
* cp-tree.h (struct lang_decl_base): New flag to track expired values
in constant evaluation.
(DECL_EXPIRED_P): Access the new flag.
(SET_DECL_EXPIRED_P): Modify the new flag.
* module.cc (trees_out::lang_decl_bools): Write out the new flag.
(trees_in::lang_decl_bools): Read in the new flag.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-ice20.C: Update error raised by test.
* g++.dg/cpp1y/constexpr-lifetime1.C: New test.
* g++.dg/cpp1y/constexpr-lifetime2.C: New test.
* g++.dg/cpp1y/constexpr-lifetime3.C: New test.
* g++.dg/cpp1y/constexpr-lifetime4.C: New test.
* g++.dg/cpp1y/constexpr-lifetime5.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 69 +++
 gcc/cp/cp-tree.h  | 10 ++-
 gcc/cp/module.cc  |  2 +
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  2 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C| 13 
 .../g++.dg/cpp1y/constexpr-lifetime2.C| 20 ++
 .../g++.dg/cpp1y/constexpr-lifetime3.C| 13 
 .../g++.dg/cpp1y/constexpr-lifetime4.C| 11 +++
 .../g++.dg/cpp1y/constexpr-lifetime5.C| 11 +++
 9 files changed, 137 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 3de60cfd0f8..bdbc12144a7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1185,10 +1185,22 @@ public:
   void put_value (tree t, tree v)
   {
 bool already_in_map = values.put (t, v);
+if (!already_in_map && DECL_P (t))
+  {
+   if (!DECL_LANG_SPECIFIC (t))
+ retrofit_lang_decl (t);
+   if (DECL_LANG_SPECIFIC (t))
+ SET_DECL_EXPIRED_P (t, false);
+  }
 if (!already_in_map && modifiable)
   modifiable->add (t);
   }
-  void remove_value (tree t) { values.remove (t); }
+  void remove_value (tree t)
+  {
+if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+  SET_DECL_EXPIRED_P (t, true);
+values.remove (t);
+  }
 };
 
 /* Helper class for constexpr_global_ctx.  In some cases we want to avoid
@@ -3157,10 +3169,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  for (tree save_expr : save_exprs)
ctx->global->remove_value (save_expr);
 
- /* Remove the parms/result from the values map.  Is it worth
-bothering to do this when the map itself is only live for
-one constexpr evaluation?  If so, maybe also clear out
-other vars from call, maybe in BIND_EXPR handling?  */
+ /* Remove the parms/result from the values map.  */
  ctx->global->remove_value (res);
  for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
ctx->global->remove_value (parm);
@@ -5708,6 +5717,13 @@ non_const_var_error (location_t loc, tree r, bool 
fundef_p)
inform (DECL_SOURCE_LOCATION (r), "allocated here");
   return;
 }
+  if (DECL_EXPIRED_P (r))
+{
+  if (constexpr_error (loc, fundef_p, "accessing object outside its "
+  "lifetime"))
+   inform (DECL_SOURCE_LOCATION (r), "declared here");
+  return;
+}
   if (!constexpr_error (loc, fundef_p, "the value of %qD is not usable in "
"a constant expression", r))
 return;
@@ -7048,6 +7064,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
  r = build_constructor (TREE_TYPE (t), NULL);
  TREE_CONSTANT (r) = true;
}
+  else if (DECL_EXPIRED_P (t))
+   {
+ if (!ctx->quiet)
+   non_const_var_error (loc, r, /*fundef_p*/false);
+ *non_constant_p = true;
+ break;
+   }
   else if (ctx->strict)
r = decl_really_constant_valu

[PATCH v2 3/3] c++: Improve location information in constexpr evaluation

2023-03-28 Thread Nathaniel Shead via Gcc-patches
This patch caches the current expression's location information in the
constexpr_global_ctx struct, which allows subexpressions that have lost
location information to still provide accurate diagnostics. Also
rewrites a number of 'error' calls as 'error_at' to provide more
specific location information.

The primary effect of this change is that many errors within evaluation
of a constexpr function will now point at the offending expression (with
expansion tracing information) rather than just the outermost call.

gcc/cp/ChangeLog:

* constexpr.cc (constexpr_global_ctx): New field for cached
tree location, defaulting to input_location.
(cxx_eval_internal_function): Fall back to ctx->global->loc
rather than input_location.
(modifying_const_object_error): Likewise.
(cxx_eval_dynamic_cast_fn): Likewise.
(eval_and_check_array_index): Likewise.
(cxx_eval_array_reference): Likewise.
(cxx_eval_bit_field_ref): Likewise.
(cxx_eval_component_reference): Likewise.
(cxx_eval_indirect_ref): Likewise.
(cxx_eval_store_expression): Likewise.
(cxx_eval_increment_expression): Likewise.
(cxx_eval_loop_expr): Likewise.
(cxx_eval_binary_expression): Likewise.
(cxx_eval_constant_expression): Cache location of trees for use
in errors, and prefer it instead of input_location.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-48089.C: Updated diagnostic locations.
* g++.dg/cpp0x/constexpr-diag3.C: Likewise.
* g++.dg/cpp0x/constexpr-ice20.C: Likewise.
* g++.dg/cpp1y/constexpr-89481.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime1.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime2.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime3.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime4.C: Likewise.
* g++.dg/cpp1y/constexpr-lifetime5.C: Likewise.
* g++.dg/cpp1y/constexpr-union5.C: Likewise.
* g++.dg/cpp1y/pr68180.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
* g++.dg/cpp2a/bit-cast11.C: Likewise.
* g++.dg/cpp2a/bit-cast12.C: Likewise.
* g++.dg/cpp2a/bit-cast14.C: Likewise.
* g++.dg/cpp2a/constexpr-98122.C: Likewise.
* g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
* g++.dg/cpp2a/constexpr-init1.C: Likewise.
* g++.dg/cpp2a/constexpr-new12.C: Likewise.
* g++.dg/cpp2a/constexpr-new3.C: Likewise.
* g++.dg/ext/constexpr-vla2.C: Likewise.
* g++.dg/ext/constexpr-vla3.C: Likewise.
* g++.dg/ubsan/pr63956.C: Likewise.

libstdc++/ChangeLog:

* testsuite/25_algorithms/equal/constexpr_neg.cc: Updated
diagnostics locations.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/constexpr.cc   | 83 +++
 gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  | 10 +--
 gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |  4 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |  3 +-
 .../g++.dg/cpp1y/constexpr-lifetime1.C|  1 +
 .../g++.dg/cpp1y/constexpr-lifetime2.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime3.C|  4 +-
 .../g++.dg/cpp1y/constexpr-lifetime4.C|  2 +-
 .../g++.dg/cpp1y/constexpr-lifetime5.C|  4 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |  4 +-
 gcc/testsuite/g++.dg/cpp1y/pr68180.C  |  4 +-
 .../g++.dg/cpp1z/constexpr-lambda6.C  |  4 +-
 gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   | 10 +--
 gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   | 10 +--
 gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   | 14 ++--
 gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |  4 +-
 .../g++.dg/cpp2a/constexpr-dynamic17.C|  5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |  5 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |  6 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   | 10 +--
 gcc/testsuite/g++.dg/ext/constexpr-vla2.C |  4 +-
 gcc/testsuite/g++.dg/ext/constexpr-vla3.C |  4 +-
 gcc/testsuite/g++.dg/ubsan/pr63956.C  |  4 +-
 .../25_algorithms/equal/constexpr_neg.cc  |  7 +-
 25 files changed, 111 insertions(+), 101 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index bdbc12144a7..74045477a92 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1165,10 +1165,12 @@ public:
   hash_set *modifiable;
   /* Number of heap VAR_DECL deallocations.  */
   unsigned heap_dealloc_count;
+  /* Current location in case subtree has no location information.  */
+  location_t loc;
   /* Constructor.  */
   constexpr_global_ctx ()
 : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr),
-  heap_dealloc_count (0) {}
+  heap_dealloc_count (0), loc (input_location) {}
 
  tree get_value (tree t)
   {
@@ -2113,7 +2115,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, 
tree t,
 
 default:
   if (!ctx->quiet)
-   

[Ping][PATCH] libstdc++: Add missing functions to [PR79700]

2023-04-17 Thread Nathaniel Shead via Gcc-patches
Hi, just checking whether there were any issues with this patch?
https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612386.html

Otherwise I assume it won't be in GCC13.

Thanks,
Nathaniel


[PATCH] c++: Fix ICE with parameter pack of decltype(auto) [PR103497]

2023-04-21 Thread Nathaniel Shead via Gcc-patches
Bootstrapped and tested on x86_64-pc-linux-gnu.

-- 8< --

This patch raises an error early when the decltype(auto) specifier is
used as a parameter of a function. This prevents any issues with an
unexpected tree type later on when performing the call.

PR 103497

gcc/cp/ChangeLog:

* parser.cc (cp_parser_simple_type_specifier): Add check for
decltype(auto) as function parameter.

gcc/testsuite/ChangeLog:

* g++.dg/pr103497.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/parser.cc| 10 ++
 gcc/testsuite/g++.dg/pr103497.C |  7 +++
 2 files changed, 17 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/pr103497.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e5f032f2330..1415e07e152 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -19884,6 +19884,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
   && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
 {
   type = saved_checks_value (token->u.tree_check_value);
+  /* Within a function parameter declaration, decltype(auto) is always an
+error.  */
+  if (parser->auto_is_implicit_function_template_parm_p
+ && TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ && AUTO_IS_DECLTYPE (type))
+   {
+ error_at (token->location,
+   "cannot declare a parameter with %");
+ type = error_mark_node;
+   }
   if (decl_specs)
{
  cp_parser_set_decl_spec_type (decl_specs, type,
diff --git a/gcc/testsuite/g++.dg/pr103497.C b/gcc/testsuite/g++.dg/pr103497.C
new file mode 100644
index 000..bcd421c2907
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103497.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++14 } }
+
+void foo(decltype(auto)... args);  // { dg-error "parameter with 
.decltype.auto..|no parameter packs" }
+
+int main() {
+  foo();
+}
-- 
2.34.1



[PATCH 1/2] libstdc++: Normalise _GLIBCXX20_DEPRECATED macro

2022-12-28 Thread Nathaniel Shead via Gcc-patches
These two patches implement P1413 (deprecate std::aligned_storage and
std::aligned_union) for C++23. Tested on x86_64-linux.

-- >8 --

Updates _GLIBCXX20_DEPRECATED to be defined and behave the same as the
versions for other standards (e.g. _GLIBCXX17_DEPRECATED).

libstdc++-v3/ChangeLog:

* doc/doxygen/user.cfg.in (PREDEFINED): Update macros.
* include/bits/c++config (_GLIBCXX20_DEPRECATED): Make
consistent with other 'deprecated' macros.
* include/std/type_traits (is_pod, is_pod_v): Use
_GLIBCXX20_DEPRECATED_SUGGEST instead.

Signed-off-by: Nathaniel Shead 
---
 libstdc++-v3/doc/doxygen/user.cfg.in | 4 ++--
 libstdc++-v3/include/bits/c++config  | 6 +++---
 libstdc++-v3/include/std/type_traits | 4 ++--
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in 
b/libstdc++-v3/doc/doxygen/user.cfg.in
index 834ad9e4fd5..fc46e722529 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -2394,8 +2394,8 @@ PREDEFINED = __cplusplus=202002L \
  "_GLIBCXX11_DEPRECATED_SUGGEST(E)= " \
  "_GLIBCXX17_DEPRECATED= " \
  "_GLIBCXX17_DEPRECATED_SUGGEST(E)= " \
- "_GLIBCXX20_DEPRECATED(E)= " \
- "_GLIBCXX20_DEPRECATED(E)= " \
+ "_GLIBCXX20_DEPRECATED= " \
+ "_GLIBCXX20_DEPRECATED_SUGGEST(E)= " \
  _GLIBCXX17_INLINE=inline \
  _GLIBCXX_CHRONO_INT64_T=int64_t \
  _GLIBCXX_DEFAULT_ABI_TAG \
diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index 50406066afe..d2b0cfa15ce 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -84,7 +84,7 @@
 //   _GLIBCXX14_DEPRECATED_SUGGEST( string-literal )
 //   _GLIBCXX17_DEPRECATED
 //   _GLIBCXX17_DEPRECATED_SUGGEST( string-literal )
-//   _GLIBCXX20_DEPRECATED( string-literal )
+//   _GLIBCXX20_DEPRECATED
 //   _GLIBCXX20_DEPRECATED_SUGGEST( string-literal )
 #ifndef _GLIBCXX_USE_DEPRECATED
 # define _GLIBCXX_USE_DEPRECATED 1
@@ -124,10 +124,10 @@
 #endif
 
 #if defined(__DEPRECATED) && (__cplusplus >= 202002L)
-# define _GLIBCXX20_DEPRECATED(MSG) [[deprecated(MSG)]]
+# define _GLIBCXX20_DEPRECATED [[__deprecated__]]
 # define _GLIBCXX20_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT)
 #else
-# define _GLIBCXX20_DEPRECATED(MSG)
+# define _GLIBCXX20_DEPRECATED
 # define _GLIBCXX20_DEPRECATED_SUGGEST(ALT)
 #endif
 
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 5dc9e1b2921..2f4d4bb8d4d 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -815,7 +815,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Could use is_standard_layout && is_trivial instead of the builtin.
   template
 struct
-_GLIBCXX20_DEPRECATED("use is_standard_layout && is_trivial instead")
+_GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout && is_trivial")
 is_pod
 : public integral_constant
 {
@@ -3210,7 +3210,7 @@ template 
 template 
   inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp);
 template 
-  _GLIBCXX20_DEPRECATED("use is_standard_layout_v && is_trivial_v instead")
+  _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout_v && is_trivial_v")
   inline constexpr bool is_pod_v = __is_pod(_Tp);
 template 
   _GLIBCXX17_DEPRECATED
-- 
2.34.1



[PATCH 2/2] libstdc++: Implement P1413R3 'deprecate aligned_storage and aligned_union'

2022-12-28 Thread Nathaniel Shead via Gcc-patches
These two patches implement P1413 (deprecate std::aligned_storage and
std::aligned_union) for C++23. Tested on x86_64-linux.

-- >8 --

Adds deprecated attributes for C++23, and makes use of it for
std::aligned_storage, std::aligned_storage_t, std::aligned_union, and
std::aligned_union_t.

libstdc++-v3/ChangeLog:

* doc/doxygen/user.cfg.in (PREDEFINED): Add new macros.
* include/bits/c++config (_GLIBCXX23_DEPRECATED)
(_GLIBCXX23_DEPRECATED_SUGGEST): New macros.
* include/std/type_traits (aligned_storage, aligned_union)
(aligned_storage_t, aligned_union_t): Deprecate for C++23.
* testsuite/20_util/aligned_storage/deprecated-2b.cc: New test.
* testsuite/20_util/aligned_union/deprecated-2b.cc: New test.

Signed-off-by: Nathaniel Shead 
---
 libstdc++-v3/doc/doxygen/user.cfg.in  |  2 ++
 libstdc++-v3/include/bits/c++config   | 10 +++
 libstdc++-v3/include/std/type_traits  | 17 +---
 .../20_util/aligned_storage/deprecated-2b.cc  | 26 +++
 .../20_util/aligned_union/deprecated-2b.cc| 26 +++
 5 files changed, 77 insertions(+), 4 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/20_util/aligned_storage/deprecated-2b.cc
 create mode 100644 
libstdc++-v3/testsuite/20_util/aligned_union/deprecated-2b.cc

diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in 
b/libstdc++-v3/doc/doxygen/user.cfg.in
index fc46e722529..31613f51517 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -2396,6 +2396,8 @@ PREDEFINED = __cplusplus=202002L \
  "_GLIBCXX17_DEPRECATED_SUGGEST(E)= " \
  "_GLIBCXX20_DEPRECATED= " \
  "_GLIBCXX20_DEPRECATED_SUGGEST(E)= " \
+ "_GLIBCXX23_DEPRECATED= " \
+ "_GLIBCXX23_DEPRECATED_SUGGEST(E)= " \
  _GLIBCXX17_INLINE=inline \
  _GLIBCXX_CHRONO_INT64_T=int64_t \
  _GLIBCXX_DEFAULT_ABI_TAG \
diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index d2b0cfa15ce..7cec5d3de2d 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -86,6 +86,8 @@
 //   _GLIBCXX17_DEPRECATED_SUGGEST( string-literal )
 //   _GLIBCXX20_DEPRECATED
 //   _GLIBCXX20_DEPRECATED_SUGGEST( string-literal )
+//   _GLIBCXX23_DEPRECATED
+//   _GLIBCXX23_DEPRECATED_SUGGEST( string-literal )
 #ifndef _GLIBCXX_USE_DEPRECATED
 # define _GLIBCXX_USE_DEPRECATED 1
 #endif
@@ -131,6 +133,14 @@
 # define _GLIBCXX20_DEPRECATED_SUGGEST(ALT)
 #endif
 
+#if defined(__DEPRECATED) && (__cplusplus >= 202100L)
+# define _GLIBCXX23_DEPRECATED [[__deprecated__]]
+# define _GLIBCXX23_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT)
+#else
+# define _GLIBCXX23_DEPRECATED
+# define _GLIBCXX23_DEPRECATED_SUGGEST(ALT)
+#endif
+
 // Macros for ABI tag attributes.
 #ifndef _GLIBCXX_ABI_TAG_CXX11
 # define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11")))
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 2f4d4bb8d4d..9df833e82be 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2088,10 +2088,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  type shall be a POD type suitable for use as uninitialized
*  storage for any object whose size is at most _Len and whose
*  alignment is a divisor of _Align.
+   *
+   *  @deprecated Deprecated in C++23. Uses can be replaced by an
+   *  array std::byte[_Len] declared with alignas(_Align).
   */
   template::__type)>
-struct aligned_storage
+struct
+_GLIBCXX23_DEPRECATED
+aligned_storage
 {
   union type
   {
@@ -2127,9 +2132,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  least size _Len.
*
*  @see aligned_storage
+   *
+   *  @deprecated Deprecated in C++23.
*/
   template 
-struct aligned_union
+struct
+_GLIBCXX23_DEPRECATED
+aligned_union
 {
 private:
   static_assert(sizeof...(_Types) != 0, "At least one type is required");
@@ -2580,10 +2589,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// Alias template for aligned_storage
   template::__type)>
-using aligned_storage_t = typename aligned_storage<_Len, _Align>::type;
+using aligned_storage_t _GLIBCXX23_DEPRECATED = typename 
aligned_storage<_Len, _Align>::type;
 
   template 
-using aligned_union_t = typename aligned_union<_Len, _Types...>::type;
+using aligned_union_t _GLIBCXX23_DEPRECATED = typename aligned_union<_Len, 
_Types...>::type;
 
   /// Alias template for decay
   template
diff --git a/libstdc++-v3/testsuite/20_util/aligned_storage/deprecated-2b.cc 
b/libstdc++-v3/testsuite/20_util/aligned_storage/deprecated-2b.cc
new file mode 100644
index 000..a0e338a5843
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/aligned_stor

[PATCH] c++: Report invalid id-expression in decltype [PR100482]

2023-04-29 Thread Nathaniel Shead via Gcc-patches
This patch ensures that any errors raised by finish_id_expression when
parsing a decltype expression are properly reported, rather than
potentially going ignored and causing invalid code to be accepted.

We can also now remove the separate check for templates without args as
this is also checked for in finish_id_expression.

PR 100482

gcc/cp/ChangeLog:

* parser.cc (cp_parser_decltype_expr): Report errors raised by
finish_id_expression.

gcc/testsuite/ChangeLog:

* g++.dg/pr100482.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/parser.cc| 22 +++---
 gcc/testsuite/g++.dg/pr100482.C | 11 +++
 2 files changed, 22 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr100482.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e5f032f2330..20ebcdc3cfd 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -16508,10 +16508,6 @@ cp_parser_decltype_expr (cp_parser *parser,
expr = cp_parser_lookup_name_simple (parser, expr,
 id_expr_start_token->location);
 
-  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)
-   /* A template without args is not a complete id-expression.  */
-   expr = error_mark_node;
-
   if (expr
   && expr != error_mark_node
   && TREE_CODE (expr) != TYPE_DECL
@@ -16532,13 +16528,17 @@ cp_parser_decltype_expr (cp_parser *parser,
&error_msg,
   id_expr_start_token->location));
 
-  if (expr == error_mark_node)
-/* We found an id-expression, but it was something that we
-   should not have found. This is an error, not something
-   we can recover from, so note that we found an
-   id-expression and we'll recover as gracefully as
-   possible.  */
-id_expression_or_member_access_p = true;
+ if (error_msg)
+   {
+ /* We found an id-expression, but it was something that we
+should not have found. This is an error, not something
+we can recover from, so report the error we found and
+we'll recover as gracefully as possible.  */
+ cp_parser_parse_definitely (parser);
+ cp_parser_error (parser, error_msg);
+ id_expression_or_member_access_p = true;
+ return error_mark_node;
+   }
 }
 
   if (expr
diff --git a/gcc/testsuite/g++.dg/pr100482.C b/gcc/testsuite/g++.dg/pr100482.C
new file mode 100644
index 000..dcf6722fda5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr100482.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+namespace N {}
+decltype(std) x;   // { dg-error "expected primary-expression" }
+
+struct S {};
+decltype(S) y;  // { dg-error "argument to .decltype. must be an expression" }
+
+template 
+struct U {};
+decltype(U) z;  // { dg-error "missing template arguments" }
-- 
2.40.0



Re: [PATCH v2 0/3] c++: Track lifetimes in constant evaluation [PR70331, ...]

2023-05-08 Thread Nathaniel Shead via Gcc-patches
Just pinging in case this fix has fallen through the cracks.

https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614811.html

On Wed, Mar 29, 2023 at 1:33 PM Nathaniel Shead
 wrote:
>
> This is an update of the patch series at
> https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614759.html
>
> The main change is modifying the first patch to store the "expired" flag
> in the C++-specific lang_decl_base struct instead of tree_decl_common.
> The second and third patches to improve diagnostic locations are
> otherwise unchanged.
>
> Bootstrapped and regression tested on x86_64 linux.
>
> Nathaniel
>
> ---
>
> Nathaniel Shead (3):
>   c++: Track lifetimes in constant evaluation [PR70331,PR96630,PR98675]
>   c++: Improve constexpr error for dangling local variables
>   c++: Improve location information in constexpr evaluation
>
>  gcc/cp/constexpr.cc   | 152 --
>  gcc/cp/cp-tree.h  |  10 +-
>  gcc/cp/module.cc  |   2 +
>  gcc/cp/semantics.cc   |   5 +-
>  gcc/cp/typeck.cc  |   5 +-
>  gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C  |  10 +-
>  gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C  |   2 +-
>  gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C  |   2 +-
>  gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C  |   3 +-
>  .../g++.dg/cpp1y/constexpr-lifetime1.C|  14 ++
>  .../g++.dg/cpp1y/constexpr-lifetime2.C|  20 +++
>  .../g++.dg/cpp1y/constexpr-lifetime3.C|  13 ++
>  .../g++.dg/cpp1y/constexpr-lifetime4.C|  11 ++
>  .../g++.dg/cpp1y/constexpr-lifetime5.C|  11 ++
>  gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C |   4 +-
>  gcc/testsuite/g++.dg/cpp1y/pr68180.C  |   4 +-
>  .../g++.dg/cpp1z/constexpr-lambda6.C  |   4 +-
>  gcc/testsuite/g++.dg/cpp2a/bit-cast11.C   |  10 +-
>  gcc/testsuite/g++.dg/cpp2a/bit-cast12.C   |  10 +-
>  gcc/testsuite/g++.dg/cpp2a/bit-cast14.C   |  14 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C  |   4 +-
>  .../g++.dg/cpp2a/constexpr-dynamic17.C|   5 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C  |   5 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C  |   6 +-
>  gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C   |  10 +-
>  gcc/testsuite/g++.dg/ext/constexpr-vla2.C |   4 +-
>  gcc/testsuite/g++.dg/ext/constexpr-vla3.C |   4 +-
>  gcc/testsuite/g++.dg/ubsan/pr63956.C  |   4 +-
>  .../g++.dg/warn/Wreturn-local-addr-6.C|   3 -
>  .../25_algorithms/equal/constexpr_neg.cc  |   7 +-
>  30 files changed, 246 insertions(+), 112 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C
>
> --
> 2.34.1
>


[PATCH] libstdc++: Set active union member in constexpr std::string [PR103295]

2022-11-11 Thread Nathaniel Shead via Gcc-patches
Hi,

Below is a patch to fix std::string in constexpr contexts on Clang. This
was originally fixed in the commits attached to PR103295, but a later
commit 98a0d72a seems to have mistakenly undone this.

Tested on x86_64-linux. Verified using clang-14 and clang-15 that the
fix works. I haven't added anything to the test suite, since this issue
is only detected by clang.

This is my first time contributing, so please let me know if I've done
anything wrong or missed something. Thanks!

Nathaniel

-- >8 --

Clang still complains about using std::string in constexpr contexts due
to the changes made in commit 98a0d72a. This patch ensures that we set
the active member of the union as according to [class.union.general] p6.

libstdc++-v3/ChangeLog:

PR libstdc++/103295
* include/bits/basic_string.h (_M_use_local_data): Set active
  member to _M_local_buf.

Signed-off-by: Nathaniel Shead 
---
 libstdc++-v3/include/bits/basic_string.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 9c2b57f5a1d..2790fd49b05 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -352,8 +352,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   {
 #if __cpp_lib_is_constant_evaluated
if (std::is_constant_evaluated())
- for (_CharT& __c : _M_local_buf)
-   __c = _CharT();
+ for (size_type i = 0; i <= _S_local_capacity; ++i)
+   _M_local_buf[i] = _CharT();
 #endif
return _M_local_data();
   }
-- 
2.34.1



Re: [PATCH] libstdc++: Set active union member in constexpr std::string [PR103295]

2022-11-11 Thread Nathaniel Shead via Gcc-patches
Thanks for that. I'll keep your comments in mind for the future.

On Fri, Nov 11, 2022 at 05:59:33PM +, Jonathan Wakely wrote:
> On Fri, 11 Nov 2022 at 17:55, Patrick Palka  wrote:
> >
> > On Fri, 11 Nov 2022, Jonathan Wakely via Libstdc++ wrote:
> >
> > > On Fri, 11 Nov 2022 at 11:23, Nathaniel Shead via Libstdc++
> > >  wrote:
> > > >
> > > > Hi,
> > > >
> > > > Below is a patch to fix std::string in constexpr contexts on Clang. This
> > > > was originally fixed in the commits attached to PR103295, but a later
> > > > commit 98a0d72a seems to have mistakenly undone this.
> > > >
> > > > Tested on x86_64-linux. Verified using clang-14 and clang-15 that the
> > > > fix works. I haven't added anything to the test suite, since this issue
> > > > is only detected by clang.
> > > >
> > > > This is my first time contributing, so please let me know if I've done
> > > > anything wrong or missed something. Thanks!
> > >
> > > Thanks for the patch, I'll get this committed today.
> > >
> > > The only thing I had to fix was the indentation in the commit log. The
> > > second line of the ChangeLog should be aligned with the * not the text
> > > following it (so indented by a single tab).
> > >
> > >
> > > >
> > > > Nathaniel
> > > >
> > > > -- >8 --
> > > >
> > > > Clang still complains about using std::string in constexpr contexts due
> > > > to the changes made in commit 98a0d72a. This patch ensures that we set
> > > > the active member of the union as according to [class.union.general] p6.
> > > >
> > > > libstdc++-v3/ChangeLog:
> > > >
> > > > PR libstdc++/103295
> > > > * include/bits/basic_string.h (_M_use_local_data): Set active
> > > >   member to _M_local_buf.
> > > >
> > > > Signed-off-by: Nathaniel Shead 
> > > > ---
> > > >  libstdc++-v3/include/bits/basic_string.h | 4 ++--
> > > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/libstdc++-v3/include/bits/basic_string.h 
> > > > b/libstdc++-v3/include/bits/basic_string.h
> > > > index 9c2b57f5a1d..2790fd49b05 100644
> > > > --- a/libstdc++-v3/include/bits/basic_string.h
> > > > +++ b/libstdc++-v3/include/bits/basic_string.h
> > > > @@ -352,8 +352,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> > > >{
> > > >  #if __cpp_lib_is_constant_evaluated
> > > > if (std::is_constant_evaluated())
> > > > - for (_CharT& __c : _M_local_buf)
> > > > -   __c = _CharT();
> > > > + for (size_type i = 0; i <= _S_local_capacity; ++i)
> > > > +   _M_local_buf[i] = _CharT();
> >
> > Just a minor nit, but we should probably uglify i to __i here.
> 
> Good catch, thanks. Fixed and pushed.
> 


[PATCH] libstdc++: Add missing functions to [PR79700]

2023-02-20 Thread Nathaniel Shead via Gcc-patches
The comments on PR79700 mentioned that it was somewhat ambiguous whether
these functions were supposed to exist for C++11 or not. I chose to add
them there, since other resources (such as cppreference) seem to think
that C++11 should be the standard these functions were introduced, and I
don't know of any reason to do otherwise.

Tested on x86_64-linux.

-- 8< --

This patch adds the -f and -l variants of the C89  functions to
 under namespace std (so std::sqrtf, std::fabsl, etc.) for C++11
and up.

libstdc++-v3/ChangeLog:

PR libstdc++/79700
* include/c_global/cmath (acosf, acosl, asinf, asinl, atanf,
atanl, atan2f, atan2l, ceilf, ceill, cosf, cosl, coshf, coshl,
expf, expl, fabsf, fabsl, floorf, floorl, fmodf, fmodl, frexpf,
frexpl, ldexpf, ldexpl, logf, logl, log10f, log10l, modff,
modfl, powf, powl, sinf, sinl, sinhf, sinhl, sqrtf, sqrtl, tanf,
tanl, tanhf, tanhl): Add aliases in namespace std.
* testsuite/26_numerics/headers/cmath/functions_std_c++17.cc:
Add checks for existence of above names.

Signed-off-by: Nathaniel Shead 
---
 libstdc++-v3/include/c_global/cmath   | 111 ++
 .../headers/cmath/functions_std_c++17.cc  |  45 +++
 2 files changed, 156 insertions(+)

diff --git a/libstdc++-v3/include/c_global/cmath 
b/libstdc++-v3/include/c_global/cmath
index 568eb354c2d..eaebde33dee 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -1767,6 +1767,117 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cplusplus >= 201103L
 
+#undef acosf
+#undef acosl
+#undef asinf
+#undef asinl
+#undef atanf
+#undef atanl
+#undef atan2f
+#undef atan2l
+#undef ceilf
+#undef ceill
+#undef cosf
+#undef cosl
+#undef coshf
+#undef coshl
+#undef expf
+#undef expl
+#undef fabsf
+#undef fabsl
+#undef floorf
+#undef floorl
+#undef fmodf
+#undef fmodl
+#undef frexpf
+#undef frexpl
+#undef ldexpf
+#undef ldexpl
+#undef logf
+#undef logl
+#undef log10f
+#undef log10l
+#undef modff
+#undef modfl
+#undef powf
+#undef powl
+#undef sinf
+#undef sinl
+#undef sinhf
+#undef sinhl
+#undef sqrtf
+#undef sqrtl
+#undef tanf
+#undef tanl
+#undef tanhf
+#undef tanhl
+
+  using ::acosf;
+  using ::acosl;
+
+  using ::asinf;
+  using ::asinl;
+
+  using ::atanf;
+  using ::atanl;
+
+  using ::atan2f;
+  using ::atan2l;
+
+  using ::ceilf;
+  using ::ceill;
+
+  using ::cosf;
+  using ::cosl;
+
+  using ::coshf;
+  using ::coshl;
+
+  using ::expf;
+  using ::expl;
+
+  using ::fabsf;
+  using ::fabsl;
+
+  using ::floorf;
+  using ::floorl;
+
+  using ::fmodf;
+  using ::fmodl;
+
+  using ::frexpf;
+  using ::frexpl;
+
+  using ::ldexpf;
+  using ::ldexpl;
+
+  using ::logf;
+  using ::logl;
+
+  using ::log10f;
+  using ::log10l;
+
+  using ::modff;
+  using ::modfl;
+
+  using ::powf;
+  using ::powl;
+
+  using ::sinf;
+  using ::sinl;
+
+  using ::sinhf;
+  using ::sinhl;
+
+  using ::sqrtf;
+  using ::sqrtl;
+
+  using ::tanf;
+  using ::tanl;
+
+  using ::tanhf;
+  using ::tanhl;
+
 #ifdef _GLIBCXX_USE_C99_MATH_TR1
 
 #undef acosh
diff --git 
a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
index 3b4ada1a756..c6ec636c183 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
@@ -44,6 +44,51 @@ namespace gnu
   using std::tan;
   using std::tanh;
 
+  using std::acosf;
+  using std::acosl;
+  using std::asinf;
+  using std::asinl;
+  using std::atanf;
+  using std::atanl;
+  using std::atan2f;
+  using std::atan2l;
+  using std::ceilf;
+  using std::ceill;
+  using std::cosf;
+  using std::cosl;
+  using std::coshf;
+  using std::coshl;
+  using std::expf;
+  using std::expl;
+  using std::fabsf;
+  using std::fabsl;
+  using std::floorf;
+  using std::floorl;
+  using std::fmodf;
+  using std::fmodl;
+  using std::frexpf;
+  using std::frexpl;
+  using std::ldexpf;
+  using std::ldexpl;
+  using std::logf;
+  using std::logl;
+  using std::log10f;
+  using std::log10l;
+  using std::modff;
+  using std::modfl;
+  using std::powf;
+  using std::powl;
+  using std::sinf;
+  using std::sinl;
+  using std::sinhf;
+  using std::sinhl;
+  using std::sqrtf;
+  using std::sqrtl;
+  using std::tanf;
+  using std::tanl;
+  using std::tanhf;
+  using std::tanhl;
+
   using std::assoc_laguerre;
   using std::assoc_laguerref;
   using std::assoc_laguerrel;
-- 
2.34.1



Re: [PATCH] libstdc++: Add missing functions to [PR79700]

2023-02-20 Thread Nathaniel Shead via Gcc-patches
On Mon, Feb 20, 2023 at 10:30 PM Jonathan Wakely  wrote:
>
> On Mon, 20 Feb 2023 at 11:23, Nathaniel Shead via Libstdc++
>  wrote:
> >
> > The comments on PR79700 mentioned that it was somewhat ambiguous whether
> > these functions were supposed to exist for C++11 or not. I chose to add
> > them there, since other resources (such as cppreference) seem to think
> > that C++11 should be the standard these functions were introduced, and I
> > don't know of any reason to do otherwise.
> >
> > Tested on x86_64-linux.
>
> Thanks for the patch, but this needs tests for the new declarations
> (which are tedious to write, which is the main reason I haven't
> already pushed my own very similar patch).
>

Ah OK, fair enough. Where should the tests go? The only tests I could
find for the existing (non -f/l) functions was just tests for their
existence in testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
which I just added the new functions to - I guess I'll add a new file
here and test that all the functions can be called and give the same
results as the relevant overloaded variants?

>
> >
> > -- 8< --
> >
> > This patch adds the -f and -l variants of the C89  functions to
> >  under namespace std (so std::sqrtf, std::fabsl, etc.) for C++11
> > and up.
> >
> > libstdc++-v3/ChangeLog:
> >
> > PR libstdc++/79700
> > * include/c_global/cmath (acosf, acosl, asinf, asinl, atanf,
> > atanl, atan2f, atan2l, ceilf, ceill, cosf, cosl, coshf, coshl,
> > expf, expl, fabsf, fabsl, floorf, floorl, fmodf, fmodl, frexpf,
> > frexpl, ldexpf, ldexpl, logf, logl, log10f, log10l, modff,
> > modfl, powf, powl, sinf, sinl, sinhf, sinhl, sqrtf, sqrtl, tanf,
> > tanl, tanhf, tanhl): Add aliases in namespace std.
> > * testsuite/26_numerics/headers/cmath/functions_std_c++17.cc:
> > Add checks for existence of above names.
> >
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  libstdc++-v3/include/c_global/cmath   | 111 ++
> >  .../headers/cmath/functions_std_c++17.cc  |  45 +++
> >  2 files changed, 156 insertions(+)
> >
> > diff --git a/libstdc++-v3/include/c_global/cmath 
> > b/libstdc++-v3/include/c_global/cmath
> > index 568eb354c2d..eaebde33dee 100644
> > --- a/libstdc++-v3/include/c_global/cmath
> > +++ b/libstdc++-v3/include/c_global/cmath
> > @@ -1767,6 +1767,117 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> >  #if __cplusplus >= 201103L
> >
> > +#undef acosf
> > +#undef acosl
> > +#undef asinf
> > +#undef asinl
> > +#undef atanf
> > +#undef atanl
> > +#undef atan2f
> > +#undef atan2l
> > +#undef ceilf
> > +#undef ceill
> > +#undef cosf
> > +#undef cosl
> > +#undef coshf
> > +#undef coshl
> > +#undef expf
> > +#undef expl
> > +#undef fabsf
> > +#undef fabsl
> > +#undef floorf
> > +#undef floorl
> > +#undef fmodf
> > +#undef fmodl
> > +#undef frexpf
> > +#undef frexpl
> > +#undef ldexpf
> > +#undef ldexpl
> > +#undef logf
> > +#undef logl
> > +#undef log10f
> > +#undef log10l
> > +#undef modff
> > +#undef modfl
> > +#undef powf
> > +#undef powl
> > +#undef sinf
> > +#undef sinl
> > +#undef sinhf
> > +#undef sinhl
> > +#undef sqrtf
> > +#undef sqrtl
> > +#undef tanf
> > +#undef tanl
> > +#undef tanhf
> > +#undef tanhl
> > +
> > +  using ::acosf;
> > +  using ::acosl;
> > +
> > +  using ::asinf;
> > +  using ::asinl;
> > +
> > +  using ::atanf;
> > +  using ::atanl;
> > +
> > +  using ::atan2f;
> > +  using ::atan2l;
> > +
> > +  using ::ceilf;
> > +  using ::ceill;
> > +
> > +  using ::cosf;
> > +  using ::cosl;
> > +
> > +  using ::coshf;
> > +  using ::coshl;
> > +
> > +  using ::expf;
> > +  using ::expl;
> > +
> > +  using ::fabsf;
> > +  using ::fabsl;
> > +
> > +  using ::floorf;
> > +  using ::floorl;
> > +
> > +  using ::fmodf;
> > +  using ::fmodl;
> > +
> > +  using ::frexpf;
> > +  using ::frexpl;
> > +
> > +  using ::ldexpf;
> > +  using ::ldexpl;
> > +
> > +  using ::logf;
> > +  using ::logl;
> > +
> > +  using ::log10f;
> > +  using ::log10l;
> > +
> > +  using ::modff;
> > +  using ::modfl;
> > +
> > +  using ::powf;
> > +  using ::powl;
> > +
> > +  using ::sinf;
> > +  using ::sinl;
> > +
> > +  using ::sinhf;
> > +  using ::sinhl;
> > +
> > +  using ::sqrtf;
> > +  using ::sqrtl;
> > +
> > +  using ::tanf;
> > +  using ::tanl;
> > +
> > +  using ::tanhf;
> > +  using ::tanhl;
> > +
> >  #ifdef _GLIBCXX_USE_C99_MATH_TR1
> >
> >  #undef acosh
> > diff --git 
> > a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc 
> > b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
> > index 3b4ada1a756..c6ec636c183 100644
> > --- 
> > a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
> > +++ 
> > b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
> > @@ -44,6 +44,51 @@ namespace gnu
> >using std::tan;
> >using std::tanh;
> >
> > +  using std::acosf;
> > +  using std::acosl;
> > +  using std::asinf;
> > +  using std::asinl;
> > 

Re: [PATCH] libstdc++: Add missing functions to [PR79700]

2023-02-21 Thread Nathaniel Shead via Gcc-patches
On Mon, Feb 20, 2023 at 12:08:38PM +, Jonathan Wakely wrote:
> On Mon, 20 Feb 2023 at 11:57, Nathaniel Shead  
> wrote:
> >
> > On Mon, Feb 20, 2023 at 10:30 PM Jonathan Wakely  wrote:
> > >
> > > On Mon, 20 Feb 2023 at 11:23, Nathaniel Shead via Libstdc++
> > >  wrote:
> > > >
> > > > The comments on PR79700 mentioned that it was somewhat ambiguous whether
> > > > these functions were supposed to exist for C++11 or not. I chose to add
> > > > them there, since other resources (such as cppreference) seem to think
> > > > that C++11 should be the standard these functions were introduced, and I
> > > > don't know of any reason to do otherwise.
> > > >
> > > > Tested on x86_64-linux.
> > >
> > > Thanks for the patch, but this needs tests for the new declarations
> > > (which are tedious to write, which is the main reason I haven't
> > > already pushed my own very similar patch).
> > >
> >
> > Ah OK, fair enough. Where should the tests go? The only tests I could
> > find for the existing (non -f/l) functions was just tests for their
> > existence in testsuite/26_numerics/headers/cmath/functions_std_c++17.cc
> > which I just added the new functions to - I guess I'll add a new file
> > here and test that all the functions can be called and give the same
> > results as the relevant overloaded variants?
> 
> Yeah, that sounds great, thanks!
> 

How does this look?

-- 8< --

This patch adds the -f and -l variants of the C89  functions to
 under namespace std (so std::sqrtf, std::fabsl, etc.) for C++11
and up.

libstdc++-v3/ChangeLog:

PR libstdc++/79700
* include/c_global/cmath (acosf, acosl, asinf, asinl, atanf,
atanl, atan2f, atan2l, ceilf, ceill, cosf, cosl, coshf, coshl,
expf, expl, fabsf, fabsl, floorf, floorl, fmodf, fmodl, frexpf,
frexpl, ldexpf, ldexpl, logf, logl, log10f, log10l, modff,
modfl, powf, powl, sinf, sinl, sinhf, sinhl, sqrtf, sqrtl, tanf,
tanl, tanhf, tanhl): Add aliases in namespace std.
* testsuite/26_numerics/headers/cmath/equivalent_functions.cc:
New test.
* testsuite/26_numerics/headers/cmath/functions_std_c++17.cc:
Add checks for existence of above names.

Signed-off-by: Nathaniel Shead 
---
 libstdc++-v3/include/c_global/cmath   | 111 +
 .../headers/cmath/equivalent_functions.cc | 224 ++
 .../headers/cmath/functions_std_c++17.cc  |  45 
 3 files changed, 380 insertions(+)
 create mode 100644 
libstdc++-v3/testsuite/26_numerics/headers/cmath/equivalent_functions.cc

diff --git a/libstdc++-v3/include/c_global/cmath 
b/libstdc++-v3/include/c_global/cmath
index 568eb354c2d..eaebde33dee 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -1767,6 +1767,117 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cplusplus >= 201103L
 
+#undef acosf
+#undef acosl
+#undef asinf
+#undef asinl
+#undef atanf
+#undef atanl
+#undef atan2f
+#undef atan2l
+#undef ceilf
+#undef ceill
+#undef cosf
+#undef cosl
+#undef coshf
+#undef coshl
+#undef expf
+#undef expl
+#undef fabsf
+#undef fabsl
+#undef floorf
+#undef floorl
+#undef fmodf
+#undef fmodl
+#undef frexpf
+#undef frexpl
+#undef ldexpf
+#undef ldexpl
+#undef logf
+#undef logl
+#undef log10f
+#undef log10l
+#undef modff
+#undef modfl
+#undef powf
+#undef powl
+#undef sinf
+#undef sinl
+#undef sinhf
+#undef sinhl
+#undef sqrtf
+#undef sqrtl
+#undef tanf
+#undef tanl
+#undef tanhf
+#undef tanhl
+
+  using ::acosf;
+  using ::acosl;
+
+  using ::asinf;
+  using ::asinl;
+
+  using ::atanf;
+  using ::atanl;
+
+  using ::atan2f;
+  using ::atan2l;
+
+  using ::ceilf;
+  using ::ceill;
+
+  using ::cosf;
+  using ::cosl;
+
+  using ::coshf;
+  using ::coshl;
+
+  using ::expf;
+  using ::expl;
+
+  using ::fabsf;
+  using ::fabsl;
+
+  using ::floorf;
+  using ::floorl;
+
+  using ::fmodf;
+  using ::fmodl;
+
+  using ::frexpf;
+  using ::frexpl;
+
+  using ::ldexpf;
+  using ::ldexpl;
+
+  using ::logf;
+  using ::logl;
+
+  using ::log10f;
+  using ::log10l;
+
+  using ::modff;
+  using ::modfl;
+
+  using ::powf;
+  using ::powl;
+
+  using ::sinf;
+  using ::sinl;
+
+  using ::sinhf;
+  using ::sinhl;
+
+  using ::sqrtf;
+  using ::sqrtl;
+
+  using ::tanf;
+  using ::tanl;
+
+  using ::tanhf;
+  using ::tanhl;
+
 #ifdef _GLIBCXX_USE_C99_MATH_TR1
 
 #undef acosh
diff --git 
a/libstdc++-v3/testsuite/26_numerics/headers/cmath/equivalent_functions.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/equivalent_functions.cc
new file mode 100644
index 000..8639279e8a1
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/equivalent_functions.cc
@@ -0,0 +1,224 @@
+// Copyright (C) 2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or 

Re: [committed] libstdc++: Add const to hash>::operator() [PR109165]

2023-03-17 Thread Nathaniel Shead via Gcc-patches
On Sat, Mar 18, 2023 at 7:36 AM Jonathan Wakely via Libstdc++
 wrote:
>
> Tested x86_64-linux. Pushed to trunk. gcc-12 backport needed too.
>
> -- >8 --
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/109165
> * include/std/coroutine (hash<>::operator()): Add const.
> * testsuite/18_support/coroutines/hash.cc: New test.
> ---
>  libstdc++-v3/include/std/coroutine|  2 +-
>  .../testsuite/18_support/coroutines/hash.cc   | 22 +++
>  2 files changed, 23 insertions(+), 1 deletion(-)
>  create mode 100644 libstdc++-v3/testsuite/18_support/coroutines/hash.cc
>
> diff --git a/libstdc++-v3/include/std/coroutine 
> b/libstdc++-v3/include/std/coroutine
> index f6e65566f10..b0ca18949db 100644
> --- a/libstdc++-v3/include/std/coroutine
> +++ b/libstdc++-v3/include/std/coroutine
> @@ -345,7 +345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  struct hash>
>  {
>size_t
> -  operator()(const coroutine_handle<_Promise>& __h) noexcept
> +  operator()(const coroutine_handle<_Promise>& __h) const noexcept
>{
> return reinterpret_cast(__h.address());
>}
> diff --git a/libstdc++-v3/testsuite/18_support/coroutines/hash.cc 
> b/libstdc++-v3/testsuite/18_support/coroutines/hash.cc
> new file mode 100644
> index 000..68e5e640477
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/18_support/coroutines/hash.cc
> @@ -0,0 +1,22 @@
> +// { dg-options "-std=gnu++2a" }
> +// { dg-do run { target c++2a } }
> +
> +#include 
> +#include 
> +
> +void
> +test01()
> +{
> +  std::hash h;
> +  std::size_t v = h(std::noop_coroutine());
> +
> +  const auto& ch = h;
> +  std::size_t v2 = h(std::noop_coroutine()); // PR libstdc++/109165

Is this supposed to be `std::size_t v2 = ch(...)`?

> +
> +  VERIFY( v2 == v );
> +}
> +
> +int main()
> +{
> +  test01();
> +}
> --
> 2.39.2
>