Re: [PATCH] c++: ICE with template NEW_EXPR [PR105803]

2022-06-02 Thread Marek Polacek via Gcc-patches
On Thu, Jun 02, 2022 at 04:26:27PM -0400, Jason Merrill wrote:
> On 6/2/22 16:10, Marek Polacek wrote:
> > index 1346a1d4c10..2bbd8785627 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -9039,10 +9039,18 @@ potential_constant_expression_1 (tree t, bool 
> > want_rval, bool strict, bool now,
> >   "before C++17");
> > return false;
> > -case DYNAMIC_CAST_EXPR:
> > -case PSEUDO_DTOR_EXPR:
> >   case NEW_EXPR:
> >   case VEC_NEW_EXPR:
> > +  if (cxx_dialect >= cxx20)
> > +   /* In C++20, new-expressions are potentially constant.  */
> > +   return true;
> > +  else if (flags & tf_error)
> > +   error_at (loc, "new-expression is not a constant expression "
> > + "before C++20");
> > +  return false;
> > +
> > +case DYNAMIC_CAST_EXPR:
> > +case PSEUDO_DTOR_EXPR:
> >   case DELETE_EXPR:
> >   case VEC_DELETE_EXPR:
> 
> Delete, too.

Duh.  Fixed:

>From 2423f6548405185e256036df3d0ef3c13fd996c5 Mon Sep 17 00:00:00 2001
From: Marek Polacek 
Date: Thu, 2 Jun 2022 15:56:18 -0400
Subject: [PATCH] c++: new-expression is potentially constant in C++20

... so adjust p_c_e accordingly.

gcc/cp/ChangeLog:

* constexpr.cc (potential_constant_expression_1): Treat
{,VEC_}NEW_EXPR and {,VEC_}DELETE_EXPRas potentially constant in C++20.
---
 gcc/cp/constexpr.cc | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 1346a1d4c10..684238883dc 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9039,12 +9039,20 @@ potential_constant_expression_1 (tree t, bool 
want_rval, bool strict, bool now,
  "before C++17");
   return false;
 
-case DYNAMIC_CAST_EXPR:
-case PSEUDO_DTOR_EXPR:
 case NEW_EXPR:
 case VEC_NEW_EXPR:
 case DELETE_EXPR:
 case VEC_DELETE_EXPR:
+  if (cxx_dialect >= cxx20)
+   /* In C++20, new-expressions are potentially constant.  */
+   return true;
+  else if (flags & tf_error)
+   error_at (loc, "new-expression is not a constant expression "
+ "before C++20");
+  return false;
+
+case DYNAMIC_CAST_EXPR:
+case PSEUDO_DTOR_EXPR:
 case THROW_EXPR:
 case OMP_PARALLEL:
 case OMP_TASK:

base-commit: 7b98910406b5000a6429c188b0c6cc14e3140637
-- 
2.36.1



Re: [PATCH] c++: ICE with template NEW_EXPR [PR105803]

2022-06-02 Thread Marek Polacek via Gcc-patches
On Thu, Jun 02, 2022 at 03:42:15PM -0400, Jason Merrill wrote:
> On 6/2/22 10:03, Marek Polacek wrote:
> > On Thu, Jun 02, 2022 at 08:42:36AM -0400, Patrick Palka wrote:
> > > On Wed, 1 Jun 2022, Marek Polacek via Gcc-patches wrote:
> > > 
> > > > Here we ICE because value_dependent_expression_p gets a NEW_EXPR
> > > > whose operand is a type, and we go to the default case which just
> > > > calls v_d_e_p on each operand of the NEW_EXPR.  Since one of them
> > > > is a type, we crash on the new assert in t_d_e_p.
> > > 
> > > Looks like NEW_EXPR is considered to be not potentially constant
> > > according to potential_constant_expression.  I thought we shouldn't
> > > be calling value_dependent_expression_p on such exprs?
> 
> Except in C++20 new-expressions are potentially constant, so the patch is

Thanks, pushed.

> OK, and we should adjust pce1 accordingly.

Is the attached patch OK then?  So far dg.exp passed.  Though it won't help
with...
 
> I notice we currently fail to handle
> 
> struct A
> {
>   int i;
>   constexpr A(int *p): i(*p) { delete p; }
> };
> 
> constexpr int i = A(new int(42)).i;
> 
> though it does work inside a function.

...this test (it complains about a TARGET_EXPR's slot variable not being
declared constexpr), so I'm going to open a PR.

>From cf70354894bc31cc542ed8df40633bea2427fee7 Mon Sep 17 00:00:00 2001
From: Marek Polacek 
Date: Thu, 2 Jun 2022 15:56:18 -0400
Subject: [PATCH] c++: new-expression is potentially constant in C++20

... so adjust p_c_e accordingly.

gcc/cp/ChangeLog:

* constexpr.cc (potential_constant_expression_1): Treat
{,VEC_}NEW_EXPR as potentially constant in C++20.
---
 gcc/cp/constexpr.cc | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 1346a1d4c10..2bbd8785627 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9039,10 +9039,18 @@ potential_constant_expression_1 (tree t, bool 
want_rval, bool strict, bool now,
  "before C++17");
   return false;
 
-case DYNAMIC_CAST_EXPR:
-case PSEUDO_DTOR_EXPR:
 case NEW_EXPR:
 case VEC_NEW_EXPR:
+  if (cxx_dialect >= cxx20)
+   /* In C++20, new-expressions are potentially constant.  */
+   return true;
+  else if (flags & tf_error)
+   error_at (loc, "new-expression is not a constant expression "
+ "before C++20");
+  return false;
+
+case DYNAMIC_CAST_EXPR:
+case PSEUDO_DTOR_EXPR:
 case DELETE_EXPR:
 case VEC_DELETE_EXPR:
 case THROW_EXPR:

base-commit: 7b98910406b5000a6429c188b0c6cc14e3140637
-- 
2.36.1



Re: [PATCH] c++: ICE with template NEW_EXPR [PR105803]

2022-06-02 Thread Marek Polacek via Gcc-patches
On Thu, Jun 02, 2022 at 08:42:36AM -0400, Patrick Palka wrote:
> On Wed, 1 Jun 2022, Marek Polacek via Gcc-patches wrote:
> 
> > Here we ICE because value_dependent_expression_p gets a NEW_EXPR
> > whose operand is a type, and we go to the default case which just
> > calls v_d_e_p on each operand of the NEW_EXPR.  Since one of them
> > is a type, we crash on the new assert in t_d_e_p.
> 
> Looks like NEW_EXPR is considered to be not potentially constant
> according to potential_constant_expression.  I thought we shouldn't
> be calling value_dependent_expression_p on such exprs?

You're correct.  This is non-obvious: instantiation_dependent_expression_p
calls p_c_e before v_d_e_p, but the expression is CAST_EXPR<[NEW_EXPR]>,
where the [] denotes a TREE_LIST, created in cp_parser_functional_cast.
This TREE_LIST has no type.  So p_c_e_1/CAST_EXPR goes to 
9183   /* If this is a dependent type, it could end up being a class
9184  with conversions.  */
9185   if (type == NULL_TREE || WILDCARD_TYPE_P (type))
9186 return true;
and returns true.

So we call v_d_e_p, which looks at the CAST_EXPR's op and sees a TREE_LIST,
so it calls any_value_dependent_elements_p, and we end up with a NEW_EXPR.

An alternative/more proper fix would be to fix p_c_e_1/CAST_EXPR.  Maybe
by calling any_type_dependent_elements_p (which currently has no uses).
Thoughts?

> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/template/new13.C
> > @@ -0,0 +1,11 @@
> > +// PR c++/105803
> > +// { dg-do compile }
> > +// { dg-additional-options "-fchecking=2" }
> > +
> > +namespace std {
> > +template  class shared_ptr;
> > +}
> > +struct S {};
> > +template  void build_matrices() {
> > +  std::shared_ptr(new S);
> > +}
> 
> I think this testcase might be IFNDR since shared_ptr is incomplete
> at the point of its non-dependent use.

Ah, overreduced.  I've made shared_ptr complete.

Marek



[PATCH] c++: ICE with template NEW_EXPR [PR105803]

2022-06-01 Thread Marek Polacek via Gcc-patches
Here we ICE because value_dependent_expression_p gets a NEW_EXPR
whose operand is a type, and we go to the default case which just
calls v_d_e_p on each operand of the NEW_EXPR.  Since one of them
is a type, we crash on the new assert in t_d_e_p.

t_d_e_p has code to handle {,VEC_}NEW_EXPR, which at this point
was already performed, so I think we can handle these two codes
specifically and skip the second operand, which is always going
to be a type.

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

PR c++/105803

gcc/cp/ChangeLog:

* pt.cc (value_dependent_expression_p): Handle {,VEC_}NEW_EXPR
in the switch.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6de8e496859..836861e1039 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27643,6 +27643,14 @@ value_dependent_expression_p (tree expression)
 under instantiate_non_dependent_expr; it can't be constant.  */
   return true;
 
+case NEW_EXPR:
+case VEC_NEW_EXPR:
+  /* The second operand is a type, which type_dependent_expression_p
+(and therefore value_dependent_expression_p) doesn't want to see.  */
+  return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
+ || value_dependent_expression_p (TREE_OPERAND (expression, 2))
+ || value_dependent_expression_p (TREE_OPERAND (expression, 3)));
+
 default:
   /* A constant expression is value-dependent if any subexpression is
 value-dependent.  */
diff --git a/gcc/testsuite/g++.dg/template/new13.C 
b/gcc/testsuite/g++.dg/template/new13.C
new file mode 100644
index 000..3168374b26d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/new13.C
@@ -0,0 +1,11 @@
+// PR c++/105803
+// { dg-do compile }
+// { dg-additional-options "-fchecking=2" }
+
+namespace std {
+template  class shared_ptr;
+}
+struct S {};
+template  void build_matrices() {
+  std::shared_ptr(new S);
+}

base-commit: 2d546ff69455f7deadab65309de89d19380a8864
-- 
2.36.1



Re: [PATCH] c++: Add !TYPE_P assert to type_dependent_expression_p [PR99080]

2022-05-27 Thread Marek Polacek via Gcc-patches
On Fri, May 27, 2022 at 11:52:12AM -0400, Jason Merrill wrote:
> On 5/26/22 20:33, Marek Polacek wrote:
> > As discussed here:
> > <https://gcc.gnu.org/pipermail/gcc-patches/2021-February/564629.html>,
> > type_dependent_expression_p should not be called with a type argument.
> > 
> > I promised I'd add an assert so here it is.  One place needed adjusting,
> > the comment explains why.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > PR c++/99080
> > 
> > gcc/cp/ChangeLog:
> > 
> > * pt.cc (type_dependent_expression_p): Assert !TYPE_P.
> > * semantics.cc (finish_id_expression_1): Don't call
> > type_dependent_expression_p for a type.
> > ---
> >   gcc/cp/pt.cc| 2 ++
> >   gcc/cp/semantics.cc | 4 +++-
> >   2 files changed, 5 insertions(+), 1 deletion(-)
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 24bbe2f4060..89156cb88b4 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -27727,6 +27727,8 @@ type_dependent_expression_p (tree expression)
> > if (expression == NULL_TREE || expression == error_mark_node)
> >   return false;
> > +  gcc_checking_assert (!TYPE_P (expression));
> > +
> > STRIP_ANY_LOCATION_WRAPPER (expression);
> > /* An unresolved name is always dependent.  */
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index cd7a2818feb..7f8502f49b0 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -4141,7 +4141,9 @@ finish_id_expression_1 (tree id_expression,
> >   }
> > else
> >   {
> > -  bool dependent_p = type_dependent_expression_p (decl);
> > +  /* DECL could be e.g. UNBOUND_CLASS_TEMPLATE which is a type which
> > +t_d_e_p doesn't accept.  */
> > +  bool dependent_p = !TYPE_P (decl) && type_dependent_expression_p 
> > (decl);
> 
> Maybe instead we could handle UNBOUND_CLASS_TEMPLATE at a higher level in
> the function, like with an 'else if' before this 'else'?

Maybe, but I think I'd have to duplicate (parts of) this block:

 4227   else if (scope)
 4228 {
 4229   if (TREE_CODE (decl) == SCOPE_REF)
 4230 {
 4231   gcc_assert (same_type_p (scope, TREE_OPERAND (decl, 0)));
 4232   decl = TREE_OPERAND (decl, 1);
 4233 }
 4234
 4235   decl = (adjust_result_of_qualified_name_lookup
 4236   (decl, scope, current_nonlambda_class_type()));
 4237
 4238   cp_warn_deprecated_use_scopes (scope);
 4239
 4240   if (TYPE_P (scope))
 4241 decl = finish_qualified_id_expr (scope,
 4242  decl,
 4243  done,
 4244  address_p,
 4245  template_p,
 4246  template_arg_p,
 4247  tf_warning_or_error);
 4248   else
 4249 decl = convert_from_reference (decl);
 4250 }

Would that be acceptable?  Can't do

  else if (TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE)
{
  gcc_checking_assert (scope);
  *idk = CP_ID_KIND_QUALIFIED;
  goto do_scope;
}
because that will complain about skipping the initialization of dependent_p.

Here's a patch with the partial duplication, which passes dg.exp:

-- >8 --
As discussed here:
<https://gcc.gnu.org/pipermail/gcc-patches/2021-February/564629.html>,
type_dependent_expression_p should not be called with a type argument.

I promised I'd add an assert so here it is.  One place needed adjusting.

PR c++/99080

gcc/cp/ChangeLog:

* pt.cc (type_dependent_expression_p): Assert !TYPE_P.
* semantics.cc (finish_id_expression_1): Handle UNBOUND_CLASS_TEMPLATE
specifically.
---
 gcc/cp/pt.cc|  2 ++
 gcc/cp/semantics.cc | 11 +++
 2 files changed, 13 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 24bbe2f4060..89156cb88b4 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27727,6 +27727,8 @@ type_dependent_expression_p (tree expression)
   if (expression == NULL_TREE || expression == error_mark_node)
 return false;
 
+  gcc_checking_assert (!TYPE_P (expression));
+
   STRIP_ANY_LOCATION_WRAPPER (expression);
 
   /* An unresolved name is always dependent.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index cdc91a38e25..f62b0a4a736 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4139,6 +4139,17 @@ finish_id_expression_1 (tree id_expression,
}
   return r;
 }
+  el

[PATCH] c++: Fix ICE with -Wmismatched-tags [PR105725]

2022-05-27 Thread Marek Polacek via Gcc-patches
Here we ICE with -Wmismatched-tags on something like

  template 
  bool B>>;

Specifically, the "class T::foo" bit.  There, class_decl_loc_t::add gets
a TYPENAME_TYPE as TYPE, rather than a class/union type, so checking
TYPE_BEING_DEFINED will crash.  I think it's OK to allow a TYPENAME_TYPE to
slip into that function; we just shouldn't consider the 'class' tag redundant
(which works as a 'typename').  In fact, every other compiler *requires* it.

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

PR c++/105725

gcc/cp/ChangeLog:

* parser.cc (class_decl_loc_t::add): Check CLASS_TYPE_P.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wmismatched-tags-10.C: New test.
---
 gcc/cp/parser.cc|  5 +++--
 gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C | 10 ++
 2 files changed, 13 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4b9859543ed..9a9f859974a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -33666,7 +33666,8 @@ class_decl_loc_t::add (cp_parser *parser, location_t 
key_loc,
   bool key_redundant = (!def_p && !decl_p
&& (decl == type_decl
|| TREE_CODE (decl) == TEMPLATE_DECL
-   || TYPE_BEING_DEFINED (type)));
+   || (CLASS_TYPE_P (type)
+   && TYPE_BEING_DEFINED (type;
 
   if (key_redundant
   && class_key != class_type
@@ -33704,7 +33705,7 @@ class_decl_loc_t::add (cp_parser *parser, location_t 
key_loc,
}
   else
{
- /* TYPE was previously defined in some unknown precompiled hdeader.
+ /* TYPE was previously defined in some unknown precompiled header.
 Simply add a record of its definition at an unknown location and
 proceed below to add a reference to it at the current location.
 (Declarations in precompiled headers that are not definitions
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C 
b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C
new file mode 100644
index 000..d7e10743bb4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C
@@ -0,0 +1,10 @@
+// PR c++/105725
+// { dg-do compile { target c++14 } }
+// { dg-options "-Wall -Wmismatched-tags" }
+
+template  struct enable_if;
+template  using enable_if_t = typename enable_if::type;
+template  bool is_class_v;
+template  bool B;
+template 
+bool B>>;

base-commit: de57440858591a88e8fd7ba2505ca54546c86021
-- 
2.36.1



[PATCH] c-family: fix attribute constructor ICE [PR90658]

2022-05-26 Thread Marek Polacek via Gcc-patches
Here the C compiler crashes because a FUNCTION_DECL got into
get_priority -> default_conversion, and the C FE's version of d_c
specifically asserts that it doesn't get a FUNCTION_DECL.  All uses
of default_conversion in c-attribs.cc are guarded by != IDENTIFIER_NODE
&& != FUNCTION_DECL, but get_priority was only checking IDENTIFIER_NODE.

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

PR c/90658

gcc/c-family/ChangeLog:

* c-attribs.cc (get_priority): Check FUNCTION_DECL.

gcc/testsuite/ChangeLog:

* c-c++-common/attr-cdtor-1.c: New test.
---
 gcc/c-family/c-attribs.cc | 2 +-
 gcc/testsuite/c-c++-common/attr-cdtor-1.c | 6 ++
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/c-c++-common/attr-cdtor-1.c

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 4dc68dbe82a..c8d96723f4c 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -1895,7 +1895,7 @@ get_priority (tree args, bool is_destructor)
 }
 
   arg = TREE_VALUE (args);
-  if (TREE_CODE (arg) == IDENTIFIER_NODE)
+  if (TREE_CODE (arg) == IDENTIFIER_NODE || TREE_CODE (arg) == FUNCTION_DECL)
 goto invalid;
   if (arg == error_mark_node)
 return DEFAULT_INIT_PRIORITY;
diff --git a/gcc/testsuite/c-c++-common/attr-cdtor-1.c 
b/gcc/testsuite/c-c++-common/attr-cdtor-1.c
new file mode 100644
index 000..ea61336c404
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-cdtor-1.c
@@ -0,0 +1,6 @@
+/* PR c/90658 */
+/* { dg-do compile } */
+
+void f ();
+void g1 () __attribute__ ((constructor(f))); /* { dg-error "priorities must be 
integers" } */
+void g2 () __attribute__ ((destructor(f))); /* { dg-error "priorities must be 
integers" } */

base-commit: 367740bf6d3a6627798b3955e5d85efc7549ef50
-- 
2.36.1



[PATCH] c++: Add !TYPE_P assert to type_dependent_expression_p [PR99080]

2022-05-26 Thread Marek Polacek via Gcc-patches
As discussed here:
,
type_dependent_expression_p should not be called with a type argument.

I promised I'd add an assert so here it is.  One place needed adjusting,
the comment explains why.

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

PR c++/99080

gcc/cp/ChangeLog:

* pt.cc (type_dependent_expression_p): Assert !TYPE_P.
* semantics.cc (finish_id_expression_1): Don't call
type_dependent_expression_p for a type.
---
 gcc/cp/pt.cc| 2 ++
 gcc/cp/semantics.cc | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 24bbe2f4060..89156cb88b4 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27727,6 +27727,8 @@ type_dependent_expression_p (tree expression)
   if (expression == NULL_TREE || expression == error_mark_node)
 return false;
 
+  gcc_checking_assert (!TYPE_P (expression));
+
   STRIP_ANY_LOCATION_WRAPPER (expression);
 
   /* An unresolved name is always dependent.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index cd7a2818feb..7f8502f49b0 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4141,7 +4141,9 @@ finish_id_expression_1 (tree id_expression,
 }
   else
 {
-  bool dependent_p = type_dependent_expression_p (decl);
+  /* DECL could be e.g. UNBOUND_CLASS_TEMPLATE which is a type which
+t_d_e_p doesn't accept.  */
+  bool dependent_p = !TYPE_P (decl) && type_dependent_expression_p (decl);
 
   /* If the declaration was explicitly qualified indicate
 that.  The semantics of `A::f(3)' are different than

base-commit: 367740bf6d3a6627798b3955e5d85efc7549ef50
-- 
2.36.1



[PATCH] c++: fix broken copy elision with nested TARGET_EXPRs [PR105550]

2022-05-26 Thread Marek Polacek via Gcc-patches
In this problem, we are failing to properly perform copy elision with
a conditional operator, so this:

  constexpr A a = true ? A{} : A{};

fails with:

  error: 'A{((const A*)(&))}' is not a constant expression

The whole initializer is

  TARGET_EXPR }> : TARGET_EXPR }>>

where the outermost TARGET_EXPR is elided, but not the nested ones.
Then we end up replacing the PLACEHOLDER_EXPRs with the temporaries the
TARGET_EXPRs represent, which is precisely what should *not* happen with
copy elision.

I've tried the approach of tweaking ctx->object, but I ran into gazillion
problems with that.  I thought that I would let cxx_eval_constant_expression
/TARGET_EXPR create a new object only when ctx->object was null, then
adjust setting of ctx->object in places like cxx_bind_parameters_in_call
and cxx_eval_component_reference but that failed completely.  Sometimes
ctx->object has to be reset, sometimes it cannot be reset, 'this' needed
special handling, etc.  I gave up.

But now that we have potential_prvalue_result_of, a simple but less
elegant solution is the following.  I thought about setting a flag on
a TARGET_EXPR to avoid adding ctx.full_expr, but a new flag would be
overkill and using TARGET_EXPR_DIRECT_INIT_P broke things.

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

PR c++/105550

gcc/cp/ChangeLog:

* constexpr.cc (struct constexpr_ctx): Add a tree member.
(init_subob_ctx): Set it.
(cxx_eval_constant_expression): Don't initialize a temporary object
if potential_prvalue_result_of says true.
(cxx_eval_outermost_constant_expr): Adjust the ctx initializer.  Set
ctx.full_expr.
* cp-tree.h (potential_prvalue_result_of): Declare.
* typeck2.cc (potential_prvalue_result_of): No longer static.  Return
if full_expr is null.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-elision1.C: New test.
---
 gcc/cp/constexpr.cc   | 33 +---
 gcc/cp/cp-tree.h  |  1 +
 gcc/cp/typeck2.cc |  4 +-
 .../g++.dg/cpp1y/constexpr-elision1.C | 53 +++
 4 files changed, 82 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-elision1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 45208478c3f..73880fb089e 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1129,6 +1129,9 @@ struct constexpr_ctx {
   tree ctor;
   /* The object we're building the CONSTRUCTOR for.  */
   tree object;
+  /* The whole initializer expression.  Currently only used when the whole
+ expression is a TARGET_EXPR.  */
+  tree full_expr;
   /* If inside SWITCH_EXPR.  */
   constexpr_switch_state *css_state;
   /* The aggregate initialization context inside which this one is nested.  
This
@@ -4700,8 +4703,11 @@ init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx 
&new_ctx,
   new_ctx.ctor = elt;
 
   if (TREE_CODE (value) == TARGET_EXPR)
-/* Avoid creating another CONSTRUCTOR when we expand the TARGET_EXPR.  */
-value = TARGET_EXPR_INITIAL (value);
+{
+  new_ctx.full_expr = value;
+  /* Avoid creating another CONSTRUCTOR when we expand the TARGET_EXPR.  */
+  value = TARGET_EXPR_INITIAL (value);
+}
 }
 
 /* We're about to process an initializer for a class or array TYPE.  Make
@@ -6822,6 +6828,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
break;
  }
gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (t));
+   /* This TARGET_EXPR may be nested inside another TARGET_EXPR, but
+  still serve as the initializer for the same object as the outer
+  TARGET_EXPR, as in
+A a = true ? A{} : A{};
+  so we can't materialize a temporary.  IOW, don't set ctx->object
+  to the TARGET_EXPR's slot.  */
+   const bool prvalue = potential_prvalue_result_of (t, ctx->full_expr);
+   gcc_checking_assert (!prvalue || lval == vc_prvalue);
/* Avoid evaluating a TARGET_EXPR more than once.  */
tree slot = TARGET_EXPR_SLOT (t);
if (tree *p = ctx->global->values.get (slot))
@@ -6831,7 +6845,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
r = *p;
break;
  }
-   if ((AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)))
+   if (!prvalue && (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)))
  {
/* We're being expanded without an explicit target, so start
   initializing a new object; expansion with an explicit target
@@ -7748,8 +7762,8 @@ cxx_eval_outermost_constant_expr (tree t, bool 
allow_non_constant,
 }
 
   constexpr_global_ctx global_ctx;
-  constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
-   allow_non_constant, strict,
+  constexpr_ctx ctx = { &global_ctx, nullptr, nullptr, NULL_TREE, NULL_TREE,
+  

Re: [PATCH v2] c++: suppress -Waddress warnings with *_cast [PR105569]

2022-05-26 Thread Marek Polacek via Gcc-patches
On Thu, May 26, 2022 at 09:26:16AM -0400, Jason Merrill wrote:
> On 5/25/22 16:25, Marek Polacek wrote:
> > On Wed, May 18, 2022 at 09:43:47AM -0400, Jason Merrill wrote:
> > > On 5/16/22 13:06, Marek Polacek wrote:
> > > > dynamic_cast can legally return nullptr, so I don't think it's helpful
> > > > for -Waddress to warn for
> > > > 
> > > > if (dynamic_cast(&ref))
> > > >   // ...
> > > > 
> > > > More generally, it's likely not useful to warn for the artificial
> > > > POINTER_PLUS_EXPRs created by build_base_path.
> > > 
> > > Normally the POINTER_PLUS_EXPR is guarded by if (nonnull).  But
> > > build_base_path isn't adding that guard in this case because the operand 
> > > is
> > > known to be a reference, which cannot be null
> > > (http://eel.is/c++draft/dcl.ref#5).  So a warning is indicated for this
> > > testcase, though it would be good to give a more informative one 
> > > ("comparing
> > > address of reference to null").
> > 
> > Ah, got it.  How about this patch instead?  Thanks,
> 
> Do we also warn about plain &ref == nullptr?

Yeah, with different wording:

p.C:5:12: warning: the compiler can assume that the address of ‘ref’ will never 
be NULL [-Waddress]
5 |   if (&ref == nullptr)
  |   ~^~

warn/Walways-true-3.C tests this.

> > -- >8 --
> > This patch improves the diagnostic for -Waddress when it warns for
> > 
> >if (dynamic_cast(&ref))
> >  // ...
> > 
> > where 'ref' is a reference, which cannot be null.  In particular, it
> > changes
> > warning: comparing the result of pointer addition '(((A*)ref) + 
> > ((sizetype)(*(long int*)((& ref)->B::_vptr.B + -24' and NULL
> > to
> > warning: comparing address of reference 'ref' to null
> > 
> > PR c++/105569
> > 
> > gcc/cp/ChangeLog:
> > 
> > * typeck.cc (warn_for_null_address): Improve the warning when
> > the POINTER_PLUS_EXPR's base is of reference type.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/warn/Waddress-9.C: New test.
> > ---
> >   gcc/cp/typeck.cc   | 12 --
> >   gcc/testsuite/g++.dg/warn/Waddress-9.C | 31 ++
> >   2 files changed, 41 insertions(+), 2 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/warn/Waddress-9.C
> > 
> > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> > index 385cdf4d733..0837f2484ba 100644
> > --- a/gcc/cp/typeck.cc
> > +++ b/gcc/cp/typeck.cc
> > @@ -4757,8 +4757,16 @@ warn_for_null_address (location_t location, tree op, 
> > tsubst_flags_t complain)
> > tree off = TREE_OPERAND (cop, 1);
> > if (!integer_zerop (off)
> >   && !warning_suppressed_p (cop, OPT_Waddress))
> > -   warning_at (location, OPT_Waddress, "comparing the result of pointer "
> > -   "addition %qE and NULL", cop);
> > +   {
> > + tree base = TREE_OPERAND (cop, 0);
> > + STRIP_NOPS (base);
> > + if (TYPE_REF_P (TREE_TYPE (base)))
> > +   warning_at (location, OPT_Waddress, "comparing address of "
> > +   "reference %qE and NULL", base);
> > + else
> > +   warning_at (location, OPT_Waddress, "comparing the result of "
> > +   "pointer addition %qE and NULL", cop);
> > +   }
> > return;
> >   }
> > else if (CONVERT_EXPR_P (op)
> > diff --git a/gcc/testsuite/g++.dg/warn/Waddress-9.C 
> > b/gcc/testsuite/g++.dg/warn/Waddress-9.C
> > new file mode 100644
> > index 000..a3654ff1f91
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/warn/Waddress-9.C
> > @@ -0,0 +1,31 @@
> > +// PR c++/105569
> > +// { dg-do compile { target c++11 } }
> > +// { dg-options -Waddress }
> > +
> > +class A {};
> > +
> > +class B : public virtual A {};
> > +
> > +class C : public A {};
> > +
> > +int main() {
> > +B* object = new B();
> > +B &ref = *object;
> > +
> > +bool b = nullptr == dynamic_cast(&ref); // { dg-warning "comparing 
> > address of reference .ref. and NULL" }
> > +bool b4 = nullptr == static_cast(&ref); // { dg-warning "comparing 
> > address of reference .ref. and NULL" }
> > +if (dynamic_cast(&ref)) // { dg-warning "comparing address of 
> > reference .ref. and NULL" }
> > +  {
> > +  }
> > +if (static_cast(&ref)) // { dg-warning "comparing address of 
> > reference .ref. and NULL" }
> > +  {
> > +  }
> > +
> > +auto ptr = dynamic_cast(&ref);
> > +bool b2 = ptr == nullptr;
> > +
> > +C* cobject = new C();
> > +C &cref = *cobject;
> > +
> > +bool b3 = nullptr == dynamic_cast(&cref);
> > +}
> > 
> > base-commit: 34970d08c6297e12f3f9117b6ac19fb2de522e24
> 

Marek



[PATCH v2] c++: suppress -Waddress warnings with *_cast [PR105569]

2022-05-25 Thread Marek Polacek via Gcc-patches
On Wed, May 18, 2022 at 09:43:47AM -0400, Jason Merrill wrote:
> On 5/16/22 13:06, Marek Polacek wrote:
> > dynamic_cast can legally return nullptr, so I don't think it's helpful
> > for -Waddress to warn for
> > 
> >if (dynamic_cast(&ref))
> >  // ...
> > 
> > More generally, it's likely not useful to warn for the artificial
> > POINTER_PLUS_EXPRs created by build_base_path.
> 
> Normally the POINTER_PLUS_EXPR is guarded by if (nonnull).  But
> build_base_path isn't adding that guard in this case because the operand is
> known to be a reference, which cannot be null
> (http://eel.is/c++draft/dcl.ref#5).  So a warning is indicated for this
> testcase, though it would be good to give a more informative one ("comparing
> address of reference to null").

Ah, got it.  How about this patch instead?  Thanks,

-- >8 --
This patch improves the diagnostic for -Waddress when it warns for

  if (dynamic_cast(&ref))
// ...

where 'ref' is a reference, which cannot be null.  In particular, it
changes
warning: comparing the result of pointer addition '(((A*)ref) + 
((sizetype)(*(long int*)((& ref)->B::_vptr.B + -24' and NULL
to
warning: comparing address of reference 'ref' to null

PR c++/105569

gcc/cp/ChangeLog:

* typeck.cc (warn_for_null_address): Improve the warning when
the POINTER_PLUS_EXPR's base is of reference type.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Waddress-9.C: New test.
---
 gcc/cp/typeck.cc   | 12 --
 gcc/testsuite/g++.dg/warn/Waddress-9.C | 31 ++
 2 files changed, 41 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Waddress-9.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 385cdf4d733..0837f2484ba 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -4757,8 +4757,16 @@ warn_for_null_address (location_t location, tree op, 
tsubst_flags_t complain)
   tree off = TREE_OPERAND (cop, 1);
   if (!integer_zerop (off)
  && !warning_suppressed_p (cop, OPT_Waddress))
-   warning_at (location, OPT_Waddress, "comparing the result of pointer "
-   "addition %qE and NULL", cop);
+   {
+ tree base = TREE_OPERAND (cop, 0);
+ STRIP_NOPS (base);
+ if (TYPE_REF_P (TREE_TYPE (base)))
+   warning_at (location, OPT_Waddress, "comparing address of "
+   "reference %qE and NULL", base);
+ else
+   warning_at (location, OPT_Waddress, "comparing the result of "
+   "pointer addition %qE and NULL", cop);
+   }
   return;
 }
   else if (CONVERT_EXPR_P (op)
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-9.C 
b/gcc/testsuite/g++.dg/warn/Waddress-9.C
new file mode 100644
index 000..a3654ff1f91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-9.C
@@ -0,0 +1,31 @@
+// PR c++/105569
+// { dg-do compile { target c++11 } }
+// { dg-options -Waddress }
+
+class A {};
+
+class B : public virtual A {};
+
+class C : public A {};
+
+int main() {
+B* object = new B();
+B &ref = *object;
+
+bool b = nullptr == dynamic_cast(&ref); // { dg-warning "comparing 
address of reference .ref. and NULL" }
+bool b4 = nullptr == static_cast(&ref); // { dg-warning "comparing 
address of reference .ref. and NULL" }
+if (dynamic_cast(&ref)) // { dg-warning "comparing address of 
reference .ref. and NULL" }
+  {
+  }
+if (static_cast(&ref)) // { dg-warning "comparing address of reference 
.ref. and NULL" }
+  {
+  }
+
+auto ptr = dynamic_cast(&ref);
+bool b2 = ptr == nullptr;
+
+C* cobject = new C();
+C &cref = *cobject;
+
+bool b3 = nullptr == dynamic_cast(&cref);
+}

base-commit: 34970d08c6297e12f3f9117b6ac19fb2de522e24
-- 
2.36.1



Re: [PATCH] c++: fix ICE on invalid attributes [PR96637]

2022-05-25 Thread Marek Polacek via Gcc-patches
On Tue, May 24, 2022 at 08:22:22AM -0400, Jason Merrill wrote:
> On 4/29/22 10:12, Marek Polacek wrote:
> > This patch fixes crashes with invalid attributes.  Arguably it could
> > make sense to assert seen_error() too.
> 
> So in this testcase we have TREE_CHAIN of a TREE_LIST pointing to
> error_mark_node?  Can we avoid that?

Yes and yes.  Sorry, my previous fix was lousy.  This one is better:

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

-- >8 --
When chaining attributes, attr_chainon should be used rather than plain
chainon, so that we don't end up with a TREE_LIST where one of the elements
is error_mark_node, which causes problems.  parser.cc has already been
fixed to use attr_chainon, but decl.cc has not.  Until now.

PR c++/96637

gcc/cp/ChangeLog:

* cp-tree.h (attr_chainon): Declare.
* decl.cc (start_decl): Use attr_chainon.
(grokdeclarator): Likewise.
* parser.cc (cp_parser_statement): No longer static.

gcc/testsuite/ChangeLog:

* g++.dg/parse/error64.C: New test.
---
 gcc/cp/cp-tree.h |  1 +
 gcc/cp/decl.cc   | 19 ++-
 gcc/cp/parser.cc |  2 +-
 gcc/testsuite/g++.dg/parse/error64.C |  4 
 4 files changed, 16 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/error64.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ba986e892b6..d77fd1eb8a9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7235,6 +7235,7 @@ extern void inject_this_parameter (tree, cp_cv_quals);
 extern location_t defparse_location (tree);
 extern void maybe_show_extern_c_location (void);
 extern bool literal_integer_zerop (const_tree);
+extern tree attr_chainon (tree, tree);
 
 /* in pt.cc */
 extern tree canonical_type_parameter   (tree);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 381259cb9cf..b1ea838ce8b 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -5557,7 +5557,7 @@ start_decl (const cp_declarator *declarator,
   *pushed_scope_p = NULL_TREE;
 
   if (prefix_attributes != error_mark_node)
-attributes = chainon (attributes, prefix_attributes);
+attributes = attr_chainon (attributes, prefix_attributes);
 
   decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
 &attributes);
@@ -12728,9 +12728,10 @@ grokdeclarator (const cp_declarator *declarator,
   as a whole.  */
late_attrs = splice_template_attributes (&attrs, type);
  returned_attrs = decl_attributes (&type,
-   chainon (returned_attrs, attrs),
+   attr_chainon (returned_attrs,
+ attrs),
attr_flags);
- returned_attrs = chainon (late_attrs, returned_attrs);
+ returned_attrs = attr_chainon (late_attrs, returned_attrs);
}
 
   inner_declarator = declarator->declarator;
@@ -12781,8 +12782,8 @@ grokdeclarator (const cp_declarator *declarator,
 
   The optional attribute-specifier-seq appertains to the
   array.  */
-   returned_attrs = chainon (returned_attrs,
- declarator->std_attributes);
+   returned_attrs = attr_chainon (returned_attrs,
+  declarator->std_attributes);
  break;
 
case cdk_function:
@@ -13122,9 +13123,9 @@ grokdeclarator (const cp_declarator *declarator,
/* transaction_safe applies to the type, but
   transaction_safe_dynamic applies to the function.  */
if (is_attribute_p ("transaction_safe", tx_qual))
- attrs = chainon (attrs, att);
+ attrs = attr_chainon (attrs, att);
else
- returned_attrs = chainon (returned_attrs, att);
+ returned_attrs = attr_chainon (returned_attrs, att);
  }
if (attrs)
  /* [dcl.fct]/2:
@@ -13438,7 +13439,7 @@ grokdeclarator (const cp_declarator *declarator,
   if (returned_attrs)
 {
   if (attrlist)
-   *attrlist = chainon (returned_attrs, *attrlist);
+   *attrlist = attr_chainon (returned_attrs, *attrlist);
   else
attrlist = &returned_attrs;
 }
@@ -13451,7 +13452,7 @@ grokdeclarator (const cp_declarator *declarator,
   /* [dcl.meaning]/1: The optional attribute-specifier-seq following
 a declarator-id appertains to the entity that is declared.  */
   if (declarator->std_attributes != error_mark_node)
-   *attrlist = chainon (*attrlist, declarator->std_attributes);
+   *attrlist = attr_chainon (*attrlist, declarator->std_attributes);
   else
/* We should have already diagnosed the issue (c++/78344).  */

Re: [wwwdocs] Add C status page

2022-05-24 Thread Marek Polacek via Gcc-patches
On Tue, May 24, 2022 at 06:11:09PM +, Joseph Myers wrote:
> On Tue, 24 May 2022, Marek Polacek via Gcc-patches wrote:
> 
> > I thought it'd be nice to have a table that documents our C support
> > status, like we have https://gcc.gnu.org/projects/cxx-status.html for C++.
> > We have https://gcc.gnu.org/c99status.html, but that's C99 only.
> > 
> > So here's a patch to add just that.  For C99, I used c99status.html but
> > added paper numbers (taken from https://clang.llvm.org/c_status.html).
> 
> For C11, see https://gcc.gnu.org/wiki/C11Status (note: I haven't checked 
> the accuracy of that page).

Ah, nice (I almost never use our wiki).  One more reason to have a single
place for such overviews.
 
> Listing in terms of features is more useful than listing in terms of 
> papers.  Referring to the original paper, even if it's the version that 
> got accepted into the standard, is liable to be actively misleading to 
> anyone working on the implementation; sometimes the paper has multiple 
> choices of which only one was accepted into the standard, or only some of 
> the listed changes were accepted, or there were various subsequent 
> features or fixes from various subsequent papers.

Right, so I think it would make sense to have one line for a feature, and
add related papers to the second column, as we do in the C++ table:
https://gcc.gnu.org/projects/cxx-status.html (see e.g. concepts).

> (By way of example, it 
> would make more sense to list _BitInt as a single entry for a missing 
> feature than to separately list N2763 and N2775 (accepted papers), while 
> N2960, to be considered at the July meeting of WG14, makes further wording 
> fixes but can't exactly be considered a feature in a sense that should be 
> listed in such a table.)

OK, so I think we should have one feature ("_BitInt") and have those three
papers in the "Proposal" column.

> Lots of papers are just cleanups, or 
> clarification of wording, or fixes to issues with previous papers, such 
> that it doesn't make sense to list them as implemented or not at all.

For those either we could say "N/A" (gray color), or not mention them at
all, though I'd perfer the former.  
 
> As usual there are also cases where a feature is implemented to the extent 
> relevant for conformance but e.g. more optimizations (such as built-in 
> functions) could be added.

Notes like these could go to the "Notes" column.

> And cases where some support in GCC should 
> definitely be done to consider the feature implemented, even when not 
> needed for conformance (e.g. the %wN, %wfN printf/scanf formats need 
> implementing in glibc, and corresponding format checking support needs 
> implementing in GCC).

These could be marked as "partially implemented" (yellow color).  Except
I often don't know which features need extensions like that.

> There are also cases where a feature is 
> substantially there but a more detailed review should be done for how it 
> matches up to the standard version (e.g. the DFP support based on TR 
> 24732-2009 could do with such a detailed review for how it matches C2x 
> requirements).

Indeed, and that's a hard problem.  I for one could never figure out this
one.  So I'd leave it in the "?" (red color) state.
 
> > +
> > +  Binary literals
> > +   > href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2549.pdf";>N2549
> > +  GCC 
> > 11
> > +  
> > +
> 
> This is an example of cases where the version where a feature was 
> supported in GCC as an extension is long before the version where 
> -pedantic knows about it being supported in a given standard version; 
> listing the version with the -pedantic change in such cases may not be 
> very helpful without noting when it was originally implemented.

Probably here we could just say "Yes" (green color) and make a note in the
"Notes" column.

> There are 
> probably other examples in the list.  (There are also examples where GCC 
> supports the feature but hasn't yet had -pedantic updated accordingly, 
> e.g. #warning.  And cases where it's largely supported but there are small 
> differences in the standard version that still need implementing, e.g. 
> typeof.)
 
Yeah, I bet.  It's tricky to decide :/.

> > +
> > +  What we think we reserve
> > +   > href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2572.pdf";>N2572
> > +  ?
> > +  
> > +
> 
> This is an example of the many cases where it doesn't make sense to 
> consider something as a feature with an "implemented" or &

Re: [PATCH v5] c++: ICE with temporary of class type in DMI [PR100252]

2022-05-24 Thread Marek Polacek via Gcc-patches
On Tue, May 24, 2022 at 04:01:37PM -0400, Jason Merrill wrote:
> On 5/24/22 09:55, Marek Polacek wrote:
> > On Tue, May 24, 2022 at 08:36:39AM -0400, Jason Merrill wrote:
> > > On 5/16/22 11:36, Marek Polacek wrote:
> > > > +static tree
> > > > +replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
> > > > +{
> > > > +  tree t = *tp;
> > > > +  tree full_expr = *static_cast(data);
> > > > +
> > > > +  /* We're looking for a TARGET_EXPR nested in the whole expression.  
> > > > */
> > > > +  if (TREE_CODE (t) == TARGET_EXPR
> > > > +  && !potential_prvalue_result_of (t, full_expr))
> > > > +{
> > > > +  tree init = TARGET_EXPR_INITIAL (t);
> > > > +  while (TREE_CODE (init) == COMPOUND_EXPR)
> > > > +   init = TREE_OPERAND (init, 1);
> > > 
> > > Hmm, how do we get a COMPOUND_EXPR around a CONSTRUCTOR?
> > 
> > Sadly, that's possible for code like (from nsdmi-aggr18.C)
> > 
> > struct D {
> >int x = 42;
> >B b = (true, A{x});
> > };
> > 
> > where the TARGET_EXPR_INITIAL is
> > <<< Unknown tree: void_cst >>>, {.x=((struct D *) this)->x, 
> > .y=(&)->x}
> 
> Hmm, perhaps cp_build_compound_expr should build an additional TARGET_EXPR
> around the COMPOUND_EXPR but leave the one inside alone. Feel free to
> investigate that if you'd like, or the patch is OK as is.

Sorry, I was unclear.  The whole expression is:

TARGET_EXPR >>, {.x=((struct D *) this)->x, .y=(&)->x}>)>

so there *is* a TARGET_EXPR around the COMPOUND_EXPR.  We'd have to build
a TARGET_EXPR around the COMPOUND_EXPR's RHS = the CONSTRUCTOR.  Frankly,
I'm not sure if it's worth the effort.  The while loop is somewhat unsightly
but not too bad.

Marek



[wwwdocs] Add C status page

2022-05-24 Thread Marek Polacek via Gcc-patches
I thought it'd be nice to have a table that documents our C support
status, like we have https://gcc.gnu.org/projects/cxx-status.html for C++.
We have https://gcc.gnu.org/c99status.html, but that's C99 only.

So here's a patch to add just that.  For C99, I used c99status.html but
added paper numbers (taken from https://clang.llvm.org/c_status.html).

I've filed the availability status of some of the features, but not all;
I know next to nothing about the floating-point features.  I hope these
will get filed in due time.

It would also be nice to have a C DR table, like we have for C++:
https://gcc.gnu.org/projects/cxx-dr-status.html
but that's a bigger task.

Validated.  Any comments before I push it?

diff --git a/htdocs/projects/c-status.html b/htdocs/projects/c-status.html
new file mode 100644
index ..cc240c07
--- /dev/null
+++ b/htdocs/projects/c-status.html
@@ -0,0 +1,995 @@
+
+
+
+
+  C Standards Support in GCC
+https://gcc.gnu.org/gcc.css"; />
+
+
+
+  C Standards Support in GCC
+
+  GCC supports different dialects of C, corresponding to the multiple
+  published ISO standards.  Which standard it implements can be selected using
+  the -std= command-line option.
+
+  
+C89
+C99
+C11
+C17
+C2x
+  
+
+
+
+  C2x Support in GCC
+
+  GCC has experimental support for the next revision of the C
+  standard.
+
+  C2X features are available since GCC 9. To enable C2X support, add the
+  command-line parameter -std=c2x to your gcc command
+  line.  Or, to enable GNU extensions in addition to C2X features, add
+  -std=gnu2x.  These options are available since
+  GCC 9.
+
+  Important: Because the ISO C2X standard is still
+evolving, GCC's support is experimental.  No attempt will
+be made to maintain backward compatibility with implementations of C2X
+features that do not reflect the final standard.
+
+  C2X Language Features
+
+  
+
+  Language Feature
+  Proposal
+  Available in GCC?
+  Notes
+
+
+
+  Evaluation formats
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2186.pdf";>N2186
+  ?
+  
+
+
+  Clarifying the restrict Keyword v2
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2260.pdf";>N2660
+  ?
+  
+
+
+  Harmonizing static_assert with C++
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2265.pdf";>N2665
+  ?
+  
+
+
+  nodiscard attribute
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2667.pdf";>N2667
+  GCC 11
+  
+
+
+  maybe_unused attribute
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2670.pdf";>N2670
+  GCC 10
+  
+
+
+  TS 18661 Integration
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2314.pdf";>N2314
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2341.pdf";>N2341
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2401.pdf";>N2401
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2359.pdf";>N2359
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2546.pdf";>N2546
+  ?
+  This is supported at least partially.
+
+
+  Preprocessor line numbers unspecified
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2322.htm";>N2322
+  ?
+  
+
+
+  deprecated attribute
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2334.pdf";>N2334
+  GCC 10
+  
+
+
+  Attributes
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2335.pdf";>N2335
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2554.pdf";>N2554
+  ?
+  
+
+
+  Defining new types in offsetof
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm";>N2350
+  ?
+  
+
+
+  fallthrough attribute
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2408.pdf";>N2408
+  GCC 10
+  
+
+
+  Two's complement sign representation
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf";>N2412
+  ?
+  
+
+
+  Adding the u8 character prefix
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2418.pdf";>N2418
+  ?
+  
+
+
+  Remove support for function definitions with identifier lists
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2432.pdf";>N2432
+  ?
+  
+
+
+
+  *_IS_IEC_60559 feature test macros
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2379.htm";>N2379
+  ?
+  
+
+
+  Floating-point negation and conversion
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2416.pdf";>N2416
+  ?
+  
+
+
+  Annex F.8 update for implementation extensions and rounding
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2384.pdf";>N2384
+  ?
+  
+
+
+  _Bool definitions for true and false
+  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2393.pdf";>N2393
+  ?
+  
+
+
+
+  [[

Re: [PATCH v5] c++: ICE with temporary of class type in DMI [PR100252]

2022-05-24 Thread Marek Polacek via Gcc-patches
On Tue, May 24, 2022 at 08:36:39AM -0400, Jason Merrill wrote:
> On 5/16/22 11:36, Marek Polacek wrote:
> > +static tree
> > +replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
> > +{
> > +  tree t = *tp;
> > +  tree full_expr = *static_cast(data);
> > +
> > +  /* We're looking for a TARGET_EXPR nested in the whole expression.  */
> > +  if (TREE_CODE (t) == TARGET_EXPR
> > +  && !potential_prvalue_result_of (t, full_expr))
> > +{
> > +  tree init = TARGET_EXPR_INITIAL (t);
> > +  while (TREE_CODE (init) == COMPOUND_EXPR)
> > +   init = TREE_OPERAND (init, 1);
> 
> Hmm, how do we get a COMPOUND_EXPR around a CONSTRUCTOR?

Sadly, that's possible for code like (from nsdmi-aggr18.C)

struct D {
  int x = 42;
  B b = (true, A{x});
};

where the TARGET_EXPR_INITIAL is
<<< Unknown tree: void_cst >>>, {.x=((struct D *) this)->x, 
.y=(&)->x}

Marek



Re: [PATCH] c: Improve build_component_ref diagnostics [PR91134]

2022-05-24 Thread Marek Polacek via Gcc-patches
On Tue, May 24, 2022 at 09:25:57AM +0200, Jakub Jelinek wrote:
> Hi!
> 
> On the following testcase (the first dg-error line) we emit a weird
> diagnostics and even fixit on pointerpointer->member
> where pointerpointer is pointer to pointer to struct and we say
> 'pointerpointer' is a pointer; did you mean to use '->'?
> The first part is indeed true, but suggesting -> when the code already
> does use -> is confusing.
> The following patch adjusts callers so that they tell it if it is from
> . parsing or from -> parsing and in the latter case suggests to dereference
> the left operand instead by adding (* before it and ) after it (before ->).
> Or would a suggestion to add [0] before -> be better?
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2022-05-24  Jakub Jelinek  
> 
>   PR c/91134
> gcc/c/
>   * c-tree.h (build_component_ref): Add ARROW_LOC location_t argument.
>   * c-typeck.cc (build_component_ref): Likewise.  If DATUM is
>   INDIRECT_REF and ARROW_LOC isn't UNKNOWN_LOCATION, print a different
>   diagnostics and fixit hint if DATUM has pointer type.

s/diagnostic/, missing "than" before if?

>   * c-parser.cc (c_parser_postfix_expression,
>   c_parser_omp_variable_list): Adjust build_component_ref callers.
>   * gimple-parser.cc (c_parser_gimple_postfix_expression_after_primary):
>   Likewise.
> gcc/objc/
>   * objc-act.cc (objc_build_component_ref): Adjust build_component_ref
>   caller.
> gcc/testsuite/
>   * gcc.dg/pr91134.c: New test.
> 
> --- gcc/c/c-tree.h.jj 2022-05-19 11:48:56.058291437 +0200
> +++ gcc/c/c-tree.h2022-05-23 20:22:05.669515990 +0200
> @@ -699,7 +699,8 @@ extern struct c_expr convert_lvalue_to_r
>  extern tree decl_constant_value_1 (tree, bool);
>  extern void mark_exp_read (tree);
>  extern tree composite_type (tree, tree);
> -extern tree build_component_ref (location_t, tree, tree, location_t);
> +extern tree build_component_ref (location_t, tree, tree, location_t,
> +  location_t);
>  extern tree build_array_ref (location_t, tree, tree);
>  extern tree build_external_ref (location_t, tree, bool, tree *);
>  extern void pop_maybe_used (bool);
> --- gcc/c/c-typeck.cc.jj  2022-05-19 11:48:56.077291176 +0200
> +++ gcc/c/c-typeck.cc 2022-05-23 20:23:44.713515875 +0200
> @@ -2457,11 +2457,12 @@ should_suggest_deref_p (tree datum_type)
>  /* Make an expression to refer to the COMPONENT field of structure or
> union value DATUM.  COMPONENT is an IDENTIFIER_NODE.  LOC is the
> location of the COMPONENT_REF.  COMPONENT_LOC is the location
> -   of COMPONENT.  */
> +   of COMPONENT.  ARROW_LOC is the location of first -> operand if

"of the first"?

> +   it is from -> operator.  */
>  
>  tree
>  build_component_ref (location_t loc, tree datum, tree component,
> -  location_t component_loc)
> +  location_t component_loc, location_t arrow_loc)
>  {
>tree type = TREE_TYPE (datum);
>enum tree_code code = TREE_CODE (type);
> @@ -2577,11 +2578,23 @@ build_component_ref (location_t loc, tre
>/* Special-case the error message for "ptr.field" for the case
>where the user has confused "." vs "->".  */
>rich_location richloc (line_table, loc);
> -  /* "loc" should be the "." token.  */
> -  richloc.add_fixit_replace ("->");
> -  error_at (&richloc,
> - "%qE is a pointer; did you mean to use %<->%>?",
> - datum);
> +  if (TREE_CODE (datum) == INDIRECT_REF && arrow_loc != UNKNOWN_LOCATION)
> + {
> +   richloc.add_fixit_insert_before (arrow_loc, "(*");
> +   richloc.add_fixit_insert_after (arrow_loc, ")");
> +   error_at (&richloc,
> + "%qE is a pointer to pointer; did you mean to dereference "
> + "it before applying %<->%> to it?",
> + TREE_OPERAND (datum, 0));
> + }
> +  else
> + {
> +   /* "loc" should be the "." token.  */
> +   richloc.add_fixit_replace ("->");
> +   error_at (&richloc,
> + "%qE is a pointer; did you mean to use %<->%>?",
> + datum);
> + }
>return error_mark_node;
>  }
>else if (code != ERROR_MARK)
> --- gcc/c/c-parser.cc.jj  2022-05-23 16:16:30.360856580 +0200
> +++ gcc/c/c-parser.cc 2022-05-23 20:33:36.683537409 +0200
> @@ -9235,8 +9235,9 @@ c_parser_postfix_expression (c_parser *p
>   if (c_parser_next_token_is (parser, CPP_NAME))
> {
>   c_token *comp_tok = c_parser_peek_token (parser);
> - offsetof_ref = build_component_ref
> -   (loc, offsetof_ref, comp_tok->value, comp_tok->location);
> + offsetof_ref
> +   = build_component_ref (loc, offsetof_ref, comp_tok->value,
> +  comp_tok->location, UNKNOWN_LOCATION);
>   c_parser_consume_token (parser);
>   while (c_par

Re: [PATCH] c++: fix ICE on invalid attributes [PR96637]

2022-05-24 Thread Marek Polacek via Gcc-patches
On Tue, May 24, 2022 at 05:29:56PM +0530, Prathamesh Kulkarni wrote:
> On Fri, 29 Apr 2022 at 19:44, Marek Polacek via Gcc-patches
>  wrote:
> >
> > This patch fixes crashes with invalid attributes.  Arguably it could
> > make sense to assert seen_error() too.
> >
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk = GCC 13?
> >
> > PR c++/96637
> >
> > gcc/ChangeLog:
> >
> > * attribs.cc (decl_attributes): Check error_mark_node.
> >
> > gcc/cp/ChangeLog:
> >
> > * decl2.cc (cp_check_const_attributes): Check error_mark_node.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/parse/error64.C: New test.
> > ---
> >  gcc/attribs.cc   | 3 +++
> >  gcc/cp/decl2.cc  | 2 ++
> >  gcc/testsuite/g++.dg/parse/error64.C | 4 
> >  3 files changed, 9 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/parse/error64.C
> >
> > diff --git a/gcc/attribs.cc b/gcc/attribs.cc
> > index b219f878042..ff157dcf81c 100644
> > --- a/gcc/attribs.cc
> > +++ b/gcc/attribs.cc
> > @@ -700,6 +700,9 @@ decl_attributes (tree *node, tree attributes, int flags,
> >   in the same order as in the source.  */
> >for (tree attr = attributes; attr; attr = TREE_CHAIN (attr))
> >  {
> > +  if (attr == error_mark_node)
> > +   continue;
> Not a comment on the patch specifically, but just wondering if it'd be
> better to use error_operand_p,
> than testing against error_mark_node explicitly ?

Not here, I don't think; it tests more than is needed here.

Marek



Re: [PATCH] c++: fix ICE on invalid attributes [PR96637]

2022-05-24 Thread Marek Polacek via Gcc-patches
Ping.

On Fri, Apr 29, 2022 at 10:12:33AM -0400, Marek Polacek via Gcc-patches wrote:
> This patch fixes crashes with invalid attributes.  Arguably it could
> make sense to assert seen_error() too.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk = GCC 13?
> 
>   PR c++/96637
> 
> gcc/ChangeLog:
> 
>   * attribs.cc (decl_attributes): Check error_mark_node.
> 
> gcc/cp/ChangeLog:
> 
>   * decl2.cc (cp_check_const_attributes): Check error_mark_node.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/parse/error64.C: New test.
> ---
>  gcc/attribs.cc   | 3 +++
>  gcc/cp/decl2.cc  | 2 ++
>  gcc/testsuite/g++.dg/parse/error64.C | 4 
>  3 files changed, 9 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/parse/error64.C
> 
> diff --git a/gcc/attribs.cc b/gcc/attribs.cc
> index b219f878042..ff157dcf81c 100644
> --- a/gcc/attribs.cc
> +++ b/gcc/attribs.cc
> @@ -700,6 +700,9 @@ decl_attributes (tree *node, tree attributes, int flags,
>   in the same order as in the source.  */
>for (tree attr = attributes; attr; attr = TREE_CHAIN (attr))
>  {
> +  if (attr == error_mark_node)
> + continue;
> +
>tree ns = get_attribute_namespace (attr);
>tree name = get_attribute_name (attr);
>tree args = TREE_VALUE (attr);
> diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
> index d2b29208ed5..c3ff1962a75 100644
> --- a/gcc/cp/decl2.cc
> +++ b/gcc/cp/decl2.cc
> @@ -1537,6 +1537,8 @@ cp_check_const_attributes (tree attributes)
>/* As we implement alignas using gnu::aligned attribute and
>alignas argument is a constant expression, force manifestly
>constant evaluation of aligned attribute argument.  */
> +  if (attr == error_mark_node)
> + continue;
>bool manifestly_const_eval
>   = is_attribute_p ("aligned", get_attribute_name (attr));
>for (arg = TREE_VALUE (attr); arg && TREE_CODE (arg) == TREE_LIST;
> diff --git a/gcc/testsuite/g++.dg/parse/error64.C 
> b/gcc/testsuite/g++.dg/parse/error64.C
> new file mode 100644
> index 000..87848a58c27
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/parse/error64.C
> @@ -0,0 +1,4 @@
> +// PR c++/96637
> +// { dg-do compile }
> +
> +void foo(int[] alignas[1] alignas(1)){} // { dg-error "" }
> 
> base-commit: 9ae8b993cd362e8aea4f65580aaf1453120207f2
> -- 
> 2.35.1
> 

Marek



Re: [PATCH v5] c++: ICE with temporary of class type in DMI [PR100252]

2022-05-24 Thread Marek Polacek via Gcc-patches
Ping.

On Mon, May 16, 2022 at 11:36:27AM -0400, Marek Polacek wrote:
> On Sat, May 14, 2022 at 11:13:28PM -0400, Jason Merrill wrote:
> > On 5/13/22 19:41, Marek Polacek wrote:
> > > --- a/gcc/cp/typeck2.cc
> > > +++ b/gcc/cp/typeck2.cc
> > > @@ -1371,6 +1371,70 @@ digest_init_flags (tree type, tree init, int 
> > > flags, tsubst_flags_t complain)
> > > return digest_init_r (type, init, 0, flags, complain);
> > >   }
> > > +/* Return true if a prvalue is used as an initializer rather than for
> > > +   temporary materialization.  For instance:
> > 
> > I might say "if SUBOB initializes the same object as FULL_EXPR"; the
> > full-expression could still end up initializing a temporary.
> 
> Fixed.
>  
> > > + A a = A{};// initializer
> > > + A a = (A{});  // initializer
> > > + A a = (1, A{});   // initializer
> > > + A a = true ? A{} : A{};  // initializer
> > > + auto x = A{}.x;   // temporary materialization
> > > + auto x = foo(A{});// temporary materialization
> > > +
> > > +   FULL_EXPR is the whole expression, SUBOB is its TARGET_EXPR 
> > > subobject.  */
> > > +
> > > +static bool
> > > +potential_prvalue_result_of (tree subob, tree full_expr)
> > > +{
> > > +  if (subob == full_expr)
> > > +return true;
> > > +  else if (TREE_CODE (full_expr) == TARGET_EXPR)
> > > +{
> > > +  tree init = TARGET_EXPR_INITIAL (full_expr);
> > > +  if (TREE_CODE (init) == COND_EXPR)
> > > + return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 1))
> > > + || potential_prvalue_result_of (subob, TREE_OPERAND (init, 2)));
> > > +  else if (TREE_CODE (init) == COMPOUND_EXPR)
> > > + return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 0))
> > 
> > We shouldn't recurse into the LHS of the comma, only the RHS.
> 
> Fixed.
>  
> > > + || potential_prvalue_result_of (subob, TREE_OPERAND (init, 1)));
> > > +  /* ??? I don't know if this can be hit.  If so, look inside the ( )
> > > +  instead of the assert.  */
> > > +  else if (TREE_CODE (init) == PAREN_EXPR)
> > > + gcc_checking_assert (false);
> > 
> > It seems trivial enough to recurse after the assert, in case it does happen
> > in the wild.
> 
> OK, adjusted.  Thanks!
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
> -- >8 --
> Consider
> 
>   struct A {
> int x;
> int y = x;
>   };
> 
>   struct B {
> int x = 0;
> int y = A{x}.y; // #1
>   };
> 
> where for #1 we end up with
> 
>   {.x=(&)->x, .y=(&)->x}
> 
> that is, two PLACEHOLDER_EXPRs for different types on the same level in
> a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism to
> avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.
> 
> Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
> cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
> finish_compound_literal
> on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
> initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
> don't
> have any object to refer to yet.  After digesting, we have
> 
>   {.x=((struct B *) this)->x, .y=(&)->x}
> 
> and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole ctor
> CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns
> 
>   TARGET_EXPR x, .y=(& struct A>)->x}>
> 
> Then we get to
> 
>   B b = {};
> 
> and call store_init_value, which digests the {}, which produces
> 
>   {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR  struct B>)->x, .y=(&)->x}>).y}
> 
> lookup_placeholder in constexpr won't find an object to replace the
> PLACEHOLDER_EXPR for B, because ctx->object will be D.2395 of type A, and we
> cannot search outward from D.2395 to find 'b'.
> 
> The call to replace_placeholders in store_init_value will not do anything:
> we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only
> a sub-expression, so replace_placeholders does nothing, so the 
> stays even though now is the perfect time to replace it because we have an
> object for it: 'b'.
> 
> Later, in cp_gimplify_init_expr the *expr_p is
> 
>   D.2395 = {.x=(&)->x, .y=(& struct A>)-

[PATCH v3] c: Implement new -Wenum-int-mismatch warning [PR105131]

2022-05-18 Thread Marek Polacek via Gcc-patches
On Wed, May 18, 2022 at 08:58:02PM +, Joseph Myers wrote:
> On Wed, 18 May 2022, Marek Polacek via Gcc-patches wrote:
> 
> > diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c 
> > b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
> > new file mode 100644
> > index 000..f71a308bc19
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
> > @@ -0,0 +1,35 @@
> > +/* PR c/105131 */
> > +/* { dg-do compile } */
> > +/* { dg-options "-Wall" } */
> 
> Since some Arm targets default to -fshort-enums, I think it would be best 
> for the tests to use -fno-short-enums or otherwise ensure the enums are 
> compatible with the expected type, so that they test what's intended.  

You're right, the tests would likely break on ARM because of that.
I've added -fno-short-enums.

> Additional tests that don't use the -W options but #include the main tests 
> might also be a good idea, to verify that all the types in the tests 
> really are compatible as intended.

I've extended the tests to use an enum with __attribute__ ((__packed__)) to
test the case when the underlying type is (un)signed char.  But it seems like
we can't have underlying types wider than int.  I've also included two tests
which #include the two main tests.  Seems like Dejagnu doesn't expect the
diagnostics as per the dg directives in the main tests, which is good.

Is the following ok?

Thanks,

-- >8 --
In C, an enumerated type is compatible with char, a signed integer type,
or an unsigned integer type (6.7.2.2/5).  Therefore this code compiles:

  enum E { l = -1, z = 0, g = 1 };
  int foo(void);
  enum E foo(void) { return z; }

if the underlying type of 'enum E' is 'int' (if not, we emit an error).
This is different for typedefs, where C11 permits typedefs to be
redeclared to the same type, but not to compatible types.  In C++, the
code above is invalid.

It seems desirable to emit a warning in the C case, because it is
probably a mistake and definitely a portability error, given that the
choice of the underlying type is implementation-defined.

To that end, this patch implements a new -Wenum-int-mismatch warning.
Conveniently, we already have comptypes_check_enum_int to detect such
mismatches.  This warning is enabled by either -Wall or -Wc++-compat.

PR c/105131

gcc/c-family/ChangeLog:

* c.opt (Wenum-int-mismatch): New.

gcc/c/ChangeLog:

* c-decl.cc (diagnose_mismatched_decls): Warn about enum/integer type
mismatches.
* c-tree.h (comptypes_check_enum_int): Declare.
* c-typeck.cc (comptypes): No longer static.

gcc/ChangeLog:

* doc/invoke.texi: Document -Wenum-int-mismatch.

gcc/testsuite/ChangeLog:

* gcc.dg/Wenum-int-mismatch-1.c: New test.
* gcc.dg/Wenum-int-mismatch-2.c: New test.
* gcc.dg/Wenum-int-mismatch-3.c: New test.
* gcc.dg/Wenum-int-mismatch-4.c: New test.
* gcc.dg/Wenum-int-mismatch-5.c: New test.
---
 gcc/c-family/c.opt  |  4 ++
 gcc/c/c-decl.cc | 13 ++-
 gcc/c/c-tree.h  |  1 +
 gcc/c/c-typeck.cc   |  2 +-
 gcc/doc/invoke.texi | 21 ++
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c | 43 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c | 43 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c | 43 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c |  5 +++
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c |  5 +++
 10 files changed, 177 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 035b1de0d84..41a20bc625e 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -638,6 +638,10 @@ Wenum-conversion
 C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C 
ObjC,Wextra)
 Warn about implicit conversion of enum types.
 
+Wenum-int-mismatch
+C ObjC Var(warn_enum_int_mismatch) Warning LangEnabledBy(C ObjC,Wall || 
Wc++-compat)
+Warn about enum/integer type mismatches.
+
 Werror
 C ObjC C++ ObjC++
 ; Documented in common.opt
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 83655548fc4..5266a61b859 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1993,9 +1993,12 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
   bool pedwarned = false;
   bool warned = false;
+  bool enum_and_int_p = false;
   auto_diagnostic_group d;
 
-  if (!comptypes (oldtype, newtype))
+  int comptypes_resu

[PATCH v2] c: Implement new -Wenum-int-mismatch warning [PR105131]

2022-05-18 Thread Marek Polacek via Gcc-patches
On Wed, May 18, 2022 at 11:14:25AM +0100, Pedro Alves wrote:
> On 2022-05-18 00:56, Marek Polacek via Gcc-patches wrote:
> 
> > +In C, an enumerated type is compatible with @code{char}, a signed
> > +integer type, or an unsigned integer type.  However, since the choice
> > +of the underlying type of an enumerated type is implementation-defined,
> > +such mismatches may cause portability issues.  In C++, such mismatches
> > +are an error.  In C, this warning is enabled by @option{-Wall}.
> 
> Should it also be enabled by -Wc++-compat?

Yes, that's a good idea.  Fixed here:

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

-- >8 --
In C, an enumerated type is compatible with char, a signed integer type,
or an unsigned integer type (6.7.2.2/5).  Therefore this code compiles:

  enum E { l = -1, z = 0, g = 1 };
  int foo(void);
  enum E foo(void) { return z; }

if the underlying type of 'enum E' is 'int' (if not, we emit an error).
This is different for typedefs, where C11 permits typedefs to be
redeclared to the same type, but not to compatible types.  In C++, the
code above is invalid.

It seems desirable to emit a warning in the C case, because it is
probably a mistake and definitely a portability error, given that the
choice of the underlying type is implementation-defined.

To that end, this patch implements a new -Wenum-int-mismatch warning.
Conveniently, we already have comptypes_check_enum_int to detect such
mismatches.  This warning is enabled by either -Wall or -Wc++-compat.

PR c/105131

gcc/c-family/ChangeLog:

* c.opt (Wenum-int-mismatch): New.

gcc/c/ChangeLog:

* c-decl.cc (diagnose_mismatched_decls): Warn about enum/integer type
mismatches.
* c-tree.h (comptypes_check_enum_int): Declare.
* c-typeck.cc (comptypes): No longer static.

gcc/ChangeLog:

* doc/invoke.texi: Document -Wenum-int-mismatch.

gcc/testsuite/ChangeLog:

* gcc.dg/Wenum-int-mismatch-1.c: New test.
* gcc.dg/Wenum-int-mismatch-2.c: New test.
* gcc.dg/Wenum-int-mismatch-3.c: New test.
---
 gcc/c-family/c.opt  |  4 +++
 gcc/c/c-decl.cc | 13 ++--
 gcc/c/c-tree.h  |  1 +
 gcc/c/c-typeck.cc   |  2 +-
 gcc/doc/invoke.texi | 21 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c | 35 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c | 35 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c | 35 +
 8 files changed, 143 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 035b1de0d84..41a20bc625e 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -638,6 +638,10 @@ Wenum-conversion
 C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C 
ObjC,Wextra)
 Warn about implicit conversion of enum types.
 
+Wenum-int-mismatch
+C ObjC Var(warn_enum_int_mismatch) Warning LangEnabledBy(C ObjC,Wall || 
Wc++-compat)
+Warn about enum/integer type mismatches.
+
 Werror
 C ObjC C++ ObjC++
 ; Documented in common.opt
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 83655548fc4..5266a61b859 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1993,9 +1993,12 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
   bool pedwarned = false;
   bool warned = false;
+  bool enum_and_int_p = false;
   auto_diagnostic_group d;
 
-  if (!comptypes (oldtype, newtype))
+  int comptypes_result = comptypes_check_enum_int (oldtype, newtype,
+  &enum_and_int_p);
+  if (!comptypes_result)
 {
   if (TREE_CODE (olddecl) == FUNCTION_DECL
  && fndecl_built_in_p (olddecl, BUILT_IN_NORMAL)
@@ -2137,6 +2140,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
  return false;
}
 }
+  /* Warn about enum/integer type mismatches.  They are compatible types
+ (C2X 6.7.2.2/5), but may pose portability problems.  */
+  else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL)
+warned = warning_at (DECL_SOURCE_LOCATION (newdecl),
+OPT_Wenum_int_mismatch,
+"conflicting types for %q+D due to enum/integer "
+"mismatch; have %qT", newdecl, newtype);
 
   /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
  but silently ignore the redeclaration if either is in a system
@@ -2146,7 +2156,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (TREE_CODE (newdecl) == TYPE_DECL)
 {
   bool types_different = false;
-   

[PATCH] c++: fix SIGFPE with -Wclass-memaccess [PR105634]

2022-05-17 Thread Marek Polacek via Gcc-patches
Here we crash because we attempt to % by 0.  Thus fixed.
While at it, I've moved the -Wclass-memaccess tests into warn/.
I've checked that the # of expected passes is the same before/after
the move.

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

PR c++/105634

gcc/cp/ChangeLog:

* call.cc (maybe_warn_class_memaccess): Avoid % by zero.

gcc/testsuite/ChangeLog:

* g++.dg/Wclass-memaccess-2.C: Moved to...
* g++.dg/warn/Wclass-memaccess-2.C: ...here.
* g++.dg/Wclass-memaccess-3.C: Moved to...
* g++.dg/warn/Wclass-memaccess-3.C: ...here.
* g++.dg/Wclass-memaccess-4.C: Moved to...
* g++.dg/warn/Wclass-memaccess-4.C: ...here.
* g++.dg/Wclass-memaccess-5.C: Moved to...
* g++.dg/warn/Wclass-memaccess-5.C: ...here.
* g++.dg/Wclass-memaccess-6.C: Moved to...
* g++.dg/warn/Wclass-memaccess-6.C: ...here.
* g++.dg/Wclass-memaccess.C: Moved to...
* g++.dg/warn/Wclass-memaccess.C: ...here.
* g++.dg/warn/Wclass-memaccess-7.C: New test.
---
 gcc/cp/call.cc  |  2 ++
 .../g++.dg/{ => warn}/Wclass-memaccess-2.C  |  0
 .../g++.dg/{ => warn}/Wclass-memaccess-3.C  |  0
 .../g++.dg/{ => warn}/Wclass-memaccess-4.C  |  0
 .../g++.dg/{ => warn}/Wclass-memaccess-5.C  |  0
 .../g++.dg/{ => warn}/Wclass-memaccess-6.C  |  0
 gcc/testsuite/g++.dg/warn/Wclass-memaccess-7.C  | 13 +
 gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess.C  |  0
 8 files changed, 15 insertions(+)
 rename gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess-2.C (100%)
 rename gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess-3.C (100%)
 rename gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess-4.C (100%)
 rename gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess-5.C (100%)
 rename gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess-6.C (100%)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wclass-memaccess-7.C
 rename gcc/testsuite/g++.dg/{ => warn}/Wclass-memaccess.C (100%)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 0240e364324..14c6037729f 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10329,6 +10329,8 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl,
  /* Finally, warn on partial copies.  */
  unsigned HOST_WIDE_INT typesize
= tree_to_uhwi (TYPE_SIZE_UNIT (desttype));
+ if (typesize == 0)
+   break;
  if (unsigned HOST_WIDE_INT partial = tree_to_uhwi (sz) % typesize)
warned = warning_at (loc, OPT_Wclass_memaccess,
 (typesize - partial > 1
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-2.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-2.C
similarity index 100%
rename from gcc/testsuite/g++.dg/Wclass-memaccess-2.C
rename to gcc/testsuite/g++.dg/warn/Wclass-memaccess-2.C
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-3.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-3.C
similarity index 100%
rename from gcc/testsuite/g++.dg/Wclass-memaccess-3.C
rename to gcc/testsuite/g++.dg/warn/Wclass-memaccess-3.C
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-4.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-4.C
similarity index 100%
rename from gcc/testsuite/g++.dg/Wclass-memaccess-4.C
rename to gcc/testsuite/g++.dg/warn/Wclass-memaccess-4.C
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-5.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-5.C
similarity index 100%
rename from gcc/testsuite/g++.dg/Wclass-memaccess-5.C
rename to gcc/testsuite/g++.dg/warn/Wclass-memaccess-5.C
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-6.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-6.C
similarity index 100%
rename from gcc/testsuite/g++.dg/Wclass-memaccess-6.C
rename to gcc/testsuite/g++.dg/warn/Wclass-memaccess-6.C
diff --git a/gcc/testsuite/g++.dg/warn/Wclass-memaccess-7.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-7.C
new file mode 100644
index 000..7e86b248629
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wclass-memaccess-7.C
@@ -0,0 +1,13 @@
+// PR c++/105634
+// { dg-do compile { target { c++11 } } }
+// { dg-options "-Wall" }
+
+struct s
+{
+  struct {} a[] = 1.0; // { dg-error "" }
+  void f (char *c)
+  {
+s s;
+__builtin_memcpy (&s, c, sizeof(s));
+  }
+};
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess.C 
b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C
similarity index 100%
rename from gcc/testsuite/g++.dg/Wclass-memaccess.C
rename to gcc/testsuite/g++.dg/warn/Wclass-memaccess.C

base-commit: c9852156dd2fedec130f6d8eb669579ef6237946
-- 
2.36.1



[PATCH] c: Implement new -Wenum-int-mismatch warning [PR105131]

2022-05-17 Thread Marek Polacek via Gcc-patches
In C, an enumerated type is compatible with char, a signed integer type,
or an unsigned integer type (6.7.2.2/5).  Therefore this code compiles:

  enum E { l = -1, z = 0, g = 1 };
  int foo(void);
  enum E foo(void) { return z; }

if the underlying type of 'enum E' is 'int' (if not, we emit an error).
This is different for typedefs, where C11 permits typedefs to be
redeclared to the same type, but not to compatible types.  In C++, the
code above is invalid.

It seems desirable to emit a warning in the C case, because it is
probably a mistake and definitely a portability error, given that the
choice of the underlying type is implementation-defined.

To that end, this patch implements a new -Wenum-int-mismatch warning.
Conveniently, we already have comptypes_check_enum_int to detect such
mismatches.

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

PR c/105131

gcc/c-family/ChangeLog:

* c.opt (Wenum-int-mismatch): New.

gcc/c/ChangeLog:

* c-decl.cc (diagnose_mismatched_decls): Warn about enum/integer type
mismatches.
* c-tree.h (comptypes_check_enum_int): Declare.
* c-typeck.cc (comptypes): No longer static.

gcc/ChangeLog:

* doc/invoke.texi: Document -Wenum-int-mismatch.

gcc/testsuite/ChangeLog:

* gcc.dg/Wenum-int-mismatch-1.c: New test.
* gcc.dg/Wenum-int-mismatch-2.c: New test.
---
 gcc/c-family/c.opt  |  4 +++
 gcc/c/c-decl.cc | 13 ++--
 gcc/c/c-tree.h  |  1 +
 gcc/c/c-typeck.cc   |  2 +-
 gcc/doc/invoke.texi | 20 
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c | 35 +
 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c | 35 +
 7 files changed, 107 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
 create mode 100644 gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 035b1de0d84..0cb64283261 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -638,6 +638,10 @@ Wenum-conversion
 C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C 
ObjC,Wextra)
 Warn about implicit conversion of enum types.
 
+Wenum-int-mismatch
+C ObjC Var(warn_enum_int_mismatch) Warning LangEnabledBy(C ObjC,Wall)
+Warn about enum/integer type mismatches.
+
 Werror
 C ObjC C++ ObjC++
 ; Documented in common.opt
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 83655548fc4..5266a61b859 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1993,9 +1993,12 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
   bool pedwarned = false;
   bool warned = false;
+  bool enum_and_int_p = false;
   auto_diagnostic_group d;
 
-  if (!comptypes (oldtype, newtype))
+  int comptypes_result = comptypes_check_enum_int (oldtype, newtype,
+  &enum_and_int_p);
+  if (!comptypes_result)
 {
   if (TREE_CODE (olddecl) == FUNCTION_DECL
  && fndecl_built_in_p (olddecl, BUILT_IN_NORMAL)
@@ -2137,6 +2140,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
  return false;
}
 }
+  /* Warn about enum/integer type mismatches.  They are compatible types
+ (C2X 6.7.2.2/5), but may pose portability problems.  */
+  else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL)
+warned = warning_at (DECL_SOURCE_LOCATION (newdecl),
+OPT_Wenum_int_mismatch,
+"conflicting types for %q+D due to enum/integer "
+"mismatch; have %qT", newdecl, newtype);
 
   /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
  but silently ignore the redeclaration if either is in a system
@@ -2146,7 +2156,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (TREE_CODE (newdecl) == TYPE_DECL)
 {
   bool types_different = false;
-  int comptypes_result;
 
   comptypes_result
= comptypes_check_different_types (oldtype, newtype, &types_different);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c70f0ba5ab6..2bcb9662620 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -685,6 +685,7 @@ extern tree require_complete_type (location_t, tree);
 extern bool same_translation_unit_p (const_tree, const_tree);
 extern int comptypes (tree, tree);
 extern int comptypes_check_different_types (tree, tree, bool *);
+extern int comptypes_check_enum_int (tree, tree, bool *);
 extern bool c_vla_type_p (const_tree);
 extern bool c_mark_addressable (tree, bool = false);
 extern void c_incomplete_type_error (location_t, const_tree, const_tree);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index bcfe08b82bc..4f3611f1b89 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1055,7 +1055,7 @@ comptypes (tree type1, tree type2)
 /* Like comptypes, but if it returns non-zero because enum a

[PATCH v3] c, c++: -Wswitch warning on [[maybe_unused]] enumerator [PR105497]

2022-05-17 Thread Marek Polacek via Gcc-patches
On Tue, May 10, 2022 at 09:54:12AM -0400, Marek Polacek wrote:
> On Tue, May 10, 2022 at 08:58:46AM -0400, Jason Merrill wrote:
> > On 5/7/22 18:26, Marek Polacek wrote:
> > > Corrected version that avoids an uninitialized warning:
> > > 
> > > This PR complains that we emit the "enumeration value not handled in
> > > switch" warning even though the enumerator was marked with the
> > > [[maybe_unused]] attribute.
> > > 
> > > The first snag was that I couldn't just check TREE_USED, because
> > > the enumerator could have been used earlier in the function, which
> > > doesn't play well with the c_do_switch_warnings warning.  Instead,
> > > I had to check the attributes on the CONST_DECL directly, which led
> > > to the second, and worse, snag: in C we don't have direct access to
> > > the CONST_DECL for the enumerator.
> > 
> > I wonder if you want to change that instead of working around it?
> 
> I wouldn't mind looking into that; I've hit this discrepancy numerous
> times throughout the years and it'd be good to unify it so that the
> c-common code doesn't need to hack around it.
>  
> Let's see how far I'll get...
 
Now done (r13-575), which makes this patch a piece of cake.

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

-- >8 --
This PR complains that we emit the "enumeration value not handled in
switch" warning even though the enumerator was marked with the
[[maybe_unused]] attribute.

I couldn't just check TREE_USED, because the enumerator could have been
used earlier in the function, which doesn't play well with the
c_do_switch_warnings warning.  Instead, I had to check the attributes on
the CONST_DECL.  This is easy since the TYPE_VALUES of an enum type are
now consistent between C and C++, both of which store the CONST_DECL in
its TREE_VALUE.

PR c++/105497

gcc/c-family/ChangeLog:

* c-warn.cc (c_do_switch_warnings): Don't warn about unhandled
enumerator when it was marked with attribute unused.

gcc/testsuite/ChangeLog:

* c-c++-common/Wswitch-1.c: New test.
* g++.dg/warn/Wswitch-4.C: New test.
---
 gcc/c-family/c-warn.cc | 11 +-
 gcc/testsuite/c-c++-common/Wswitch-1.c | 29 ++
 gcc/testsuite/g++.dg/warn/Wswitch-4.C  | 52 ++
 3 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wswitch-1.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wswitch-4.C

diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index cae89294aea..ea7335f3edf 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1738,8 +1738,8 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
   for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
 {
   tree value = TREE_VALUE (chain);
-  if (TREE_CODE (value) == CONST_DECL)
-   value = DECL_INITIAL (value);
+  tree attrs = DECL_ATTRIBUTES (value);
+  value = DECL_INITIAL (value);
   node = splay_tree_lookup (cases, (splay_tree_key) value);
   if (node)
{
@@ -1769,6 +1769,13 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
   /* We've now determined that this enumerated literal isn't
 handled by the case labels of the switch statement.  */
 
+  /* Don't warn if the enumerator was marked as unused.  We can't use
+TREE_USED here: it could have been set on the enumerator if the
+enumerator was used earlier.  */
+  if (lookup_attribute ("unused", attrs)
+ || lookup_attribute ("maybe_unused", attrs))
+   continue;
+
   /* If the switch expression is a constant, we only really care
 about whether that constant is handled by the switch.  */
   if (cond && tree_int_cst_compare (cond, value))
diff --git a/gcc/testsuite/c-c++-common/Wswitch-1.c 
b/gcc/testsuite/c-c++-common/Wswitch-1.c
new file mode 100644
index 000..de9ee03b0a3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wswitch-1.c
@@ -0,0 +1,29 @@
+/* PR c++/105497 */
+/* { dg-options "-Wswitch" } */
+
+enum E {
+  A,
+  B,
+  C __attribute((unused)),
+  D
+};
+
+void
+g (enum E e)
+{
+  switch (e)
+{
+case A:
+case B:
+case D:
+  break;
+}
+
+  switch (e) // { dg-warning "not handled in switch" }
+{
+case A:
+case B:
+case C:
+  break;
+}
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wswitch-4.C 
b/gcc/testsuite/g++.dg/warn/Wswitch-4.C
new file mode 100644
index 000..553a57d777b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wswitch-4.C
@@ -0,0 +1,52 @@
+// PR c++/105497
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wswitch" }

Re: [PATCH] c: use CONST_DECL for enumerators in TYPE_VALUES

2022-05-17 Thread Marek Polacek via Gcc-patches
On Tue, May 17, 2022 at 02:59:00PM -0700, Ian Lance Taylor wrote:
> On Tue, May 17, 2022 at 2:46 PM Marek Polacek  wrote:
> >
> > On Tue, May 17, 2022 at 09:35:14PM +, Joseph Myers wrote:
> > > On Tue, 17 May 2022, Marek Polacek via Gcc-patches wrote:
> > >
> > > > The C and C++ FEs differ in TYPE_VALUES for an enum type: an entry in
> > > > the list in the C++ FE has a CONST_DECL in the TREE_VALUE, but the C FE
> > > > has only the numerical value of the CONST_DECL there.  This has caused
> > > > me some trouble in my PR105497 patch.  Using a CONST_DECL is preferable
> > > > because a CONST_DECL can track more information (e.g., attributes), and
> > > > you can always get the value simply by looking at its DECL_INITIAL.
> > > >
> > > > This turned out to be a trivial change.  One place in godump.cc had to 
> > > > be
> > > > adjusted.  I'm not changing the CONST_DECL check in c_do_switch_warnings
> > > > because I'll be changing it soon in my next patch.  I didn't see any 
> > > > other
> > > > checks that this patch makes redundant.
> > > >
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > >
> > > > gcc/c/ChangeLog:
> > > >
> > > > * c-decl.cc (finish_enum): Store the CONST_DECL into TREE_VALUE, not
> > > > its value.
> > >
> > > The C front-end changes are OK.
> >
> > Thanks.  Ian, are the (more or less obvious) godump.cc changes also OK?
> 
> Yes, that change is OK (assuming it works).  Thanks.

Thanks.  It still works, the code in question is tested by e.g.
testsuite/gcc.misc-tests/godump-1.c.

Marek



Re: [PATCH] c: use CONST_DECL for enumerators in TYPE_VALUES

2022-05-17 Thread Marek Polacek via Gcc-patches
On Tue, May 17, 2022 at 09:35:14PM +, Joseph Myers wrote:
> On Tue, 17 May 2022, Marek Polacek via Gcc-patches wrote:
> 
> > The C and C++ FEs differ in TYPE_VALUES for an enum type: an entry in
> > the list in the C++ FE has a CONST_DECL in the TREE_VALUE, but the C FE
> > has only the numerical value of the CONST_DECL there.  This has caused
> > me some trouble in my PR105497 patch.  Using a CONST_DECL is preferable
> > because a CONST_DECL can track more information (e.g., attributes), and
> > you can always get the value simply by looking at its DECL_INITIAL.
> > 
> > This turned out to be a trivial change.  One place in godump.cc had to be
> > adjusted.  I'm not changing the CONST_DECL check in c_do_switch_warnings
> > because I'll be changing it soon in my next patch.  I didn't see any other
> > checks that this patch makes redundant.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > gcc/c/ChangeLog:
> > 
> > * c-decl.cc (finish_enum): Store the CONST_DECL into TREE_VALUE, not
> > its value.
> 
> The C front-end changes are OK.

Thanks.  Ian, are the (more or less obvious) godump.cc changes also OK?

Marek



[PATCH] c: use CONST_DECL for enumerators in TYPE_VALUES

2022-05-17 Thread Marek Polacek via Gcc-patches
The C and C++ FEs differ in TYPE_VALUES for an enum type: an entry in
the list in the C++ FE has a CONST_DECL in the TREE_VALUE, but the C FE
has only the numerical value of the CONST_DECL there.  This has caused
me some trouble in my PR105497 patch.  Using a CONST_DECL is preferable
because a CONST_DECL can track more information (e.g., attributes), and
you can always get the value simply by looking at its DECL_INITIAL.

This turned out to be a trivial change.  One place in godump.cc had to be
adjusted.  I'm not changing the CONST_DECL check in c_do_switch_warnings
because I'll be changing it soon in my next patch.  I didn't see any other
checks that this patch makes redundant.

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

gcc/c/ChangeLog:

* c-decl.cc (finish_enum): Store the CONST_DECL into TREE_VALUE, not
its value.

gcc/ChangeLog:

* godump.cc (go_output_typedef): Use the DECL_INITIAL of the TREE_VALUE.
---
 gcc/c/c-decl.cc | 4 +++-
 gcc/godump.cc   | 9 +
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index e49879ab286..83655548fc4 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9253,7 +9253,9 @@ finish_enum (tree enumtype, tree values, tree attributes)
 
  DECL_INITIAL (enu) = ini;
  TREE_PURPOSE (pair) = DECL_NAME (enu);
- TREE_VALUE (pair) = ini;
+ /* To match the C++ FE, store the CONST_DECL rather than just its
+value.  */
+ TREE_VALUE (pair) = enu;
}
 
   TYPE_VALUES (enumtype) = values;
diff --git a/gcc/godump.cc b/gcc/godump.cc
index 2ae0bcc9672..c0f52bbd0f2 100644
--- a/gcc/godump.cc
+++ b/gcc/godump.cc
@@ -1114,6 +1114,7 @@ go_output_typedef (class godump_container *container, 
tree decl)
  struct macro_hash_value *mhval;
  void **slot;
  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ tree value = DECL_INITIAL (TREE_VALUE (element));
 
  name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
 
@@ -1127,12 +1128,12 @@ go_output_typedef (class godump_container *container, 
tree decl)
  if (*slot != NULL)
macro_hash_del (*slot);
 
- if (tree_fits_shwi_p (TREE_VALUE (element)))
+ if (tree_fits_shwi_p (value))
snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
-tree_to_shwi (TREE_VALUE (element)));
- else if (tree_fits_uhwi_p (TREE_VALUE (element)))
+tree_to_shwi (value));
+ else if (tree_fits_uhwi_p (value))
snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
- tree_to_uhwi (TREE_VALUE (element)));
+ tree_to_uhwi (value));
  else
print_hex (wi::to_wide (element), buf);
 

base-commit: b7501739f3b14ac7749aace93f636d021fd607f7
-- 
2.36.1



[PATCH] c++: suppress -Waddress warnings with *_cast [PR105569]

2022-05-16 Thread Marek Polacek via Gcc-patches
dynamic_cast can legally return nullptr, so I don't think it's helpful
for -Waddress to warn for

  if (dynamic_cast(&ref))
// ...

More generally, it's likely not useful to warn for the artificial
POINTER_PLUS_EXPRs created by build_base_path.

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

PR c++/105569

gcc/cp/ChangeLog:

* class.cc (build_base_path): Suppress -Waddress warning.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 3c195b35396..06167380423 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -518,6 +518,8 @@ build_base_path (enum tree_code code,
 
   expr = build1 (NOP_EXPR, ptr_target_type, expr);
 
+  suppress_warning (expr, OPT_Waddress);
+
  indout:
   if (!want_pointer)
 {
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-9.C 
b/gcc/testsuite/g++.dg/warn/Waddress-9.C
new file mode 100644
index 000..2ec41949ccf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-9.C
@@ -0,0 +1,34 @@
+// PR c++/105569
+// { dg-do compile { target c++11 } }
+// { dg-options -Waddress }
+
+class A {};
+
+class B : public virtual A {};
+
+class C : public A {};
+
+int main() {
+B* object = new B();
+B &ref = *object;
+
+// -Waddress warns here
+bool b = nullptr == dynamic_cast(&ref); // { dg-bogus "-Waddress" }
+bool b4 = nullptr == static_cast(&ref); // { dg-bogus "-Waddress" }
+if (dynamic_cast(&ref)) // { dg-bogus "-Waddress" }
+  {
+  }
+if (static_cast(&ref)) // { dg-bogus "-Waddress" }
+  {
+  }
+
+// -Waddress doesn't warn anymore
+auto ptr = dynamic_cast(&ref); 
+bool b2 = ptr == nullptr;
+
+C* cobject = new C();
+C &cref = *cobject;
+
+// -Waddress also doesn't warn anymore
+bool b3 = nullptr == dynamic_cast(&cref);
+}

base-commit: 682e587f1021241758f7dfe0b22651008622a312
-- 
2.36.1



[PATCH v5] c++: ICE with temporary of class type in DMI [PR100252]

2022-05-16 Thread Marek Polacek via Gcc-patches
On Sat, May 14, 2022 at 11:13:28PM -0400, Jason Merrill wrote:
> On 5/13/22 19:41, Marek Polacek wrote:
> > --- a/gcc/cp/typeck2.cc
> > +++ b/gcc/cp/typeck2.cc
> > @@ -1371,6 +1371,70 @@ digest_init_flags (tree type, tree init, int flags, 
> > tsubst_flags_t complain)
> > return digest_init_r (type, init, 0, flags, complain);
> >   }
> > +/* Return true if a prvalue is used as an initializer rather than for
> > +   temporary materialization.  For instance:
> 
> I might say "if SUBOB initializes the same object as FULL_EXPR"; the
> full-expression could still end up initializing a temporary.

Fixed.
 
> > + A a = A{};  // initializer
> > + A a = (A{});// initializer
> > + A a = (1, A{}); // initializer
> > + A a = true ? A{} : A{};  // initializer
> > + auto x = A{}.x; // temporary materialization
> > + auto x = foo(A{});  // temporary materialization
> > +
> > +   FULL_EXPR is the whole expression, SUBOB is its TARGET_EXPR subobject.  
> > */
> > +
> > +static bool
> > +potential_prvalue_result_of (tree subob, tree full_expr)
> > +{
> > +  if (subob == full_expr)
> > +return true;
> > +  else if (TREE_CODE (full_expr) == TARGET_EXPR)
> > +{
> > +  tree init = TARGET_EXPR_INITIAL (full_expr);
> > +  if (TREE_CODE (init) == COND_EXPR)
> > +   return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 1))
> > +   || potential_prvalue_result_of (subob, TREE_OPERAND (init, 2)));
> > +  else if (TREE_CODE (init) == COMPOUND_EXPR)
> > +   return (potential_prvalue_result_of (subob, TREE_OPERAND (init, 0))
> 
> We shouldn't recurse into the LHS of the comma, only the RHS.

Fixed.
 
> > +   || potential_prvalue_result_of (subob, TREE_OPERAND (init, 1)));
> > +  /* ??? I don't know if this can be hit.  If so, look inside the ( )
> > +instead of the assert.  */
> > +  else if (TREE_CODE (init) == PAREN_EXPR)
> > +   gcc_checking_assert (false);
> 
> It seems trivial enough to recurse after the assert, in case it does happen
> in the wild.

OK, adjusted.  Thanks!

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

-- >8 --
Consider

  struct A {
int x;
int y = x;
  };

  struct B {
int x = 0;
int y = A{x}.y; // #1
  };

where for #1 we end up with

  {.x=(&)->x, .y=(&)->x}

that is, two PLACEHOLDER_EXPRs for different types on the same level in
a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism to
avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.

Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
finish_compound_literal
on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
don't
have any object to refer to yet.  After digesting, we have

  {.x=((struct B *) this)->x, .y=(&)->x}

and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole ctor
CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns

  TARGET_EXPR x, .y=(&)->x}>

Then we get to

  B b = {};

and call store_init_value, which digests the {}, which produces

  {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR )->x, .y=(&)->x}>).y}

lookup_placeholder in constexpr won't find an object to replace the
PLACEHOLDER_EXPR for B, because ctx->object will be D.2395 of type A, and we
cannot search outward from D.2395 to find 'b'.

The call to replace_placeholders in store_init_value will not do anything:
we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only
a sub-expression, so replace_placeholders does nothing, so the 
stays even though now is the perfect time to replace it because we have an
object for it: 'b'.

Later, in cp_gimplify_init_expr the *expr_p is

  D.2395 = {.x=(&)->x, .y=(&)->x}

where D.2395 is of type A, but we crash because we hit , which
has a different type.

My idea was to replace  with D.2384 after creating the
TARGET_EXPR because that means we have an object we can refer to.
Then clear CONSTRUCTOR_PLACEHOLDER_BOUNDARY because we no longer have
a PLACEHOLDER_EXPR in the {}.  Then store_init_value will be able to
replace  with 'b', and we should be good to go.  We must
be careful not to break guaranteed copy elision, so this replacement
happens in digest_nsdmi_init where we can see the whole initializer,
and avoid replacing any placeholders in TARGET_EXPRs used in the context
of initialization/copy elision.  Th

[pushed] c++: Add fixed test [PR81952]

2022-05-13 Thread Marek Polacek via Gcc-patches
This was fixed by r258755:
PR c++/81311 - wrong C++17 overload resolution.

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

PR c++/81952

gcc/testsuite/ChangeLog:

* g++.dg/overload/conv-op4.C: New test.
---
 gcc/testsuite/g++.dg/overload/conv-op4.C | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/overload/conv-op4.C

diff --git a/gcc/testsuite/g++.dg/overload/conv-op4.C 
b/gcc/testsuite/g++.dg/overload/conv-op4.C
new file mode 100644
index 000..80de19549e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/conv-op4.C
@@ -0,0 +1,22 @@
+// PR c++/81952
+// { dg-do run { target c++11 } }
+
+template 
+struct opt {
+opt() { }
+opt(opt const& ) { __builtin_abort (); }
+opt(opt&& ) { __builtin_abort (); }
+
+template 
+opt(U&& ) { }
+};
+
+struct foo 
+{
+explicit operator opt() { __builtin_abort (); return {}; }
+};
+
+int main()
+{
+opt o(foo{});
+}

base-commit: dd7813f05df50d2ad8e0dc34503f2dff0b521d89
-- 
2.36.1



[PATCH v4] c++: ICE with temporary of class type in DMI [PR100252]

2022-05-13 Thread Marek Polacek via Gcc-patches
On Sat, May 07, 2022 at 06:02:13PM -0400, Jason Merrill wrote:
> On 5/7/22 15:11, Marek Polacek wrote:
> > On Tue, May 03, 2022 at 04:59:38PM -0400, Jason Merrill wrote:
> > > Does this testcase still work with this patch?
> > > 
> > > struct A {
> > >const A* p = this;
> > > };
> > > 
> > > struct B {
> > >A a = A{};
> > > };
> > > 
> > > constexpr B b;
> > > static_assert (b.a.p == &b.a);
> > 
> > Ouch, no.  Thanks for catching this, it would have been very unpleasant
> > to hit this problem later...
> > 
> > The reason your testcase was rejected is that replacing a PLACEHOLDER
> > in the outermost TARGET_EXPR broke guaranteed copy elision.  Now that
> > I've spent another day on this, I still think we have to replace the
> > placeholders created when temporary materialization takes place in an
> > NSDMI, but it must happen in digest_nsdmi_init (as Patrick suggested),
> > where we can see the full initializer.  That way I can avoid breaking
> > copy elision.
> > 
> > I've added a bunch of new testcases and updated the
> > (already long) description.  The yuge comment hopefully also explains
> > how this problem is avoided.  Thanks again,
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > Consider
> > 
> >struct A {
> >  int x;
> >  int y = x;
> >};
> > 
> >struct B {
> >  int x = 0;
> >  int y = A{x}.y; // #1
> >};
> > 
> > where for #1 we end up with
> > 
> >{.x=(&)->x, .y=(& > A>)->x}
> > 
> > that is, two PLACEHOLDER_EXPRs for different types on the same level in
> > a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism 
> > to
> > avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.
> > 
> > Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
> > cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
> > finish_compound_literal
> > on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
> > initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
> > don't
> > have any object to refer to yet.  After digesting, we have
> > 
> >{.x=((struct B *) this)->x, .y=(&)->x}
> > 
> > and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole 
> > ctor
> > CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns
> > 
> >TARGET_EXPR x, .y=(& > struct A>)->x}>
> > 
> > Then we get to
> > 
> >B b = {};
> > 
> > and call store_init_value, which digests the {}, which produces
> > 
> >{.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR  > {.x=(&)->x, .y=(& > A>)->x}>).y}
> > 
> > lookup_placeholder in constexpr won't find an object to replace the
> > PLACEHOLDER_EXPR for B, because ctx->object will be D.2395 of type A, and we
> > cannot search outward from D.2395 to find 'b'.
> > 
> > The call to replace_placeholders in store_init_value will not do anything:
> > we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only
> > a sub-expression, so replace_placeholders does nothing, so the  > B>
> > stays even though now is the perfect time to replace it because we have an
> > object for it: 'b'.
> > 
> > Later, in cp_gimplify_init_expr the *expr_p is
> > 
> >D.2395 = {.x=(&)->x, .y=(& > struct A>)->x}
> > 
> > where D.2395 is of type A, but we crash because we hit , which
> > has a different type.
> > 
> > My idea was to replace  with D.2384 after creating the
> > TARGET_EXPR because that means we have an object we can refer to.
> > Then clear CONSTRUCTOR_PLACEHOLDER_BOUNDARY because we no longer have
> > a PLACEHOLDER_EXPR in the {}.  Then store_init_value will be able to
> > replace  with 'b', and we should be good to go.  We must
> > be careful not to break guaranteed copy elision, so this replacement
> > happens in digest_nsdmi_init where we can see the whole initializer,
> > and avoid replacing any placeholders in the outermost TARGET_EXPR.
> > 
> > PR c++/100252
> > 
> > gcc/cp/ChangeLog:
> > 
> > * typeck2.cc (replace_placeholders_for_class_temp_r): New.
> > (digest_nsdmi_init

Re: [PATCH] testsuite: Update Wconversion testcase check type.

2022-05-10 Thread Marek Polacek via Gcc-patches
On Tue, May 10, 2022 at 02:58:49PM -0700, Palmer Dabbelt wrote:
> On Thu, 05 May 2022 11:45:50 PDT (-0700), gcc-patches@gcc.gnu.org wrote:
> > On Thu, May 05, 2022 at 06:33:20PM +0800, jiawei wrote:
> > > Some compiler target like arm-linux\riscv\power\s390x\xtensa-gcc handle
> > > char as unsigned char, then there are no warnings occur and got FAIL 
> > > cases.
> > > Just change the type char into explicit signed char to keep the feature
> > > consistency.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > > * c-c++-common/Wconversion-1.c: Update type.
> > 
> > Ok, and sorry for introducing this problem!
> 
> So this is OK for trunk?  Happy to commit it if you'd like, just wanted to
> make sure as I'm not seeing it on trunk.

Yes, please go ahead.
 
Marek



Re: [PATCH v2] c, c++: -Wswitch warning on [[maybe_unused]] enumerator [PR105497]

2022-05-10 Thread Marek Polacek via Gcc-patches
On Tue, May 10, 2022 at 08:58:46AM -0400, Jason Merrill wrote:
> On 5/7/22 18:26, Marek Polacek wrote:
> > Corrected version that avoids an uninitialized warning:
> > 
> > This PR complains that we emit the "enumeration value not handled in
> > switch" warning even though the enumerator was marked with the
> > [[maybe_unused]] attribute.
> > 
> > The first snag was that I couldn't just check TREE_USED, because
> > the enumerator could have been used earlier in the function, which
> > doesn't play well with the c_do_switch_warnings warning.  Instead,
> > I had to check the attributes on the CONST_DECL directly, which led
> > to the second, and worse, snag: in C we don't have direct access to
> > the CONST_DECL for the enumerator.
> 
> I wonder if you want to change that instead of working around it?

I wouldn't mind looking into that; I've hit this discrepancy numerous
times throughout the years and it'd be good to unify it so that the
c-common code doesn't need to hack around it.
 
Let's see how far I'll get...

> > +  const bool unused_p = (lookup_attribute ("unused", attrs)
> > +|| lookup_attribute ("maybe_unused", attrs));
> 
> Why is this calculation...
> 
> > node = splay_tree_lookup (cases, (splay_tree_key) value);
> > if (node)
> > {
> > @@ -1769,6 +1784,10 @@ c_do_switch_warnings (splay_tree cases, location_t 
> > switch_location,
> > /* We've now determined that this enumerated literal isn't
> >  handled by the case labels of the switch statement.  */
> > +  /* Don't warn if the enumerator was marked as unused.  */
> > +  if (unused_p)
> > +   continue;
> 
> ...separate from this test?

Ah, that must be a remnant from a previous version of the patch.  No reason
for the separation anymore.

Thanks,
Marek



[PATCH] c++: ICE with constexpr dtor on ARM [PR105529]

2022-05-09 Thread Marek Polacek via Gcc-patches
When compiling this test on ARM with -O, we ICE in cxx_eval_store_expression
while evaluating a CALL_EXPR allocator::~allocator (&D.4529).  Its body
has this store:

   = this

The RHS is evaluated into &D.4529 of type allocator *.  The object,
, is of type void *.  Their types don't match so we go into
the new

  if (empty_base || !(same_type_ignoring_top_level_qualifiers_p
  (TREE_TYPE (init), type)))
{
  empty_base = true;
  gcc_assert (is_empty_class (TREE_TYPE (init)));

branch where we crash because is_empty_class will always say false for
a pointer type.  It seems like the new branch expects code like

  D.2181 = {}

where the type of the LHS is the derived type and the type of the RHS is
the base type.  But it only expects to see actual class types, not
pointers to them.  With this patch we will do what we did before the
empty bases cleanup patch: set *valp and return the initializer.

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

PR c++/105529

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_store_expression): Check CLASS_TYPE_P before
checking initialization of an empty base.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-dtor13.C: New test.
* g++.dg/cpp2a/constexpr-dtor14.C: New test.
---
 gcc/cp/constexpr.cc   |  5 +++--
 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C | 11 +++
 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C | 13 +
 3 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index e560d842e8c..e4498c15f1e 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -5916,8 +5916,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
 
   gcc_checking_assert (!*valp || (same_type_ignoring_top_level_qualifiers_p
  (TREE_TYPE (*valp), type)));
-  if (empty_base || !(same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (init), type)))
+  if (empty_base || (CLASS_TYPE_P (TREE_TYPE (init))
+&& !(same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (init), type
 {
   /* For initialization of an empty base, the original target will be
*(base*)this, evaluation of which resolves to the object
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C 
b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C
new file mode 100644
index 000..7b289614fc1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C
@@ -0,0 +1,11 @@
+// PR c++/105529
+// { dg-do compile { target c++20 } }
+// { dg-options "-O" }
+
+struct allocator {
+  constexpr ~allocator() {}
+};
+struct S {
+  S(int, int, allocator = allocator());
+};
+void to_string() { S(0, '\0'); }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C 
b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C
new file mode 100644
index 000..9c55121eb8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C
@@ -0,0 +1,13 @@
+// PR c++/105529
+// { dg-do compile { target c++20 } }
+// { dg-options "-O" }
+// Like constexpr-dtor13.C, except that allocator is not an empty class.
+
+struct allocator {
+  constexpr ~allocator() {}
+  int a;
+};
+struct S {
+  S(int, int, allocator = allocator());
+};
+void to_string() { S(0, '\0'); }

base-commit: 8a39c7c128dbf4405821778724c5a1017ab12e06
-- 
2.35.3



[PATCH] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539]

2022-05-08 Thread Marek Polacek via Gcc-patches
This patch implements C++23 , which allows
labels at the end of a compound statement.   Its C FE counterpart was
already implemented in r11-4813.

In cp_parser_statement I rely on in_compound to determine whether we're
in a compound-statement, so that the patch doesn't accidentally allow

  void fn(int c) {
if (c)
  label:
  }

Strangely, in_compound was reset after seeing a label (this is tested in
c-c++-common/gomp/pr63326.c), so I've made a modifiable copy specific
for OpenMP #pragma purposes.

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

PR c++/103539

gcc/cp/ChangeLog:

* parser.cc (cp_parser_statement): Constify the in_compound parameter.
Create a modifiable copy.  Allow labels at the end of compound
statements.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/label1.C: New test.
* g++.dg/cpp23/label2.C: New test.
---
 gcc/cp/parser.cc| 43 +++---
 gcc/testsuite/g++.dg/cpp23/label1.C | 89 +
 gcc/testsuite/g++.dg/cpp23/label2.C | 52 +
 3 files changed, 175 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp23/label1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp23/label2.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3ebaa414a3d..a4c3d8aa234 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -12174,7 +12174,7 @@ cp_parser_handle_directive_omp_attributes (cp_parser 
*parser, tree *pattrs,
  atomic-statement
 
   IN_COMPOUND is true when the statement is nested inside a
-  cp_parser_compound_statement; this matters for certain pragmas.
+  cp_parser_compound_statement.
 
   If IF_P is not NULL, *IF_P is set to indicate whether the statement
   is a (possibly labeled) if statement which is not enclosed in braces
@@ -12184,7 +12184,7 @@ cp_parser_handle_directive_omp_attributes (cp_parser 
*parser, tree *pattrs,
 
 static void
 cp_parser_statement (cp_parser* parser, tree in_statement_expr,
-bool in_compound, bool *if_p, vec *chain,
+const bool in_compound, bool *if_p, vec *chain,
 location_t *loc_after_labels)
 {
   tree statement, std_attrs = NULL_TREE;
@@ -12192,6 +12192,9 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
   location_t statement_location, attrs_loc;
   bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
   bool has_std_attrs;
+  /* A copy of IN_COMPOUND which is set to false after seeing a label.
+ This matters for certain pragmas.  */
+  bool in_compound_for_pragma = in_compound;
 
  restart:
   if (if_p != NULL)
@@ -12286,7 +12289,7 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
 Parse the label, and then use tail recursion to parse
 the statement.  */
  cp_parser_label_for_labeled_statement (parser, std_attrs);
- in_compound = false;
+ in_compound_for_pragma = false;
  in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
  goto restart;
 
@@ -12370,7 +12373,21 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
 the statement.  */
 
  cp_parser_label_for_labeled_statement (parser, std_attrs);
- in_compound = false;
+
+ /* If there's no statement, it's not a labeled-statement, just
+a label.  That's allowed in C++23, but only if we're at the
+end of a compound-statement.  */
+ if (in_compound
+ && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+   {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (cxx_dialect < cxx23)
+   pedwarn (loc, OPT_Wc__23_extensions,
+"label at end of compound statement only available "
+"with %<-std=c++2b%> or %<-std=gnu++2b%>");
+ return;
+   }
+ in_compound_for_pragma = false;
  in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
  goto restart;
}
@@ -12393,7 +12410,7 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
 the context of a compound, accept the pragma as a "statement" and
 return so that we can check for a close brace.  Otherwise we
 require a real statement and must go back and read one.  */
-  if (in_compound)
+  if (in_compound_for_pragma)
cp_parser_pragma (parser, pragma_compound, if_p);
   else if (!cp_parser_pragma (parser, pragma_stmt, if_p))
do_restart = true;
@@ -12544,9 +12561,13 @@ attr_chainon (tree attrs, tree attr)
 
 /* Parse the label for a labeled-statement, i.e.
 
-   identifier :
-   case constant-expression :
-   default :
+   label:
+ attribute-specifier-seq[opt] identifier :
+ attribute-specifier-seq[opt] case constant-expression :
+ attribute-specifier-seq[opt] defaul

[PATCH v2] c, c++: -Wswitch warning on [[maybe_unused]] enumerator [PR105497]

2022-05-07 Thread Marek Polacek via Gcc-patches
Corrected version that avoids an uninitialized warning:

This PR complains that we emit the "enumeration value not handled in
switch" warning even though the enumerator was marked with the
[[maybe_unused]] attribute.

The first snag was that I couldn't just check TREE_USED, because
the enumerator could have been used earlier in the function, which
doesn't play well with the c_do_switch_warnings warning.  Instead,
I had to check the attributes on the CONST_DECL directly, which led
to the second, and worse, snag: in C we don't have direct access to
the CONST_DECL for the enumerator.  I had to handle that by adding
a new function that extracts the decl from an identifier's binding.

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

PR c++/105497

gcc/c-family/ChangeLog:

* c-common.h (get_decl_for_identifier): Declare.
* c-warn.cc (c_do_switch_warnings): Don't warn about unhandled
enumerator when it was marked as unused.

gcc/c/ChangeLog:

* c-decl.cc (get_decl_for_identifier): New.

gcc/cp/ChangeLog:

* tree.cc (get_decl_for_identifier): New.

gcc/testsuite/ChangeLog:

* c-c++-common/Wswitch-1.c: New test.
* g++.dg/warn/Wswitch-4.C: New test.
---
 gcc/c-family/c-common.h|  1 +
 gcc/c-family/c-warn.cc | 24 ++--
 gcc/c/c-decl.cc| 10 +
 gcc/cp/tree.cc |  8 
 gcc/testsuite/c-c++-common/Wswitch-1.c | 29 ++
 gcc/testsuite/g++.dg/warn/Wswitch-4.C  | 52 ++
 6 files changed, 121 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wswitch-1.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wswitch-4.C

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index f10be9bd67e..c4221089a18 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -831,6 +831,7 @@ extern tree (*make_fname_decl) (location_t, tree, int);
 
 /* In c-decl.cc and cp/tree.cc.  FIXME.  */
 extern void c_register_addr_space (const char *str, addr_space_t as);
+extern tree get_decl_for_identifier (tree);
 
 /* In c-common.cc.  */
 extern bool in_late_binary_op;
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index cae89294aea..03cbc0541b2 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1738,8 +1738,23 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
   for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
 {
   tree value = TREE_VALUE (chain);
+  tree id = TREE_PURPOSE (chain);
+  tree attrs = NULL_TREE;
+  /* In C++, the TREE_VALUE is a CONST_DECL.  */
   if (TREE_CODE (value) == CONST_DECL)
-   value = DECL_INITIAL (value);
+   {
+ attrs = DECL_ATTRIBUTES (value);
+ value = DECL_INITIAL (value);
+   }
+  /* In C, the TREE_VALUE is an integer constant.  The TREE_PURPOSE is
+an identifier from which we must tease out the CONST_DECL.  */
+  else if (tree decl = get_decl_for_identifier (id))
+   attrs = DECL_ATTRIBUTES (decl);
+  /* Track if the enumerator was marked as unused.  We can't use
+TREE_USED here: it could have been set on the enumerator if
+the enumerator was used earlier.  */
+  const bool unused_p = (lookup_attribute ("unused", attrs)
+|| lookup_attribute ("maybe_unused", attrs));
   node = splay_tree_lookup (cases, (splay_tree_key) value);
   if (node)
{
@@ -1769,6 +1784,10 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
   /* We've now determined that this enumerated literal isn't
 handled by the case labels of the switch statement.  */
 
+  /* Don't warn if the enumerator was marked as unused.  */
+  if (unused_p)
+   continue;
+
   /* If the switch expression is a constant, we only really care
 about whether that constant is handled by the switch.  */
   if (cond && tree_int_cst_compare (cond, value))
@@ -1791,8 +1810,7 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
  (default_node || !warn_switch
   ? OPT_Wswitch_enum
   : OPT_Wswitch),
- "enumeration value %qE not handled in switch",
- TREE_PURPOSE (chain));
+ "enumeration value %qE not handled in switch", id);
 }
 
   /* Warn if there are case expressions that don't correspond to
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c701f07befe..c2c813d922a 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -12466,4 +12466,14 @@ c_check_in_current_scope (tree decl)
   return b != NULL && B_IN_CURRENT_SCOPE (b);
 }
 
+/* Returns the symbol associated with an identifier ID.  Currently, this
+   is used only in c_do_switch_warnings so that we can obtain the CONST_DECL
+   associated with an enumerator identifier.  */
+
+tree
+get_decl_for_id

[PATCH] c, c++: -Wswitch warning on [[maybe_unused]] enumerator [PR105497]

2022-05-07 Thread Marek Polacek via Gcc-patches
This PR complains that we emit the "enumeration value not handled in
switch" warning even though the enumerator was marked with the
[[maybe_unused]] attribute.

The first snag was that I couldn't just check TREE_USED, because
the enumerator could have been used earlier in the function, which
doesn't play well with the c_do_switch_warnings warning.  Instead,
I had to check the attributes on the CONST_DECL directly, which led
to the second, and worse, snag: in C we don't have direct access to
the CONST_DECL for the enumerator.  I had to handle that by adding
a new function that extracts the decl from an identifier's binding.

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

PR c++/105497

gcc/c-family/ChangeLog:

* c-common.h (get_decl_for_identifier): Declare.
* c-warn.cc (c_do_switch_warnings): Don't warn about unhandled
enumerator when it was marked as unused.

gcc/c/ChangeLog:

* c-decl.cc (get_decl_for_identifier): New.

gcc/cp/ChangeLog:

* tree.cc (get_decl_for_identifier): New.

gcc/testsuite/ChangeLog:

* c-c++-common/Wswitch-1.c: New test.
* g++.dg/warn/Wswitch-4.C: New test.
---
 gcc/c-family/c-common.h|  1 +
 gcc/c-family/c-warn.cc | 24 ++--
 gcc/c/c-decl.cc| 10 +
 gcc/cp/tree.cc |  8 
 gcc/testsuite/c-c++-common/Wswitch-1.c | 29 ++
 gcc/testsuite/g++.dg/warn/Wswitch-4.C  | 52 ++
 6 files changed, 121 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wswitch-1.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wswitch-4.C

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index f10be9bd67e..c4221089a18 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -831,6 +831,7 @@ extern tree (*make_fname_decl) (location_t, tree, int);
 
 /* In c-decl.cc and cp/tree.cc.  FIXME.  */
 extern void c_register_addr_space (const char *str, addr_space_t as);
+extern tree get_decl_for_identifier (tree);
 
 /* In c-common.cc.  */
 extern bool in_late_binary_op;
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index cae89294aea..01765624eb5 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1738,8 +1738,23 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
   for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
 {
   tree value = TREE_VALUE (chain);
+  tree id = TREE_PURPOSE (chain);
+  tree attrs;
+  /* In C++, the TREE_VALUE is a CONST_DECL.  */
   if (TREE_CODE (value) == CONST_DECL)
-   value = DECL_INITIAL (value);
+   {
+ attrs = DECL_ATTRIBUTES (value);
+ value = DECL_INITIAL (value);
+   }
+  /* In C, the TREE_VALUE is an integer constant.  The TREE_PURPOSE is
+an identifier from which we must tease out the CONST_DECL.  */
+  else if (tree decl = get_decl_for_identifier (id))
+   attrs = DECL_ATTRIBUTES (decl);
+  /* Track if the enumerator was marked as unused.  We can't use
+TREE_USED here: it could have been set on the enumerator if
+the enumerator was used earlier.  */
+  const bool unused_p = (lookup_attribute ("unused", attrs)
+|| lookup_attribute ("maybe_unused", attrs));
   node = splay_tree_lookup (cases, (splay_tree_key) value);
   if (node)
{
@@ -1769,6 +1784,10 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
   /* We've now determined that this enumerated literal isn't
 handled by the case labels of the switch statement.  */
 
+  /* Don't warn if the enumerator was marked as unused.  */
+  if (unused_p)
+   continue;
+
   /* If the switch expression is a constant, we only really care
 about whether that constant is handled by the switch.  */
   if (cond && tree_int_cst_compare (cond, value))
@@ -1791,8 +1810,7 @@ c_do_switch_warnings (splay_tree cases, location_t 
switch_location,
  (default_node || !warn_switch
   ? OPT_Wswitch_enum
   : OPT_Wswitch),
- "enumeration value %qE not handled in switch",
- TREE_PURPOSE (chain));
+ "enumeration value %qE not handled in switch", id);
 }
 
   /* Warn if there are case expressions that don't correspond to
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c701f07befe..c2c813d922a 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -12466,4 +12466,14 @@ c_check_in_current_scope (tree decl)
   return b != NULL && B_IN_CURRENT_SCOPE (b);
 }
 
+/* Returns the symbol associated with an identifier ID.  Currently, this
+   is used only in c_do_switch_warnings so that we can obtain the CONST_DECL
+   associated with an enumerator identifier.  */
+
+tree
+get_decl_for_identifier (tree id)
+{
+  return I_SYMBOL_DECL (id);
+}
+
 #include "g

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

2022-05-07 Thread Marek Polacek via Gcc-patches
On Tue, May 03, 2022 at 04:59:38PM -0400, Jason Merrill wrote:
> Does this testcase still work with this patch?
> 
> struct A {
>   const A* p = this;
> };
> 
> struct B {
>   A a = A{};
> };
> 
> constexpr B b;
> static_assert (b.a.p == &b.a);

Ouch, no.  Thanks for catching this, it would have been very unpleasant
to hit this problem later...

The reason your testcase was rejected is that replacing a PLACEHOLDER
in the outermost TARGET_EXPR broke guaranteed copy elision.  Now that
I've spent another day on this, I still think we have to replace the
placeholders created when temporary materialization takes place in an
NSDMI, but it must happen in digest_nsdmi_init (as Patrick suggested),
where we can see the full initializer.  That way I can avoid breaking
copy elision.  I've added a bunch of new testcases and updated the
(already long) description.  The yuge comment hopefully also explains
how this problem is avoided.  Thanks again,

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

-- >8 --
Consider

  struct A {
int x;
int y = x;
  };

  struct B {
int x = 0;
int y = A{x}.y; // #1
  };

where for #1 we end up with

  {.x=(&)->x, .y=(&)->x}

that is, two PLACEHOLDER_EXPRs for different types on the same level in
a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism to
avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.

Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
finish_compound_literal
on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
don't
have any object to refer to yet.  After digesting, we have

  {.x=((struct B *) this)->x, .y=(&)->x}

and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole ctor
CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns

  TARGET_EXPR x, .y=(&)->x}>

Then we get to

  B b = {};

and call store_init_value, which digests the {}, which produces

  {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR )->x, .y=(&)->x}>).y}

lookup_placeholder in constexpr won't find an object to replace the
PLACEHOLDER_EXPR for B, because ctx->object will be D.2395 of type A, and we
cannot search outward from D.2395 to find 'b'.

The call to replace_placeholders in store_init_value will not do anything:
we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only
a sub-expression, so replace_placeholders does nothing, so the 
stays even though now is the perfect time to replace it because we have an
object for it: 'b'.

Later, in cp_gimplify_init_expr the *expr_p is

  D.2395 = {.x=(&)->x, .y=(&)->x}

where D.2395 is of type A, but we crash because we hit , which
has a different type.

My idea was to replace  with D.2384 after creating the
TARGET_EXPR because that means we have an object we can refer to.
Then clear CONSTRUCTOR_PLACEHOLDER_BOUNDARY because we no longer have
a PLACEHOLDER_EXPR in the {}.  Then store_init_value will be able to
replace  with 'b', and we should be good to go.  We must
be careful not to break guaranteed copy elision, so this replacement
happens in digest_nsdmi_init where we can see the whole initializer,
and avoid replacing any placeholders in the outermost TARGET_EXPR.

PR c++/100252

gcc/cp/ChangeLog:

* typeck2.cc (replace_placeholders_for_class_temp_r): New.
(digest_nsdmi_init): Call it.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/nsdmi-aggr14.C: New test.
* g++.dg/cpp1y/nsdmi-aggr15.C: New test.
* g++.dg/cpp1y/nsdmi-aggr16.C: New test.
* g++.dg/cpp1y/nsdmi-aggr17.C: New test.
* g++.dg/cpp1y/nsdmi-aggr18.C: New test.
---
 gcc/cp/typeck2.cc | 54 +++
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C | 46 +++
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr15.C | 29 
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr16.C | 19 
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr17.C | 47 
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr18.C | 25 +++
 6 files changed, 220 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr15.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr16.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr17.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr18.C

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 63d95c1529a..72d7cfaf1d3 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1371,6 +1371,34 @@ digest_init_flags (tree type, tree init, int flags, 
tsubst_flags_t complain)
   return digest_init_r (type, init, 0, flags, complain);
 }
 
+/* Callback to replace PLACEHOLDER_EXPRs in a TARGET_EXPR (which isn't used
+   in the context of guaranteed copy elision).  */
+
+static tree
+replace_placeholders_for_class_

Re: [PATCH] c++: constexpr init of union sub-aggr w/ base [PR105491]

2022-05-06 Thread Marek Polacek via Gcc-patches
On Fri, May 06, 2022 at 11:56:30AM -0400, Jason Merrill via Gcc-patches wrote:
> On 5/6/22 11:22, Patrick Palka wrote:
> > Here ever since r10-7313-gb599bf9d6d1e18, reduced_constant_expression_p
> > in C++11/14 is rejecting the marked sub-aggregate initializer (of type S)
> > 
> >W w = {.D.2445={.s={.D.2387={.m=0}, .b=0}}}
> >   ^
> > 
> > ultimately because said initializer has CONSTRUCTOR_NO_CLEARING set, and
> > so the function proceeds to verify that all fields of S are initialized.
> > And before C++17 we don't expect to see base class fields (since
> > next_initializable_field skips over the), so the base class initializer
> > causes r_c_e_p to return false.
> 
> That seems like the primary bug.  I guess r_c_e_p shouldn't be using
> next_initializable_field.  Really that function should only be used for
> aggregates.

Can we please make a note to this effect in the n_i_f comment?

Thanks,
Marek



[PATCH v2] c++: wrong error with MVP and pushdecl [PR64679]

2022-05-05 Thread Marek Polacek via Gcc-patches
On Wed, May 04, 2022 at 09:29:46PM -0400, Jason Merrill wrote:
> On 5/4/22 19:20, Marek Polacek wrote:
> > On Wed, May 04, 2022 at 05:44:45PM -0400, Jason Merrill wrote:
> > > On 5/4/22 16:03, Marek Polacek wrote:
> > > > This patch fixes the second half of 64679.  Here we issue a wrong
> > > > "redefinition of 'int x'" for the following:
> > > > 
> > > > struct Bar {
> > > >   Bar(int, int, int);
> > > > };
> > > > 
> > > > int x = 1;
> > > > Bar bar(int(x), int(x), int{x}); // #1
> > > > 
> > > > cp_parser_parameter_declaration_list does pushdecl every time it sees
> > > > a named parameter, so the second "int(x)" causes the error.  That's
> > > > premature, since this turns out to be a constructor call after the
> > > > third argument!
> > > > 
> > > > If the first parameter is parenthesized, we can't push until we've
> > > > established we're looking at a function declaration.  Therefore this
> > > > could be fixed by some kind of lookahead.  I thought about introducing
> > > > a lightweight variant of cp_parser_parameter_declaration_list that would
> > > > not have any side effects and would return as soon as it figures out
> > > > whether it's looking at a declaration or expression.  Since that would
> > > > require fairly nontrivial changes, I wanted something simpler.  
> > > > Something
> > > > like delaying the pushdecl until we've reached the ')' following the
> > > > parameter-declaration-clause.  But that doesn't quite cut it: we must
> > > > have pushed the parameters before processing a default argument, as in:
> > > > 
> > > > Bar bar(int(a), int(b), int c = sizeof(a));  // valid
> > > 
> > > I wondered how this would affect
> > > 
> > >void f(int (i), decltype(i) j = 42);
> > > 
> > > interestingly, clang and EDG both reject this, but they accept
> > > 
> > >void f(int (i), bool b = true, decltype(i) j = 42);
> > > 
> > > which suggests a similar implementation strategy.  MSVC accepts both.
> > 
> > Sigh, C++.
> > 
> > So the former would be rejected with this patch because decltype(i)
> > is parsed as the declspec.  And I can't play any cute games with decltype
> > because a decltype doesn't necessarily mean a parameter:
> > 
> > struct F {
> >F(int, int);
> > };
> > 
> > void
> > g ()
> > {
> >int x = 42;
> > 
> >F v1(int(x), decltype(x)(42));
> > 
> >F f1(int(i), decltype(i) j = 42);
> >F f2(int(i), decltype(i) j);
> >F f3(int(i), decltype(i)(j));
> >F f4(int(i), decltype(i)(j) = 42);
> >F f5(int (i), bool b = true, decltype(i) j = 42);
> >F f6(int(i), decltype(x)(x));
> > }
> > 
> > 
> > But I think there's a way out: we could pushdecl the parameters as we
> > go and only stash when there would be a clash, if parsing tentatively.
> > And then push the pending parameters only at the end of the clause, solely
> > to get the redefinition/redeclaration error.  That is:
> > 
> >Bar b(int(x), int(x), int{x});
> > 
> > would mean:
> > push x
> > store x
> > it's not a decl -> discard it, parse as an expression
> > 
> >Bar b(int(x), int(x), int);
> > 
> > would mean:
> > push x
> > store x
> > it's a decl -> push pending parameters -> error
> > 
> > And then I don't need to push when about to commit, avoiding the need to
> > change cp_parser_parameter_declaration.  WDYT?
> 
> Sounds good to me.

Thanks!  Here's that approach in a patch form:

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

-- >8 --
This patch fixes the second half of 64679.  Here we issue a wrong
"redefinition of 'int x'" for the following:

  struct Bar {
Bar(int, int, int);
  };

  int x = 1;
  Bar bar(int(x), int(x), int{x}); // #1

cp_parser_parameter_declaration_list does pushdecl every time it sees
a named parameter, so the second "int(x)" causes the error.  That's
premature, since this turns out to be a constructor call after the
third argument!

If the first parameter is parenthesized, we can't push until we've
established we're looking at a function declaration.  Therefore this
could be fixed by some kind of lookahead.  I thought a

Re: [PATCH] testsuite: Update Wconversion testcase check type.

2022-05-05 Thread Marek Polacek via Gcc-patches
On Thu, May 05, 2022 at 06:33:20PM +0800, jiawei wrote:
> Some compiler target like arm-linux\riscv\power\s390x\xtensa-gcc handle 
> char as unsigned char, then there are no warnings occur and got FAIL cases.
> Just change the type char into explicit signed char to keep the feature
> consistency.
> 
> gcc/testsuite/ChangeLog:
> 
> * c-c++-common/Wconversion-1.c: Update type.

Ok, and sorry for introducing this problem!
 
> ---
>  gcc/testsuite/c-c++-common/Wconversion-1.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gcc/testsuite/c-c++-common/Wconversion-1.c 
> b/gcc/testsuite/c-c++-common/Wconversion-1.c
> index ed65918c70f..7053f6b5dbb 100644
> --- a/gcc/testsuite/c-c++-common/Wconversion-1.c
> +++ b/gcc/testsuite/c-c++-common/Wconversion-1.c
> @@ -10,5 +10,5 @@ void g()
>signed char sc = 300; /* { dg-warning "conversion from .int. to .signed 
> char. changes value from .300. to .44." } */
>unsigned char uc = 300; /* { dg-warning "conversion from .int. to 
> .unsigned char. changes value from .300. to .44." } */
>unsigned char uc2 = 300u; /* { dg-warning "conversion from .unsigned int. 
> to .unsigned char. changes value from .300. to .44." } */
> -  char c2 = (double)1.0 + 200; /* { dg-warning "overflow in conversion from 
> .double. to .char. changes value from .2.01e\\+2. to .127." } */
> +  signed char c2 = (double)1.0 + 200; /* { dg-warning "overflow in 
> conversion from .double. to .signed char. changes value from .2.01e\\+2. to 
> .127." } */
>  }
> -- 
> 2.25.1
> 

Marek



Re: [PATCH] Come up with {,UN}LIKELY macros.

2022-05-05 Thread Marek Polacek via Gcc-patches
On Thu, May 05, 2022 at 02:31:05PM +0200, Martin Liška wrote:
> Some parts of the compiler already define:
> #define likely(cond) __builtin_expect ((cond), 1)
> 
> So the patch should unify it.
> 
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> 
> Ready to be installed?
> Thanks,
> Martin
> 
> gcc/c/ChangeLog:
> 
>   * c-parser.cc (c_parser_conditional_expression): Use {,UN}LIKELY
>   macros.
>   (c_parser_binary_expression): Likewise.
> 
> gcc/cp/ChangeLog:
> 
>   * cp-gimplify.cc (cp_genericize_r): Use {,UN}LIKELY
>   macros.
>   * parser.cc (cp_finalize_omp_declare_simd): Likewise.
>   (cp_finalize_oacc_routine): Likewise.

That's funny, yesterday I added another one: 
cp/parser.cc:cp_parser_init_declarator
which is not replaced in this patch.

I would've preferred the name gcc_{,un}likely but I don't want to start
a long bikeshedding...

Thanks,

Marek



Re: [PATCH] c++: wrong error with MVP and pushdecl [PR64679]

2022-05-04 Thread Marek Polacek via Gcc-patches
On Wed, May 04, 2022 at 05:44:45PM -0400, Jason Merrill wrote:
> On 5/4/22 16:03, Marek Polacek wrote:
> > This patch fixes the second half of 64679.  Here we issue a wrong
> > "redefinition of 'int x'" for the following:
> > 
> >struct Bar {
> >  Bar(int, int, int);
> >};
> > 
> >int x = 1;
> >Bar bar(int(x), int(x), int{x}); // #1
> > 
> > cp_parser_parameter_declaration_list does pushdecl every time it sees
> > a named parameter, so the second "int(x)" causes the error.  That's
> > premature, since this turns out to be a constructor call after the
> > third argument!
> > 
> > If the first parameter is parenthesized, we can't push until we've
> > established we're looking at a function declaration.  Therefore this
> > could be fixed by some kind of lookahead.  I thought about introducing
> > a lightweight variant of cp_parser_parameter_declaration_list that would
> > not have any side effects and would return as soon as it figures out
> > whether it's looking at a declaration or expression.  Since that would
> > require fairly nontrivial changes, I wanted something simpler.  Something
> > like delaying the pushdecl until we've reached the ')' following the
> > parameter-declaration-clause.  But that doesn't quite cut it: we must
> > have pushed the parameters before processing a default argument, as in:
> > 
> >Bar bar(int(a), int(b), int c = sizeof(a));  // valid
> 
> I wondered how this would affect
> 
>   void f(int (i), decltype(i) j = 42);
> 
> interestingly, clang and EDG both reject this, but they accept
> 
>   void f(int (i), bool b = true, decltype(i) j = 42);
> 
> which suggests a similar implementation strategy.  MSVC accepts both.

Sigh, C++.

So the former would be rejected with this patch because decltype(i)
is parsed as the declspec.  And I can't play any cute games with decltype
because a decltype doesn't necessarily mean a parameter:

struct F {
  F(int, int);
};

void
g ()
{
  int x = 42;

  F v1(int(x), decltype(x)(42));

  F f1(int(i), decltype(i) j = 42);
  F f2(int(i), decltype(i) j);
  F f3(int(i), decltype(i)(j));
  F f4(int(i), decltype(i)(j) = 42);
  F f5(int (i), bool b = true, decltype(i) j = 42);
  F f6(int(i), decltype(x)(x));
}


But I think there's a way out: we could pushdecl the parameters as we
go and only stash when there would be a clash, if parsing tentatively.
And then push the pending parameters only at the end of the clause, solely
to get the redefinition/redeclaration error.  That is:

  Bar b(int(x), int(x), int{x});

would mean:
push x
store x
it's not a decl -> discard it, parse as an expression

  Bar b(int(x), int(x), int);

would mean:
push x
store x
it's a decl -> push pending parameters -> error

And then I don't need to push when about to commit, avoiding the need to
change cp_parser_parameter_declaration.  WDYT?

Marek



[PATCH] c++: wrong error with MVP and pushdecl [PR64679]

2022-05-04 Thread Marek Polacek via Gcc-patches
This patch fixes the second half of 64679.  Here we issue a wrong
"redefinition of 'int x'" for the following:

  struct Bar {
Bar(int, int, int);
  };

  int x = 1;
  Bar bar(int(x), int(x), int{x}); // #1

cp_parser_parameter_declaration_list does pushdecl every time it sees
a named parameter, so the second "int(x)" causes the error.  That's
premature, since this turns out to be a constructor call after the
third argument!

If the first parameter is parenthesized, we can't push until we've
established we're looking at a function declaration.  Therefore this
could be fixed by some kind of lookahead.  I thought about introducing
a lightweight variant of cp_parser_parameter_declaration_list that would
not have any side effects and would return as soon as it figures out
whether it's looking at a declaration or expression.  Since that would
require fairly nontrivial changes, I wanted something simpler.  Something
like delaying the pushdecl until we've reached the ')' following the
parameter-declaration-clause.  But that doesn't quite cut it: we must
have pushed the parameters before processing a default argument, as in:

  Bar bar(int(a), int(b), int c = sizeof(a));  // valid

After more trial and error than I'd be willing to admit I came up with
the following, which stashes parameters into a vector when parsing
tentatively, and only pushes when we're about to commit to any tentative
parse (that handles the default argument case) or we're at the end of
a parameter-declaration-clause followed by a ')' (so that we still diagnose
redefining a parameter).

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

PR c++/64679

gcc/cp/ChangeLog:

* parser.cc (push_pending_decls): New.
(cp_parser_parameter_declaration_clause): Maintain a vector of
parameters that haven't been pushed yet.  Push them at the end of
a valid parameter-declaration-clause
(cp_parser_parameter_declaration_list): Take a new auto_vec parameter.
Pass it down to cp_parser_parameter_declaration.  Do not pushdecl
while parsing tentatively.
(cp_parser_parameter_declaration): Take a new auto_vec parameter.
push_pending_decls when we're about to commit.
(cp_parser_cache_defarg): Adjust the call to
cp_parser_parameter_declaration_list.

gcc/testsuite/ChangeLog:

* g++.dg/parse/ambig11.C: New test.
* g++.dg/parse/ambig12.C: New test.
* g++.dg/parse/ambig13.C: New test.
---
 gcc/cp/parser.cc | 76 
 gcc/testsuite/g++.dg/parse/ambig11.C | 39 ++
 gcc/testsuite/g++.dg/parse/ambig12.C | 12 +
 gcc/testsuite/g++.dg/parse/ambig13.C | 32 
 4 files changed, 148 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/ambig11.C
 create mode 100644 gcc/testsuite/g++.dg/parse/ambig12.C
 create mode 100644 gcc/testsuite/g++.dg/parse/ambig13.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 5fa743b5a8e..dd51b3a7b79 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2391,9 +2391,9 @@ static void cp_parser_type_specifier_seq
 static tree cp_parser_parameter_declaration_clause
   (cp_parser *, cp_parser_flags);
 static tree cp_parser_parameter_declaration_list
-  (cp_parser *, cp_parser_flags);
+  (cp_parser *, cp_parser_flags, auto_vec *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
-  (cp_parser *, cp_parser_flags, bool, bool *);
+  (cp_parser *, cp_parser_flags, bool, bool *, auto_vec * = nullptr);
 static tree cp_parser_default_argument
   (cp_parser *, bool);
 static void cp_parser_function_body
@@ -24438,6 +24438,27 @@ function_being_declared_is_template_p (cp_parser* 
parser)
  (current_class_type));
 }
 
+/* Push any pending named parameters we have seen in this function declaration
+   and stashed into PENDING_DECLS.  This mechanism is used for cases like
+
+ S foo(int(x), int(x), int{x});
+
+   where it's not clear if we're dealing with a constructor call or a function
+   declaration until we've seen the last argument which breaks it up.  Pushing
+   immediately would result in the redefinition error on the second 'x'.
+
+   We only have to do this if the first parameter is parenthesized.  */
+
+static void
+push_pending_decls (auto_vec *pending_decls)
+{
+  if (!pending_decls)
+return;
+  for (tree p : pending_decls)
+pushdecl (p);
+  pending_decls->truncate (0);
+}
+
 /* Parse a parameter-declaration-clause.
 
parameter-declaration-clause:
@@ -24494,8 +24515,12 @@ cp_parser_parameter_declaration_clause (cp_parser* 
parser,
   return explicit_void_list_node;
 }
 
+  /* A vector of parameters that haven't been pushed yet.  */
+  auto_vec pending_decls;
+
   /* Parse the parameter-declaration-list.  */
-  parameters = cp_parser_parameter_declaration_list (parser, flags);
+  parameters = cp_parser_parameter_declaration_list (parser, flags,
+ 

Re: [PATCH] c++: wrong parse with functors [PR64679]

2022-05-04 Thread Marek Polacek via Gcc-patches
On Tue, May 03, 2022 at 04:43:05PM -0400, Jason Merrill via Gcc-patches wrote:
> On 5/2/22 12:18, Marek Polacek wrote:
> > Consider
> > 
> >struct F {
> >  F(int) {}
> >  F operator()(int) const { return *this; }
> >};
> > 
> > and
> > 
> >F(i)(0)(0);
> > 
> > where we're supposed to first call the constructor and then invoke
> > the operator() twice.  However, we parse this as an init-declarator:
> > "(i)" looks like a perfectly valid declarator, then we see an '(' and
> > think it must be an initializer, so we commit and we're toast.
> 
> How vexing!

:-) Most vexing indeed!
 
> > My
> > fix is to look a little bit farther before deciding we've seen an
> > initializer.
> > 
> > This is only a half of c++/64679, the other part of the PR is unrelated:
> > there the problem is that we are calling pushdecl while parsing
> > tentatively (in cp_parser_parameter_declaration_list), which is bad.
> > I don't know how to fix it though, maybe move the pushdecl call to
> > grokparms?  Tricky :(.
> 
> Can we pop the parm decls when the tentative parse fails?

Unfortunately no, we'll have already given a hard error when that
happens.  About to send a patch where I describe the problem in
detail.

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

Thanks!

Marek



Re: [PATCH] c++: parse error with >= in template argument list [PR105436]

2022-05-04 Thread Marek Polacek via Gcc-patches
On Tue, May 03, 2022 at 04:46:11PM -0400, Jason Merrill wrote:
> On 5/3/22 16:43, Jakub Jelinek wrote:
> > On Tue, May 03, 2022 at 04:26:51PM -0400, Jason Merrill wrote:
> > > On 5/2/22 12:19, Marek Polacek wrote:
> > > > This patch fixes an oversight whereby we treated >= as the end of
> > > > a template argument.  This causes problems in C++14, because in
> > > > cp_parser_template_argument we go different ways for C++14 and C++17:
> > > > 
> > > > /* It must be a non-type argument.  In C++17 any 
> > > > constant-expression is
> > > >allowed.  */
> > > > if (cxx_dialect > cxx14)
> > > >   goto general_expr;
> > > > 
> > > > so in this testcase in C++14 we get "N" as the template argument but in
> > > > C++17 it is the whole "N >= 5" expression.  So in C++14 the remaining
> > > > ">= 5" triggered the newly-added diagnostic.
> > > 
> > > Hmm, I think >>= is questionable as well, as it could resolve to a 
> > > constexpr
> > > operator>>=.  Seems like the two calls to
> > 
> > The template argument is a constant-expression and >>= can't appear 
> > non-nested
> > in constant-expression non-terminal, can it?
> 
> Ah, true, a constant-expression is a conditional-expression, which can't
> involve an assignment operator.

So do you want me to make any changes or is the patch OK as-is?

Marek



[PATCH] c++: parse error with >= in template argument list [PR105436]

2022-05-02 Thread Marek Polacek via Gcc-patches
This patch fixes an oversight whereby we treated >= as the end of
a template argument.  This causes problems in C++14, because in
cp_parser_template_argument we go different ways for C++14 and C++17:

  /* It must be a non-type argument.  In C++17 any constant-expression is
 allowed.  */
  if (cxx_dialect > cxx14)
goto general_expr;

so in this testcase in C++14 we get "N" as the template argument but in
C++17 it is the whole "N >= 5" expression.  So in C++14 the remaining
">= 5" triggered the newly-added diagnostic.

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

PR c++/105436

gcc/cp/ChangeLog:

* parser.cc (cp_parser_next_token_ends_template_argument_p): Don't
return true for CPP_GREATER_EQ.

gcc/testsuite/ChangeLog:

* g++.dg/parse/template31.C: New test.
---
 gcc/cp/parser.cc| 1 -
 gcc/testsuite/g++.dg/parse/template31.C | 4 
 2 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/template31.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a5cbb3e896f..5fa743b5a8e 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -33224,7 +33224,6 @@ cp_parser_next_token_ends_template_argument_p 
(cp_parser *parser)
  || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT)
  /* For better diagnostics, treat >>= like that too, that
 shouldn't appear non-nested in template arguments.  */
- || token->type == CPP_GREATER_EQ
  || token->type == CPP_RSHIFT_EQ);
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/template31.C 
b/gcc/testsuite/g++.dg/parse/template31.C
new file mode 100644
index 000..a5693e851f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template31.C
@@ -0,0 +1,4 @@
+// PR c++/105436
+
+template struct A;
+template A= 5> f();

base-commit: 1cb220498e1f59021dab36c39c5d726e9f070c6a
-- 
2.35.1



[PATCH] c++: wrong parse with functors [PR64679]

2022-05-02 Thread Marek Polacek via Gcc-patches
Consider

  struct F {
F(int) {}
F operator()(int) const { return *this; }
  };

and

  F(i)(0)(0);

where we're supposed to first call the constructor and then invoke
the operator() twice.  However, we parse this as an init-declarator:
"(i)" looks like a perfectly valid declarator, then we see an '(' and
think it must be an initializer, so we commit and we're toast.  My
fix is to look a little bit farther before deciding we've seen an
initializer.

This is only a half of c++/64679, the other part of the PR is unrelated:
there the problem is that we are calling pushdecl while parsing
tentatively (in cp_parser_parameter_declaration_list), which is bad.
I don't know how to fix it though, maybe move the pushdecl call to
grokparms?  Tricky :(.

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

PR c++/64679

gcc/cp/ChangeLog:

* parser.cc (cp_parser_init_declarator): Properly handle a series of
operator() calls, they are not part of an init-declarator.

gcc/testsuite/ChangeLog:

* g++.dg/parse/functor1.C: New test.
---
 gcc/cp/parser.cc  | 25 -
 gcc/testsuite/g++.dg/parse/functor1.C | 22 ++
 2 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/functor1.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a5cbb3e896f..6e2936b68ef 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -22636,11 +22636,34 @@ cp_parser_init_declarator (cp_parser* parser,
   return error_mark_node;
 }
 
-  /* An `=' or an `(', or an '{' in C++0x, indicates an initializer.  */
+  /* An `=' or an '{' in C++11, indicate an initializer.  An '(' may indicate
+ an initializer as well. */
   if (token->type == CPP_EQ
   || token->type == CPP_OPEN_PAREN
   || token->type == CPP_OPEN_BRACE)
 {
+  /* Don't get fooled into thinking that F(i)(1)(2) is an initializer.
+It isn't; it's an expression.  (Here '(i)' would have already been
+parsed as a declarator.)   */
+  if (token->type == CPP_OPEN_PAREN
+ && cp_parser_uncommitted_to_tentative_parse_p (parser))
+   {
+ cp_lexer_save_tokens (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_skip_to_closing_parenthesis (parser,
+/*recovering*/false,
+/*or_comma*/false,
+/*consume_paren*/true);
+ /* If this is an initializer, only a ',' or ';' can follow: either
+we have another init-declarator, or we're at the end of an
+init-declarator-list which can only be followed by a ';'.  */
+ bool ok = (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+|| cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
+ cp_lexer_rollback_tokens (parser->lexer);
+ if (__builtin_expect (!ok, 0))
+   /* Not an init-declarator.  */
+   return error_mark_node;
+   }
   is_initialized = SD_INITIALIZED;
   initialization_kind = token->type;
   declarator->init_loc = token->location;
diff --git a/gcc/testsuite/g++.dg/parse/functor1.C 
b/gcc/testsuite/g++.dg/parse/functor1.C
new file mode 100644
index 000..c014114c098
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/functor1.C
@@ -0,0 +1,22 @@
+// PR c++/64679
+// { dg-do run }
+
+struct F {
+  F(int) { }
+  F(int, int) { }
+  F operator()(int) const { return *this; }
+  F operator()(int, int) const { return *this; }
+};
+
+int main()
+{
+  // Init-declarators.
+  int i = 0;
+  int (j)(1);
+  // None of these is an init-declarator.
+  F(i)(1)(2);
+  F(i)(1, 2)(3);
+  F(i)(1)(2, 3);
+  F(i)(2)(3)(4)(5);
+  F(i, j)(1)(2)(3)(4)(5)(6);
+}

base-commit: 1cb220498e1f59021dab36c39c5d726e9f070c6a
-- 
2.35.1



[PATCH] c++: fix ICE on invalid attributes [PR96637]

2022-04-29 Thread Marek Polacek via Gcc-patches
This patch fixes crashes with invalid attributes.  Arguably it could
make sense to assert seen_error() too.

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

PR c++/96637

gcc/ChangeLog:

* attribs.cc (decl_attributes): Check error_mark_node.

gcc/cp/ChangeLog:

* decl2.cc (cp_check_const_attributes): Check error_mark_node.

gcc/testsuite/ChangeLog:

* g++.dg/parse/error64.C: New test.
---
 gcc/attribs.cc   | 3 +++
 gcc/cp/decl2.cc  | 2 ++
 gcc/testsuite/g++.dg/parse/error64.C | 4 
 3 files changed, 9 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/parse/error64.C

diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index b219f878042..ff157dcf81c 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -700,6 +700,9 @@ decl_attributes (tree *node, tree attributes, int flags,
  in the same order as in the source.  */
   for (tree attr = attributes; attr; attr = TREE_CHAIN (attr))
 {
+  if (attr == error_mark_node)
+   continue;
+
   tree ns = get_attribute_namespace (attr);
   tree name = get_attribute_name (attr);
   tree args = TREE_VALUE (attr);
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index d2b29208ed5..c3ff1962a75 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -1537,6 +1537,8 @@ cp_check_const_attributes (tree attributes)
   /* As we implement alignas using gnu::aligned attribute and
 alignas argument is a constant expression, force manifestly
 constant evaluation of aligned attribute argument.  */
+  if (attr == error_mark_node)
+   continue;
   bool manifestly_const_eval
= is_attribute_p ("aligned", get_attribute_name (attr));
   for (arg = TREE_VALUE (attr); arg && TREE_CODE (arg) == TREE_LIST;
diff --git a/gcc/testsuite/g++.dg/parse/error64.C 
b/gcc/testsuite/g++.dg/parse/error64.C
new file mode 100644
index 000..87848a58c27
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error64.C
@@ -0,0 +1,4 @@
+// PR c++/96637
+// { dg-do compile }
+
+void foo(int[] alignas[1] alignas(1)){} // { dg-error "" }

base-commit: 9ae8b993cd362e8aea4f65580aaf1453120207f2
-- 
2.35.1



[PATCH] c++: pedwarn for empty unnamed enum in decl [PR67048]

2022-04-29 Thread Marek Polacek via Gcc-patches
[dcl.dcl]/5 says that

  enum { };

is ill-formed, and since r197742 we issue a pedwarn.  However, the
pedwarn also fires for

   enum { } x;

which is well-formed.  So only warn when {} is followed by a ;.  This
should be correct since you can't have "enum {}, " -- that
produces "expected unqualified-id before ',' token".

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  I think
this could go to 12.2 and 11.4 too.

PR c++/67048

gcc/cp/ChangeLog:

* parser.cc (cp_parser_enum_specifier): Warn about empty unnamed enum
only when it's followed by a semicolon.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/enum42.C: New test.
---
 gcc/cp/parser.cc| 4 +++-
 gcc/testsuite/g++.dg/cpp0x/enum42.C | 7 +++
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum42.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 2235da10c7c..0fa37fdfb66 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -21007,7 +21007,9 @@ cp_parser_enum_specifier (cp_parser* parser)
   /* If the next token is not '}', then there are some enumerators.  */
   else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
{
- if (is_unnamed && !scoped_enum_p)
+ if (is_unnamed && !scoped_enum_p
+ /* Don't warn for enum {} a; here.  */
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_SEMICOLON))
pedwarn (type_start_token->location, OPT_Wpedantic,
 "ISO C++ forbids empty unnamed enum");
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum42.C 
b/gcc/testsuite/g++.dg/cpp0x/enum42.C
new file mode 100644
index 000..05b372a1947
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum42.C
@@ -0,0 +1,7 @@
+// PR c++/67048
+// { dg-do compile { target c++11 } }
+// { dg-options -Wpedantic }
+
+typedef enum {} X;
+enum {} x;
+enum {} y, z;

base-commit: 9ae8b993cd362e8aea4f65580aaf1453120207f2
-- 
2.35.1



[pushed] c++: Add fixed test [PR83596]

2022-04-29 Thread Marek Polacek via Gcc-patches
This was fixed by r269078.

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

PR c++/83596

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype5.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype5.C
new file mode 100644
index 000..7e6639dd175
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype5.C
@@ -0,0 +1,11 @@
+// PR c++/83596
+// { dg-do compile { target c++17 } }
+
+struct X { int x; int y; };
+template  int get(X& x) { return x.*mp; }
+constexpr int X::* getMP() { return &X::y; }
+constexpr int X::* mptr = getMP();
+int test() {
+X x{1, 2};
+return get(x);
+}

base-commit: bb7cf39b05a216431a431499d0c36a6034f6acc4
-- 
2.35.1



[pushed] c++: Add fixed test [PR78244]

2022-04-29 Thread Marek Polacek via Gcc-patches
This was finally fixed for GCC 11 by r11-434.

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

PR c++/78244

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing20.C 
b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing20.C
new file mode 100644
index 000..17a6001266d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing20.C
@@ -0,0 +1,26 @@
+// PR c++/78244
+// { dg-do compile { target c++11 } }
+
+struct S { S(int); int d; };
+
+template 
+auto f1() -> decltype(S{2.0}, void()) { } // { dg-error "narrowing conversion" 
}
+
+template 
+auto f2() -> decltype(S{2.0}, 1) { return 1; } // { dg-error "narrowing 
conversion" }
+
+template 
+auto f3() -> decltype(void(), S{2.0}, 1) { return 1; } // { dg-error 
"narrowing conversion" }
+
+template 
+auto f4() -> decltype((S{2.0}, 1)) { return 1; } // { dg-error "narrowing 
conversion" }
+
+// Test OVERLOAD in a template.
+int id(int v) { return v; }
+double id(double v) { return v; }
+
+template 
+auto f5(double v) -> decltype((S{id(v)}, 1)) { return 1; } // { dg-error 
"narrowing conversion" }
+
+template 
+auto f6(int v) -> decltype((S{id(v)}, 1)) { return 1; }

base-commit: e1115a4f1b4afb346341237355186949f8e568a8
-- 
2.35.1



[pushed] c++: Add fixed test [PR71424]

2022-04-29 Thread Marek Polacek via Gcc-patches
This was fixed by r12-6329-g4f6bc28fc7dd86.

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

PR c++/71424

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array15.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-array15.C
new file mode 100644
index 000..67e30d8d93e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array15.C
@@ -0,0 +1,13 @@
+// PR c++/71424
+// { dg-do compile { target c++11 } }
+
+#include 
+
+void f(std::initializer_list list)
+{
+}
+
+int main()
+{
+   f({ { 1.0, 2.0 }, { 3.0, 4.0 } });
+}

base-commit: a0a2554d7c86c126de85fcbd5bd7e16dbb5a2693
-- 
2.35.1



Re: [PATCH v2] c++: ICE with temporary of class type in DMI [PR100252]

2022-04-28 Thread Marek Polacek via Gcc-patches
On Thu, Apr 28, 2022 at 10:12:04AM -0400, Patrick Palka wrote:
> On Wed, 27 Apr 2022, Marek Polacek wrote:
> 
> > On Wed, Apr 27, 2022 at 11:00:46AM -0400, Patrick Palka wrote:
> > > On Tue, 26 Apr 2022, Marek Polacek wrote:
> > > 
> > > > Consider
> > > > 
> > > >   struct A {
> > > > int x;
> > > > int y = x;
> > > >   };
> > > > 
> > > >   struct B {
> > > > int x = 0;
> > > > int y = A{x}.y; // #1
> > > >   };
> > > > 
> > > > where for #1 we end up with
> > > > 
> > > >   {.x=(&)->x, .y=(& > > > A>)->x}
> > > > 
> > > > that is, two PLACEHOLDER_EXPRs for different types on the same level in
> > > > a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY 
> > > > mechanism to
> > > > avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.
> > > > 
> > > > Here's why we wound up with those PLACEHOLDER_EXPRs: When we're 
> > > > performing
> > > > cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
> > > > finish_compound_literal
> > > > on type=A, compound_literal={((struct B *) this)->x}.  When digesting 
> > > > this
> > > > initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A 
> > > > -- we don't
> > > > have any object to refer to yet.  After digesting, we have
> > > > 
> > > >   {.x=((struct B *) this)->x, .y=(&)->x}
> > > > 
> > > > and since we've created a PLACEHOLDER_EXPR inside it, we marked the 
> > > > whole ctor
> > > > CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and 
> > > > returns
> > > > 
> > > >   TARGET_EXPR x, 
> > > > .y=(&)->x}>
> > > > 
> > > > Then we get to
> > > > 
> > > >   B b = {};
> > > > 
> > > > and call store_init_value, which digest the {}, which produces
> > > > 
> > > >   {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR  > > > {.x=(&)->x, .y=(& > > > A>)->x}>).y}
> > > > 
> > > > The call to replace_placeholders in store_init_value will not do 
> > > > anything:
> > > > we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's 
> > > > only
> > > > a sub-expression, so replace_placeholders does nothing, so the  > > > struct B>
> > > > stays even though now is the perfect time to replace it because we have 
> > > > an
> > > > object for it: 'b'.
> > > > 
> > > > Later, in cp_gimplify_init_expr the *expr_p is
> > > > 
> > > >   D.2395 = {.x=(&)->x, 
> > > > .y=(&)->x}
> > > > 
> > > > where D.2395 is of type A, but we crash because we hit , 
> > > > which
> > > > has a different type.
> > > > 
> > > > My idea was to replace  with D.2384 in f_c_l after 
> > > > creating the
> > > > TARGET_EXPR because that means we have an object we can refer to.  Then 
> > > > clear
> > > > CONSTRUCTOR_PLACEHOLDER_BOUNDARY because we no longer have a 
> > > > PLACEHOLDER_EXPR
> > > > in the {}.  Then store_init_value will be able to replace  > > > B> with
> > > > 'b', and we should be good to go.
> > > 
> > > Makes sense to me.  It seems all was well until break_out_target_exprs,
> > > called from get_nsdmi for B::y, replaced the 'this' in the initializer
> > > 
> > >   (TARGET_EXPR x, 
> > > .y=(&)->x}>).y;
> > > 
> > > with a PLACEHOLDER_EXPR;
> > > 
> > >   (TARGET_EXPR )->x, 
> > > .y=(&)->x}>).y;
> > > 
> > > This seems to be the wrong thing to do when the 'this' appears inside a
> > > CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructor because the new
> > > PLACEHOLDER_EXPR then can't be resolved correctly.
> > 
> > Exactly.
> > 
> > > So in light of this I wonder if we should instead perform this handling
> > > you added to finish_compound_literal in break_out_target_exprs /
> > > bot_manip instead?
> > 
> > Unfortunately that causes an ICE in gimplify_var_or_parm_decl on the new
> > testcase I've added here.  bot_manip is a different context and so I can't
> > use parsing_nsdmi anymore, and it seems we'd replace the placeholders too
> > aggressively in bot_manip.  So I'm not sure if that's the best place.
> 
> Ah :/ good catch...
> 
> FWIW the transformation itself (doing replace_placeholders followed by
> clearing CONSTRUCTOR_PLACEHOLDER_BOUNDARY) makes sense to me, and I'm
> happy with doing it in finish_compound_literal when parsing_nsdmi, so
> the patch LGTM.

Thanks for taking a look.
 
> (I guess we could also consider doing the transformation in get_nsdmi or
> digest_nsdmi_init via cp_walk_tree, but I don't have a preference either 
> way..)

I actually considered doing it in get_nsdmi, but it's either too early (don't
have a TARGET_EXPR yet, therefore no object to refer to), or too late -- we're
just about to introduce .  I felt like it may be
best to replace the  at the earliest opportunity,
which if f_c_l.

Marek



[PATCH] c++: global-namespace-qualified var after class def [PR90107]

2022-04-27 Thread Marek Polacek via Gcc-patches
Here we wrongly reject the definition of "::N::a"

  struct A;
  namespace N { extern A a; }
  struct A {} ::N::a;

because our code to diagnose a missing ; after a class definition doesn't
realize that :: can follow a class definition.

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

PR c++/90107

gcc/cp/ChangeLog:

* parser.cc (cp_parser_class_specifier_1): Accept :: after a class
definition.

gcc/testsuite/ChangeLog:

* g++.dg/parse/qualified6.C: New test.
---
 gcc/cp/parser.cc|  1 +
 gcc/testsuite/g++.dg/parse/qualified6.C | 10 ++
 2 files changed, 11 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/parse/qualified6.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 169e6a62f5f..2235da10c7c 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -25933,6 +25933,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
   case CPP_OPEN_PAREN:
   case CPP_CLOSE_PAREN:
   case CPP_COMMA:
+  case CPP_SCOPE:
 want_semicolon = false;
 break;
 
diff --git a/gcc/testsuite/g++.dg/parse/qualified6.C 
b/gcc/testsuite/g++.dg/parse/qualified6.C
new file mode 100644
index 000..68b51f771ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/qualified6.C
@@ -0,0 +1,10 @@
+// PR c++/90107
+// { dg-do compile }
+
+struct A;
+namespace N { extern A a; }
+struct A {} ::N::a;
+
+struct A1;
+struct B { static A1 a1; };
+struct A1 {} ::B::a1;

base-commit: 58e4a744b6e8140499ed6c33a8e9a6557e102f74
-- 
2.35.1



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

2022-04-27 Thread Marek Polacek via Gcc-patches
On Wed, Apr 27, 2022 at 11:00:46AM -0400, Patrick Palka wrote:
> On Tue, 26 Apr 2022, Marek Polacek wrote:
> 
> > Consider
> > 
> >   struct A {
> > int x;
> > int y = x;
> >   };
> > 
> >   struct B {
> > int x = 0;
> > int y = A{x}.y; // #1
> >   };
> > 
> > where for #1 we end up with
> > 
> >   {.x=(&)->x, .y=(& > A>)->x}
> > 
> > that is, two PLACEHOLDER_EXPRs for different types on the same level in
> > a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism 
> > to
> > avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.
> > 
> > Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
> > cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
> > finish_compound_literal
> > on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
> > initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
> > don't
> > have any object to refer to yet.  After digesting, we have
> > 
> >   {.x=((struct B *) this)->x, .y=(&)->x}
> > 
> > and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole 
> > ctor
> > CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns
> > 
> >   TARGET_EXPR x, .y=(& > struct A>)->x}>
> > 
> > Then we get to
> > 
> >   B b = {};
> > 
> > and call store_init_value, which digest the {}, which produces
> > 
> >   {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR  > struct B>)->x, .y=(&)->x}>).y}
> > 
> > The call to replace_placeholders in store_init_value will not do anything:
> > we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only
> > a sub-expression, so replace_placeholders does nothing, so the  > B>
> > stays even though now is the perfect time to replace it because we have an
> > object for it: 'b'.
> > 
> > Later, in cp_gimplify_init_expr the *expr_p is
> > 
> >   D.2395 = {.x=(&)->x, .y=(& > struct A>)->x}
> > 
> > where D.2395 is of type A, but we crash because we hit , which
> > has a different type.
> > 
> > My idea was to replace  with D.2384 in f_c_l after creating 
> > the
> > TARGET_EXPR because that means we have an object we can refer to.  Then 
> > clear
> > CONSTRUCTOR_PLACEHOLDER_BOUNDARY because we no longer have a 
> > PLACEHOLDER_EXPR
> > in the {}.  Then store_init_value will be able to replace  
> > with
> > 'b', and we should be good to go.
> 
> Makes sense to me.  It seems all was well until break_out_target_exprs,
> called from get_nsdmi for B::y, replaced the 'this' in the initializer
> 
>   (TARGET_EXPR x, .y=(& struct A>)->x}>).y;
> 
> with a PLACEHOLDER_EXPR;
> 
>   (TARGET_EXPR )->x, 
> .y=(&)->x}>).y;
> 
> This seems to be the wrong thing to do when the 'this' appears inside a
> CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructor because the new
> PLACEHOLDER_EXPR then can't be resolved correctly.

Exactly.

> So in light of this I wonder if we should instead perform this handling
> you added to finish_compound_literal in break_out_target_exprs /
> bot_manip instead?

Unfortunately that causes an ICE in gimplify_var_or_parm_decl on the new
testcase I've added here.  bot_manip is a different context and so I can't
use parsing_nsdmi anymore, and it seems we'd replace the placeholders too
aggressively in bot_manip.  So I'm not sure if that's the best place.

-- >8 --
Consider

  struct A {
int x;
int y = x;
  };

  struct B {
int x = 0;
int y = A{x}.y; // #1
  };

where for #1 we end up with

  {.x=(&)->x, .y=(&)->x}

that is, two PLACEHOLDER_EXPRs for different types on the same level in
a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism to
avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.

Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
finish_compound_literal
on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
don't
have any object to refer to yet.  After digesting, we have

  {.x=((struct B *) this)->x, .y=(&)->x}

and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole ctor
CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_

Re: [PATCH] c++: enum in generic lambda at global scope [PR105398]

2022-04-27 Thread Marek Polacek via Gcc-patches
On Wed, Apr 27, 2022 at 11:47:02AM -0400, Jason Merrill wrote:
> On 4/27/22 08:59, Marek Polacek wrote:
> > On Wed, Apr 27, 2022 at 08:24:54AM -0400, Patrick Palka wrote:
> > > On Tue, 26 Apr 2022, Marek Polacek via Gcc-patches wrote:
> > > 
> > > > We crash compiling this test since r11-7993 which changed
> > > > lookup_template_class_1 so that we only call tsubst_enum when
> > > > 
> > > >!uses_template_parms (current_nonlambda_scope ())
> > > > 
> > > > But here current_nonlambda_scope () is the global NAMESPACE_DECL ::, 
> > > > which
> > > > doesn't have a type, therefore is considered type-dependent.  So we 
> > > > don't
> > > > call tsubst_enum, and crash in tsubst_copy/CONST_DECL because we didn't
> > > > find the e1 enumerator.
> > > > 
> > > > I don't think any namespace can depend on any template parameter, so
> > > > this patch tweaks uses_template_parms.
> > > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
> > > > 
> > > > PR c++/105398
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * pt.cc (uses_template_parms): Return false for any 
> > > > NAMESPACE_DECL.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp1y/lambda-generic-enum2.C: New test.
> > > > ---
> > > >   gcc/cp/pt.cc  |  2 +-
> > > >   gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C | 15 +++
> > > >   2 files changed, 16 insertions(+), 1 deletion(-)
> > > >   create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C
> > > > 
> > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > > > index 3cf1d7af8d2..e785c5db142 100644
> > > > --- a/gcc/cp/pt.cc
> > > > +++ b/gcc/cp/pt.cc
> > > > @@ -10905,7 +10905,7 @@ uses_template_parms (tree t)
> > > >|| uses_template_parms (TREE_CHAIN (t)));
> > > > else if (TREE_CODE (t) == TYPE_DECL)
> > > >   dependent_p = dependent_type_p (TREE_TYPE (t));
> > > > -  else if (t == error_mark_node)
> > > > +  else if (t == error_mark_node || TREE_CODE (t) == NAMESPACE_DECL)
> > > 
> > > LGTM.  In passing, perhaps we should move this t == error_mark_node test
> > > to the beginning of the function alongside the t == NULL_TREE test?
> > 
> > Thanks, yeah, maybe.  I also don't like the separate declaration of
> > saved_processing_template_decl, the return type, but I've resisted cleaning
> > that up, otherwise I never know when to stop.  But here's a version with 
> > more
> > cleanups:
> > 
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index e9a3d09ac4c..d0ebbb7a196 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -7311,7 +7311,7 @@ extern tree lookup_template_class (tree, 
> > tree, tree, tree,
> >  int, tsubst_flags_t);
> >   extern tree lookup_template_function  (tree, tree);
> >   extern tree lookup_template_variable  (tree, tree);
> > -extern int uses_template_parms (tree);
> > +extern bool uses_template_parms(tree);
> >   extern bool uses_template_parms_level (tree, int);
> >   extern bool in_template_function  (void);
> >   extern bool need_generic_capture  (void);
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 3cf1d7af8d2..dc5b9938f2c 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -10884,35 +10884,30 @@ find_template_parameters (tree t, tree ctx_parms)
> >   /* Returns true if T depends on any template parameter.  */
> > -int
> > +bool
> >   uses_template_parms (tree t)
> >   {
> > -  if (t == NULL_TREE)
> > +  if (t == NULL_TREE || t == error_mark_node)
> >   return false;
> > -  bool dependent_p;
> > -  int saved_processing_template_decl;
> > +  /* Namespaces can't depend on any template parameters.  */
> > +  if (TREE_CODE (t) == NAMESPACE_DECL)
> > +return false;
> > +
> > +  processing_template_decl_sentinel ptds (/*reset*/false);
> > +  ++processing_template_decl;
> > -  saved_processing_template_decl = processing_template_decl;
> > -  

Re: [PATCH RFA] c-family: attribute ((aligned, mode)) [PR100545]

2022-04-27 Thread Marek Polacek via Gcc-patches
On Wed, Apr 27, 2022 at 11:19:57AM -0400, Jason Merrill via Gcc-patches wrote:
> The problem here was that handle_mode_attribute clobbered the changes of any
> previous attribute, only copying type qualifiers to the new type.  And
> common_handle_aligned_attribute had previously set up the typedef, so when
> we later called set_underlying_type it saw DECL_ORIGINAL_TYPE set and just
> returned, even though handle_mode_attribute had messed up the TREE_TYPE.
> So, let's fix handle_mode_attribute to copy attributes, alignment, and
> typedefness to the new type.
> 
> Tested x86_64-pc-linux-gnu, OK for trunk now or after 12.1?

I think I'd slightly prefer 12.1, it doesn't seem to be a regression.
 
>   PR c/100545
> 
> gcc/c-family/ChangeLog:
> 
>   * c-attribs.cc (handle_mode_attribute): Copy attributes, aligned,
>   and typedef.
>   * c-common.cc (set_underlying_type): Add assert.
> 
> gcc/testsuite/ChangeLog:
> 
>   * c-c++-common/attr-mode-1.c: New test.
> ---
>  gcc/c-family/c-attribs.cc| 15 ++-
>  gcc/c-family/c-common.cc |  7 ---
>  gcc/testsuite/c-c++-common/attr-mode-1.c |  3 +++
>  3 files changed, 21 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/c-c++-common/attr-mode-1.c
> 
> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
> index 111a33f405a..26876d0f309 100644
> --- a/gcc/c-family/c-attribs.cc
> +++ b/gcc/c-family/c-attribs.cc
> @@ -2199,7 +2199,20 @@ handle_mode_attribute (tree *node, tree name, tree 
> args,
> return NULL_TREE;
>   }
>  
> -  *node = build_qualified_type (typefm, TYPE_QUALS (type));
> +  /* Copy any quals and attributes to the new type.  */
> +  *node = build_type_attribute_qual_variant (typefm, TYPE_ATTRIBUTES 
> (type),
> +  TYPE_QUALS (type));
> +  if (TYPE_USER_ALIGN (type))
> + *node = build_aligned_type (*node, TYPE_ALIGN (type));
> +  if (typedef_variant_p (type))
> + {
> +   /* Set up the typedef all over again.  */
> +   tree decl = TYPE_NAME (type);
> +   DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
> +   TREE_TYPE (decl) = *node;
> +   set_underlying_type (decl);
> +   *node = TREE_TYPE (decl);
> + }
>  }
>  
>return NULL_TREE;
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index bb0544eeaea..730faa9e87f 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -8153,15 +8153,16 @@ check_missing_format_attribute (tree ltype, tree 
> rtype)
>  void
>  set_underlying_type (tree x)
>  {
> -  if (x == error_mark_node)
> +  if (x == error_mark_node || TREE_TYPE (x) == error_mark_node)

Maybe error_operand_p?

>  return;
>if (DECL_IS_UNDECLARED_BUILTIN (x) && TREE_CODE (TREE_TYPE (x)) != 
> ARRAY_TYPE)
>  {
>if (TYPE_NAME (TREE_TYPE (x)) == 0)
>   TYPE_NAME (TREE_TYPE (x)) = x;
>  }
> -  else if (TREE_TYPE (x) != error_mark_node
> -&& DECL_ORIGINAL_TYPE (x) == NULL_TREE)
> +  else if (DECL_ORIGINAL_TYPE (x))
> +gcc_checking_assert (TYPE_NAME (TREE_TYPE (x)) == x);
> +  else
>  {
>tree tt = TREE_TYPE (x);
>DECL_ORIGINAL_TYPE (x) = tt;
> diff --git a/gcc/testsuite/c-c++-common/attr-mode-1.c 
> b/gcc/testsuite/c-c++-common/attr-mode-1.c
> new file mode 100644
> index 000..59b20cd99e8
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/attr-mode-1.c
> @@ -0,0 +1,3 @@
> +// PR c/100545
> +
> +typedef int fatp_t __attribute__((aligned, mode(SI)));

I think you need to add "dg-options -g", otherwise the bug doesn't
manifest.

Marek



Re: [PATCH] c++: enum in generic lambda at global scope [PR105398]

2022-04-27 Thread Marek Polacek via Gcc-patches
On Wed, Apr 27, 2022 at 08:24:54AM -0400, Patrick Palka wrote:
> On Tue, 26 Apr 2022, Marek Polacek via Gcc-patches wrote:
> 
> > We crash compiling this test since r11-7993 which changed
> > lookup_template_class_1 so that we only call tsubst_enum when
> > 
> >   !uses_template_parms (current_nonlambda_scope ())
> > 
> > But here current_nonlambda_scope () is the global NAMESPACE_DECL ::, which
> > doesn't have a type, therefore is considered type-dependent.  So we don't
> > call tsubst_enum, and crash in tsubst_copy/CONST_DECL because we didn't
> > find the e1 enumerator.
> > 
> > I don't think any namespace can depend on any template parameter, so
> > this patch tweaks uses_template_parms.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
> > 
> > PR c++/105398
> > 
> > gcc/cp/ChangeLog:
> > 
> > * pt.cc (uses_template_parms): Return false for any NAMESPACE_DECL.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp1y/lambda-generic-enum2.C: New test.
> > ---
> >  gcc/cp/pt.cc  |  2 +-
> >  gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C | 15 +++
> >  2 files changed, 16 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 3cf1d7af8d2..e785c5db142 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -10905,7 +10905,7 @@ uses_template_parms (tree t)
> >|| uses_template_parms (TREE_CHAIN (t)));
> >else if (TREE_CODE (t) == TYPE_DECL)
> >  dependent_p = dependent_type_p (TREE_TYPE (t));
> > -  else if (t == error_mark_node)
> > +  else if (t == error_mark_node || TREE_CODE (t) == NAMESPACE_DECL)
> 
> LGTM.  In passing, perhaps we should move this t == error_mark_node test
> to the beginning of the function alongside the t == NULL_TREE test?

Thanks, yeah, maybe.  I also don't like the separate declaration of
saved_processing_template_decl, the return type, but I've resisted cleaning
that up, otherwise I never know when to stop.  But here's a version with more
cleanups:

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e9a3d09ac4c..d0ebbb7a196 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7311,7 +7311,7 @@ extern tree lookup_template_class (tree, tree, 
tree, tree,
 int, tsubst_flags_t);
 extern tree lookup_template_function   (tree, tree);
 extern tree lookup_template_variable   (tree, tree);
-extern int uses_template_parms (tree);
+extern bool uses_template_parms(tree);
 extern bool uses_template_parms_level  (tree, int);
 extern bool in_template_function   (void);
 extern bool need_generic_capture   (void);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3cf1d7af8d2..dc5b9938f2c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10884,35 +10884,30 @@ find_template_parameters (tree t, tree ctx_parms)
 
 /* Returns true if T depends on any template parameter.  */
 
-int
+bool
 uses_template_parms (tree t)
 {
-  if (t == NULL_TREE)
+  if (t == NULL_TREE || t == error_mark_node)
 return false;
 
-  bool dependent_p;
-  int saved_processing_template_decl;
+  /* Namespaces can't depend on any template parameters.  */
+  if (TREE_CODE (t) == NAMESPACE_DECL)
+return false;
+
+  processing_template_decl_sentinel ptds (/*reset*/false);
+  ++processing_template_decl;
 
-  saved_processing_template_decl = processing_template_decl;
-  if (!saved_processing_template_decl)
-processing_template_decl = 1;
   if (TYPE_P (t))
-dependent_p = dependent_type_p (t);
+return dependent_type_p (t);
   else if (TREE_CODE (t) == TREE_VEC)
-dependent_p = any_dependent_template_arguments_p (t);
+return any_dependent_template_arguments_p (t);
   else if (TREE_CODE (t) == TREE_LIST)
-dependent_p = (uses_template_parms (TREE_VALUE (t))
-  || uses_template_parms (TREE_CHAIN (t)));
+return (uses_template_parms (TREE_VALUE (t))
+   || uses_template_parms (TREE_CHAIN (t)));
   else if (TREE_CODE (t) == TYPE_DECL)
-dependent_p = dependent_type_p (TREE_TYPE (t));
-  else if (t == error_mark_node)
-dependent_p = false;
+return dependent_type_p (TREE_TYPE (t));
   else
-dependent_p = instantiation_dependent_expression_p (t);
-
-  processing_template_decl = saved_processing_template_decl;
-
-  return dependent_p;
+return instantiation_dependent_expression_p (t);
 }
 
 /* Returns true iff we're processing an incompletely instantiated function


Maybe go with the original patch for GCC 12 and leave the cleanups for GCC 13?

Marek



[PATCH] c++: enum in generic lambda at global scope [PR105398]

2022-04-26 Thread Marek Polacek via Gcc-patches
We crash compiling this test since r11-7993 which changed
lookup_template_class_1 so that we only call tsubst_enum when

  !uses_template_parms (current_nonlambda_scope ())

But here current_nonlambda_scope () is the global NAMESPACE_DECL ::, which
doesn't have a type, therefore is considered type-dependent.  So we don't
call tsubst_enum, and crash in tsubst_copy/CONST_DECL because we didn't
find the e1 enumerator.

I don't think any namespace can depend on any template parameter, so
this patch tweaks uses_template_parms.

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

PR c++/105398

gcc/cp/ChangeLog:

* pt.cc (uses_template_parms): Return false for any NAMESPACE_DECL.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3cf1d7af8d2..e785c5db142 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10905,7 +10905,7 @@ uses_template_parms (tree t)
   || uses_template_parms (TREE_CHAIN (t)));
   else if (TREE_CODE (t) == TYPE_DECL)
 dependent_p = dependent_type_p (TREE_TYPE (t));
-  else if (t == error_mark_node)
+  else if (t == error_mark_node || TREE_CODE (t) == NAMESPACE_DECL)
 dependent_p = false;
   else
 dependent_p = instantiation_dependent_expression_p (t);
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C
new file mode 100644
index 000..77cf0bb9d02
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum2.C
@@ -0,0 +1,15 @@
+// PR c++/105398
+// { dg-do compile { target c++14 } }
+
+auto f = [](auto &&m) {
+enum E { _,e3,e2,e1,C4,C3,C2,C1 };
+static constexpr int x_coeffs[3][4] = {
+{e1,C2,C3,C4},
+{e2,C1,C3,C4},
+{e3,C1,C2,C4},
+};
+};
+
+int main() {
+f(0);
+}

base-commit: 9ace5d4dab2ab39072b0f07089621a823580f27c
-- 
2.35.1



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

2022-04-26 Thread Marek Polacek via Gcc-patches
Consider

  struct A {
int x;
int y = x;
  };

  struct B {
int x = 0;
int y = A{x}.y; // #1
  };

where for #1 we end up with

  {.x=(&)->x, .y=(&)->x}

that is, two PLACEHOLDER_EXPRs for different types on the same level in
a {}.  This crashes because our CONSTRUCTOR_PLACEHOLDER_BOUNDARY mechanism to
avoid replacing unrelated PLACEHOLDER_EXPRs cannot deal with it.

Here's why we wound up with those PLACEHOLDER_EXPRs: When we're performing
cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we use 
finish_compound_literal
on type=A, compound_literal={((struct B *) this)->x}.  When digesting this
initializer, we call get_nsdmi which creates a PLACEHOLDER_EXPR for A -- we 
don't
have any object to refer to yet.  After digesting, we have

  {.x=((struct B *) this)->x, .y=(&)->x}

and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole ctor
CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns

  TARGET_EXPR x, .y=(&)->x}>

Then we get to

  B b = {};

and call store_init_value, which digest the {}, which produces

  {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR )->x, .y=(&)->x}>).y}

The call to replace_placeholders in store_init_value will not do anything:
we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only
a sub-expression, so replace_placeholders does nothing, so the 
stays even though now is the perfect time to replace it because we have an
object for it: 'b'.

Later, in cp_gimplify_init_expr the *expr_p is

  D.2395 = {.x=(&)->x, .y=(&)->x}

where D.2395 is of type A, but we crash because we hit , which
has a different type.

My idea was to replace  with D.2384 in f_c_l after creating the
TARGET_EXPR because that means we have an object we can refer to.  Then clear
CONSTRUCTOR_PLACEHOLDER_BOUNDARY because we no longer have a PLACEHOLDER_EXPR
in the {}.  Then store_init_value will be able to replace  with
'b', and we should be good to go.

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

PR c++/100252

gcc/cp/ChangeLog:

* semantics.cc (finish_compound_literal): replace_placeholders after
creating the TARGET_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/nsdmi-aggr14.C: New test.
---
 gcc/cp/semantics.cc   | 31 +++
 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C | 46 +++
 2 files changed, 77 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ab48f11c9be..770369458bb 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -3296,6 +3296,37 @@ finish_compound_literal (tree type, tree 
compound_literal,
   if (TREE_CODE (compound_literal) == CONSTRUCTOR)
TREE_HAS_CONSTRUCTOR (compound_literal) = false;
   compound_literal = get_target_expr_sfinae (compound_literal, complain);
+  /* We may have A{} in a NSDMI.  */
+  if (parsing_nsdmi ())
+   {
+ /* Digesting the {} could have introduced a PLACEHOLDER_EXPR
+referring to A.  Now that we've built up a TARGET_EXPR, we
+have an object we can refer to.  The reason we bother doing
+this here is for code like
+
+  struct A {
+int x;
+int y = x;
+  };
+
+  struct B {
+int x = 0;
+int y = A{x}.y; // #1
+  };
+
+where in #1 we don't want to end up with two PLACEHOLDER_EXPRs
+for different types on the same level in a {} as in 100252.  */
+ tree init = TARGET_EXPR_INITIAL (compound_literal);
+ if (TREE_CODE (init) == CONSTRUCTOR
+ && CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init))
+   {
+ tree obj = TARGET_EXPR_SLOT (compound_literal);
+ replace_placeholders (compound_literal, obj);
+ /* We should have dealt with the PLACEHOLDER_EXPRs.  */
+ CONSTRUCTOR_PLACEHOLDER_BOUNDARY (init) = false;
+ gcc_checking_assert (!find_placeholders (init));
+   }
+   }
 }
   else
 /* For e.g. int{42} just make sure it's a prvalue.  */
diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C 
b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C
new file mode 100644
index 000..7d508f52b48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr14.C
@@ -0,0 +1,46 @@
+// PR c++/100252
+// { dg-do run { target c++14 } }
+
+#define SA(X) static_assert ((X),#X)
+
+struct A {
+  int x;
+  int y = x;
+};
+
+struct B {
+  int x = 0;
+  int y = A{x}.y;
+};
+
+constexpr B csb1 = { };
+SA(csb1.x == 0 && csb1.y == csb1.x);
+constexpr B csb2 = { 1 };
+SA(csb2.x == 1 && csb2.y == csb2.x);
+constexpr B csb3 = { 1, 2 };
+SA(csb3.x == 1 && csb3.y == 2);
+
+B sb1 = { };
+B sb2 = { 1 };
+B sb3 = { 1, 2};
+
+int
+main ()
+{
+  if (sb1.x != 0 || sb1.x != sb1.y)
+__builtin_abort();
+  if (sb2.x != 1 || sb2.x != sb2.y)
+__builtin_abort()

[PATCH] c++: __builtin_shufflevector with value-dep expr [PR105353]

2022-04-22 Thread Marek Polacek via Gcc-patches
Here we issue an error from c_build_shufflevector while parsing a template
because it got a TEMPLATE_PARM_INDEX, but this function expects INTEGER_CSTs
(except the first two arguments).  It checks if any of the arguments are
type-dependent, if so, we leave the processing for later, but it should
also check value-dependency for the 3rd+ arguments, so as to avoid the
problem above.

This is not a regression -- __builtin_shufflevector was introduced in
GCC 12, but it looks safe enough.

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

PR c++/105353

gcc/cp/ChangeLog:

* typeck.cc (build_x_shufflevector): Use
instantiation_dependent_expression_p except for the first two
arguments.

gcc/testsuite/ChangeLog:

* g++.dg/ext/builtin-shufflevector-3.C: New test.
---
 gcc/cp/typeck.cc  |  4 +++-
 .../g++.dg/ext/builtin-shufflevector-3.C  | 23 +++
 2 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/builtin-shufflevector-3.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 26a7cb4b50d..0da6f2485d0 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -6315,7 +6315,9 @@ build_x_shufflevector (location_t loc, vec 
*args,
   if (processing_template_decl)
 {
   for (unsigned i = 0; i < args->length (); ++i)
-   if (type_dependent_expression_p ((*args)[i]))
+   if (i <= 1
+   ? type_dependent_expression_p ((*args)[i])
+   : instantiation_dependent_expression_p ((*args)[i]))
  {
tree exp = build_min_nt_call_vec (NULL, args);
CALL_EXPR_IFN (exp) = IFN_SHUFFLEVECTOR;
diff --git a/gcc/testsuite/g++.dg/ext/builtin-shufflevector-3.C 
b/gcc/testsuite/g++.dg/ext/builtin-shufflevector-3.C
new file mode 100644
index 000..0f3cbbee563
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-shufflevector-3.C
@@ -0,0 +1,23 @@
+// PR c++/105353
+// { dg-do compile { target c++17 } }
+// { dg-additional-options "-Wno-psabi" }
+
+typedef unsigned char Simd128U8VectT __attribute__((__vector_size__(16)));
+
+template
+static inline Simd128U8VectT ShufFunc(Simd128U8VectT vect) noexcept {
+if constexpr(unsigned(ShuffleIndex) >= 16)
+return Simd128U8VectT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
};
+else if constexpr(ShuffleIndex == 0)
+return vect;
+else
+return __builtin_shufflevector(vect, vect, ShuffleIndex, ShuffleIndex 
+ 1,
+ShuffleIndex + 2, ShuffleIndex + 3, ShuffleIndex + 4, ShuffleIndex 
+ 5,
+ShuffleIndex + 6, ShuffleIndex + 7, ShuffleIndex + 8, ShuffleIndex 
+ 9,
+ShuffleIndex + 10, ShuffleIndex + 11, ShuffleIndex + 12, 
ShuffleIndex + 13,
+ShuffleIndex + 14, ShuffleIndex + 15);
+}
+
+auto func1(Simd128U8VectT vect) noexcept {
+return ShufFunc<5>(vect);
+}

base-commit: 7c21556daf385fe9ece37319f574776dd7d8ab1c
-- 
2.35.1



[PATCH v3] c, c++: attribute format on a ctor with a vbase [PR101833, PR47634]

2022-04-21 Thread Marek Polacek via Gcc-patches
On Thu, Apr 14, 2022 at 11:55:10PM -0400, Jason Merrill wrote:
> On 4/13/22 19:17, Marek Polacek wrote:
> > -static tree
> > -get_constant (const_tree fntype, const_tree atname, tree expr, int argno,
> > +   N.B. This function modifies EXPR.  */
> > +
> > +static bool
> > +get_constant (const_tree fn, const_tree atname, tree &expr, int argno,
> 
> I think this function could use a new name to reflect its new behavior;
> maybe validate_constant?

Done.
 
> > -handle_format_attribute (tree *node, tree atname, tree args,
> > +handle_format_attribute (tree node[3], tree atname, tree args,
> >  int flags, bool *no_add_attrs)
> >   {
> > const_tree type = *node;
> > +  /* NODE[2] may be NULL, and it also may be a PARM_DECL for function
> > + pointers.  */
> > +  const_tree fndecl = ((node[2] && TREE_CODE (node[2]) == FUNCTION_DECL)
> > +  ? node[2] : NULL_TREE);
> 
> I notice that the comment for the handler member of attribute_spec could use
> an update to note that the node argument now points to an array of 3.
> 
> With those changes, OK for GCC 13.

Thanks, this is the updated patch, scheduled for GCC 13:

-- >8 --
Attribute format takes three arguments: archetype, string-index, and
first-to-check.  The last two specify the position in the function
parameter list.  r63030 clarified that "Since non-static C++ methods have
an implicit this argument, the arguments of such methods should be counted
from two, not one, when giving values for string-index and first-to-check."
Therefore one has to write

  struct D {
D(const char *, ...) __attribute__((format(printf, 2, 3)));
  };

However -- and this is the problem in this PR -- ctors with virtual
bases also get two additional parameters: the in-charge parameter and
the VTT parameter (added in maybe_retrofit_in_chrg).  In fact we'll end up
with two clones of the ctor: an in-charge and a not-in-charge version (see
build_cdtor_clones).  That means that the argument position the user
specified in the attribute argument will refer to different arguments,
depending on which constructor we're currently dealing with.  This can
cause a range of problems: wrong errors, confusing warnings, or crashes.

This patch corrects that; for C we don't have to do anything, and in C++
we can use num_artificial_parms_for.  It would be wrong to rewrite the
attributes the user supplied, so I've changed POS to be passed by
reference so that we don't have to change all the call sites of
positional_argument and we still get the default_conversion adjustment.

Attribute format_arg is not affected, because it requires that the
function returns "const char *" which will never be the case for cdtors.

PR c++/101833
PR c++/47634

gcc/c-family/ChangeLog:

* c-attribs.cc (positional_argument): Pass POS by reference.  Deal
with FN being either a function declaration or function type.  Use
maybe_adjust_arg_pos_for_attribute.
* c-common.cc (check_function_arguments): Maybe pass FNDECL down to
check_function_format.
* c-common.h (maybe_adjust_arg_pos_for_attribute): Declare.
(positional_argument): Adjust.
* c-format.cc (get_constant): Rename to ...
(validate_constant): ... this.  Take EXPR by reference.  Return bool
instead of tree.
(handle_format_arg_attribute): Don't overwrite FORMAT_NUM_EXPR by the
return value of validate_constant.
(decode_format_attr): Don't overwrite FORMAT_NUM_EXPR and
FIRST_ARG_NUM_EXPR by the return value of validate_constant.
(check_function_format): Adjust a parameter name.
(handle_format_attribute): Maybe pass FNDECL down to decode_format_attr.

gcc/c/ChangeLog:

* c-objc-common.cc (maybe_adjust_arg_pos_for_attribute): New.

gcc/cp/ChangeLog:

* tree.cc (maybe_adjust_arg_pos_for_attribute): New.

gcc/ChangeLog:

* tree-core.h (struct attribute_spec): Update comment for HANDLER.

gcc/testsuite/ChangeLog:

* g++.dg/ext/attr-format-arg1.C: New test.
* g++.dg/ext/attr-format1.C: New test.
* g++.dg/ext/attr-format2.C: New test.
* g++.dg/ext/attr-format3.C: New test.
---
 gcc/c-family/c-attribs.cc   | 33 ++---
 gcc/c-family/c-common.cc|  4 +-
 gcc/c-family/c-common.h |  3 +-
 gcc/c-family/c-format.cc| 77 ++---
 gcc/c/c-objc-common.cc  |  9 +++
 gcc/cp/tree.cc  | 19 +
 gcc/testsuite/g++.dg/ext/attr-format-arg1.C | 26 +++
 gcc/testsuite/g++.dg/ext/attr-format1.C | 32 +
 gcc/testsuite/g++.dg/ext/attr-format2.C | 38 ++
 gcc/testsuite/g++.dg/ext/attr-format3.C | 15 
 gcc/tr

Re: [PATCH v2] c++: wrong error with constexpr COMPOUND_EXPR [PR105321]

2022-04-21 Thread Marek Polacek via Gcc-patches
On Thu, Apr 21, 2022 at 04:22:03PM +0200, Jakub Jelinek wrote:
> On Thu, Apr 21, 2022 at 09:20:48AM -0400, Marek Polacek via Gcc-patches wrote:
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -4566,19 +4566,18 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree 
> > t, bool *non_constant_p,
> >  static tree
> >  cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t,
> >   tree bailout_value, tree continue_value,
> > -bool lval,
> > -bool *non_constant_p, bool *overflow_p)
> > +bool, bool *non_constant_p, bool *overflow_p)
> 
> Wouldn't it be better to remove the unused lval argument from
> cxx_eval_logical_expression and adjust the 2 callers?

I'm going to fix it with this patch, sorry for not doing it in the
original patch.

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_logical_expression): Remove unused
parameter.
(cxx_eval_constant_expression) ,
: Adjust calls to cxx_eval_logical_expression.
---
 gcc/cp/constexpr.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa65290e938..47d5113ace2 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4566,7 +4566,7 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool 
*non_constant_p,
 static tree
 cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t,
  tree bailout_value, tree continue_value,
-bool, bool *non_constant_p, bool *overflow_p)
+bool *non_constant_p, bool *overflow_p)
 {
   tree r;
   tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
@@ -7105,7 +7105,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
 case TRUTH_ANDIF_EXPR:
   r = cxx_eval_logical_expression (ctx, t, boolean_false_node,
   boolean_true_node,
-  lval,
   non_constant_p, overflow_p);
   break;
 
@@ -7113,7 +7112,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
 case TRUTH_ORIF_EXPR:
   r = cxx_eval_logical_expression (ctx, t, boolean_true_node,
   boolean_false_node,
-  lval,
   non_constant_p, overflow_p);
   break;
 

base-commit: 93b65ed9706e2ceb4be7b28c9ff9be759e68a614
-- 
2.35.1



[PATCH v2] c++: wrong error with constexpr COMPOUND_EXPR [PR105321]

2022-04-21 Thread Marek Polacek via Gcc-patches
On Thu, Apr 21, 2022 at 08:56:23AM -0400, Jason Merrill wrote:
> On 4/20/22 18:40, Marek Polacek wrote:
> > Here we issue a bogus error for the first assert in the test.  Therein
> > we have
> > 
> >  = (void) (VIEW_CONVERT_EXPR(yes) || handle_error ());, 
> > VIEW_CONVERT_EXPR(value);
> > 
> > which has a COMPOUND_EXPR, so we get to cxx_eval_constant_expression
> > .  The problem here is that we call
> > 
> > 7044 /* Check that the LHS is constant and then discard it.  */
> > 7045 cxx_eval_constant_expression (ctx, op0,
> > 7046   true, non_constant_p, 
> > overflow_p,
> > 7047   jump_target);
> > 
> > where lval is always true, so the PARM_DECL 'yes' is not evaluated into
> > its value.  r218832 changed the argument for 'lval' from false to true:
> > 
> > (cxx_eval_constant_expression) [COMPOUND_EXPR]: Pass true for lval.
> > 
> > but I think we want to pass 'lval' instead.  Jakub tells me that's what
> > we do for "(void) expr" as well.  [expr.comma] says that the left expression
> > is a discarded-value expression, but [expr.context] doesn't suggest that
> > we should always be passing false for lval as pre-r218832.
> 
> In a discarded-value expression, we don't do the lvalue-rvalue conversion;
> whether we want an lvalue for the RHS of the comma is irrelevant.

Ah, that's what I misread -- [expr.context]/2.8 cares only about the right 
operand :(.
 
> The bug here seems to be that we aren't doing the l->r conversion for the
> LHS of the TRUTH_OR_EXPR; I'd think that cxx_eval_logical_expression should
> pass false for lval to both recursive calls, there's no case where we
> actually expect an lvalue from a TRUTH_*.

Yeah, that makes sense.

Bootstrap/regtest running on x86_64-pc-linux-gnu, ok for trunk/11.3 if it
passes?

-- >8 --
Here we issue a bogus error for the first assert in the test.  Therein
we have

 = (void) (VIEW_CONVERT_EXPR(yes) || handle_error ());, 
VIEW_CONVERT_EXPR(value);

which has a COMPOUND_EXPR, so we get to cxx_eval_constant_expression
.  The problem here is that we call

7044 /* Check that the LHS is constant and then discard it.  */
7045 cxx_eval_constant_expression (ctx, op0,
7046   true, non_constant_p, overflow_p,
7047   jump_target);

where lval is always true, so the PARM_DECL 'yes' is not evaluated into
its value.

Fixed by always passing false for 'lval' in cxx_eval_logical_expression;
there's no case where we actually expect an lvalue from a TRUTH_*.

PR c++/105321

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_logical_expression): Always pass false for lval
to cxx_eval_constant_expression.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-105321.C: New test.
---
 gcc/cp/constexpr.cc   |  9 -
 gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C | 18 ++
 2 files changed, 22 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index e89440e770f..fa65290e938 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4566,19 +4566,18 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, 
bool *non_constant_p,
 static tree
 cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t,
  tree bailout_value, tree continue_value,
-bool lval,
-bool *non_constant_p, bool *overflow_p)
+bool, bool *non_constant_p, bool *overflow_p)
 {
   tree r;
   tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
-  lval,
-  non_constant_p, overflow_p);
+  /*lval*/false, non_constant_p,
+  overflow_p);
   VERIFY_CONSTANT (lhs);
   if (tree_int_cst_equal (lhs, bailout_value))
 return lhs;
   gcc_assert (tree_int_cst_equal (lhs, continue_value));
   r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
-   lval, non_constant_p,
+   /*lval*/false, non_constant_p,
overflow_p);
   VERIFY_CONSTANT (r);
   return r;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C
new file mode 100644
index 000..adb6830ff22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C
@@ -0,0 +1,18 @@
+//

[PATCH] c++: wrong error with constexpr COMPOUND_EXPR [PR105321]

2022-04-20 Thread Marek Polacek via Gcc-patches
Here we issue a bogus error for the first assert in the test.  Therein
we have

 = (void) (VIEW_CONVERT_EXPR(yes) || handle_error ());, 
VIEW_CONVERT_EXPR(value);

which has a COMPOUND_EXPR, so we get to cxx_eval_constant_expression
.  The problem here is that we call

7044 /* Check that the LHS is constant and then discard it.  */
7045 cxx_eval_constant_expression (ctx, op0,
7046   true, non_constant_p, overflow_p,
7047   jump_target);

where lval is always true, so the PARM_DECL 'yes' is not evaluated into
its value.  r218832 changed the argument for 'lval' from false to true:

(cxx_eval_constant_expression) [COMPOUND_EXPR]: Pass true for lval.

but I think we want to pass 'lval' instead.  Jakub tells me that's what
we do for "(void) expr" as well.  [expr.comma] says that the left expression
is a discarded-value expression, but [expr.context] doesn't suggest that
we should always be passing false for lval as pre-r218832.

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

PR c++/105321

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_constant_expression) : Pass
lval to cxx_eval_constant_expression.

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index e89440e770f..28271d4405d 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -7043,7 +7043,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
  {
/* Check that the LHS is constant and then discard it.  */
cxx_eval_constant_expression (ctx, op0,
- true, non_constant_p, overflow_p,
+ lval, non_constant_p, overflow_p,
  jump_target);
if (*non_constant_p)
  return t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C
new file mode 100644
index 000..adb6830ff22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-105321.C
@@ -0,0 +1,18 @@
+// PR c++/105321
+// { dg-do compile { target c++11 } }
+
+bool handle_error();
+
+constexpr int echo(int value, bool yes = true) noexcept
+{
+return (yes || handle_error()), value;
+}
+
+static_assert(echo(10) == 10, "");
+
+constexpr int echo2(int value, bool no = false) noexcept
+{
+return (!no || handle_error()), value;
+}
+
+static_assert(echo2(10) == 10, "");

base-commit: 5bde80f48bcc594658c788895ad1fd86d0916fc2
-- 
2.35.1



[PATCH] c++: wrong error with variadic concept [PR105268]

2022-04-14 Thread Marek Polacek via Gcc-patches
Here we issue a wrong error for the

  template>> void g();

line in the testcase.  I surmise that's because we mistakenly parse
C_many as a placeholder-type-specifier, and things go wrong from
there.  We are in a default argument so we should reject parsing C_many
as a placeholder-type-specifier, which would mean creating a new parameter.
We want C_many to be a concept-id instead.

It's interesting to see why the same problem didn't occur for C_one.
In that case, cp_parser_placeholder_type_specifier -> finish_type_constraints
-> build_type_constraint -> build_concept_check -> build_standard_check ->
coerce_template_parms fails the parse here:

 8916   nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
 8917   if ((nargs - variadic_args_p > nparms && !variadic_p)
 8918   || (nargs < nparms - variadic_p
 8919   && require_all_args
 8920   && !variadic_args_p
 8921   && (!use_default_args
 8922   || (TREE_VEC_ELT (parms, nargs) != error_mark_node
 8923   && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))
 8924 {
 8925 bad_nargs:
 ...
 8943   return error_mark_node;

because nargs is 2 (the targs are ) while nparms is
1 (for the one 'typename' in the tparam list of C_one).  But for
C_many variadic_p is true so we don't return error_mark_node but
.

This patch does not issue any error for the !tentative case because
I didn't figure out how to trigger that.

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

PR c++/105268

gcc/cp/ChangeLog:

* parser.cc (cp_parser_placeholder_type_specifier): Return
error_mark_node when trying to build up a constrained parameter in
a default argument.

gcc/testsuite/ChangeLog:

* g++.dg/concepts/variadic6.C: New test.
---
 gcc/cp/parser.cc  |  7 ++-
 gcc/testsuite/g++.dg/concepts/variadic6.C | 20 
 2 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/concepts/variadic6.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index bfd16e1ef62..dfb613168b6 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -20041,7 +20041,12 @@ cp_parser_placeholder_type_specifier (cp_parser 
*parser, location_t loc,
   /* In a template parameter list, a type-parameter can be introduced
  by type-constraints alone.  */
   if (processing_template_parmlist && !placeholder)
-return build_constrained_parameter (con, proto, args);
+{
+  /* In a default argument we may not be creating new parameters.  */
+  if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN)
+   return error_mark_node;
+  return build_constrained_parameter (con, proto, args);
+}
 
   /* Diagnose issues placeholder issues.  */
   if (!flag_concepts_ts
diff --git a/gcc/testsuite/g++.dg/concepts/variadic6.C 
b/gcc/testsuite/g++.dg/concepts/variadic6.C
new file mode 100644
index 000..0b386b0cd6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/variadic6.C
@@ -0,0 +1,20 @@
+// PR c++/105268
+// { dg-do compile { target concepts } }
+
+template concept C_one = true;
+template concept C_many = true;
+
+template struct S { };
+
+template>> void f();
+template>> void g();
+
+void
+fn (auto a = S>{})
+{
+}
+
+void
+fn2 (auto a = S>{})
+{
+}

base-commit: 82536fbb8a7d150b829650378e0ba07dad5c8fb8
-- 
2.35.1



[PATCH v2] c, c++: attribute format on a ctor with a vbase [PR101833, PR47634]

2022-04-13 Thread Marek Polacek via Gcc-patches
On Tue, Apr 12, 2022 at 04:01:14PM -0400, Jason Merrill wrote:
> On 4/12/22 14:38, Marek Polacek wrote:
> > On Mon, Apr 11, 2022 at 04:39:22PM -0400, Jason Merrill wrote:
> > > On 4/8/22 15:21, Marek Polacek wrote:
> > > > On Wed, Apr 06, 2022 at 04:55:54PM -0400, Jason Merrill wrote:
> > > > > On 4/1/22 15:14, Marek Polacek wrote:
> > > > > > Attribute format takes three arguments: archetype, string-index, and
> > > > > > first-to-check.  The last two specify the position in the function
> > > > > > parameter list.  r63030 clarified that "Since non-static C++ 
> > > > > > methods have
> > > > > > an implicit this argument, the arguments of such methods should be 
> > > > > > counted
> > > > > > from two, not one, when giving values for string-index and 
> > > > > > first-to-check."
> > > > > > Therefore one has to write
> > > > > > 
> > > > > >  struct D {
> > > > > >D(const char *, ...) __attribute__((format(printf, 2, 3)));
> > > > > >  };
> > > > > > 
> > > > > > However -- and this is the problem in this PR -- ctors with virtual
> > > > > > bases also get two additional parameters: the in-charge parameter 
> > > > > > and
> > > > > > the VTT parameter (added in maybe_retrofit_in_chrg).  In fact we'll 
> > > > > > end up
> > > > > > with two clones of the ctor: an in-charge and a not-in-charge 
> > > > > > version (see
> > > > > > build_cdtor_clones).  That means that the argument position the user
> > > > > > specified in the attribute argument will refer to different 
> > > > > > arguments,
> > > > > > depending on which constructor we're currently dealing with.  This 
> > > > > > can
> > > > > > cause a range of problems: wrong errors, confusing warnings, or 
> > > > > > crashes.
> > > > > > 
> > > > > > This patch corrects that; for C we don't have to do anything, and 
> > > > > > in C++
> > > > > > we can use num_artificial_parms_for.  It would be wrong to rewrite 
> > > > > > the
> > > > > > attributes the user supplied, so I've added an extra parameter 
> > > > > > called
> > > > > > adjust_pos.
> > > > > > 
> > > > > > Attribute format_arg is not affected, because it requires that the
> > > > > > function returns "const char *" which will never be the case for 
> > > > > > cdtors.
> > > > > > 
> > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > > > 
> > > > > > PR c++/101833
> > > > > > PR c++/47634
> > > > > > 
> > > > > > gcc/c-family/ChangeLog:
> > > > > > 
> > > > > > * c-attribs.cc (positional_argument): Add new argument 
> > > > > > adjust_pos,
> > > > > > use it.
> > > > > > * c-common.cc (check_function_arguments): Pass fndecl to
> > > > > > check_function_format.
> > > > > > * c-common.h (check_function_format): Adjust declaration.
> > > > > > (maybe_adjust_arg_pos_for_attribute): Add.
> > > > > > (positional_argument): Adjust declaration.
> > > > > > * c-format.cc (decode_format_attr): Add fndecl argument.  Pass 
> > > > > > it to
> > > > > > maybe_adjust_arg_pos_for_attribute.  Adjust calls to 
> > > > > > get_constant.
> > > > > 
> > > > > I wonder about, instead of adding another parameter, allowing the 
> > > > > current
> > > > > fntype parameter to be the fndecl when we have one.
> > > > > 
> > > > > And then that gets passed down into positional_argument, so we can 
> > > > > call
> > > > > maybe_adjust_arg_pos_for_attribute there, and adjust the return value
> > > > > appropriately so we don't need the extra adjustment in get_constant?
> > > > 
> > > > Unfortunately I can't do that.  positional_argument can't return the
> > > > adjusted position, because get_con

[PATCH] c++: ambiguous call not diagnosed after DR2352 [PR97296]

2022-04-12 Thread Marek Polacek via Gcc-patches
DR 2352 changed the definitions of reference-related (so that it uses
"similar type" instead of "same type") and of reference-compatible (use
a standard conversion sequence).  That means that reference-related is
now more broad, which means that we will be binding more things directly.

The original patch for DR 2352 caused some problems, which were fixed in
r276251 by creating a "fake" ck_qual in direct_reference_binding, so
that in

  void f(int *); // #1
  void f(const int * const &); // #2
  int *x;
  int main()
  {
f(x); // call #1
  }

we call #1.  The extra ck_qual in #2 causes compare_ics to select #1,
which is a better match for "int *" because then we don't have to do
a qualification conversion.

Let's turn to the problem in this PR.  We have

  void f(const int * const &); // #1
  void f(const int *); // #2
  int *x;
  int main()
  {
f(x);
  }

We arrive in compare_ics to decide which one is better. The ICS for #1
looks like

ck_ref_bind  <-ck_qual <-   ck_identity
  const int *const & const int *const int *

and the ICS for #2 is

ck_qual <-  ck_rvalue   <-  ck_identity
  const int *  int *   int *

We strip the reference and then comp_cv_qual_signature when comparing two
ck_quals sees that "const int *" is a proper subset of "const int *const"
and we return -1.  But that's wrong; presumably the top-level "const"
should be ignored and the call should be ambiguous.  This patch adjust
the type of the "fake" ck_qual so that this problem doesn't arise.

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

PR c++/97296

gcc/cp/ChangeLog:

* call.cc (direct_reference_binding): strip_top_quals when creating
a ck_qual.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/ref-bind4.C: Add dg-error.
* g++.dg/cpp0x/ref-bind8.C: New test.
---
 gcc/cp/call.cc | 15 +--
 gcc/testsuite/g++.dg/cpp0x/ref-bind4.C |  2 +-
 gcc/testsuite/g++.dg/cpp0x/ref-bind8.C | 10 ++
 3 files changed, 24 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/ref-bind8.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 3a8d7e4b131..fc2fc009f14 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -1680,8 +1680,19 @@ direct_reference_binding (tree type, conversion *conv)
because the types "int *" and "const int *const" are
reference-related and we were binding both directly and they
had the same rank.  To break it up, we add a ck_qual under the
-   ck_ref_bind so that conversion sequence ranking chooses #1.  */
-conv = build_conv (ck_qual, t, conv);
+   ck_ref_bind so that conversion sequence ranking chooses #1.
+
+   We strip_top_quals here which is also what standard_conversion
+   does.  Failure to do so would confuse comp_cv_qual_signature
+   into thinking that in
+
+void f(const int * const &); // #1
+void f(const int *); // #2
+int *x;
+f(x);
+
+   #2 is a better match than #1 even thought they're ambiguous (97296).  */
+conv = build_conv (ck_qual, strip_top_quals (t), conv);
 
   return build_conv (ck_ref_bind, type, conv);
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C 
b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
index 85ac9fbfd79..d296d7c3b72 100644
--- a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
@@ -51,6 +51,6 @@ g (int *p, const int *pc, const int **q)
  similar  types  T1 and T2 (_conv.qual_), respectively, and the cv-
  qualification signature of type T1 is a proper subset of  the  cv-
  qualification signature of type T2  */
-  f8 (q);
+  f8 (q); // { dg-error "call of overloaded" }
   f9 (q);
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C 
b/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
new file mode 100644
index 000..eee78fd5e74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
@@ -0,0 +1,10 @@
+// PR c++/97296
+// { dg-do compile }
+
+void f(const int * const &);
+void f(const int *);
+int *x;
+int main()
+{
+  f(x); // { dg-error "call of overloaded" }
+}

base-commit: 3c742621ed28540cf42d4cfbc2bf03433cd26738
-- 
2.35.1



Re: [PATCH] c, c++: attribute format on a ctor with a vbase [PR101833, PR47634]

2022-04-12 Thread Marek Polacek via Gcc-patches
On Mon, Apr 11, 2022 at 04:39:22PM -0400, Jason Merrill wrote:
> On 4/8/22 15:21, Marek Polacek wrote:
> > On Wed, Apr 06, 2022 at 04:55:54PM -0400, Jason Merrill wrote:
> > > On 4/1/22 15:14, Marek Polacek wrote:
> > > > Attribute format takes three arguments: archetype, string-index, and
> > > > first-to-check.  The last two specify the position in the function
> > > > parameter list.  r63030 clarified that "Since non-static C++ methods 
> > > > have
> > > > an implicit this argument, the arguments of such methods should be 
> > > > counted
> > > > from two, not one, when giving values for string-index and 
> > > > first-to-check."
> > > > Therefore one has to write
> > > > 
> > > > struct D {
> > > >   D(const char *, ...) __attribute__((format(printf, 2, 3)));
> > > > };
> > > > 
> > > > However -- and this is the problem in this PR -- ctors with virtual
> > > > bases also get two additional parameters: the in-charge parameter and
> > > > the VTT parameter (added in maybe_retrofit_in_chrg).  In fact we'll end 
> > > > up
> > > > with two clones of the ctor: an in-charge and a not-in-charge version 
> > > > (see
> > > > build_cdtor_clones).  That means that the argument position the user
> > > > specified in the attribute argument will refer to different arguments,
> > > > depending on which constructor we're currently dealing with.  This can
> > > > cause a range of problems: wrong errors, confusing warnings, or crashes.
> > > > 
> > > > This patch corrects that; for C we don't have to do anything, and in C++
> > > > we can use num_artificial_parms_for.  It would be wrong to rewrite the
> > > > attributes the user supplied, so I've added an extra parameter called
> > > > adjust_pos.
> > > > 
> > > > Attribute format_arg is not affected, because it requires that the
> > > > function returns "const char *" which will never be the case for cdtors.
> > > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > PR c++/101833
> > > > PR c++/47634
> > > > 
> > > > gcc/c-family/ChangeLog:
> > > > 
> > > > * c-attribs.cc (positional_argument): Add new argument 
> > > > adjust_pos,
> > > > use it.
> > > > * c-common.cc (check_function_arguments): Pass fndecl to
> > > > check_function_format.
> > > > * c-common.h (check_function_format): Adjust declaration.
> > > > (maybe_adjust_arg_pos_for_attribute): Add.
> > > > (positional_argument): Adjust declaration.
> > > > * c-format.cc (decode_format_attr): Add fndecl argument.  Pass 
> > > > it to
> > > > maybe_adjust_arg_pos_for_attribute.  Adjust calls to 
> > > > get_constant.
> > > 
> > > I wonder about, instead of adding another parameter, allowing the current
> > > fntype parameter to be the fndecl when we have one.
> > > 
> > > And then that gets passed down into positional_argument, so we can call
> > > maybe_adjust_arg_pos_for_attribute there, and adjust the return value
> > > appropriately so we don't need the extra adjustment in get_constant?
> > 
> > Unfortunately I can't do that.  positional_argument can't return the
> > adjusted position, because get_constant returns it and in decode_format_attr
> > it's used to rewrite the arguments in the attribute list:
> > 
> >tree *format_num_expr = &TREE_VALUE (TREE_CHAIN (args));
> >tree *first_arg_num_expr = &TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
> >...
> >  if (tree val = get_constant (fntype, atname, *format_num_expr,
> > 2, &info->format_num, 0, validated_p,
> > adjust_pos))
> >  *format_num_expr = val;
> 
> Could we not do that?  Currently isn't it just overwriting the value with
> the same value after default_conversion?  

I think it is.

> Maybe do that conversion directly in decode_format_attr instead?

I'm afraid I can't move the default_conversion call out of positional_argument
because positional_argument is called from a lot of handle_*_attribute
functions, and each of those would have to call default_conversion, which

Re: -Wformat-overflow handling for %b and %B directives in C2X standard

2022-04-11 Thread Marek Polacek via Gcc-patches
On Thu, Apr 07, 2022 at 02:10:48AM +0500, Frolov Daniil wrote:
> Hello! Thanks for your feedback. I've tried to take into account your
> comments. New patch applied to the letter.

Thanks.
 
> The only thing I have not removed is the check_std_c2x () function. From my
> point of view -Wformat-overflow shouldn't be thrown if the standard < C2X.
> So it's protection for false triggering.

Sorry but I still think that is the wrong behavior.  If you want to warn
about C2X constructs in pre-C2X modes, use -Wpedantic.  But if you want
to use %b/%B as an extension in older dialects, that's OK too, so I don't
know why users would want -Wformat-overflow disabled in that case.  But
perhaps other people disagree with me.

> сб, 2 апр. 2022 г. в 01:15, Marek Polacek :
> 
> > On Sat, Apr 02, 2022 at 12:19:47AM +0500, Frolov Daniil via Gcc-patches
> > wrote:
> > > Hello, I've noticed that -Wformat-overflow doesn't handle %b and %B
> > > directives in the sprintf function. I've added a relevant issue in
> > bugzilla
> > > (bug #105129).
> > > I attach a patch with a possible solution to the letter.
> >
> > Thanks for the patch.  Support for C2X %b, %B formats is relatively new
> > (Oct 2021) so it looks like gimple-ssa-sprintf.cc hasn't caught up.
> >
> > This is not a regression, so should probably wait till GCC 13.  Anyway...
> >
> > > From 2051344e9500651f6e94c44cbc7820715382b957 Mon Sep 17 00:00:00 2001
> > > From: Frolov Daniil 
> > > Date: Fri, 1 Apr 2022 00:47:03 +0500
> > > Subject: [PATCH] Support %b, %B for -Wformat-overflow (sprintf, snprintf)
> > >
> > > testsuite: add tests to check -Wformat-overflow on %b.
> > > Wformat-overflow1.c is compiled using -std=c2x so warning has to
> > > be throwed
> > >
> > > Wformat-overflow2.c doesn't throw warnings cause c2x std isn't
> > > used
> > >
> > > gcc/ChangeLog:
> > >
> > >   * gimple-ssa-sprintf.cc
> > > (check_std_c2x): New function
> > >   (fmtresult::type_max_digits): add base == 2 handling
> > >   (tree_digits): add handle for base == 2
> > >   (format_integer): now handle %b and %B using base = 2
> > >   (parse_directive): add cases to handle %b and %B directives
> > >   (compute_format_length): add handling for base = 2
> >
> > The descriptions should start with a capital letter and end with a period,
> > like "Handle base == 2."
> >
> > > gcc/testsuite/ChangeLog:
> > >
> > >   * gcc.dg/Wformat-overflow1.c: New test. (using -std=c2x)
> > >   * gcc.dg/Wformat-overflow2.c: New test. (-std=c11 no warning)
> >
> > You can just say "New test."
> >
> > > ---
> > >  gcc/gimple-ssa-sprintf.cc| 42 
> > >  gcc/testsuite/gcc.dg/Wformat-overflow1.c | 28 
> > >  gcc/testsuite/gcc.dg/Wformat-overflow2.c | 16 +
> > >  3 files changed, 79 insertions(+), 7 deletions(-)
> > >  create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow1.c
> > >  create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow2.c
> > >
> > > diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
> > > index c93f12f90b5..7f68c2b6e51 100644
> > > --- a/gcc/gimple-ssa-sprintf.cc
> > > +++ b/gcc/gimple-ssa-sprintf.cc
> > > @@ -107,6 +107,15 @@ namespace {
> > >
> > >  static int warn_level;
> > >
> > > +/* b_overflow_flag depends on the current standart when using gcc */
> >
> > "standard"
> >
> > /* Comments should be formatted like this.  */
> >
> > > +static bool b_overflow_flag;
> > > +
> > > +/* check is current standart version equals C2X*/
> > > +static bool check_std_c2x ()
> > > +{
> > > +  return !strcmp (lang_hooks.name, "GNU C2X");
> > > +}
> >
> > Is this really needed?  ISTM that this new checking shouldn't depend on
> > -std=c2x.  If not using C2X, you only get a warning if -Wpedantic.  So
> > I think you should remove b_overflow_flag.
> >
> > >  /* The minimum, maximum, likely, and unlikely maximum number of bytes
> > > of output either a formatting function or an individual directive
> > > can result in.  */
> > > @@ -535,6 +544,8 @@ fmtresult::type_max_digits (tree type, int base)
> > >unsigned prec = TYPE_PRECISION (type);
> > >switch (base)
> > >  {
>

Re: [PATCH] c-family: Initialize ridpointers for __int128 etc. [PR105186]

2022-04-09 Thread Marek Polacek via Gcc-patches
On Fri, Apr 08, 2022 at 09:29:52AM +0200, Jakub Jelinek wrote:
> Hi!
> 
> The following testcase ICEs with C++ and is incorrectly rejected with C.
> The reason is that both FEs use ridpointers identifiers for CPP_KEYWORD
> and value or u.value for CPP_NAME e.g. when parsing attributes or OpenMP
> directives etc., like:
>  /* Save away the identifier that indicates which attribute
> this is.  */
>  identifier = (token->type == CPP_KEYWORD)
>/* For keywords, use the canonical spelling, not the
>   parsed identifier.  */
>? ridpointers[(int) token->keyword]
>: id_token->u.value;
> 
>  identifier = canonicalize_attr_name (identifier);
> I've tried to change those to use ridpointers only if non-NULL and otherwise
> use the value/u.value even for CPP_KEYWORDS, but that was a large 10 hunks
> patch.
> 
> The following patch instead just initializes ridpointers for the __intNN
> keywords.  It can't be done earlier before we record_builtin_type as there
> are 2 different spellings and if we initialize those ridpointers early, the
> second record_builtin_type fails miserably.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2022-04-08  Jakub Jelinek  
> 
>   PR c++/105186
>   * c-common.cc (c_common_nodes_and_builtins): After registering __int%d
>   and __int%d__ builtin types, initialize corresponding ridpointers
>   entry.
> 
>   * c-c++-common/pr105186.c: New test.
> 
> --- gcc/c-family/c-common.cc.jj   2022-04-07 17:18:14.378883472 +0200
> +++ gcc/c-family/c-common.cc  2022-04-07 17:21:07.950463695 +0200
> @@ -4278,6 +4278,8 @@ c_common_nodes_and_builtins (void)
>sprintf (name, "__int%d__", int_n_data[i].bitsize);
>record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
>  int_n_trees[i].signed_type);
> +  ridpointers[RID_FIRST_INT_N + i]
> + = DECL_NAME (TYPE_NAME (int_n_trees[i].signed_type));

So this also covers the range for the unsigned variants of these types.

I think the patch is OK, thanks.

>sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
>record_builtin_type (RID_MAX, name, int_n_trees[i].unsigned_type);
> --- gcc/testsuite/c-c++-common/pr105186.c.jj  2022-04-07 17:25:32.084781386 
> +0200
> +++ gcc/testsuite/c-c++-common/pr105186.c 2022-04-07 17:25:13.736037189 
> +0200
> @@ -0,0 +1,5 @@
> +/* PR c++/105186 */
> +/* { dg-do compile } */
> +
> +__attribute__((__int128)) int i; /* { dg-warning "'__int128' attribute 
> directive ignored" } */
> +__attribute__((__int128__)) int j;   /* { dg-warning "'__int128' attribute 
> directive ignored" } */

Marek



Re: [PATCH] c, c++: attribute format on a ctor with a vbase [PR101833, PR47634]

2022-04-08 Thread Marek Polacek via Gcc-patches
On Wed, Apr 06, 2022 at 04:55:54PM -0400, Jason Merrill wrote:
> On 4/1/22 15:14, Marek Polacek wrote:
> > Attribute format takes three arguments: archetype, string-index, and
> > first-to-check.  The last two specify the position in the function
> > parameter list.  r63030 clarified that "Since non-static C++ methods have
> > an implicit this argument, the arguments of such methods should be counted
> > from two, not one, when giving values for string-index and first-to-check."
> > Therefore one has to write
> > 
> >struct D {
> >  D(const char *, ...) __attribute__((format(printf, 2, 3)));
> >};
> > 
> > However -- and this is the problem in this PR -- ctors with virtual
> > bases also get two additional parameters: the in-charge parameter and
> > the VTT parameter (added in maybe_retrofit_in_chrg).  In fact we'll end up
> > with two clones of the ctor: an in-charge and a not-in-charge version (see
> > build_cdtor_clones).  That means that the argument position the user
> > specified in the attribute argument will refer to different arguments,
> > depending on which constructor we're currently dealing with.  This can
> > cause a range of problems: wrong errors, confusing warnings, or crashes.
> > 
> > This patch corrects that; for C we don't have to do anything, and in C++
> > we can use num_artificial_parms_for.  It would be wrong to rewrite the
> > attributes the user supplied, so I've added an extra parameter called
> > adjust_pos.
> > 
> > Attribute format_arg is not affected, because it requires that the
> > function returns "const char *" which will never be the case for cdtors.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > PR c++/101833
> > PR c++/47634
> > 
> > gcc/c-family/ChangeLog:
> > 
> > * c-attribs.cc (positional_argument): Add new argument adjust_pos,
> > use it.
> > * c-common.cc (check_function_arguments): Pass fndecl to
> > check_function_format.
> > * c-common.h (check_function_format): Adjust declaration.
> > (maybe_adjust_arg_pos_for_attribute): Add.
> > (positional_argument): Adjust declaration.
> > * c-format.cc (decode_format_attr): Add fndecl argument.  Pass it to
> > maybe_adjust_arg_pos_for_attribute.  Adjust calls to get_constant.
> 
> I wonder about, instead of adding another parameter, allowing the current
> fntype parameter to be the fndecl when we have one.
> 
> And then that gets passed down into positional_argument, so we can call
> maybe_adjust_arg_pos_for_attribute there, and adjust the return value
> appropriately so we don't need the extra adjustment in get_constant?

Unfortunately I can't do that.  positional_argument can't return the
adjusted position, because get_constant returns it and in decode_format_attr
it's used to rewrite the arguments in the attribute list:

  tree *format_num_expr = &TREE_VALUE (TREE_CHAIN (args));
  tree *first_arg_num_expr = &TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
  ...
if (tree val = get_constant (fntype, atname, *format_num_expr,
   2, &info->format_num, 0, validated_p,
   adjust_pos))
*format_num_expr = val;

Replacing the arguments in the attribute list would lead to problems, because
when we're processing the constructor clone without the additional parameters,
the adjusted argument position would be out of whack at this point.

I've attempted to reduce the number of parameters, but it hardly seemed like
a win, here's the patch I came up with:

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 6e17847ec9e..972476fbdf4 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -594,7 +594,7 @@ attribute_takes_identifier_p (const_tree attr_id)
 }
 
 /* Verify that argument value POS at position ARGNO to attribute NAME
-   applied to function TYPE refers to a function parameter at position
+   applied to function FNTYPE refers to a function parameter at position
POS and the expected type CODE.  Treat CODE == INTEGER_TYPE as
matching all C integral types except bool.  If successful, return
POS after default conversions, if any.  Otherwise, issue appropriate
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 6f08b55d4a7..ffa36673ec0 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -6069,7 +6069,7 @@ check_function_arguments (location_t loc, const_tree 
fndecl, const_tree fntype,
   /* Check for errors in format strings.  */
 
   if (warn_format || warn_suggest_attribute_format)
-check_function_format (f

Re: [PATCH] c: Error on va_arg with function type [PR105149]

2022-04-07 Thread Marek Polacek via Gcc-patches
On Thu, Apr 07, 2022 at 05:52:53PM +0200, Jakub Jelinek wrote:
> Hi!
> 
> In the PR Joseph said that the C standard for va_arg talks about
> pointers to object type and as a function type is not object type,
> it is invalid.
> 
> The following patch diagnoses it in the FE, instead of ICEing later on
> when optimizations are turned on (and with -O0 doing something weird
> at runtime).
> 
> Bootstrapped/regtested on powerpc64le-linux, ok for trunk?

Ok, thanks.
 
> 2022-04-07  Jakub Jelinek  
> 
>   PR c/105149
>   * c-typeck.cc (c_build_va_arg): Reject function types.
> 
>   * gcc.dg/pr105149.c: New test.
> 
> --- gcc/c/c-typeck.cc.jj  2022-03-23 10:29:20.172967605 +0100
> +++ gcc/c/c-typeck.cc 2022-04-07 12:26:17.236469809 +0200
> @@ -15896,6 +15896,12 @@ c_build_va_arg (location_t loc1, tree ex
>   "type %qT", type);
>return error_mark_node;
>  }
> +  else if (TREE_CODE (type) == FUNCTION_TYPE)
> +{
> +  error_at (loc2, "second argument to % is a function type %qT",
> + type);
> +  return error_mark_node;
> +}
>else if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
>  warning_at (loc2, OPT_Wc___compat,
>   "C++ requires promoted type, not enum type, in %");
> --- gcc/testsuite/gcc.dg/pr105149.c.jj2022-04-07 12:39:08.202711511 
> +0200
> +++ gcc/testsuite/gcc.dg/pr105149.c   2022-04-07 12:38:21.418364583 +0200
> @@ -0,0 +1,16 @@
> +/* PR c/105149 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include 
> +
> +void
> +foo (int s, ...)
> +{
> +  int e;
> +  va_list ap;
> +
> +  va_start (ap, s);
> +  e = va_arg (ap, int (void)) ();/* { dg-error "second argument to 
> 'va_arg' is a function type" } */
> +  va_end (ap);
> +}

Marek



Re: tolerate cdtors returning this in constexpr

2022-04-06 Thread Marek Polacek via Gcc-patches
On Wed, Apr 06, 2022 at 04:36:49PM -0300, Alexandre Oliva via Gcc-patches wrote:
> 
> On targets that return this from cdtors, cxx_eval_call_expression may
> flag flowing off the end of a dtor.  That's preempted for ctors, and
> avoided entirely when dtors return void, but when they return this,
> the return value should be conceptually disregarded, without making
> room for such internal ABI details to make a program ill-formed, as in
> g++.dg/cpp2a/constexpr-dtor12.C on arm-eabi.
> 
> Regstrapped on x86_64-linux-gnu, also verified the testcase fix on
> arm-eabi.  Ok to install?
> 
> 
> for  gcc/cp/ChangeLog
> 
>   * constexpr.cc (cxx_eval_call_expression): Disregard dtor
>   result.
> ---
>  gcc/cp/constexpr.cc |3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 9c40b0515747d..d8bc864ae6bcc 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -2889,7 +2889,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
> tree t,
> else
>   {
> result = *ctx->global->values.get (res);
> -   if (result == NULL_TREE && !*non_constant_p)
> +   if (result == NULL_TREE && !*non_constant_p
> +   && !DECL_DESTRUCTOR_P (fun))

Would it make sense to use 

  && !(DECL_DESTRUCTOR_P (fun) && targetm.cxx.cdtor_returns_this ())

instead?

>   {
> if (!ctx->quiet)
>   error ("% call flows off the end "

Marek



Re: -Wformat-overflow handling for %b and %B directives in C2X standard

2022-04-01 Thread Marek Polacek via Gcc-patches
On Sat, Apr 02, 2022 at 12:19:47AM +0500, Frolov Daniil via Gcc-patches wrote:
> Hello, I've noticed that -Wformat-overflow doesn't handle %b and %B
> directives in the sprintf function. I've added a relevant issue in bugzilla
> (bug #105129).
> I attach a patch with a possible solution to the letter.

Thanks for the patch.  Support for C2X %b, %B formats is relatively new
(Oct 2021) so it looks like gimple-ssa-sprintf.cc hasn't caught up.

This is not a regression, so should probably wait till GCC 13.  Anyway...

> From 2051344e9500651f6e94c44cbc7820715382b957 Mon Sep 17 00:00:00 2001
> From: Frolov Daniil 
> Date: Fri, 1 Apr 2022 00:47:03 +0500
> Subject: [PATCH] Support %b, %B for -Wformat-overflow (sprintf, snprintf)
> 
> testsuite: add tests to check -Wformat-overflow on %b.
> Wformat-overflow1.c is compiled using -std=c2x so warning has to
> be throwed
> 
> Wformat-overflow2.c doesn't throw warnings cause c2x std isn't
> used
> 
> gcc/ChangeLog:
> 
>   * gimple-ssa-sprintf.cc
> (check_std_c2x): New function
>   (fmtresult::type_max_digits): add base == 2 handling
>   (tree_digits): add handle for base == 2
>   (format_integer): now handle %b and %B using base = 2
>   (parse_directive): add cases to handle %b and %B directives
>   (compute_format_length): add handling for base = 2

The descriptions should start with a capital letter and end with a period,
like "Handle base == 2."
 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.dg/Wformat-overflow1.c: New test. (using -std=c2x)
>   * gcc.dg/Wformat-overflow2.c: New test. (-std=c11 no warning)

You can just say "New test."

> ---
>  gcc/gimple-ssa-sprintf.cc| 42 
>  gcc/testsuite/gcc.dg/Wformat-overflow1.c | 28 
>  gcc/testsuite/gcc.dg/Wformat-overflow2.c | 16 +
>  3 files changed, 79 insertions(+), 7 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow1.c
>  create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow2.c
> 
> diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
> index c93f12f90b5..7f68c2b6e51 100644
> --- a/gcc/gimple-ssa-sprintf.cc
> +++ b/gcc/gimple-ssa-sprintf.cc
> @@ -107,6 +107,15 @@ namespace {
>  
>  static int warn_level;
>  
> +/* b_overflow_flag depends on the current standart when using gcc */

"standard"

/* Comments should be formatted like this.  */

> +static bool b_overflow_flag;
> +
> +/* check is current standart version equals C2X*/
> +static bool check_std_c2x () 
> +{
> +  return !strcmp (lang_hooks.name, "GNU C2X");
> +}

Is this really needed?  ISTM that this new checking shouldn't depend on
-std=c2x.  If not using C2X, you only get a warning if -Wpedantic.  So
I think you should remove b_overflow_flag.

>  /* The minimum, maximum, likely, and unlikely maximum number of bytes
> of output either a formatting function or an individual directive
> can result in.  */
> @@ -535,6 +544,8 @@ fmtresult::type_max_digits (tree type, int base)
>unsigned prec = TYPE_PRECISION (type);
>switch (base)
>  {
> +case 2:
> +  return prec;
>  case 8:
>return (prec + 2) / 3;
>  case 10:
> @@ -857,11 +868,11 @@ tree_digits (tree x, int base, HOST_WIDE_INT prec, bool 
> plus, bool prefix)
>  
>/* Adjust a non-zero value for the base prefix, either hexadecimal,
>   or, unless precision has resulted in a leading zero, also octal.  */
> -  if (prefix && absval && (base == 16 || prec <= ndigs))
> +  if (prefix && absval && (base == 2 || base == 16 || prec <= ndigs))
>  {
>if (base == 8)
>   res += 1;
> -  else if (base == 16)
> +  else if (base == 16 || base == 2) /*0x...(0X...) and 0b...(0B...)*/
>   res += 2;
>  }
>  
> @@ -1229,6 +1240,10 @@ format_integer (const directive &dir, tree arg, 
> pointer_query &ptr_qry)
>  case 'u':
>base = 10;
>break;
> +case 'b':
> +case 'B':
> +  base = 2;
> +  break;
>  case 'o':
>base = 8;
>break;
> @@ -1351,10 +1366,10 @@ format_integer (const directive &dir, tree arg, 
> pointer_query &ptr_qry)
>  
>/* Bump up the counters if WIDTH is greater than LEN.  */
>res.adjust_for_width_or_precision (dir.width, dirtype, base,
> -  (sign | maybebase) + (base == 16));
> +  (sign | maybebase) + (base == 2 || 
> base == 16));
>/* Bump up the counters again if PRECision is greater still.  */
>res.adjust_for_width_or_precision (dir.prec, dirtype, base,
> -  (sign | maybebase) + (base == 16));
> +  (sign | maybebase) + (base == 2 || 
> base == 16));
>  
>return res;
>  }
> @@ -1503,7 +1518,7 @@ format_integer (const directive &dir, tree arg, 
> pointer_query &ptr_qry)
> if (res.range.min == 1)
>   res.range.likely += base == 8 ? 1 : 2;
> else if (re

[PATCH] c, c++: attribute format on a ctor with a vbase [PR101833, PR47634]

2022-04-01 Thread Marek Polacek via Gcc-patches
Attribute format takes three arguments: archetype, string-index, and
first-to-check.  The last two specify the position in the function
parameter list.  r63030 clarified that "Since non-static C++ methods have
an implicit this argument, the arguments of such methods should be counted
from two, not one, when giving values for string-index and first-to-check."
Therefore one has to write

  struct D {
D(const char *, ...) __attribute__((format(printf, 2, 3)));
  };

However -- and this is the problem in this PR -- ctors with virtual
bases also get two additional parameters: the in-charge parameter and
the VTT parameter (added in maybe_retrofit_in_chrg).  In fact we'll end up
with two clones of the ctor: an in-charge and a not-in-charge version (see
build_cdtor_clones).  That means that the argument position the user
specified in the attribute argument will refer to different arguments,
depending on which constructor we're currently dealing with.  This can
cause a range of problems: wrong errors, confusing warnings, or crashes.

This patch corrects that; for C we don't have to do anything, and in C++
we can use num_artificial_parms_for.  It would be wrong to rewrite the
attributes the user supplied, so I've added an extra parameter called
adjust_pos.

Attribute format_arg is not affected, because it requires that the
function returns "const char *" which will never be the case for cdtors.

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

PR c++/101833
PR c++/47634

gcc/c-family/ChangeLog:

* c-attribs.cc (positional_argument): Add new argument adjust_pos,
use it.
* c-common.cc (check_function_arguments): Pass fndecl to
check_function_format.
* c-common.h (check_function_format): Adjust declaration.
(maybe_adjust_arg_pos_for_attribute): Add.
(positional_argument): Adjust declaration.
* c-format.cc (decode_format_attr): Add fndecl argument.  Pass it to
maybe_adjust_arg_pos_for_attribute.  Adjust calls to get_constant.
(handle_format_arg_attribute): Pass 0 to get_constant.
(get_constant): Add new argument adjust_pos, use it.
(check_function_format): Add fndecl argument.  Pass it to
decode_format_attr.
(handle_format_attribute): Get the fndecl from node[2].  Pass it to
decode_format_attr.

gcc/c/ChangeLog:

* c-objc-common.cc (maybe_adjust_arg_pos_for_attribute): New.

gcc/cp/ChangeLog:

* tree.cc (maybe_adjust_arg_pos_for_attribute): New.

gcc/testsuite/ChangeLog:

* g++.dg/ext/attr-format-arg1.C: New test.
* g++.dg/ext/attr-format1.C: New test.
* g++.dg/ext/attr-format2.C: New test.
* g++.dg/ext/attr-format3.C: New test.
---
 gcc/c-family/c-attribs.cc   | 14 ---
 gcc/c-family/c-common.cc|  4 +-
 gcc/c-family/c-common.h |  5 ++-
 gcc/c-family/c-format.cc| 46 +
 gcc/c/c-objc-common.cc  |  9 
 gcc/cp/tree.cc  | 19 +
 gcc/testsuite/g++.dg/ext/attr-format-arg1.C | 26 
 gcc/testsuite/g++.dg/ext/attr-format1.C | 32 ++
 gcc/testsuite/g++.dg/ext/attr-format2.C | 38 +
 gcc/testsuite/g++.dg/ext/attr-format3.C | 15 +++
 10 files changed, 182 insertions(+), 26 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-format-arg1.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-format1.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-format2.C
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-format3.C

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 111a33f405a..6e17847ec9e 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -599,12 +599,15 @@ attribute_takes_identifier_p (const_tree attr_id)
matching all C integral types except bool.  If successful, return
POS after default conversions, if any.  Otherwise, issue appropriate
warnings and return null.  A non-zero 1-based ARGNO should be passed
-   in by callers only for attributes with more than one argument.  */
+   in by callers only for attributes with more than one argument.
+   ADJUST_POS is used and non-zero in C++ when the function type has
+   invisible parameters generated by the compiler, such as the in-charge
+   or VTT parameters.  */
 
 tree
 positional_argument (const_tree fntype, const_tree atname, tree pos,
 tree_code code, int argno /* = 0 */,
-int flags /* = posargflags () */)
+int flags /* = posargflags () */, int adjust_pos /* = 0 */)
 {
   if (pos && TREE_CODE (pos) != IDENTIFIER_NODE
   && TREE_CODE (pos) != FUNCTION_DECL)
@@ -690,7 +693,7 @@ positional_argument (const_tree fntype, const_tree atname, 
tree pos,
   if (!nargs
   || !tree_fits_uhwi_p (pos)
   || ((flags & POSARG_ELLIPSIS) == 0
- && !

[PATCH] c-family: Tweak -Woverflow diagnostic

2022-03-30 Thread Marek Polacek via Gcc-patches
When g++ emits

warning: overflow in conversion from 'int' to 'char' changes value from '300' 
to '',''

for code like "char c = 300;" it might raise a few eyebrows.  With this
warning we're not interested in the ASCII representation of the char, only
the numerical value, so convert constants of type char to int.  It looks
like this conversion only needs to be done for char_type_node.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  I'm also happy
to defer this to GCC 13.

gcc/c-family/ChangeLog:

* c-warn.cc (warnings_for_convert_and_check): Convert constants of type
char to int.

gcc/testsuite/ChangeLog:

* c-c++-common/Wconversion-1.c: New test.
---
 gcc/c-family/c-warn.cc | 16 +++-
 gcc/testsuite/c-c++-common/Wconversion-1.c | 14 ++
 2 files changed, 25 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wconversion-1.c

diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index f24ac5d0539..cae89294aea 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1404,8 +1404,14 @@ warnings_for_convert_and_check (location_t loc, tree 
type, tree expr,
 result = TREE_OPERAND (result, 1);
 
   bool cst = TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant;
-
   tree exprtype = TREE_TYPE (expr);
+  tree result_diag;
+  /* We're interested in the actual numerical value here, not its ASCII
+ representation.  */
+  if (cst && TYPE_MAIN_VARIANT (TREE_TYPE (result)) == char_type_node)
+result_diag = fold_convert (integer_type_node, result);
+  else
+result_diag = result;
 
   if (TREE_CODE (expr) == INTEGER_CST
   && (TREE_CODE (type) == INTEGER_TYPE
@@ -1430,7 +1436,7 @@ warnings_for_convert_and_check (location_t loc, tree 
type, tree expr,
  "changes value from %qE to %qE")
 : G_("unsigned conversion from %qT to %qT "
  "changes value from %qE to %qE")),
-   exprtype, type, expr, result);
+   exprtype, type, expr, result_diag);
  else
warning_at (loc, OPT_Woverflow,
(TYPE_UNSIGNED (exprtype)
@@ -1449,7 +1455,7 @@ warnings_for_convert_and_check (location_t loc, tree 
type, tree expr,
warning_at (loc, OPT_Woverflow,
"overflow in conversion from %qT to %qT "
"changes value from %qE to %qE",
-   exprtype, type, expr, result);
+   exprtype, type, expr, result_diag);
  else
warning_at (loc, OPT_Woverflow,
"overflow in conversion from %qT to %qT "
@@ -1466,7 +1472,7 @@ warnings_for_convert_and_check (location_t loc, tree 
type, tree expr,
warning_at (loc, OPT_Woverflow,
"overflow in conversion from %qT to %qT "
"changes value from %qE to %qE",
-   exprtype, type, expr, result);
+   exprtype, type, expr, result_diag);
  else
warning_at (loc, OPT_Woverflow,
"overflow in conversion from %qT to %qT "
@@ -1483,7 +1489,7 @@ warnings_for_convert_and_check (location_t loc, tree 
type, tree expr,
warning_at (loc, OPT_Woverflow,
"overflow in conversion from %qT to %qT "
"changes value from %qE to %qE",
-   exprtype, type, expr, result);
+   exprtype, type, expr, result_diag);
   else
warning_at (loc, OPT_Woverflow,
"overflow in conversion from %qT to %qT "
diff --git a/gcc/testsuite/c-c++-common/Wconversion-1.c 
b/gcc/testsuite/c-c++-common/Wconversion-1.c
new file mode 100644
index 000..ed65918c70f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wconversion-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+typedef char T;
+
+void g()
+{
+  char c = 300; /* { dg-warning "conversion from .int. to .char. changes value 
from .300. to .44." } */
+  T t = 300; /* { dg-warning "conversion from .int. to .T. {aka .char.} 
changes value from .300. to .44." } */
+  signed char sc = 300; /* { dg-warning "conversion from .int. to .signed 
char. changes value from .300. to .44." } */
+  unsigned char uc = 300; /* { dg-warning "conversion from .int. to .unsigned 
char. changes value from .300. to .44." } */
+  unsigned char uc2 = 300u; /* { dg-warning "conversion from .unsigned int. to 
.unsigned char. changes value from .300. to .44." } */
+  char c2 = (double)1.0 + 200; /* { dg-warning "overflow in conversion from 
.double. to .char. changes value from .2.01e\\+2. to .127." } */
+}

base-commit: b4e4b35f4ebe561826489bed971324efc99c5423
-- 
2.35.1



Re: [PATCH] c-family: ICE with -Wconversion and A ?: B [PR101030]

2022-03-30 Thread Marek Polacek via Gcc-patches
On Tue, Mar 29, 2022 at 10:21:47PM -0400, Jason Merrill wrote:
> On 3/29/22 16:53, Marek Polacek wrote:
> > This patch fixes a crash in conversion_warning on a null expression.
> > It is null because the testcase uses the GNU A ?: B extension.  We
> > could also use op0 instead of op1 in this case, but it doesn't seem
> > to be necessary.
> 
> I wonder why we don't represent the extension as
> 
> SAVE_EXPR(A) ? SAVE_EXPR(A) : B
> 
> so we don't hit this sort of problem.  But the patch is OK.

The reason there are no SAVE_EXPRs is that we don't create them
in a template: cp_save_expr:

  /* There is no reason to create a SAVE_EXPR within a template; if
 needed, we can create the SAVE_EXPR when instantiating the
 template.  Furthermore, the middle-end cannot handle C++-specific
 tree codes.  */
  if (processing_template_decl)
return expr;

and when instantiating we see the first expression is tree_invariant_p_1
aka constant, so no SAVE_EXPR gets created.

Patch pushed, thanks.

Marek



Re: [PATCH] c++: ICE with aggregate assignment and DMI [PR104583]

2022-03-30 Thread Marek Polacek via Gcc-patches
On Tue, Mar 29, 2022 at 10:19:47PM -0400, Jason Merrill wrote:
> On 3/25/22 18:16, Marek Polacek wrote:
> > The attached 93280 test no longer ICEs but looks like it was never added to 
> > the
> > testsuite.  The 104583 test, modified so that it closely resembles 93280, 
> > still
> > ICEs.
> > 
> > The problem is that in 104583 we have a value-init from {} (the line A 
> > a{};),
> > so this code in convert_like_internal
> > 
> >   7960 /* If we're initializing from {}, it's value-initialization. 
> >  */
> >   7961 if (BRACE_ENCLOSED_INITIALIZER_P (expr)
> >   7962 && CONSTRUCTOR_NELTS (expr) == 0
> >   7963 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)
> >   7964 && !processing_template_decl)
> >   7965   {
> >   7966 bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
> > ...
> >   7974 TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
> > 
> > sets TARGET_EXPR_DIRECT_INIT_P.  This does not happen in 93280 where we
> > initialize from {0}.
> > 
> > In 104583, when gimplifying, the d = {}; line, we have
> > 
> > d = {.a=TARGET_EXPR  >4
> >__ct_comp
> >D.2474
> >(struct A *) <<< Unknown tree: void_cst >>> >>>>}
> > 
> > where the TARGET_EXPR is the one with TARGET_EXPR_DIRECT_INIT_P set.  In
> > gimplify_init_ctor_preeval we do
> > 
> >   4724   FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
> >   4725 gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
> > 
> > so we gimplify the TARGET_EXPR, crashing at
> > 
> >   744 case TARGET_EXPR:
> >   745   /* A TARGET_EXPR that expresses direct-initialization should 
> > have
> > been
> >   746  elided by cp_gimplify_init_expr.  */
> >   747   gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));
> > 
> > but there is no INIT_EXPR so cp_gimplify_init_expr was never called!
> > 
> > Now, the fix for c++/93280
> > <https://gcc.gnu.org/pipermail/gcc-patches/2020-January/538414.html>
> > says "let's only set TARGET_EXPR_DIRECT_INIT_P when we're using the DMI in
> > a constructor." and the comment talks about the full initialization.  Is
> > is accurate to say that our TARGET_EXPR does not represent the full
> > initialization, because it only initializes the 'a' subobject?  If so,
> > then maybe get_nsdmi should clear TARGET_EXPR_DIRECT_INIT_P when in_ctor
> > is false.
> > 
> > I've compared the 93280.s and 104583.s files, they differ only in one
> > movl $0, so there are no extra calls and similar.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > PR c++/93280
> > PR c++/104583
> > 
> > gcc/cp/ChangeLog:
> > 
> > * init.cc (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P to in_ctor.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/nsdmi-list7.C: New test.
> > * g++.dg/cpp0x/nsdmi-list8.C: New test.
> > ---
> >   gcc/cp/init.cc   |  8 
> >   gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C | 17 +
> >   gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C | 17 +
> >   3 files changed, 38 insertions(+), 4 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C
> > 
> > diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
> > index 08767679dd4..fd32a8bd90f 100644
> > --- a/gcc/cp/init.cc
> > +++ b/gcc/cp/init.cc
> > @@ -679,10 +679,10 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t 
> > complain)
> > if (simple_target)
> >   init = TARGET_EXPR_INITIAL (init);
> > init = break_out_target_exprs (init, /*loc*/true);
> > -  if (in_ctor && init && TREE_CODE (init) == TARGET_EXPR)
> > -/* This expresses the full initialization, prevent perform_member_init 
> > from
> > -   calling another constructor (58162).  */
> > -TARGET_EXPR_DIRECT_INIT_P (init) = true;
> > +  if (init && TREE_CODE (init) == TARGET_EXPR)
> > +/* If this expresses the full initialization, prevent 
> > perform_member_init
> 
> Maybe "In a constructor, this expresses..." ?  The added "if" suggests a
> test that I don't see in the code.  OK with that change.

Ah, the "if" was meant to be about the value of in_ctor.  I've changed the
wording and pushed the patch.  Thanks!

Marek



Re: [PATCH] c-family: ICE with -Wconversion and A ?: B [PR101030]

2022-03-29 Thread Marek Polacek via Gcc-patches
On Tue, Mar 29, 2022 at 04:53:21PM -0400, Marek Polacek via Gcc-patches wrote:
> This patch fixes a crash in conversion_warning on a null expression.
> It is null because the testcase uses the GNU A ?: B extension.  We
> could also use op0 instead of op1 in this case, but it doesn't seem
> to be necessary.

A related issue: we print
warning: overflow in conversion from 'int' to 'char' changes value from '300' 
to '',''
in the test in the patch.  That's because the value is 44, it's type is char,
and the ASCII value for ',' is 44.  So I think we should convert values of char
type to int for the diagnostic.

Marek



[PATCH] c-family: ICE with -Wconversion and A ?: B [PR101030]

2022-03-29 Thread Marek Polacek via Gcc-patches
This patch fixes a crash in conversion_warning on a null expression.
It is null because the testcase uses the GNU A ?: B extension.  We
could also use op0 instead of op1 in this case, but it doesn't seem
to be necessary.

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

PR c++/101030

gcc/c-family/ChangeLog:

* c-warn.cc (conversion_warning) : Don't call
conversion_warning when OP1 is null.

gcc/testsuite/ChangeLog:

* g++.dg/ext/cond5.C: New test.
---
 gcc/c-family/c-warn.cc   |  2 +-
 gcc/testsuite/g++.dg/ext/cond5.C | 13 +
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/cond5.C

diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 9025fc1c20e..f24ac5d0539 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1300,7 +1300,7 @@ conversion_warning (location_t loc, tree type, tree expr, 
tree result)
tree op1 = TREE_OPERAND (expr, 1);
tree op2 = TREE_OPERAND (expr, 2);
 
-   return (conversion_warning (loc, type, op1, result)
+   return ((op1 && conversion_warning (loc, type, op1, result))
|| conversion_warning (loc, type, op2, result));
   }
 
diff --git a/gcc/testsuite/g++.dg/ext/cond5.C b/gcc/testsuite/g++.dg/ext/cond5.C
new file mode 100644
index 000..a92f28998f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/cond5.C
@@ -0,0 +1,13 @@
+// PR c++/101030
+// { dg-do compile { target { c++11 } } }
+// { dg-options "-Wconversion" }
+
+template 
+struct jj {
+int ii[N ?: 1];
+char c = N ?: 1; // { dg-warning "conversion from .int. to .char. changes 
value from .300. to " }
+};
+
+int main() {
+jj<300> kk;
+}

base-commit: 69db6e7f4e1d07bf8f33e93a29139cc16c1e0a2f
-- 
2.35.1



[PATCH] gimple: Wrong -Wimplicit-fallthrough with if(1) [PR103597]

2022-03-29 Thread Marek Polacek via Gcc-patches
This patch fixes a wrong -Wimplicit-fallthrough warning for

case 0:
  if (1)  // wrong may fallthrough
return 0;
case 1:

which in .gimple looks like

: // case 0
if (1 != 0) goto ; else goto ;
:
D.1987 = 0;
// predicted unlikely by early return (on trees) predictor.
return D.1987;
:  // dead
: // case 1

and the warning thinks that : falls through to :.  It
does not know that  is effectively a dead label, only reachable
through fallthrough from previous instructions, never jumped to.  To
that effect, Jakub introduced UNUSED_LABEL_P, which is set on such dead
labels.

collect_fallthrough_labels has code to deal with cases like

case 2:
  if (e != 10)
i++; // this may fallthru, warn
  else
return 44;
case 3:

which collects labels that may fall through.  Here it sees the "goto ;"
at the end of the then branch and so when the warning reaches

...
: // from if-then
: // case 3

it knows it should warn about the possible fallthrough.  But an UNUSED_LABEL_P
is not a label that can fallthrough like that, so it should ignore those.

However, we still want to warn about this:

case 0:
  if (1)
n++; // falls through
case 1:

so collect_fallthrough_labels needs to return the "n = n + 1;" statement, rather
than the dead label.

Co-authored-by: Jakub Jelinek 

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

PR middle-end/103597

gcc/ChangeLog:

* gimplify.cc (collect_fallthrough_labels): Don't push UNUSED_LABEL_Ps
into labels.  Maybe set prev to the statement preceding UNUSED_LABEL_P.
(gimplify_cond_expr): Set UNUSED_LABEL_P.
* tree.h (UNUSED_LABEL_P): New.

gcc/testsuite/ChangeLog:

* c-c++-common/Wimplicit-fallthrough-39.c: New test.
---
 gcc/gimplify.cc   |  54 ++-
 .../c-c++-common/Wimplicit-fallthrough-39.c   | 140 ++
 gcc/tree.h|   6 +
 3 files changed, 194 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-39.c

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index f62f150fc08..2588824dce2 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -2250,9 +2250,9 @@ last_stmt_in_scope (gimple *stmt)
 }
 }
 
-/* Collect interesting labels in LABELS and return the statement preceding
-   another case label, or a user-defined label.  Store a location useful
-   to give warnings at *PREVLOC (usually the location of the returned
+/* Collect labels that may fall through into LABELS and return the statement
+   preceding another case label, or a user-defined label.  Store a location
+   useful to give warnings at *PREVLOC (usually the location of the returned
statement or of its surrounding scope).  */
 
 static gimple *
@@ -2331,8 +2331,12 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
  if (gsi_end_p (*gsi_p))
break;
 
- struct label_entry l = { false_lab, if_loc };
- labels->safe_push (l);
+ /* A dead label can't fall through.  */
+ if (!UNUSED_LABEL_P (false_lab))
+   {
+ struct label_entry l = { false_lab, if_loc };
+ labels->safe_push (l);
+   }
 
  /* Go to the last statement of the then branch.  */
  gsi_prev (gsi_p);
@@ -2359,6 +2363,17 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
  labels->safe_push (l);
}
}
+ /* This case is about
+ if (1 != 0) goto ; else goto ;
+ :
+ n = n + 1; // #1
+ :  // #2
+ :  // #3
+where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
+through to #3.  So set PREV to #1.  */
+ else if (UNUSED_LABEL_P (false_lab))
+   prev = gsi_stmt (*gsi_p);
+
  /* And move back.  */
  gsi_next (gsi_p);
}
@@ -4461,9 +4476,19 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, 
fallback_t fallback)
   if (TREE_OPERAND (expr, 1) == NULL_TREE
  && !have_else_clause_p
  && TREE_OPERAND (expr, 2) != NULL_TREE)
-   label_cont = label_true;
+   {
+ /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
+handling that label_cont == label_true can be only reached
+through fallthrough from { code; }.  */
+ if (integer_zerop (COND_EXPR_COND (expr)))
+   UNUSED_LABEL_P (label_true) = 1;
+ label_cont = label_true;
+   }
   else
{
+ bool then_side_effects
+   = (TREE_OPERAND (expr, 1)
+  && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
  gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
  have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
  /* For if (...) { code; } else {} or
@@ -4477,6 +4502,16 @@ gi

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

2022-03-28 Thread Marek Polacek via Gcc-patches
Hi,

On Sun, Mar 27, 2022 at 06:25:16PM -0300, Alexandre Oliva via Gcc-patches wrote:
> Hello, Marek,
> 
> The patch looks good to me, and I'd have no trouble approving it if we
> were in stage1.  Since we aren't, I'd prefer if we waited for another
> build system maintainer to give it a look, if it's to go in gcc-12.  If
> release managers feel I'm being overcautious, I don't mind if they
> overrule my request.

Thanks a lot for having a look!  I'll wait till GCC 13; I don't think
it's very important to have the feature in GCC 12.

Marek



[PATCH] c++: ICE with aggregate assignment and DMI [PR104583]

2022-03-25 Thread Marek Polacek via Gcc-patches
The attached 93280 test no longer ICEs but looks like it was never added to the
testsuite.  The 104583 test, modified so that it closely resembles 93280, still
ICEs.

The problem is that in 104583 we have a value-init from {} (the line A a{};),
so this code in convert_like_internal

 7960 /* If we're initializing from {}, it's value-initialization.  */
 7961 if (BRACE_ENCLOSED_INITIALIZER_P (expr)
 7962 && CONSTRUCTOR_NELTS (expr) == 0
 7963 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)
 7964 && !processing_template_decl)
 7965   {
 7966 bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
...
 7974 TARGET_EXPR_DIRECT_INIT_P (expr) = direct;

sets TARGET_EXPR_DIRECT_INIT_P.  This does not happen in 93280 where we
initialize from {0}.

In 104583, when gimplifying, the d = {}; line, we have

d = {.a=TARGET_EXPR >> }

where the TARGET_EXPR is the one with TARGET_EXPR_DIRECT_INIT_P set.  In
gimplify_init_ctor_preeval we do

 4724   FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
 4725 gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);

so we gimplify the TARGET_EXPR, crashing at

 744 case TARGET_EXPR:
 745   /* A TARGET_EXPR that expresses direct-initialization should have
been
 746  elided by cp_gimplify_init_expr.  */
 747   gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

but there is no INIT_EXPR so cp_gimplify_init_expr was never called!

Now, the fix for c++/93280

says "let's only set TARGET_EXPR_DIRECT_INIT_P when we're using the DMI in
a constructor." and the comment talks about the full initialization.  Is
is accurate to say that our TARGET_EXPR does not represent the full
initialization, because it only initializes the 'a' subobject?  If so,
then maybe get_nsdmi should clear TARGET_EXPR_DIRECT_INIT_P when in_ctor
is false.

I've compared the 93280.s and 104583.s files, they differ only in one
movl $0, so there are no extra calls and similar.

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

PR c++/93280
PR c++/104583

gcc/cp/ChangeLog:

* init.cc (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P to in_ctor.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/nsdmi-list7.C: New test.
* g++.dg/cpp0x/nsdmi-list8.C: New test.
---
 gcc/cp/init.cc   |  8 
 gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C | 17 +
 gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C | 17 +
 3 files changed, 38 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 08767679dd4..fd32a8bd90f 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -679,10 +679,10 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t 
complain)
   if (simple_target)
 init = TARGET_EXPR_INITIAL (init);
   init = break_out_target_exprs (init, /*loc*/true);
-  if (in_ctor && init && TREE_CODE (init) == TARGET_EXPR)
-/* This expresses the full initialization, prevent perform_member_init from
-   calling another constructor (58162).  */
-TARGET_EXPR_DIRECT_INIT_P (init) = true;
+  if (init && TREE_CODE (init) == TARGET_EXPR)
+/* If this expresses the full initialization, prevent perform_member_init
+   from calling another constructor (58162).  */
+TARGET_EXPR_DIRECT_INIT_P (init) = in_ctor;
   if (simple_target && TREE_CODE (init) != CONSTRUCTOR)
 /* Now put it back so C++17 copy elision works.  */
 init = get_target_expr (init);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C
new file mode 100644
index 000..62b07429bec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list7.C
@@ -0,0 +1,17 @@
+// PR c++/93280
+// { dg-do compile { target c++11 } }
+
+struct A {
+  template  A(T);
+  int c;
+};
+
+struct D {
+  A a{0};
+};
+
+void g()
+{
+  D d;
+  d = {};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C
new file mode 100644
index 000..fe73da8f98d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list8.C
@@ -0,0 +1,17 @@
+// PR c++/104583
+// { dg-do compile { target c++11 } }
+
+struct A {
+  A();
+  int c;
+};
+
+struct D {
+  A a{};
+};
+
+void g()
+{
+  D d;
+  d = {};
+}

base-commit: bdd7b679e8497c07e25726f6ab6429e4c4d429c7
-- 
2.35.1



Re: [PATCH] c++: diagnosing if-stmt with non-constant branches [PR105050]

2022-03-25 Thread Marek Polacek via Gcc-patches
On Fri, Mar 25, 2022 at 12:07:31PM -0400, Patrick Palka via Gcc-patches wrote:
> When an if-stmt is deemed non-constant because both of its branches are
> non-constant, we issue a rather generic error which, given that it points
> to the 'if' token, misleadingly suggests the condition is at fault:
> 
>   constexpr-105050.C:8:3: error: expression ‘’ is not a constant 
> expression
>   8 |   if (p != q && *p < 0)
> |   ^~
> 
> This patch clarifies the error message to read:
> 
>   constexpr-105050.C:8:3: error: neither branch of ‘if’ is a constant 
> expression
>   8 |   if (p != q && *p < 0)
> |   ^~
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?

LGTM.
 
>   PR c++/105050
> 
> gcc/cp/ChangeLog:
> 
>   * constexpr.cc (potential_constant_expression_1) :
>   Clarify error message when a if-stmt is non-constant because its
>   branches are non-constant.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/cpp1y/constexpr-105050.C: New test.
> ---
>  gcc/cp/constexpr.cc   |  7 ++-
>  gcc/testsuite/g++.dg/cpp1y/constexpr-105050.C | 12 
>  2 files changed, 18 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-105050.C
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 778680b8270..9c40b051574 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -9439,7 +9439,12 @@ potential_constant_expression_1 (tree t, bool 
> want_rval, bool strict, bool now,
>   }
>   }
>if (flags & tf_error)
> - error_at (loc, "expression %qE is not a constant expression", t);
> + {
> +   if (TREE_CODE (t) == IF_STMT)
> + error_at (loc, "neither branch of % is a constant expression");
> +   else
> + error_at (loc, "expression %qE is not a constant expression", t);
> + }
>return false;
>  
>  case VEC_INIT_EXPR:
> diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-105050.C 
> b/gcc/testsuite/g++.dg/cpp1y/constexpr-105050.C
> new file mode 100644
> index 000..99d5c9960ac
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-105050.C
> @@ -0,0 +1,12 @@
> +// PR c++/105050
> +// { dg-do compile { target c++14 } }
> +
> +void g();
> +void h();
> +
> +constexpr void f(int* p, int *q) {
> +  if (p != q && *p < 0) // { dg-error "neither branch of 'if' is a constant 
> expression" }
> +g();
> +  else
> +h();
> +}
> -- 
> 2.35.1.655.ga68dfadae5
> 

Marek



Re: [PATCH v3] c++: alignas and alignof void [PR104944]

2022-03-25 Thread Marek Polacek via Gcc-patches
On Fri, Mar 25, 2022 at 09:36:10AM -0400, Jason Merrill wrote:
> On 3/24/22 18:43, Marek Polacek wrote:
> > On Thu, Mar 24, 2022 at 05:12:12PM -0400, Jason Merrill wrote:
> > > On 3/24/22 15:56, Marek Polacek wrote:
> > > > On Thu, Mar 24, 2022 at 12:02:29PM -0400, Jason Merrill wrote:
> > > > > On 3/24/22 11:49, Marek Polacek wrote:
> > > > > > I started looking into this PR because in GCC 4.9 we were able to
> > > > > > detect the invalid
> > > > > > 
> > > > > >  struct alignas(void) S{};
> > > > > > 
> > > > > > but I broke it in r210262.
> > > > > > 
> > > > > > It's ill-formed code in C++:
> > > > > > [dcl.align]/3: "An alignment-specifier of the form alignas(type-id) 
> > > > > > has
> > > > > > the same effect as alignas(alignof(type-id))", and [expr.align]/1:
> > > > > > "The operand shall be a type-id representing a complete object type,
> > > > > > or an array thereof, or a reference to one of those types." and void
> > > > > > is not a complete type.
> > > > > > 
> > > > > > It's also invalid in C:
> > > > > > 6.7.5: _Alignas(type-name) is equivalent to 
> > > > > > _Alignas(_Alignof(type-name))
> > > > > > 6.5.3.4: "The _Alignof operator shall not be applied to a function 
> > > > > > type
> > > > > > or an incomplete type."
> > > > > > 
> > > > > > We have a GNU extension whereby we treat sizeof(void) as 1, but I 
> > > > > > assume
> > > > > > it doesn't apply to alignof, so I'd like to reject it in C too.
> > > > > 
> > > > > That makes sense to me in principle, but we've allowed it since the
> > > > > beginning of version control, back when c_alignof was a separate 
> > > > > function.
> > > > > Changing that seems questionable for a regression fix.
> > > > 
> > > > Ok, that makes sense.  How about rejecting alignof(void) in C++ only
> > > > now (where it is a regression), and maybe come back to this in GCC 13 
> > > > for C?
> > > 
> > > I'd probably just leave it alone for C and __alignof.
> > 
> > Fair enough.
> > 
> > > > PR c++/104944
> > > > 
> > > > gcc/c-family/ChangeLog:
> > > > 
> > > > * c-common.cc (c_sizeof_or_alignof_type): Do not allow 
> > > > alignof(void)
> > > > in C++.
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * typeck.cc (cxx_alignas_expr): Call cxx_sizeof_or_alignof_type 
> > > > with
> > > > complain == true.
> > > 
> > > This hunk is OK.  But let's put the diagnostic in
> > > cxx_sizeof_or_alignof_type, where it can depend on std_alignof.
> > 
> > Like so?  With this patch __alignof only produces a pedwarn (there's no
> > __alignas to worry about).
> > 
> > -- >8 --
> > I started looking into this PR because in GCC 4.9 we were able to
> > detect the invalid
> > 
> >struct alignas(void) S{};
> > 
> > but I broke it in r210262.
> > 
> > It's ill-formed code in C++:
> > [dcl.align]/3: "An alignment-specifier of the form alignas(type-id) has
> > the same effect as alignas(alignof(type-id))", and [expr.align]/1:
> > "The operand shall be a type-id representing a complete object type,
> > or an array thereof, or a reference to one of those types." and void
> > is not a complete type.
> > 
> > It's also invalid in C:
> > 6.7.5: _Alignas(type-name) is equivalent to _Alignas(_Alignof(type-name))
> > 6.5.3.4: "The _Alignof operator shall not be applied to a function type
> > or an incomplete type."
> > 
> > We have a GNU extension whereby we treat sizeof(void) as 1, but I assume
> > it doesn't apply to alignof, at least in C++.  However, __alignof__(void)
> > is still accepted with a -Wpedantic warning.
> > 
> > (We still say "invalid application of '__alignof__'" rather than
> > 'alignas' but I felt that fixing that may not be suitable as part of this
> > patch.)
> 
> Do we still say '__alignof__' in this version of the patch?  Seems like now
> we might as well say 'alignof'.  OK with that change.

When diagnosing alignof(void) we now say 'alignof', for __alignof__(void) we
say '__alignof__', but the "incomplete type" diagnostic still always prints
'__alignof__' :(.

I'll fix the note and push, thanks!

Marek



[PATCH v3] c++: alignas and alignof void [PR104944]

2022-03-24 Thread Marek Polacek via Gcc-patches
On Thu, Mar 24, 2022 at 05:12:12PM -0400, Jason Merrill wrote:
> On 3/24/22 15:56, Marek Polacek wrote:
> > On Thu, Mar 24, 2022 at 12:02:29PM -0400, Jason Merrill wrote:
> > > On 3/24/22 11:49, Marek Polacek wrote:
> > > > I started looking into this PR because in GCC 4.9 we were able to
> > > > detect the invalid
> > > > 
> > > > struct alignas(void) S{};
> > > > 
> > > > but I broke it in r210262.
> > > > 
> > > > It's ill-formed code in C++:
> > > > [dcl.align]/3: "An alignment-specifier of the form alignas(type-id) has
> > > > the same effect as alignas(alignof(type-id))", and [expr.align]/1:
> > > > "The operand shall be a type-id representing a complete object type,
> > > > or an array thereof, or a reference to one of those types." and void
> > > > is not a complete type.
> > > > 
> > > > It's also invalid in C:
> > > > 6.7.5: _Alignas(type-name) is equivalent to 
> > > > _Alignas(_Alignof(type-name))
> > > > 6.5.3.4: "The _Alignof operator shall not be applied to a function type
> > > > or an incomplete type."
> > > > 
> > > > We have a GNU extension whereby we treat sizeof(void) as 1, but I assume
> > > > it doesn't apply to alignof, so I'd like to reject it in C too.
> > > 
> > > That makes sense to me in principle, but we've allowed it since the
> > > beginning of version control, back when c_alignof was a separate function.
> > > Changing that seems questionable for a regression fix.
> > 
> > Ok, that makes sense.  How about rejecting alignof(void) in C++ only
> > now (where it is a regression), and maybe come back to this in GCC 13 for C?
> 
> I'd probably just leave it alone for C and __alignof.

Fair enough.

> > PR c++/104944
> > 
> > gcc/c-family/ChangeLog:
> > 
> > * c-common.cc (c_sizeof_or_alignof_type): Do not allow alignof(void)
> > in C++.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * typeck.cc (cxx_alignas_expr): Call cxx_sizeof_or_alignof_type with
> > complain == true.
> 
> This hunk is OK.  But let's put the diagnostic in
> cxx_sizeof_or_alignof_type, where it can depend on std_alignof.

Like so?  With this patch __alignof only produces a pedwarn (there's no
__alignas to worry about).

-- >8 --
I started looking into this PR because in GCC 4.9 we were able to
detect the invalid

  struct alignas(void) S{};

but I broke it in r210262.

It's ill-formed code in C++:
[dcl.align]/3: "An alignment-specifier of the form alignas(type-id) has
the same effect as alignas(alignof(type-id))", and [expr.align]/1:
"The operand shall be a type-id representing a complete object type,
or an array thereof, or a reference to one of those types." and void
is not a complete type.

It's also invalid in C:
6.7.5: _Alignas(type-name) is equivalent to _Alignas(_Alignof(type-name))
6.5.3.4: "The _Alignof operator shall not be applied to a function type
or an incomplete type."

We have a GNU extension whereby we treat sizeof(void) as 1, but I assume
it doesn't apply to alignof, at least in C++.  However, __alignof__(void)
is still accepted with a -Wpedantic warning.

(We still say "invalid application of '__alignof__'" rather than
'alignas' but I felt that fixing that may not be suitable as part of this
patch.)

PR c++/104944

gcc/cp/ChangeLog:

* typeck.cc (cxx_sizeof_or_alignof_type): Diagnose alignof(void).
(cxx_alignas_expr): Call cxx_sizeof_or_alignof_type with
complain == true.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alignas20.C: New test.
---
 gcc/cp/typeck.cc   | 21 +++--
 gcc/testsuite/g++.dg/cpp0x/alignas20.C | 26 ++
 2 files changed, 41 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alignas20.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 516fa574ef6..26a7cb4b50d 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -1873,9 +1873,9 @@ compparms (const_tree parms1, const_tree parms2)
 }
 
 
-/* Process a sizeof or alignof expression where the operand is a
-   type. STD_ALIGNOF indicates whether an alignof has C++11 (minimum alignment)
-   or GNU (preferred alignment) semantics; it is ignored if op is
+/* Process a sizeof or alignof expression where the operand is a type.
+   STD_ALIGNOF indicates whether an alignof has C++11 (minimum alignment)
+   or GNU (preferred alignment) semantics; it is ignored if OP is
SIZEOF_EXPR.  */
 
 tree
@@ -1899,6 +1899,13 @@ cxx_sizeof_or_ali

[PATCH v3] c++: ICE with template code in constexpr [PR104284]

2022-03-24 Thread Marek Polacek via Gcc-patches
On Thu, Mar 24, 2022 at 11:40:11AM -0400, Jason Merrill wrote:
> On 3/18/22 17:55, Marek Polacek wrote:
> > On Fri, Mar 11, 2022 at 06:46:42PM -0500, Jason Merrill wrote:
> > > On 3/10/22 18:04, Marek Polacek wrote:
> > > > Since r9-6073 cxx_eval_store_expression preevaluates the value to
> > > > be stored, and that revealed a crash where a template code (here,
> > > > code=IMPLICIT_CONV_EXPR) leaks into cxx_eval*.
> > > > 
> > > > It happens because we're performing build_vec_init while processing
> > > > a template
> > > 
> > > Hmm, that seems like the bug.  Where's that call coming from?
> > 
> >  From build_aggr_init.  So we're handling e.g.
> > 
> >template
> >constexpr void g () {
> >  constexpr S s2[]{{'a'}};
> >}
> > 
> > cp_finish_decl (decl=s2, init={{'a'}}) sees we're in 
> > processing_template_decl,
> > but also that we have a constexpr var which is not dependent, nor is its
> > initializer:
> > 
> >else if (init
> > && (init_const_expr_p || DECL_DECLARED_CONSTEXPR_P (decl))
> > && !TYPE_REF_P (type)
> > && decl_maybe_constant_var_p (decl)
> > && !(dep_init = value_dependent_init_p (init)))
> >  {
> >/* This variable seems to be a non-dependent constant, so process
> >   its initializer.  If check_initializer returns non-null the
> >   initialization wasn't constant after all.  */
> >tree init_code;
> >cleanups = make_tree_vector ();
> >init_code = check_initializer (decl, init, flags, &cleanups);
> > 
> > so we call check_initializer, where we go down this path:
> > 
> >init_code = build_aggr_init_full_exprs (decl, init, flags);
> > 
> > build_aggr_init sees that the type of 's2' is ARRAY_TYPE, so it calls
> > build_vec_init.
> > 
> > I now recall that we've discussed build_vec_init in a template in the
> > past, for example in the context of c++/93676.  So I agree we ought to
> > make an effort to avoid calling build_vec_init in a template.  Perhaps
> > like this: use an INIT_EXPR.  With that, we should call build_vec_init
> > if needed while instantiating.  Does that make any sense?
> 
> Hmm.  If we do that, then we get back to
> 
> >   if (TREE_CODE (init_code) == INIT_EXPR)
> 
> in check_initializer, and pull out the same init again, and set
> LOOKUP_ALREADY_DIGESTED.  But I think that's wrong, we haven't digested it
> yet.

Yeah, that's probably no good :(
 
> Maybe we could avoid entering the below block of check_initializer at all in
> this situation?
> 
> >   if (((type_build_ctor_call (type) || CLASS_TYPE_P (type))
> >&& !(flags & LOOKUP_ALREADY_DIGESTED)
> >&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
> > && CP_AGGREGATE_TYPE_P (type)
> > && (CLASS_TYPE_P (type)
> 
> Maybe by adding || processing_template_decl here?

That seems to work!  Thanks.

I've checked that we call build_vec_init when instantiating, so we
shouldn't be losing any of its effects.

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

-- >8 --
Since r9-6073 cxx_eval_store_expression preevaluates the value to
be stored, and that revealed a crash where a template code (here,
code=IMPLICIT_CONV_EXPR) leaks into cxx_eval*.

It happens because we're performing build_vec_init while processing
a template, which calls get_temp_regvar which creates an INIT_EXPR.
This INIT_EXPR's RHS contains an rvalue conversion so we create an
IMPLICIT_CONV_EXPR.  Its operand is not type-dependent and the whole
INIT_EXPR is not type-dependent.  So we call build_non_dependent_expr
which, with -fchecking=2, calls fold_non_dependent_expr.  At this
point the expression still has an IMPLICIT_CONV_EXPR, which ought to
be handled in instantiate_non_dependent_expr_internal.  However,
tsubst_copy_and_build doesn't handle INIT_EXPR; it will just call
tsubst_copy which does nothing when args is null.  So we fail to
replace the IMPLICIT_CONV_EXPR and ICE.

The problem is that we call build_vec_init in a template in the
first place.  We can avoid doing so by checking p_t_d before
calling build_aggr_init in check_initializer.

PR c++/104284

gcc/cp/ChangeLog:

* decl.cc (check_initializer): Don't call build_aggr_init in
a template.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-104

[PATCH v2] c++: alignas and alignof void [PR104944]

2022-03-24 Thread Marek Polacek via Gcc-patches
On Thu, Mar 24, 2022 at 12:02:29PM -0400, Jason Merrill wrote:
> On 3/24/22 11:49, Marek Polacek wrote:
> > I started looking into this PR because in GCC 4.9 we were able to
> > detect the invalid
> > 
> >struct alignas(void) S{};
> > 
> > but I broke it in r210262.
> > 
> > It's ill-formed code in C++:
> > [dcl.align]/3: "An alignment-specifier of the form alignas(type-id) has
> > the same effect as alignas(alignof(type-id))", and [expr.align]/1:
> > "The operand shall be a type-id representing a complete object type,
> > or an array thereof, or a reference to one of those types." and void
> > is not a complete type.
> > 
> > It's also invalid in C:
> > 6.7.5: _Alignas(type-name) is equivalent to _Alignas(_Alignof(type-name))
> > 6.5.3.4: "The _Alignof operator shall not be applied to a function type
> > or an incomplete type."
> > 
> > We have a GNU extension whereby we treat sizeof(void) as 1, but I assume
> > it doesn't apply to alignof, so I'd like to reject it in C too.
> 
> That makes sense to me in principle, but we've allowed it since the
> beginning of version control, back when c_alignof was a separate function.
> Changing that seems questionable for a regression fix.

Ok, that makes sense.  How about rejecting alignof(void) in C++ only
now (where it is a regression), and maybe come back to this in GCC 13 for C?

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

-- >8 --
I started looking into this PR because in GCC 4.9 we were able to
detect the invalid

  struct alignas(void) S{};

but I broke it in r210262.

It's ill-formed code in C++:
[dcl.align]/3: "An alignment-specifier of the form alignas(type-id) has
the same effect as alignas(alignof(type-id))", and [expr.align]/1:
"The operand shall be a type-id representing a complete object type,
or an array thereof, or a reference to one of those types." and void
is not a complete type.

It's also invalid in C:
6.7.5: _Alignas(type-name) is equivalent to _Alignas(_Alignof(type-name))
6.5.3.4: "The _Alignof operator shall not be applied to a function type
or an incomplete type."

We have a GNU extension whereby we treat sizeof(void) as 1, but I assume
it doesn't apply to alignof, so I'd like to reject it in C too, but it's
probably not a good time to do so in stage4.

(We still say "invalid application of '__alignof__'" rather than
'alignas' but I felt that fixing that may not be suitable as part of this
patch.)

PR c++/104944

gcc/c-family/ChangeLog:

* c-common.cc (c_sizeof_or_alignof_type): Do not allow alignof(void)
in C++.

gcc/cp/ChangeLog:

* typeck.cc (cxx_alignas_expr): Call cxx_sizeof_or_alignof_type with
complain == true.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alignas20.C: New test.
---
 gcc/c-family/c-common.cc   | 20 +++-
 gcc/cp/typeck.cc   | 14 --
 gcc/testsuite/g++.dg/cpp0x/alignas20.C | 24 
 3 files changed, 47 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alignas20.C

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index d034837bb5b..f99717f540b 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -3849,7 +3849,7 @@ c_common_get_alias_set (tree t)
the IS_SIZEOF parameter indicates which operator is being applied.
The COMPLAIN flag controls whether we should diagnose possibly
ill-formed constructs or not.  LOC is the location of the SIZEOF or
-   TYPEOF operator.  If MIN_ALIGNOF, the least alignment required for
+   ALIGNOF operator.  If MIN_ALIGNOF, the least alignment required for
a type in any context should be returned, rather than the normal
alignment for that type.  */
 
@@ -3891,10 +3891,20 @@ c_sizeof_or_alignof_type (location_t loc,
 }
   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
 {
-  if (type_code == VOID_TYPE
- && complain && warn_pointer_arith)
-   pedwarn (loc, OPT_Wpointer_arith,
-"invalid application of %qs to a void type", op_name);
+  if (type_code == VOID_TYPE && complain)
+   {
+ /* sizeof(void) is a GNU extension.  */
+ if (is_sizeof || !c_dialect_cxx ())
+   pedwarn (loc, OPT_Wpointer_arith,
+"invalid application of %qs to a void type", op_name);
+ /* But alignof(void) is not (in C++).  */
+ else
+   {
+ error_at (loc, "invalid application of %qs to a void type",
+   op_name);
+ return error_mark_node;
+   }
+   }
   else if (!complain)
 re

[PATCH v2] c++: FIX_TRUNC_EXPR in tsubst [PR102990]

2022-03-24 Thread Marek Polacek via Gcc-patches
On Thu, Mar 24, 2022 at 09:32:19AM -0400, Jason Merrill wrote:
> On 3/23/22 19:26, Marek Polacek wrote:
> > On Wed, Mar 23, 2022 at 04:35:32PM -0400, Jason Merrill wrote:
> > > On 3/22/22 19:55, Marek Polacek wrote:
> > > > This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
> > > > where it hits gcc_unreachable ().
> > > > 
> > > > The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
> > > > was introduced in r181478, but it did the wrong thing, whereupon it
> > > > was turned into gcc_unreachable () in r258821 (see this thread:
> > > > <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
> > > > 
> > > > In a template, we should never create a FIX_TRUNC_EXPR (that's what
> > > > conv_unsafe_in_template_p is for).  But in this test we are NOT in
> > > > a template when we call digest_nsdmi_init which ends up calling
> > > > convert_like, converting 1.0e+0 to int, so convert_to_integer_1
> > > > gives us a FIX_TRUNC_EXPR.
> > > > 
> > > > But then when we get to parsing f's parameters, we are in a template
> > > > when processing decltype(Helpers{}), and since r268321, when the
> > > > compound literal isn't instantiation-dependent and the type isn't
> > > > type-dependent, finish_compound_literal falls back to the normal
> > > > processing, so it calls digest_init, which does fold_non_dependent_init
> > > > and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
> > > > therefore crash in tsubst_copy_and_build.
> > > 
> > > Hmm, we shouldn't be doing fold_non_dependent_init on the result of
> > > get_nsdmi.  Why does that happen?
> > 
> > OK, so we have decltype(Helpers{}), finish_compound_literal gets
> > Helpers{}, it's not type-dependent, so:
> > 
> > - call digest_init (type=Helpers, init={})
> >init is BRACE_ENCLOSED_INITIALIZER_P, type is !TYPE_NON_AGGREGATE_CLASS
> >so go down to...
> > - process_init_constructor_record (type=Helpers, init={})
> > - we walk the fields of Helpers, there's 'inputs' of type knob_t
> >   type_build_ctor_call (knob_t) is true, we want to default-init this
> >   field
> > - create a {} as the init for default-initialization
> > - call massage_init_elt (type=knob_t, init={}) to adjust the init
> >   - we do so by calling digest_init_r (type=knob_t, init={})
> > - here we again call process_init_constructor_record, walk knob_t's
> >   fields, see the field 'value', it has a DECL_INITIAL, so call
> >  get_nsdmi, that returns the FIX_TRUNC_EXPR we've created before
> > - so digesting {} for knob_t produced
> >   init = {.value=(int) NON_LVALUE_EXPR <1.0e+0>}
> >   - then we call fold_non_dependent_init on this init, and die
> 
> Maybe we shouldn't call fold_non_dependent_init on a CONSTRUCTOR here, since
> presumably we already called it on elements that needed it in the recursive
> digest_init_r.

Ah, that works.  It's still a bit weird that we don't treat FLOAT_EXPR and
FIX_TRUNC_EXPR the same.

I've tried to remove the call to fold_non_dependent_init in massage_init_elt
to see what breaks...a lot.  So it has to stay at least in this form.

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

Thanks,

-- >8 --
This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
where it hits gcc_unreachable ().

The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
was introduced in r181478, but it did the wrong thing, whereupon it
was turned into gcc_unreachable () in r258821 (see this thread:
<https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).

In a template, we should never create a FIX_TRUNC_EXPR (that's what
conv_unsafe_in_template_p is for).  But in this test we are NOT in
a template when we call digest_nsdmi_init which ends up calling
convert_like, converting 1.0e+0 to int, so convert_to_integer_1
gives us a FIX_TRUNC_EXPR.

But then when we get to parsing f's parameters, we are in a template
when processing decltype(Helpers{}), and since r268321, when the
compound literal isn't instantiation-dependent and the type isn't
type-dependent, finish_compound_literal falls back to the normal
processing, so it calls digest_init, which does fold_non_dependent_init
and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
therefore crash in tsubst_copy_and_build.

The fateful call to fold_non_dependent_init comes from massage_init_elt,
We 

[PATCH] c, c++: alignas and alignof void [PR104944]

2022-03-24 Thread Marek Polacek via Gcc-patches
I started looking into this PR because in GCC 4.9 we were able to
detect the invalid

  struct alignas(void) S{};

but I broke it in r210262.

It's ill-formed code in C++:
[dcl.align]/3: "An alignment-specifier of the form alignas(type-id) has
the same effect as alignas(alignof(type-id))", and [expr.align]/1:
"The operand shall be a type-id representing a complete object type,
or an array thereof, or a reference to one of those types." and void
is not a complete type.

It's also invalid in C:
6.7.5: _Alignas(type-name) is equivalent to _Alignas(_Alignof(type-name))
6.5.3.4: "The _Alignof operator shall not be applied to a function type
or an incomplete type."

We have a GNU extension whereby we treat sizeof(void) as 1, but I assume
it doesn't apply to alignof, so I'd like to reject it in C too.

(We still say "invalid application of '__alignof__'" rather than
'alignas' but I felt that fixing that may not be suitable as part of this
patch.)

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

PR c++/104944

gcc/c-family/ChangeLog:

* c-common.cc (c_sizeof_or_alignof_type): Do not allow alignof(void).

gcc/cp/ChangeLog:

* typeck.cc (cxx_alignas_expr): Call cxx_sizeof_or_alignof_type with
complain == true.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/alignas20.C: New test.
* gcc.dg/c11-align-10.c: New test.
---
 gcc/c-family/c-common.cc   | 20 +++-
 gcc/cp/typeck.cc   | 14 --
 gcc/testsuite/g++.dg/cpp0x/alignas20.C | 24 
 gcc/testsuite/gcc.dg/c11-align-10.c| 18 ++
 4 files changed, 65 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alignas20.C
 create mode 100644 gcc/testsuite/gcc.dg/c11-align-10.c

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index d034837bb5b..8b76eba64c2 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -3849,7 +3849,7 @@ c_common_get_alias_set (tree t)
the IS_SIZEOF parameter indicates which operator is being applied.
The COMPLAIN flag controls whether we should diagnose possibly
ill-formed constructs or not.  LOC is the location of the SIZEOF or
-   TYPEOF operator.  If MIN_ALIGNOF, the least alignment required for
+   ALIGNOF operator.  If MIN_ALIGNOF, the least alignment required for
a type in any context should be returned, rather than the normal
alignment for that type.  */
 
@@ -3891,10 +3891,20 @@ c_sizeof_or_alignof_type (location_t loc,
 }
   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
 {
-  if (type_code == VOID_TYPE
- && complain && warn_pointer_arith)
-   pedwarn (loc, OPT_Wpointer_arith,
-"invalid application of %qs to a void type", op_name);
+  if (type_code == VOID_TYPE && complain)
+   {
+ /* sizeof(void) is a GNU extension.  */
+ if (is_sizeof)
+   pedwarn (loc, OPT_Wpointer_arith,
+"invalid application of %qs to a void type", op_name);
+ /* But alignof(void) is not.  */
+ else
+   {
+ error_at (loc, "invalid application of %qs to a void type",
+   op_name);
+ return error_mark_node;
+   }
+   }
   else if (!complain)
 return error_mark_node;
   value = size_one_node;
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 516fa574ef6..96653c4f96e 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -1873,9 +1873,9 @@ compparms (const_tree parms1, const_tree parms2)
 }
 
 
-/* Process a sizeof or alignof expression where the operand is a
-   type. STD_ALIGNOF indicates whether an alignof has C++11 (minimum alignment)
-   or GNU (preferred alignment) semantics; it is ignored if op is
+/* Process a sizeof or alignof expression where the operand is a type.
+   STD_ALIGNOF indicates whether an alignof has C++11 (minimum alignment)
+   or GNU (preferred alignment) semantics; it is ignored if OP is
SIZEOF_EXPR.  */
 
 tree
@@ -2132,11 +2132,13 @@ cxx_alignas_expr (tree e)
 /* [dcl.align]/3:

   When the alignment-specifier is of the form
-  alignas(type-id ), it shall have the same effect as
-  alignas(alignof(type-id )).  */
+  alignas(type-id), it shall have the same effect as
+  alignas(alignof(type-id)).  */
 
 return cxx_sizeof_or_alignof_type (input_location,
-  e, ALIGNOF_EXPR, true, false);
+  e, ALIGNOF_EXPR,
+  /*std_alignof=*/true,
+  /*complain=*/true);
   
   /* If we reach this point, it means the alignas expression if of
  the form "alignas(assignment-expression)", so we should follow
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignas20.C 
b/gcc/testsuite/g++.dg/cpp0x/alignas20.C
new file mode 100644
index 0

Re: [PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990]

2022-03-23 Thread Marek Polacek via Gcc-patches
On Wed, Mar 23, 2022 at 04:35:32PM -0400, Jason Merrill wrote:
> On 3/22/22 19:55, Marek Polacek wrote:
> > This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
> > where it hits gcc_unreachable ().
> > 
> > The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
> > was introduced in r181478, but it did the wrong thing, whereupon it
> > was turned into gcc_unreachable () in r258821 (see this thread:
> > <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/495853.html>).
> > 
> > In a template, we should never create a FIX_TRUNC_EXPR (that's what
> > conv_unsafe_in_template_p is for).  But in this test we are NOT in
> > a template when we call digest_nsdmi_init which ends up calling
> > convert_like, converting 1.0e+0 to int, so convert_to_integer_1
> > gives us a FIX_TRUNC_EXPR.
> > 
> > But then when we get to parsing f's parameters, we are in a template
> > when processing decltype(Helpers{}), and since r268321, when the
> > compound literal isn't instantiation-dependent and the type isn't
> > type-dependent, finish_compound_literal falls back to the normal
> > processing, so it calls digest_init, which does fold_non_dependent_init
> > and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
> > therefore crash in tsubst_copy_and_build.
> 
> Hmm, we shouldn't be doing fold_non_dependent_init on the result of
> get_nsdmi.  Why does that happen?

OK, so we have decltype(Helpers{}), finish_compound_literal gets
Helpers{}, it's not type-dependent, so:

- call digest_init (type=Helpers, init={})
  init is BRACE_ENCLOSED_INITIALIZER_P, type is !TYPE_NON_AGGREGATE_CLASS
  so go down to...
- process_init_constructor_record (type=Helpers, init={})
   - we walk the fields of Helpers, there's 'inputs' of type knob_t
 type_build_ctor_call (knob_t) is true, we want to default-init this
 field
   - create a {} as the init for default-initialization
   - call massage_init_elt (type=knob_t, init={}) to adjust the init
 - we do so by calling digest_init_r (type=knob_t, init={})
   - here we again call process_init_constructor_record, walk knob_t's
 fields, see the field 'value', it has a DECL_INITIAL, so call
 get_nsdmi, that returns the FIX_TRUNC_EXPR we've created before
   - so digesting {} for knob_t produced
 init = {.value=(int) NON_LVALUE_EXPR <1.0e+0>}
 - then we call fold_non_dependent_init on this init, and die

Do we have a mechanism to avoid folding get_nsdmi's trees that I've missed?
 
> > Either I can tweak p_c_e to say that a FIX_TRUNC_EXPR in a template
> > is not potentially constant, or I can just remove the whole F_T_E
> > case, since:
> > a) we could not have created an IMPLICIT_CONV_EXPR here, and
> > b) similar code, FLOAT_EXPR, is not handled here, either.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
> > 
> > PR c++/102990
> > 
> > gcc/cp/ChangeLog:
> > 
> > * pt.cc (tsubst_copy_and_build) : Remove.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/nsdmi-template22.C: New test.
> > * g++.dg/cpp0x/nsdmi-template23.C: New test.
> > ---
> >   gcc/cp/pt.cc  |  4 
> >   gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +
> >   gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +
> >   3 files changed, 26 insertions(+), 4 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 715eea27577..a3becc19290 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -20184,10 +20184,6 @@ tsubst_copy_and_build (tree t,
> > templated_operator_saved_lookups (t),
> > complain|decltype_flag));
> > -case FIX_TRUNC_EXPR:
> > -  /* convert_like should have created an IMPLICIT_CONV_EXPR.  */
> > -  gcc_unreachable ();
> > -
> >   case ADDR_EXPR:
> > op1 = TREE_OPERAND (t, 0);
> > if (TREE_CODE (op1) == LABEL_DECL)
> > diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C 
> > b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> > new file mode 100644
> > index 000..4ed2501035c
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
> > @@ -0,0 +1,13 @@
> > +// PR c++/102990
> > +// { dg-do compile { target c++11 } }
> > +
> &

[PATCH] c++: FIX_TRUNC_EXPR in tsubst [PR102990]

2022-03-22 Thread Marek Polacek via Gcc-patches
This is a crash where a FIX_TRUNC_EXPR gets into tsubst_copy_and_build
where it hits gcc_unreachable ().

The history of tsubst_copy_and_build/FIX_TRUNC_EXPR is such that it
was introduced in r181478, but it did the wrong thing, whereupon it
was turned into gcc_unreachable () in r258821 (see this thread:
).

In a template, we should never create a FIX_TRUNC_EXPR (that's what
conv_unsafe_in_template_p is for).  But in this test we are NOT in
a template when we call digest_nsdmi_init which ends up calling
convert_like, converting 1.0e+0 to int, so convert_to_integer_1
gives us a FIX_TRUNC_EXPR.

But then when we get to parsing f's parameters, we are in a template
when processing decltype(Helpers{}), and since r268321, when the
compound literal isn't instantiation-dependent and the type isn't
type-dependent, finish_compound_literal falls back to the normal
processing, so it calls digest_init, which does fold_non_dependent_init
and since the FIX_TRUNC_EXPR isn't dependent, we instantiate and
therefore crash in tsubst_copy_and_build.

Either I can tweak p_c_e to say that a FIX_TRUNC_EXPR in a template
is not potentially constant, or I can just remove the whole F_T_E
case, since:
a) we could not have created an IMPLICIT_CONV_EXPR here, and
b) similar code, FLOAT_EXPR, is not handled here, either.

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

PR c++/102990

gcc/cp/ChangeLog:

* pt.cc (tsubst_copy_and_build) : Remove.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/nsdmi-template22.C: New test.
* g++.dg/cpp0x/nsdmi-template23.C: New test.
---
 gcc/cp/pt.cc  |  4 
 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C | 13 +
 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C | 13 +
 3 files changed, 26 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 715eea27577..a3becc19290 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20184,10 +20184,6 @@ tsubst_copy_and_build (tree t,
templated_operator_saved_lookups (t),
complain|decltype_flag));
 
-case FIX_TRUNC_EXPR:
-  /* convert_like should have created an IMPLICIT_CONV_EXPR.  */
-  gcc_unreachable ();
-
 case ADDR_EXPR:
   op1 = TREE_OPERAND (t, 0);
   if (TREE_CODE (op1) == LABEL_DECL)
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
new file mode 100644
index 000..4ed2501035c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template22.C
@@ -0,0 +1,13 @@
+// PR c++/102990
+// { dg-do compile { target c++11 } }
+
+struct knob_t {
+  /* Let's create a FIX_TRUNC_EXPR.  */
+  int value = 1.0;
+};
+
+struct Helpers {
+  knob_t inputs;
+};
+
+template void f(decltype(Helpers{}));
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
new file mode 100644
index 000..240cab4347a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template23.C
@@ -0,0 +1,13 @@
+// PR c++/102990
+// { dg-do compile { target c++11 } }
+
+struct knob_t {
+  /* Let's create a FLOAT_EXPR.  */
+  double value = 1UL;
+};
+
+struct Helpers {
+  knob_t inputs;
+};
+
+template void f(decltype(Helpers{}));

base-commit: 5d2233f4033dfa37ad88dc2eab138524fe64242e
-- 
2.35.1



Re: [PATCH] c++: Fall through for arrays of T vs T cv [PR104996]

2022-03-22 Thread Marek Polacek via Gcc-patches
On Tue, Mar 22, 2022 at 08:39:21PM +, Ed Catmur wrote:
> If two arrays do not have the exact same element type including 
> qualification, this could be e.g. f(int (&&)[]) vs. f(int const (&)[]), which 
> can still be distinguished by the lvalue-rvalue tiebreaker.
> 
> By tightening this branch (in accordance with the letter of the Standard) we 
> fall through to the next branch, which tests whether they have different 
> element type ignoring qualification and returns 0 in that case; thus we only 
> actually fall through in the T[...] vs. T cv[...] case, eventually 
> considering the lvalue-rvalue tiebreaker at the end of compare_ics.
> 
> Add test.
> 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104996

Thanks, the patch looks reasonable.  Can you describe how it's been tested?

You're going to need a ChangeLog entry, something like

* call.c (compare_ics): When comparing list-initialization sequences,
do not return early.

and an entry for the test, which...

> ---
>  gcc/cp/call.cc  | 7 ++-
>  gcc/testsuite/g++.dg/pr104996.C | 5 +
>  2 files changed, 7 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/pr104996.C
> 
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 23d3fc496b822..28589ab3459ea 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -11535,12 +11535,9 @@ compare_ics (conversion *ics1, conversion *ics2)
>P0388R4.)  */
>else if (t1->kind == ck_aggr
>  && TREE_CODE (t1->type) == ARRAY_TYPE
> -&& TREE_CODE (t2->type) == ARRAY_TYPE)
> +&& TREE_CODE (t2->type) == ARRAY_TYPE
> +&& same_type_p (TREE_TYPE (t1->type), TREE_TYPE (t2->type)))
>   {
> -   /* The type of the array elements must be the same.  */
> -   if (!same_type_p (TREE_TYPE (t1->type), TREE_TYPE (t2->type)))
> - return 0;
> -
> tree n1 = nelts_initialized_by_list_init (t1);
> tree n2 = nelts_initialized_by_list_init (t2);
> if (tree_int_cst_lt (n1, n2))
> diff --git a/gcc/testsuite/g++.dg/pr104996.C b/gcc/testsuite/g++.dg/pr104996.C
> new file mode 100644
> index 0..2e7558c7b9c77
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr104996.C

...can you please rename the test to initlist129.C and put it into g++.dg/cpp0x?

> @@ -0,0 +1,5 @@

Also please add

// PR c++/104996

in the first line.

> +// { dg-do compile { target c++11 } }
> +
> +template char f(int (&&)[size]);
> +template int f(int const (&)[size]);
> +static_assert(sizeof(f({1, 2, 3})) == 1, "");
> 

Marek



[PATCH] c: -Wmissing-field-initializers and designated inits [PR82283, PR84685]

2022-03-22 Thread Marek Polacek via Gcc-patches
This patch fixes two kinds of wrong -Wmissing-field-initializers
warnings.  Our docs say that this warning "does not warn about designated
initializers", but we give a warning for

1) the array case:

  struct S {
struct N {
  int a;
  int b;
} c[1];
  } d = {
.c[0].a = 1,
.c[0].b = 1, // missing initializer for field 'b' of 'struct N'
  };

we warn because push_init_level, when constructing an array, clears
constructor_designated (which the warning relies on), and we forget
that we were in a designated initializer context.  Fixed by the
push_init_level hunk; and

2) the compound literal case:

  struct T {
int a;
int *b;
int c;
  };

  struct T t = { .b = (int[]){1} }; // missing initializer for field 'c' of 
'struct T'

where set_designator properly sets constructor_designated to 1, but the
compound literal causes us to create a whole new initializer_stack in
start_init, which clears constructor_designated.  Then, after we've parsed
the compound literal, finish_init flushes the initializer_stack entry,
but doesn't restore constructor_designated, so we forget we were in
a designated initializer context, which causes the bogus warning.  (The
designated flag is also tracked in constructor_stack, but in this case,
we didn't perform push_init_level between set_designator and start_init
so it wasn't saved anywhere.)

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?  Maybe 11 too.

PR c/82283
PR c/84685

gcc/c/ChangeLog:

* c-typeck.cc (struct initializer_stack): Add 'designated' member.
(start_init): Set it.
(finish_init): Restore constructor_designated.
(push_init_level): Set constructor_designated to the value of
constructor_designated in the upper constructor_stack.

gcc/testsuite/ChangeLog:

* gcc.dg/Wmissing-field-initializers-1.c: New test.
* gcc.dg/Wmissing-field-initializers-2.c: New test.
* gcc.dg/Wmissing-field-initializers-3.c: New test.
* gcc.dg/Wmissing-field-initializers-4.c: New test.
* gcc.dg/Wmissing-field-initializers-5.c: New test.
---
 gcc/c/c-typeck.cc | 10 +++--
 .../gcc.dg/Wmissing-field-initializers-1.c| 22 ++
 .../gcc.dg/Wmissing-field-initializers-2.c| 11 +
 .../gcc.dg/Wmissing-field-initializers-3.c| 24 +++
 .../gcc.dg/Wmissing-field-initializers-4.c| 43 +++
 .../gcc.dg/Wmissing-field-initializers-5.c| 22 ++
 6 files changed, 128 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wmissing-field-initializers-1.c
 create mode 100644 gcc/testsuite/gcc.dg/Wmissing-field-initializers-2.c
 create mode 100644 gcc/testsuite/gcc.dg/Wmissing-field-initializers-3.c
 create mode 100644 gcc/testsuite/gcc.dg/Wmissing-field-initializers-4.c
 create mode 100644 gcc/testsuite/gcc.dg/Wmissing-field-initializers-5.c

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index c0812de84b4..6c4af5e4cde 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -8438,6 +8438,7 @@ struct initializer_stack
   char top_level;
   char require_constant_value;
   char require_constant_elements;
+  char designated;
   rich_location *missing_brace_richloc;
 };
 
@@ -8464,6 +8465,7 @@ start_init (tree decl, tree asmspec_tree 
ATTRIBUTE_UNUSED, int top_level,
   p->top_level = constructor_top_level;
   p->next = initializer_stack;
   p->missing_brace_richloc = richloc;
+  p->designated = constructor_designated;
   initializer_stack = p;
 
   constructor_decl = decl;
@@ -8522,6 +8524,7 @@ finish_init (void)
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
+  constructor_designated = p->designated;
   constructor_range_stack = p->constructor_range_stack;
   constructor_elements = p->elements;
   spelling = p->spelling;
@@ -8731,7 +8734,9 @@ push_init_level (location_t loc, int implicit,
   constructor_depth = SPELLING_DEPTH ();
   constructor_elements = NULL;
   constructor_incremental = 1;
-  constructor_designated = 0;
+  /* If the upper initializer is designated, then mark this as
+ designated too to prevent bogus warnings.  */
+  constructor_designated = p->designated;
   constructor_pending_elts = 0;
   if (!implicit)
 {
@@ -8756,9 +8761,6 @@ push_init_level (location_t loc, int implicit,
  push_member_name (constructor_fields);
  constructor_depth++;
}
-  /* If upper initializer is designated, then mark this as
-designated too to prevent bogus warnings.  */
-  constructor_designated = p->designated;
 }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
 {
diff --git a/gcc/testsuite/gcc.dg/Wmissing-field-initializers-1.c 
b/gcc/testsuite/gcc.dg/Wmissing-field-initializers-1.c
new file mode 100644
index 000..fbcca44db5f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmissing-field-initializers-

[PATCH v2] c++: ICE with template code in constexpr [PR104284]

2022-03-18 Thread Marek Polacek via Gcc-patches
On Fri, Mar 11, 2022 at 06:46:42PM -0500, Jason Merrill wrote:
> On 3/10/22 18:04, Marek Polacek wrote:
> > Since r9-6073 cxx_eval_store_expression preevaluates the value to
> > be stored, and that revealed a crash where a template code (here,
> > code=IMPLICIT_CONV_EXPR) leaks into cxx_eval*.
> > 
> > It happens because we're performing build_vec_init while processing
> > a template
> 
> Hmm, that seems like the bug.  Where's that call coming from?

>From build_aggr_init.  So we're handling e.g.

  template
  constexpr void g () {
constexpr S s2[]{{'a'}};
  }

cp_finish_decl (decl=s2, init={{'a'}}) sees we're in processing_template_decl,
but also that we have a constexpr var which is not dependent, nor is its
initializer:

  else if (init
   && (init_const_expr_p || DECL_DECLARED_CONSTEXPR_P (decl))
   && !TYPE_REF_P (type)
   && decl_maybe_constant_var_p (decl)
   && !(dep_init = value_dependent_init_p (init)))
{
  /* This variable seems to be a non-dependent constant, so process
 its initializer.  If check_initializer returns non-null the
 initialization wasn't constant after all.  */
  tree init_code;
  cleanups = make_tree_vector ();
  init_code = check_initializer (decl, init, flags, &cleanups);

so we call check_initializer, where we go down this path:

  init_code = build_aggr_init_full_exprs (decl, init, flags);

build_aggr_init sees that the type of 's2' is ARRAY_TYPE, so it calls
build_vec_init.

I now recall that we've discussed build_vec_init in a template in the
past, for example in the context of c++/93676.  So I agree we ought to
make an effort to avoid calling build_vec_init in a template.  Perhaps
like this: use an INIT_EXPR.  With that, we should call build_vec_init
if needed while instantiating.  Does that make any sense?

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

-- >8 --
Since r9-6073 cxx_eval_store_expression preevaluates the value to
be stored, and that revealed a crash where a template code (here,
code=IMPLICIT_CONV_EXPR) leaks into cxx_eval*.

It happens because we're performing build_vec_init while processing
a template, which calls get_temp_regvar which creates an INIT_EXPR.
This INIT_EXPR's RHS contains an rvalue conversion so we create an
IMPLICIT_CONV_EXPR.  Its operand is not type-dependent and the whole
INIT_EXPR is not type-dependent.  So we call build_non_dependent_expr
which, with -fchecking=2, calls fold_non_dependent_expr.  At this
point the expression still has an IMPLICIT_CONV_EXPR, which ought to
be handled in instantiate_non_dependent_expr_internal.  However,
tsubst_copy_and_build doesn't handle INIT_EXPR; it will just call
tsubst_copy which does nothing when args is null.  So we fail to
replace the IMPLICIT_CONV_EXPR and ICE.

The problem is that we call build_vec_init in a template in the
first place.  It should work to create an INIT_EXPR in a template
and only perform build_vec_init when instantiating.

PR c++/104284

gcc/cp/ChangeLog:

* init.cc (build_aggr_init): Don't call build_vec_init in
a template, create an INIT_EXPR instead.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-104284-1.C: New test.
* g++.dg/cpp1y/constexpr-104284-2.C: New test.
* g++.dg/cpp1y/constexpr-104284-3.C: New test.
* g++.dg/cpp1y/constexpr-104284-4.C: New test.
---
 gcc/cp/init.cc| 11 +++---
 .../g++.dg/cpp1y/constexpr-104284-1.C | 34 ++
 .../g++.dg/cpp1y/constexpr-104284-2.C | 33 +
 .../g++.dg/cpp1y/constexpr-104284-3.C | 33 +
 .../g++.dg/cpp1y/constexpr-104284-4.C | 35 +++
 5 files changed, 142 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-104284-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-104284-2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-104284-3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-104284-4.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 7575597c8fd..58e66adbfe1 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -2006,10 +2006,13 @@ build_aggr_init (tree exp, tree init, int flags, 
tsubst_flags_t complain)
}
}
 
-  stmt_expr = build_vec_init (exp, NULL_TREE, init,
- /*explicit_value_init_p=*/false,
- from_array,
-  complain);
+  /* build_vec_init is not meant to be used in templates.  */
+  if (processing_template_decl)
+   stmt_expr = build2 (INIT_EXPR, itype, exp, init);
+  else
+   stmt_expr = build_vec_init (exp, NULL_TREE, init,

Re: [PATCH v2] middle-end/104854: Limit strncmp overread warnings

2022-03-17 Thread Marek Polacek via Gcc-patches
On Wed, Mar 16, 2022 at 06:54:51AM +0530, Siddhesh Poyarekar wrote:
> On 16/03/2022 02:06, Martin Sebor wrote:
> > The intended use of the strncmp bound is to limit the comparison to
> > at most the size of the arrays or (in a subset of cases) the length
> > of an initial substring. Providing an arbitrary bound that's not
> > related to the sizes as you describe sounds very much like a misuse.
> 
> Nothing in the standard says that the bound is related to the sizes of input
> buffers.  I don't think deducing that intent makes sense either, nor
> concluding that any other use case is misuse.
> 
> > As a historical note, strncmp was first introduced in UNIX v7 where
> > its purpose, alongside strncpy, was to manipulate (potentially)
> > unterminated character arrays like file names stored in fixed size
> > arrays (typically 14 bytes).  Strncpy would fill the buffers with
> > ASCII data up to their size and pad the rest with nuls only if there
> > was room.
> > 
> > Strncmp was then used to compare these potentially unterminated
> > character arrays (e.g., archive headers in ld and ranlib).  The bound
> > was the size of the fixed size array.  Its other use case was to compare
> > leading portions of strings (e.g, when looking for an environment
> > variable or when stripping "./" from path names).
> 
> Thanks for sharing the historical perspective.
> 
> > Since the early UNIX days, both strncpy and to a lesser extent strncmp
> > have been widely misused and, along with many other functions in
> > , a frequent source of bugs due to common misunderstanding
> > of their intended purpose.  The aim of these warnings is to detect
> > the common (and sometimes less common) misuses and bugs.
> 
> They're all valid uses however since they do not violate the standard. If we
> find at compile time that the strings don't terminate at the bounds,
> emitting the warning is OK but the more pessimistic check seems like
> overkill.

I think I agree, I've tried

#include 
char a[] = "abc";
char b[] = "abcd";

int f (void)
{
  return strncmp (a, b, 8);
}
 
where I get

t.c:7:10: warning: ‘strncmp’ specified bound 8 exceeds source size 5 
[-Wstringop-overread]
7 |   return strncmp (a, b, 8);   // -Wstringop-overread
  |  ^

even without -Wall.  strncmp sees that a[3] is '\0' so it stops comparing
and there's no UB.

GCC 11 didn't emit that, so +1 for dialing this warning down.

> > I haven't seen these so I can't very well comment on them.  But I can
> > assure you that warning for the code above is intentional.  Whether
> > or not the arrays are nul-terminated, the expected way to call
> > the function is with a bound no greater than their size (some coding
> > guidelines are explicit about this; see for example the CERT C Secure
> > Coding standard rule ARR38-C).
> > 
> > (Granted, the manual makes it sound like -Wstringop-overread only
> > detects provable past-the-end reads.  That's a mistake in
> > the documentation that should be fixed.  The warning was never quite
> > so limited, nor was it intended to be.)
> 
> The contention is not that it's not provable, it's more that it's doesn't
> even pass the "based on available information this is definitely buggy"
> assertion, making it more a strong suggestion than a warning that something
> is definitely amiss.  Which is why IMO it is more suitable as an analyzer
> check than a warning.
> 
> Thanks,
> Siddhesh
> 

Marek



[PATCH] c++: alias template and empty parameter packs [PR104008]

2022-03-16 Thread Marek Polacek via Gcc-patches
Zero-length pack expansions are treated as if no list were provided
at all, that is, with

  template struct S { };
  template
  void g() {
S...>;
  }

g will result in S<>.  In the following test we have something
similar:

  template 
  using IsOneOf = disjunction...>;

and then we have "IsOneOf..." where OtherHolders is an
empty pack.  Since r11-7931, we strip_typedefs in TYPE_PACK_EXPANSION.
In this test that results in "IsOneOf" being turned into
"disjunction<>".  So the whole expansion is now "disjunction<>...".  But
then we error in make_pack_expansion because find_parameter_packs_r won't
find the pack OtherHolders.

We strip the alias template because dependent_alias_template_spec_p says
it's not dependent.  It it not dependent because this alias is not
TEMPLATE_DECL_COMPLEX_ALIAS_P.  My understanding is that currently we
consider an alias complex if it

1) expands a pack from the enclosing class, as in

template typename... TT>
struct S {
  template
  using X = P...>;
};

   where the alias expands TT; or

2) the expansion does *not* name all the template parameters, as in

template struct R;
template
using U = R...>;

   where T is not named in the expansion.

But IsOneOf is neither.  And it can't know how it's going to be used.
Therefore I think we cannot make it complex (and in turn dependent) to fix
this bug.

After much gnashing of teeth, I think we simply want to avoid stripping
the alias if the new pattern doesn't have any parameter packs to expand.

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

PR c++/104008

gcc/cp/ChangeLog:

* tree.cc (strip_typedefs): Don't strip an alias template when
doing so would result in losing a parameter pack.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/variadic-alias3.C: New test.
* g++.dg/cpp0x/variadic-alias4.C: New test.
---
 gcc/cp/tree.cc   | 13 +-
 gcc/testsuite/g++.dg/cpp0x/variadic-alias3.C | 45 ++
 gcc/testsuite/g++.dg/cpp0x/variadic-alias4.C | 48 
 3 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-alias3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-alias4.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 6e9be713c51..eb59e56610b 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -1778,7 +1778,18 @@ strip_typedefs (tree t, bool *remove_attributes, 
unsigned int flags)
if (TYPE_P (pat))
  {
type = strip_typedefs (pat, remove_attributes, flags);
-   if (type != pat)
+   /* Empty packs can thwart our efforts here.  Consider
+
+   template 
+   using IsOneOf = disjunction...>;
+
+ where IsOneOf seemingly uses all of its template parameters in
+ its expansion (and does not expand a pack from the enclosing
+ class), so the alias is not marked as complex.  However, it may
+ be used as in "IsOneOf", where Ts is an empty parameter pack,
+ and stripping it down into "disjunction<>" here would exclude the
+ Ts pack, resulting in an error.  */
+   if (type != pat && uses_parameter_packs (type))
  {
result = copy_node (t);
PACK_EXPANSION_PATTERN (result) = type;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-alias3.C 
b/gcc/testsuite/g++.dg/cpp0x/variadic-alias3.C
new file mode 100644
index 000..6b6dd9f4c85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-alias3.C
@@ -0,0 +1,45 @@
+// PR c++/104008
+// { dg-do compile { target c++11 } }
+
+template  struct conjunction;
+template  struct disjunction;
+template  struct is_same;
+template  struct enable_if;
+template  using enable_if_t = typename enable_if<_Cond>::type;
+struct B;
+struct __uniq_ptr_impl {
+  struct _Ptr {
+using type = B *;
+  };
+  using pointer = _Ptr::type;
+};
+struct unique_ptr {
+  using pointer = __uniq_ptr_impl::pointer;
+  unique_ptr(pointer);
+};
+template 
+using IsOneOf = disjunction...>;
+
+template  struct any_badge;
+
+struct badge {
+  badge(any_badge<>);
+  badge();
+};
+
+template  struct any_badge {
+  template ...>::value>>
+  any_badge();
+};
+
+template  unique_ptr make_unique(_Args... __args);
+
+struct B {
+  B(badge);
+  unique_ptr b_ = make_unique(badge{});
+};
+
+template  unique_ptr make_unique(_Args... __args) 
{
+  return new B(__args...);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-alias4.C 
b/gcc/testsuite/g++.dg/cpp0x/variadic-alias4.C
new file mode 100644
index 000..896a4725627
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-alias4.C
@@ -0,0 +1,48 @@
+// PR c++/104008
+// { dg-do compile { target c++11 } }
+// Differs from variadic-alias3.C only in the pattern of a pack expansion
+// in line 34.  But it's important to check that we also deal with more
+// complex patterns.
+
+template  struct conjunctio

<    3   4   5   6   7   8   9   10   11   12   >