Re: [PATCH v2] c++: Improve diagnostics for constexpr cast from void*

2023-10-19 Thread Jason Merrill

On 10/11/23 11:41, Marek Polacek wrote:

On Wed, Oct 11, 2023 at 10:57:06AM +1100, Nathaniel Shead wrote:

On Mon, Oct 09, 2023 at 04:10:20PM -0400, Jason Merrill wrote:

On 10/9/23 06:03, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26,impcx.

-- >8 --

This patch improves the errors given when casting from void* in C++26 to
include the expected type if the type of the pointed-to object was
not similar to the casted-to type.

It also ensures (for all standard modes) that void* casts are checked
even for DECL_ARTIFICIAL declarations, such as lifetime-extended
temporaries, and is only ignored for cases where we know it's OK (heap
identifiers and source_location::current). This provides more accurate
diagnostics when using the pointer and ensures that some other casts
from void* are now correctly rejected.

gcc/cp/ChangeLog:

* constexpr.cc (is_std_source_location_current): New.
(cxx_eval_constant_expression): Only ignore cast from void* for
specific cases and improve other diagnostics.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Nathaniel Shead 
---
   gcc/cp/constexpr.cc  | 83 +---
   gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C |  7 ++
   2 files changed, 78 insertions(+), 12 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 0f948db7c2d..f38d541a662 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2301,6 +2301,36 @@ is_std_allocator_allocate (const constexpr_call *call)
  && is_std_allocator_allocate (call->fundef->decl));
   }
+/* Return true if FNDECL is std::source_location::current.  */
+
+static inline bool
+is_std_source_location_current (tree fndecl)
+{
+  if (!decl_in_std_namespace_p (fndecl))
+return false;
+
+  tree name = DECL_NAME (fndecl);
+  if (name == NULL_TREE || !id_equal (name, "current"))
+return false;
+
+  tree ctx = DECL_CONTEXT (fndecl);
+  if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
+return false;
+
+  name = DECL_NAME (TYPE_MAIN_DECL (ctx));
+  return name && id_equal (name, "source_location");
+}
+
+/* Overload for the above taking constexpr_call*.  */
+
+static inline bool
+is_std_source_location_current (const constexpr_call *call)
+{
+  return (call
+ && call->fundef
+ && is_std_source_location_current (call->fundef->decl));
+}
+
   /* Return true if FNDECL is __dynamic_cast.  */
   static inline bool
@@ -7850,33 +7880,62 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
if (TYPE_PTROB_P (type)
&& TYPE_PTR_P (TREE_TYPE (op))
&& VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
-   /* Inside a call to std::construct_at or to
-  std::allocator::{,de}allocate, we permit casting from void*
+   /* Inside a call to std::construct_at,
+  std::allocator::{,de}allocate, or
+  std::source_location::current, we permit casting from void*
   because that is compiler-generated code.  */
&& !is_std_construct_at (ctx->call)
-   && !is_std_allocator_allocate (ctx->call))
+   && !is_std_allocator_allocate (ctx->call)
+   && !is_std_source_location_current (ctx->call))
  {
/* Likewise, don't error when casting from void* when OP is
   &heap uninit and similar.  */
tree sop = tree_strip_nop_conversions (op);
-   if (TREE_CODE (sop) == ADDR_EXPR
-   && VAR_P (TREE_OPERAND (sop, 0))
-   && DECL_ARTIFICIAL (TREE_OPERAND (sop, 0)))
+   tree decl = NULL_TREE;
+   if (TREE_CODE (sop) == ADDR_EXPR)
+ decl = TREE_OPERAND (sop, 0);
+   if (decl
+   && VAR_P (decl)
+   && DECL_ARTIFICIAL (decl)
+   && (DECL_NAME (decl) == heap_identifier
+   || DECL_NAME (decl) == heap_uninit_identifier
+   || DECL_NAME (decl) == heap_vec_identifier
+   || DECL_NAME (decl) == heap_vec_uninit_identifier))
  /* OK */;
/* P2738 (C++26): a conversion from a prvalue P of type "pointer to
   cv void" to a pointer-to-object type T unless P points to an
   object whose type is similar to T.  */
-   else if (cxx_dialect > cxx23
-&& (sop = cxx_fold_indirect_ref (ctx, loc,
- TREE_TYPE (type), sop)))
+   else if (cxx_dialect > cxx23)
  {
-   r = build1 (ADDR_EXPR, type, sop);
-   break;
+   r = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), sop);
+   if (r)
+ {
+   r = build1 (ADDR_EXPR, type, r);
+   break;
+  

Re: [PATCH v2] c++: Improve diagnostics for constexpr cast from void*

2023-10-11 Thread Marek Polacek
On Wed, Oct 11, 2023 at 10:57:06AM +1100, Nathaniel Shead wrote:
> On Mon, Oct 09, 2023 at 04:10:20PM -0400, Jason Merrill wrote:
> > On 10/9/23 06:03, Nathaniel Shead wrote:
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu with
> > > GXX_TESTSUITE_STDS=98,11,14,17,20,23,26,impcx.
> > > 
> > > -- >8 --
> > > 
> > > This patch improves the errors given when casting from void* in C++26 to
> > > include the expected type if the type of the pointed-to object was
> > > not similar to the casted-to type.
> > > 
> > > It also ensures (for all standard modes) that void* casts are checked
> > > even for DECL_ARTIFICIAL declarations, such as lifetime-extended
> > > temporaries, and is only ignored for cases where we know it's OK (heap
> > > identifiers and source_location::current). This provides more accurate
> > > diagnostics when using the pointer and ensures that some other casts
> > > from void* are now correctly rejected.
> > > 
> > > gcc/cp/ChangeLog:
> > > 
> > >   * constexpr.cc (is_std_source_location_current): New.
> > >   (cxx_eval_constant_expression): Only ignore cast from void* for
> > >   specific cases and improve other diagnostics.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > >   * g++.dg/cpp0x/constexpr-cast4.C: New test.
> > > 
> > > Signed-off-by: Nathaniel Shead 
> > > ---
> > >   gcc/cp/constexpr.cc  | 83 +---
> > >   gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C |  7 ++
> > >   2 files changed, 78 insertions(+), 12 deletions(-)
> > >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C
> > > 
> > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > index 0f948db7c2d..f38d541a662 100644
> > > --- a/gcc/cp/constexpr.cc
> > > +++ b/gcc/cp/constexpr.cc
> > > @@ -2301,6 +2301,36 @@ is_std_allocator_allocate (const constexpr_call 
> > > *call)
> > > && is_std_allocator_allocate (call->fundef->decl));
> > >   }
> > > +/* Return true if FNDECL is std::source_location::current.  */
> > > +
> > > +static inline bool
> > > +is_std_source_location_current (tree fndecl)
> > > +{
> > > +  if (!decl_in_std_namespace_p (fndecl))
> > > +return false;
> > > +
> > > +  tree name = DECL_NAME (fndecl);
> > > +  if (name == NULL_TREE || !id_equal (name, "current"))
> > > +return false;
> > > +
> > > +  tree ctx = DECL_CONTEXT (fndecl);
> > > +  if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
> > > +return false;
> > > +
> > > +  name = DECL_NAME (TYPE_MAIN_DECL (ctx));
> > > +  return name && id_equal (name, "source_location");
> > > +}
> > > +
> > > +/* Overload for the above taking constexpr_call*.  */
> > > +
> > > +static inline bool
> > > +is_std_source_location_current (const constexpr_call *call)
> > > +{
> > > +  return (call
> > > +   && call->fundef
> > > +   && is_std_source_location_current (call->fundef->decl));
> > > +}
> > > +
> > >   /* Return true if FNDECL is __dynamic_cast.  */
> > >   static inline bool
> > > @@ -7850,33 +7880,62 @@ cxx_eval_constant_expression (const constexpr_ctx 
> > > *ctx, tree t,
> > >   if (TYPE_PTROB_P (type)
> > >   && TYPE_PTR_P (TREE_TYPE (op))
> > >   && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
> > > - /* Inside a call to std::construct_at or to
> > > -std::allocator::{,de}allocate, we permit casting from void*
> > > + /* Inside a call to std::construct_at,
> > > +std::allocator::{,de}allocate, or
> > > +std::source_location::current, we permit casting from void*
> > >  because that is compiler-generated code.  */
> > >   && !is_std_construct_at (ctx->call)
> > > - && !is_std_allocator_allocate (ctx->call))
> > > + && !is_std_allocator_allocate (ctx->call)
> > > + && !is_std_source_location_current (ctx->call))
> > > {
> > >   /* Likewise, don't error when casting from void* when OP is
> > >  &heap uninit and similar.  */
> > >   tree sop = tree_strip_nop_conversions (op);
> > > - if (TREE_CODE (sop) == ADDR_EXPR
> > > - && VAR_P (TREE_OPERAND (sop, 0))
> > > - && DECL_ARTIFICIAL (TREE_OPERAND (sop, 0)))
> > > + tree decl = NULL_TREE;
> > > + if (TREE_CODE (sop) == ADDR_EXPR)
> > > +   decl = TREE_OPERAND (sop, 0);
> > > + if (decl
> > > + && VAR_P (decl)
> > > + && DECL_ARTIFICIAL (decl)
> > > + && (DECL_NAME (decl) == heap_identifier
> > > + || DECL_NAME (decl) == heap_uninit_identifier
> > > + || DECL_NAME (decl) == heap_vec_identifier
> > > + || DECL_NAME (decl) == heap_vec_uninit_identifier))
> > > /* OK */;
> > >   /* P2738 (C++26): a conversion from a prvalue P of type 
> > > "pointer to
> > >  cv void" to a pointer-to-object type T unless P points 
> > > to an
> > >  object whose type is similar to T.  */
> > > - else if (cxx_diale

[PATCH v2] c++: Improve diagnostics for constexpr cast from void*

2023-10-10 Thread Nathaniel Shead
On Mon, Oct 09, 2023 at 04:10:20PM -0400, Jason Merrill wrote:
> On 10/9/23 06:03, Nathaniel Shead wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu with
> > GXX_TESTSUITE_STDS=98,11,14,17,20,23,26,impcx.
> > 
> > -- >8 --
> > 
> > This patch improves the errors given when casting from void* in C++26 to
> > include the expected type if the type of the pointed-to object was
> > not similar to the casted-to type.
> > 
> > It also ensures (for all standard modes) that void* casts are checked
> > even for DECL_ARTIFICIAL declarations, such as lifetime-extended
> > temporaries, and is only ignored for cases where we know it's OK (heap
> > identifiers and source_location::current). This provides more accurate
> > diagnostics when using the pointer and ensures that some other casts
> > from void* are now correctly rejected.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (is_std_source_location_current): New.
> > (cxx_eval_constant_expression): Only ignore cast from void* for
> > specific cases and improve other diagnostics.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/constexpr-cast4.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >   gcc/cp/constexpr.cc  | 83 +---
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C |  7 ++
> >   2 files changed, 78 insertions(+), 12 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 0f948db7c2d..f38d541a662 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -2301,6 +2301,36 @@ is_std_allocator_allocate (const constexpr_call 
> > *call)
> >   && is_std_allocator_allocate (call->fundef->decl));
> >   }
> > +/* Return true if FNDECL is std::source_location::current.  */
> > +
> > +static inline bool
> > +is_std_source_location_current (tree fndecl)
> > +{
> > +  if (!decl_in_std_namespace_p (fndecl))
> > +return false;
> > +
> > +  tree name = DECL_NAME (fndecl);
> > +  if (name == NULL_TREE || !id_equal (name, "current"))
> > +return false;
> > +
> > +  tree ctx = DECL_CONTEXT (fndecl);
> > +  if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
> > +return false;
> > +
> > +  name = DECL_NAME (TYPE_MAIN_DECL (ctx));
> > +  return name && id_equal (name, "source_location");
> > +}
> > +
> > +/* Overload for the above taking constexpr_call*.  */
> > +
> > +static inline bool
> > +is_std_source_location_current (const constexpr_call *call)
> > +{
> > +  return (call
> > + && call->fundef
> > + && is_std_source_location_current (call->fundef->decl));
> > +}
> > +
> >   /* Return true if FNDECL is __dynamic_cast.  */
> >   static inline bool
> > @@ -7850,33 +7880,62 @@ cxx_eval_constant_expression (const constexpr_ctx 
> > *ctx, tree t,
> > if (TYPE_PTROB_P (type)
> > && TYPE_PTR_P (TREE_TYPE (op))
> > && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
> > -   /* Inside a call to std::construct_at or to
> > -  std::allocator::{,de}allocate, we permit casting from void*
> > +   /* Inside a call to std::construct_at,
> > +  std::allocator::{,de}allocate, or
> > +  std::source_location::current, we permit casting from void*
> >because that is compiler-generated code.  */
> > && !is_std_construct_at (ctx->call)
> > -   && !is_std_allocator_allocate (ctx->call))
> > +   && !is_std_allocator_allocate (ctx->call)
> > +   && !is_std_source_location_current (ctx->call))
> >   {
> > /* Likewise, don't error when casting from void* when OP is
> >&heap uninit and similar.  */
> > tree sop = tree_strip_nop_conversions (op);
> > -   if (TREE_CODE (sop) == ADDR_EXPR
> > -   && VAR_P (TREE_OPERAND (sop, 0))
> > -   && DECL_ARTIFICIAL (TREE_OPERAND (sop, 0)))
> > +   tree decl = NULL_TREE;
> > +   if (TREE_CODE (sop) == ADDR_EXPR)
> > + decl = TREE_OPERAND (sop, 0);
> > +   if (decl
> > +   && VAR_P (decl)
> > +   && DECL_ARTIFICIAL (decl)
> > +   && (DECL_NAME (decl) == heap_identifier
> > +   || DECL_NAME (decl) == heap_uninit_identifier
> > +   || DECL_NAME (decl) == heap_vec_identifier
> > +   || DECL_NAME (decl) == heap_vec_uninit_identifier))
> >   /* OK */;
> > /* P2738 (C++26): a conversion from a prvalue P of type "pointer to
> >cv void" to a pointer-to-object type T unless P points to an
> >object whose type is similar to T.  */
> > -   else if (cxx_dialect > cxx23
> > -&& (sop = cxx_fold_indirect_ref (ctx, loc,
> > - TREE_TYPE (type), sop)))
> > +   else if (cxx_dialect > cxx23)
> >   {
> > -   r = build1 (ADDR_EXPR, type, sop);
> > -   break;
> > +   r = cxx_fold_indirect_ref (ct