Re: [PATCH v2 1/2] c++: overeager type completion in convert_to_void [PR111419]

2023-09-18 Thread Jason Merrill via Gcc-patches

On 9/18/23 12:19, Patrick Palka wrote:

On Mon, 18 Sep 2023, Patrick Palka wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

Here convert_to_void always completes the type of an indirection or
id-expression, but according to [expr.context] an lvalue-to-rvalue
conversion is applied to a discarded-value expression only if "the
expression is a glvalue of volatile-qualified type".  This patch
restricts convert_to_void's type completion to match.

PR c++/111419

gcc/cp/ChangeLog:

* cvt.cc (convert_to_void) : Only call
complete_type if the type is volatile.
: Only call complete_type if the type is volatile.
Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-requires36.C: New test.
* g++.dg/expr/discarded1.C: New test.
* g++.dg/expr/discarded1a.C: New test.
---
  gcc/cp/cvt.cc   | 10 ++
  .../g++.dg/cpp2a/concepts-requires36.C  | 16 
  gcc/testsuite/g++.dg/expr/discarded1.C  | 15 +++
  gcc/testsuite/g++.dg/expr/discarded1a.C | 17 +
  4 files changed, 54 insertions(+), 4 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C
  create mode 100644 gcc/testsuite/g++.dg/expr/discarded1.C
  create mode 100644 gcc/testsuite/g++.dg/expr/discarded1a.C

diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index c6b52f07050..4424670356c 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1250,9 +1250,10 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
  case INDIRECT_REF:
{
tree type = TREE_TYPE (expr);
-   int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0)));


Oops, this removal of is_reference should happen in the follow-up patch
instead, consider that fixed.


OK with that fixed.


int is_volatile = TYPE_VOLATILE (type);
-   int is_complete = COMPLETE_TYPE_P (complete_type (type));
+   if (is_volatile)
+ complete_type (type);
+   int is_complete = COMPLETE_TYPE_P (type);
  
  	/* Can't load the value if we don't know the type.  */

if (is_volatile && !is_complete)
@@ -1412,9 +1413,10 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
{
/* External variables might be incomplete.  */
tree type = TREE_TYPE (expr);
-   int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
-	if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning))

+   if (TYPE_VOLATILE (type)
+   && !COMPLETE_TYPE_P (complete_type (type))
+   && (complain & tf_warning))
  switch (implicit)
{
  case ICV_CAST:
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C
new file mode 100644
index 000..8d3a4fcd2aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C
@@ -0,0 +1,16 @@
+// PR c++/111419
+// { dg-do compile { target c++20 } }
+
+template
+concept invocable = requires(F& f) { f(); };
+
+template
+concept deref_invocable = requires(F& f) { *f(); };
+
+struct Incomplete;
+
+template
+struct Holder { T t; };
+
+static_assert(invocable& ()>);
+static_assert(deref_invocable* ()>);
diff --git a/gcc/testsuite/g++.dg/expr/discarded1.C 
b/gcc/testsuite/g++.dg/expr/discarded1.C
new file mode 100644
index 000..c0c22e9e95b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/discarded1.C
@@ -0,0 +1,15 @@
+// PR c++/111419
+
+struct Incomplete;
+
+template struct Holder { T t; }; // { dg-bogus "incomplete" }
+
+extern Holder a;
+extern Holder& b;
+extern Holder* c;
+
+int main() {
+  a;
+  b;
+  *c;
+}
diff --git a/gcc/testsuite/g++.dg/expr/discarded1a.C 
b/gcc/testsuite/g++.dg/expr/discarded1a.C
new file mode 100644
index 000..1c4dff4553e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/discarded1a.C
@@ -0,0 +1,17 @@
+// A version of discarded1.C using volatile types.
+// PR c++/111419
+
+struct Incomplete;
+
+template struct Holder { T t; }; // { dg-error "incomplete" }
+
+extern volatile Holder a;
+extern volatile Holder& b;
+extern volatile Holder* c;
+
+int main() {
+  a; // { dg-message "required from here" }
+  b; // { dg-message "required from here" }
+  // { dg-warning "implicit dereference will not access object" "" { target 
*-*-* } .-1 }
+  *c; // { dg-message "required from here" }
+}
--
2.42.0.216.gbda494f404








Re: [PATCH v2 2/2] c++: convert_to_void and volatile references

2023-09-18 Thread Jason Merrill via Gcc-patches

On 9/18/23 12:12, Patrick Palka wrote:

Jason pointed out that even implicit loads of volatile references need
to undergo lvalue-to-rvalue conversion, but we currently emit a warning
in this case and discard the load.  This patch changes this behavior so
that we don't issue a warning, and preserve the load.

gcc/cp/ChangeLog:

* cvt.cc (convert_to_void) : Remove warning
for an implicit load of a volatile reference.  Simplify as if
is_reference is false.  Check REFERENCE_REF_P in the test
guarding the -Wunused-value diagnostic.

gcc/testsuite/ChangeLog:

* g++.dg/expr/discarded1a.C: No longer expect warning for
implicit load of a volatile reference.
* g++.old-deja/g++.bugs/900428_01.C: Likewise.
* g++.dg/expr/volatile2.C: New test.
---
  gcc/cp/cvt.cc | 56 ++-
  gcc/testsuite/g++.dg/expr/discarded1a.C   |  1 -
  gcc/testsuite/g++.dg/expr/volatile2.C | 12 
  .../g++.old-deja/g++.bugs/900428_01.C | 26 -
  4 files changed, 30 insertions(+), 65 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/expr/volatile2.C

diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index 4424670356c..1cb6c1222c2 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1251,12 +1251,9 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
{
tree type = TREE_TYPE (expr);
int is_volatile = TYPE_VOLATILE (type);
-   if (is_volatile)
- complete_type (type);
-   int is_complete = COMPLETE_TYPE_P (type);
  
  	/* Can't load the value if we don't know the type.  */

-   if (is_volatile && !is_complete)
+   if (is_volatile && !COMPLETE_TYPE_P (complete_type (type)))
{
  if (complain & tf_warning)
  switch (implicit)
@@ -1298,50 +1295,7 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
gcc_unreachable ();
}
}
-   /* Don't load the value if this is an implicit dereference, or if
-  the type needs to be handled by ctors/dtors.  */
-   else if (is_volatile && is_reference)
-  {
-if (complain & tf_warning)
- switch (implicit)
-   {
- case ICV_CAST:
-   warning_at (loc, 0, "conversion to void will not access "
-   "object of type %qT", type);
-   break;
- case ICV_SECOND_OF_COND:
-   warning_at (loc, 0, "implicit dereference will not access "
-   "object of type %qT in second operand of "
-   "conditional expression", type);
-   break;
- case ICV_THIRD_OF_COND:
-   warning_at (loc, 0, "implicit dereference will not access "
-   "object of type %qT in third operand of "
-   "conditional expression", type);
-   break;
- case ICV_RIGHT_OF_COMMA:
-   warning_at (loc, 0, "implicit dereference will not access "
-   "object of type %qT in right operand of "
-   "comma operator", type);
-   break;
- case ICV_LEFT_OF_COMMA:
-   warning_at (loc, 0, "implicit dereference will not access "
-   "object of type %qT in left operand of comma "
-   "operator", type);
-   break;
- case ICV_STATEMENT:
-   warning_at (loc, 0, "implicit dereference will not access "
-   "object of type %qT in statement",  type);
-break;
- case ICV_THIRD_IN_FOR:
-   warning_at (loc, 0, "implicit dereference will not access "
-   "object of type %qT in for increment 
expression",
-   type);
-   break;
- default:
-   gcc_unreachable ();
-   }
-  }
+   /* Don't load the value if the type needs to be handled by cdtors.  */
else if (is_volatile && TREE_ADDRESSABLE (type))
  {
if (complain & tf_warning)
@@ -1386,7 +1340,7 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
gcc_unreachable ();
}
  }
-   if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE 
(type))
+   if (!is_volatile || !COMPLETE_TYPE_P (type))
{
  /* Emit a warning (if enabled) when the "effect-less" INDIRECT_REF
 operation is stripped off. Note that we don't warn about
@@ -1397,8 +1351,8 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t 

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

2023-09-18 Thread Jason Merrill via Gcc-patches

On 9/18/23 17:42, Marek Polacek wrote:

+  /* The purpose of this is not to emit errors for mce_unknown.  */
+  const tsubst_flags_t complain = (data->flags == ff_fold_immediate
+  ? tf_none : tf_error);


Maybe check flags & ff_mce_false, instead?  OK with that change.

Thanks,
Jason



Re: [PATCH] c++: optimize tsubst_template_decl for function templates

2023-09-18 Thread Jason Merrill via Gcc-patches

On 9/18/23 08:58, Patrick Palka wrote:

On Sun, 17 Sep 2023, Jason Merrill wrote:


On 9/17/23 15:13, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

r14-2655-g92d1425ca78040 made instantiate_template avoid redundantly
performing a specialization lookup when instantiating a function or
alias template.  This patch applies the same optimization to
tsubst_template_decl when (partially) instantiating a function template,
which allows us to remove a check from register_specialization since
tsubst_function_decl no longer calls register_specialization for
a function template partial instantiation.

gcc/cp/ChangeLog:

* pt.cc (register_specialization): Remove now-unnecessary
early exit for FUNCTION_DECL partial instantiation.
(tsubst_template_decl): Pass use_spec_table=false to
tsubst_function_decl.  Set DECL_TI_ARGS of a non-lambda
FUNCTION_DECL specialization to the full set of arguments.
Simplify register_specialization call accordingly.

gcc/testsuite/ChangeLog:

* g++.dg/template/nontype12.C: Expect two instead of three
duplicate diagnostics for A::bar() specialization.
---
   gcc/cp/pt.cc  | 29 +++
   gcc/testsuite/g++.dg/template/nontype12.C |  1 -
   2 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c311a6b88f5..a0296a1ea16 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1507,21 +1507,6 @@ register_specialization (tree spec, tree tmpl, tree
args, bool is_friend,
  || (TREE_CODE (tmpl) == FIELD_DECL
  && TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK));
   -  if (TREE_CODE (spec) == FUNCTION_DECL
-  && uses_template_parms (DECL_TI_ARGS (spec)))
-/* This is the FUNCTION_DECL for a partial instantiation.  Don't
-   register it; we want the corresponding TEMPLATE_DECL instead.
-   We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than
-   the more obvious `uses_template_parms (spec)' to avoid problems
-   with default function arguments.  In particular, given
-   something like this:
-
- template  void f(T t1, T t = T())
-
-   the default argument expression is not substituted for in an
-   instantiation unless and until it is actually needed.  */
-return spec;
-
 spec_entry elt;
 elt.tmpl = tmpl;
 elt.args = args;
@@ -14663,7 +14648,7 @@ tsubst_template_decl (tree t, tree args,
tsubst_flags_t complain,
 tree in_decl = t;
 tree spec;
 tree tmpl_args;
-  tree full_args;
+  tree full_args = NULL_TREE;
 tree r;
 hashval_t hash = 0;
   @@ -14754,7 +14739,8 @@ tsubst_template_decl (tree t, tree args,
tsubst_flags_t complain,
 tree inner = decl;
 ++processing_template_decl;
 if (TREE_CODE (inner) == FUNCTION_DECL)
-inner = tsubst_function_decl (inner, args, complain, lambda_fntype);
+inner = tsubst_function_decl (inner, args, complain, lambda_fntype,
+ /*use_spec_table=*/false);
 else
   {
 if (TREE_CODE (inner) == TYPE_DECL && !TYPE_DECL_ALIAS_P (inner))
@@ -14792,6 +14778,11 @@ tsubst_template_decl (tree t, tree args,
tsubst_flags_t complain,
   }
 else
   {
+  if (TREE_CODE (inner) == FUNCTION_DECL)
+   /* Set DECL_TI_ARGS to the full set of template arguments, which
+  tsubst_function_decl didn't do due to use_spec_table=false.  */
+   DECL_TI_ARGS (inner) = full_args;
+
 DECL_TI_TEMPLATE (inner) = r;
 DECL_TI_ARGS (r) = DECL_TI_ARGS (inner);
   }
@@ -14822,9 +14813,7 @@ tsubst_template_decl (tree t, tree args,
tsubst_flags_t complain,
   if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype)
   /* Record this non-type partial instantiation.  */
-register_specialization (r, t,
-DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
-false, hash);
+register_specialization (r, t, full_args, false, hash);
   return r;
   }
diff --git a/gcc/testsuite/g++.dg/template/nontype12.C
b/gcc/testsuite/g++.dg/template/nontype12.C
index 9a9c3ac1e66..e36a9f16f94 100644
--- a/gcc/testsuite/g++.dg/template/nontype12.C
+++ b/gcc/testsuite/g++.dg/template/nontype12.C
@@ -5,7 +5,6 @@ template struct A
   {
 template int foo();// { dg-error "double" ""
{ target c++17_down } }
 template class> int bar();// { dg-bogus
{double[^\n]*\n[^\n]*C:7:[^\n]*double} "" { xfail c++17_down } }
-  // { dg-error "double" "" { target c++17_down } .-1 }


Hmm, I thought this line was to check that we get one error even if we don't
want two?


The xfailed dg-bogus directive seems to "consume" the two errors, and
prevents the dg-error from matching either of them.  Before this patch,
we issued three duplicate errors and so this arrangement worked out
since the xfailed dg-bogus consumes only two of 

Re: [PATCH] c++: non-dependent assignment checking [PR63198, PR18474]

2023-09-18 Thread Jason Merrill via Gcc-patches

On 9/18/23 09:12, Patrick Palka wrote:

On Sun, 17 Sep 2023, Jason Merrill wrote:


On 9/17/23 14:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  Patch generatde with -w to avoid noisy whitespace changes.

-- >8 --

This patch makes us recognize and check non-dependent simple assigments
ahead of time, like we already do for compound assignments.  This means
the templated representation of such assignments will now usually have
an implicit INDIRECT_REF (due to the reference return type), which the
-Wparentheses code needs to handle.  As a drive-by improvement, this
patch also makes maybe_convert_cond issue -Wparentheses warnings ahead
of time.

This revealed some libstdc++ tests were attempting to modify a data
member from a uninstantiated const member function; naively fixed by
making the data member mutable.

PR c++/63198
PR c++/18474

gcc/cp/ChangeLog:

* semantics.cc (maybe_convert_cond): Look through implicit
INDIRECT_REF when deciding whether to issue a -Wparentheses
warning, and consider templated assignment expressions as well.
(finish_parenthesized_expr): Look through implicit INDIRECT_REF
when suppressing -Wparentheses warning.
* typeck.cc (build_x_modify_expr): Check simple assignments
ahead time too, not just compound assignments.  Give the second
operand of MODOP_EXPR a non-null type so that it's not considered
always instantiation-dependent.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/static_assert15.C: Expect diagnostic for
non-constant static_assert condition.
* g++.dg/expr/unary2.C: Remove xfails.
* g++.dg/template/init7.C: Make initializer type-dependent to
preserve intent of test.
* g++.dg/template/recurse3.C: Likewise for the erroneous
statement.
* g++.dg/template/non-dependent26.C: New test.
* g++.dg/warn/Wparentheses-32.C: New test.

libstdc++/ChangeLog:

* testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc:
Make seed_seq::called member mutable.
*
testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc:
Likewise.
*
testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc
Likewise.
*
testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc:
Likewise.
* testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc:
Likewise.
*
testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc:
Likewise.
*
testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc
Likewise.
---
   gcc/cp/semantics.cc   | 17 +++
   gcc/cp/typeck.cc  | 23 +++
   gcc/testsuite/g++.dg/cpp0x/static_assert15.C  |  2 +-
   gcc/testsuite/g++.dg/expr/unary2.C|  8 ++
   gcc/testsuite/g++.dg/template/init7.C |  2 +-
   .../g++.dg/template/non-dependent26.C | 25 +
   gcc/testsuite/g++.dg/template/recurse3.C  |  8 +++---
   gcc/testsuite/g++.dg/warn/Wparentheses-32.C   | 28 +++
   .../discard_block_engine/cons/seed_seq2.cc|  2 +-
   .../independent_bits_engine/cons/seed_seq2.cc |  2 +-
   .../cons/seed_seq2.cc |  2 +-
   .../mersenne_twister_engine/cons/seed_seq2.cc |  2 +-
   .../shuffle_order_engine/cons/seed_seq2.cc|  2 +-
   .../cons/seed_seq2.cc |  2 +-
   .../cons/seed_seq2.cc |  2 +-
   15 files changed, 91 insertions(+), 36 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/template/non-dependent26.C
   create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-32.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 0f7f4e87ae4..b57c1ac868b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 459739d5866..74f5fced060 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9739,15 +9739,15 @@ build_x_modify_expr (location_t loc, tree lhs, enum
tree_code modifycode,
 rhs = build_non_dependent_expr (rhs);
   }
   -  if (modifycode != NOP_EXPR)
-{
-  tree op = build_nt (modifycode, NULL_TREE, NULL_TREE);
-  tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
+  tree rval;
+  if (modifycode == NOP_EXPR)
+rval = cp_build_modify_expr (loc, lhs, modifycode, rhs, complain);
+  else
+rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
 lhs, rhs, op, lookups, , complain);
-  if (rval)
-   {
 if (rval == error_mark_node)
-   return rval;
+return error_mark_node;
+  if (modifycode != NOP_EXPR)
   suppress_warning (rval /* What warning? */);


Did you try disabling this to see if it's still needed?


Looks like it's not needed 

[pushed] doc: GTY((cache)) documentation tweak

2023-09-17 Thread Jason Merrill via Gcc-patches
Applying to trunk as obvious (explaining existing behavior).

-- 8< --

gcc/ChangeLog:

* doc/gty.texi: Add discussion of cache vs. deletable.
---
 gcc/doc/gty.texi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 15f9fa07405..1dfe4652644 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -306,6 +306,13 @@ called on that variable between the mark and sweep phases 
of garbage
 collection.  The gt_clear_cache function is free to mark blocks as used, or to
 clear pointers in the variable.
 
+In a hash table, the @samp{gt_cleare_cache} function discards entries
+if the key is not marked, or marks the value if the key is marked.
+
+Note that caches should generally use @code{deletable} instead;
+@code{cache} is only preferable if the value is impractical to
+recompute from the key when needed.
+
 @findex deletable
 @item deletable
 

base-commit: 68845f7c4d58186cc0a5b09f7511f3c0a8f07e88
-- 
2.39.3



Re: [pushed] c++: [[no_unique_address]] and cv-qualified type

2023-09-17 Thread Jason Merrill via Gcc-patches

On 9/5/23 23:19, Jason Merrill wrote:

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

-- 8< --

We were checking for overlap using same_type_p and therefore allocating two
Empty subobjects at the same offset because one was cv-qualified.

This gives the warning at the location of the class name rather than the
member declaration, but this should be a rare enough issue that it doesn't
seem worth trying to be more precise.


The ABI and language seem to be settling on referring to "similar types" 
here rather than same ignoring top-level cv-qualifiers.


Tested x86_64-pc-linux-gnu, applying to trunk.
From 3f65c1dc56f3a6dd4be85a064d0023b7be3fcd8a Mon Sep 17 00:00:00 2001
From: Jason Merrill 
Date: Tue, 12 Sep 2023 12:15:13 -0400
Subject: [PATCH] c++: overlapping subobjects tweak
To: gcc-patches@gcc.gnu.org

The ABI is settling on "similar" for this rule.

gcc/cp/ChangeLog:

	* class.cc (check_subobject_offset): Use similar_type_p.
---
 gcc/cp/class.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 9139a0075ab..d270dcbb14c 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -4065,7 +4065,7 @@ check_subobject_offset (tree type, tree offset, splay_tree offsets)
 	return 1;
 
   if (cv_check != ignore
-	  && same_type_ignoring_top_level_qualifiers_p (elt, type))
+	  && similar_type_p (elt, type))
 	{
 	  if (cv_check == fast)
 	return 1;
-- 
2.39.3



Re: [PATCH] c++: non-dependent assignment checking [PR63198, PR18474]

2023-09-17 Thread Jason Merrill via Gcc-patches

On 9/17/23 14:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  Patch generatde with -w to avoid noisy whitespace changes.

-- >8 --

This patch makes us recognize and check non-dependent simple assigments
ahead of time, like we already do for compound assignments.  This means
the templated representation of such assignments will now usually have
an implicit INDIRECT_REF (due to the reference return type), which the
-Wparentheses code needs to handle.  As a drive-by improvement, this
patch also makes maybe_convert_cond issue -Wparentheses warnings ahead
of time.

This revealed some libstdc++ tests were attempting to modify a data
member from a uninstantiated const member function; naively fixed by
making the data member mutable.

PR c++/63198
PR c++/18474

gcc/cp/ChangeLog:

* semantics.cc (maybe_convert_cond): Look through implicit
INDIRECT_REF when deciding whether to issue a -Wparentheses
warning, and consider templated assignment expressions as well.
(finish_parenthesized_expr): Look through implicit INDIRECT_REF
when suppressing -Wparentheses warning.
* typeck.cc (build_x_modify_expr): Check simple assignments
ahead time too, not just compound assignments.  Give the second
operand of MODOP_EXPR a non-null type so that it's not considered
always instantiation-dependent.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/static_assert15.C: Expect diagnostic for
non-constant static_assert condition.
* g++.dg/expr/unary2.C: Remove xfails.
* g++.dg/template/init7.C: Make initializer type-dependent to
preserve intent of test.
* g++.dg/template/recurse3.C: Likewise for the erroneous
statement.
* g++.dg/template/non-dependent26.C: New test.
* g++.dg/warn/Wparentheses-32.C: New test.

libstdc++/ChangeLog:

* testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc:
Make seed_seq::called member mutable.
* 
testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc:
Likewise.
* 
testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc
Likewise.
* 
testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc:
Likewise.
* testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc:
Likewise.
* 
testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc:
Likewise.
* 
testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc
Likewise.
---
  gcc/cp/semantics.cc   | 17 +++
  gcc/cp/typeck.cc  | 23 +++
  gcc/testsuite/g++.dg/cpp0x/static_assert15.C  |  2 +-
  gcc/testsuite/g++.dg/expr/unary2.C|  8 ++
  gcc/testsuite/g++.dg/template/init7.C |  2 +-
  .../g++.dg/template/non-dependent26.C | 25 +
  gcc/testsuite/g++.dg/template/recurse3.C  |  8 +++---
  gcc/testsuite/g++.dg/warn/Wparentheses-32.C   | 28 +++
  .../discard_block_engine/cons/seed_seq2.cc|  2 +-
  .../independent_bits_engine/cons/seed_seq2.cc |  2 +-
  .../cons/seed_seq2.cc |  2 +-
  .../mersenne_twister_engine/cons/seed_seq2.cc |  2 +-
  .../shuffle_order_engine/cons/seed_seq2.cc|  2 +-
  .../cons/seed_seq2.cc |  2 +-
  .../cons/seed_seq2.cc |  2 +-
  15 files changed, 91 insertions(+), 36 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/template/non-dependent26.C
  create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-32.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 0f7f4e87ae4..b57c1ac868b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 459739d5866..74f5fced060 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9739,15 +9739,15 @@ build_x_modify_expr (location_t loc, tree lhs, enum 
tree_code modifycode,
rhs = build_non_dependent_expr (rhs);
  }
  
-  if (modifycode != NOP_EXPR)

-{
-  tree op = build_nt (modifycode, NULL_TREE, NULL_TREE);
-  tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
+  tree rval;
+  if (modifycode == NOP_EXPR)
+rval = cp_build_modify_expr (loc, lhs, modifycode, rhs, complain);
+  else
+rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
 lhs, rhs, op, lookups, , complain);
-  if (rval)
-   {
if (rval == error_mark_node)
-   return rval;
+return error_mark_node;
+  if (modifycode != NOP_EXPR)
  suppress_warning (rval /* What warning? */);


Did you try disabling this to see if it's still needed?

Jason



Re: [PATCH] c++: optimize tsubst_template_decl for function templates

2023-09-17 Thread Jason Merrill via Gcc-patches

On 9/17/23 15:13, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

r14-2655-g92d1425ca78040 made instantiate_template avoid redundantly
performing a specialization lookup when instantiating a function or
alias template.  This patch applies the same optimization to
tsubst_template_decl when (partially) instantiating a function template,
which allows us to remove a check from register_specialization since
tsubst_function_decl no longer calls register_specialization for
a function template partial instantiation.

gcc/cp/ChangeLog:

* pt.cc (register_specialization): Remove now-unnecessary
early exit for FUNCTION_DECL partial instantiation.
(tsubst_template_decl): Pass use_spec_table=false to
tsubst_function_decl.  Set DECL_TI_ARGS of a non-lambda
FUNCTION_DECL specialization to the full set of arguments.
Simplify register_specialization call accordingly.

gcc/testsuite/ChangeLog:

* g++.dg/template/nontype12.C: Expect two instead of three
duplicate diagnostics for A::bar() specialization.
---
  gcc/cp/pt.cc  | 29 +++
  gcc/testsuite/g++.dg/template/nontype12.C |  1 -
  2 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c311a6b88f5..a0296a1ea16 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1507,21 +1507,6 @@ register_specialization (tree spec, tree tmpl, tree 
args, bool is_friend,
  || (TREE_CODE (tmpl) == FIELD_DECL
  && TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK));
  
-  if (TREE_CODE (spec) == FUNCTION_DECL

-  && uses_template_parms (DECL_TI_ARGS (spec)))
-/* This is the FUNCTION_DECL for a partial instantiation.  Don't
-   register it; we want the corresponding TEMPLATE_DECL instead.
-   We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than
-   the more obvious `uses_template_parms (spec)' to avoid problems
-   with default function arguments.  In particular, given
-   something like this:
-
- template  void f(T t1, T t = T())
-
-   the default argument expression is not substituted for in an
-   instantiation unless and until it is actually needed.  */
-return spec;
-
spec_entry elt;
elt.tmpl = tmpl;
elt.args = args;
@@ -14663,7 +14648,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t 
complain,
tree in_decl = t;
tree spec;
tree tmpl_args;
-  tree full_args;
+  tree full_args = NULL_TREE;
tree r;
hashval_t hash = 0;
  
@@ -14754,7 +14739,8 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,

tree inner = decl;
++processing_template_decl;
if (TREE_CODE (inner) == FUNCTION_DECL)
-inner = tsubst_function_decl (inner, args, complain, lambda_fntype);
+inner = tsubst_function_decl (inner, args, complain, lambda_fntype,
+ /*use_spec_table=*/false);
else
  {
if (TREE_CODE (inner) == TYPE_DECL && !TYPE_DECL_ALIAS_P (inner))
@@ -14792,6 +14778,11 @@ tsubst_template_decl (tree t, tree args, 
tsubst_flags_t complain,
  }
else
  {
+  if (TREE_CODE (inner) == FUNCTION_DECL)
+   /* Set DECL_TI_ARGS to the full set of template arguments, which
+  tsubst_function_decl didn't do due to use_spec_table=false.  */
+   DECL_TI_ARGS (inner) = full_args;
+
DECL_TI_TEMPLATE (inner) = r;
DECL_TI_ARGS (r) = DECL_TI_ARGS (inner);
  }
@@ -14822,9 +14813,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t 
complain,
  
if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype)

  /* Record this non-type partial instantiation.  */
-register_specialization (r, t,
-DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
-false, hash);
+register_specialization (r, t, full_args, false, hash);
  
return r;

  }
diff --git a/gcc/testsuite/g++.dg/template/nontype12.C 
b/gcc/testsuite/g++.dg/template/nontype12.C
index 9a9c3ac1e66..e36a9f16f94 100644
--- a/gcc/testsuite/g++.dg/template/nontype12.C
+++ b/gcc/testsuite/g++.dg/template/nontype12.C
@@ -5,7 +5,6 @@ template struct A
  {
template int foo();// { dg-error "double" "" { 
target c++17_down } }
template class> int bar();// { dg-bogus 
{double[^\n]*\n[^\n]*C:7:[^\n]*double} "" { xfail c++17_down } }
-  // { dg-error "double" "" { target c++17_down } .-1 }


Hmm, I thought this line was to check that we get one error even if we 
don't want two?


Jason



Re: [PATCH] c++: constness of decltype of NTTP object [PR98820]

2023-09-17 Thread Jason Merrill via Gcc-patches

On 9/16/23 18:00, Patrick Palka wrote:

On Sat, 16 Sep 2023, Jason Merrill wrote:


On 9/15/23 13:55, Patrick Palka wrote:

This corrects decltype of a (class) NTTP object as per
[dcl.type.decltype]/1.2 and [temp.param]/6 in the type-dependent case.
In the non-dependent case (nontype-class8.C) we resolve the decltype
ahead of time, and finish_decltype_type already made sure to drop the
const VIEW_CONVERT_EXPR wrapper around the TEMPLATE_PARM_INDEX.


Hmm, seems like dropping the VIEW_CONVERT_EXPR is wrong in this case? I'm not
sure why I added that.


Ah sorry, my commit message was a bit sloppy.

In the non-dependent case we resolve the decltype ahead of time, in
which case finish_decltype_type drops the const VIEW_CONVERT_EXPR
wrapper around the TEMPLATE_PARM_INDEX, and the latter has the
desired non-const type.

In the type-dependent case, tsubst drops the VIEW_CONVERT_EXPR
because the substituted class NTTP is the already const object
created by get_template_parm_object.  So finish_decltype_type
at instantiation time sees the bare const object, which this patch
now adds special handling for.

So we need to continue dropping the VIEW_CONVERT_EXPR to handle the
non-dependent case.


Aha.  The patch is OK, then.

Jason



Re: [PATCH] c++: overeager type completion in convert_to_void [PR111419]

2023-09-17 Thread Jason Merrill via Gcc-patches

On 9/16/23 17:41, Patrick Palka wrote:

On Sat, 16 Sep 2023, Jason Merrill wrote:


On 9/15/23 12:03, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

Here convert_to_void always completes the type of an INDIRECT_REF or
VAR_DECL expression, but according to [expr.context] an lvalue-to-rvalue
conversion is applied to a discarded-value expression only if "the
expression is a glvalue of volatile-qualified type".  This patch restricts
convert_to_void's type completion accordingly.

PR c++/111419

gcc/cp/ChangeLog:

* cvt.cc (convert_to_void) : Only call
complete_type if the type is volatile and the INDIRECT_REF
isn't an implicit one.


Hmm, what does implicit have to do with it?  The expression forms listed in
https://eel.is/c++draft/expr.context#2 include "id-expression"...


When there's an implicit INDIRECT_REF, I reckoned the type of the
id-expression is really a reference type, which can't be cv-qualified?


A name can have reference type, but its use as an expression doesn't:
https://eel.is/c++draft/expr.type#1.sentence-1


diff --git a/gcc/testsuite/g++.dg/expr/discarded1a.C
b/gcc/testsuite/g++.dg/expr/discarded1a.C
new file mode 100644
index 000..5516ff46fe9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/discarded1a.C
@@ -0,0 +1,16 @@
+// PR c++/111419
+
+struct Incomplete;
+
+template struct Holder { T t; }; // { dg-error "incomplete" }
+
+extern volatile Holder a;
+extern volatile Holder& b;
+extern volatile Holder* c;
+
+int main() {
+  a; // { dg-message "required from here" }
+  b; // { dg-warning "implicit dereference will not access object" }
+ // { dg-bogus "required from here" "" { target *-*-* } .-1 }


...so it seems to me this line should get the lvalue-rvalue conversion (and
not the warning about no access).


+  *c; // { dg-message "required from here" }
+}




Re: [PATCH] c++: always check arity before deduction

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/12/23 20:33, Patrick Palka wrote:

Bootstrpaped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


OK.


-- >8 --

This simple patch extends the r12-3271-gf1e73199569287 optimization
to apply to deduction without explicit template arguments as well.
The motivation for this is to accept testcases such as conv20.C and
ttp40.C below, which don't use explicit template arguments but for which
unnecessary template instantiation during deduction could be avoided if
we pruned overloads according to arity early in this case as well.  This
incidentally causes us to accept one reduced testcase from PR c++/84075,
but the underlying issue there still remains unfixed.

As an added bonus, this change ends up causing the "candidate expects
N argument(s)" note during overload resolution failure to point to the
template candidate instead of the call site, which seems like an
improvement similar to r14-309-g14e881eb030509.

gcc/cp/ChangeLog:

* call.cc (add_template_candidate_real): Check arity even
when there are no explicit template arguments.  Combine the
two adjacent '!obj' tests into one.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/vt-57397-1.C: Expect "candidate expects ... N
argument(s)" at the declaration site instead of the call site.
* g++.dg/cpp0x/vt-57397-2.C: Likewise.
* g++.dg/overload/template5.C: Likewise.
* g++.dg/template/local6.C: Likewise.
* g++.dg/template/conv20.C: New test.
* g++.dg/template/ttp40.C: New test.
---
  gcc/cp/call.cc| 14 ++---
  gcc/testsuite/g++.dg/cpp0x/vt-57397-1.C   |  6 +++---
  gcc/testsuite/g++.dg/cpp0x/vt-57397-2.C   |  6 +++---
  gcc/testsuite/g++.dg/overload/template5.C |  4 ++--
  gcc/testsuite/g++.dg/template/conv20.C| 17 +++
  gcc/testsuite/g++.dg/template/local6.C|  4 ++--
  gcc/testsuite/g++.dg/template/ttp40.C | 25 +++
  7 files changed, 58 insertions(+), 18 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/template/conv20.C
  create mode 100644 gcc/testsuite/g++.dg/template/ttp40.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 399345307ea..2bbaeee039d 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -3535,13 +3535,13 @@ add_template_candidate_real (struct z_candidate 
**candidates, tree tmpl,
  }
gcc_assert (ia == nargs_without_in_chrg);
  
-  if (!obj && explicit_targs)

+  if (!obj)
  {
/* Check that there's no obvious arity mismatch before proceeding with
 deduction.  This avoids substituting explicit template arguments
-into the template (which could result in an error outside the
-immediate context) when the resulting candidate would be unviable
-anyway.  */
+into the template or e.g. derived-to-base parm/arg unification
+(which could result in an error outside the immediate context) when
+the resulting candidate would be unviable anyway.  */
int min_arity = 0, max_arity = 0;
tree parms = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
parms = skip_artificial_parms_for (tmpl, parms);
@@ -3571,11 +3571,7 @@ add_template_candidate_real (struct z_candidate 
**candidates, tree tmpl,
  reason = arity_rejection (NULL_TREE, max_arity, ia);
  goto fail;
}
-}
  
-  errs = errorcount+sorrycount;

-  if (!obj)
-{
convs = alloc_conversions (nargs);
  
if (shortcut_bad_convs

@@ -3602,6 +3598,8 @@ add_template_candidate_real (struct z_candidate 
**candidates, tree tmpl,
}
}
  }
+
+  errs = errorcount+sorrycount;
fn = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
nargs_without_in_chrg,
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-57397-1.C 
b/gcc/testsuite/g++.dg/cpp0x/vt-57397-1.C
index 440bea5b2f7..bac3b64ad7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-57397-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-57397-1.C
@@ -3,20 +3,20 @@
  
  template

  void foo(T1, Tn...);
+// { dg-message "candidate expects at least 1 argument, 0 provided" "" { 
target *-*-* } .-1 }
  
  template

  void bar(T1, T2, Tn...);
+// { dg-message "candidate expects at least 2 arguments, 0 provided" "" { 
target *-*-* } .-1 }
+// { dg-message "candidate expects at least 2 arguments, 1 provided" "" { 
target *-*-* } .-2 }
  
  int main()

  {
foo();   // { dg-error "no matching" }
-  // { dg-message "candidate expects at least 1 argument, 0 provided" "" { 
target *-*-* } .-1 }
foo(1);
foo(1, 2);
bar();   // { dg-error "no matching" }
-  // { dg-message "candidate expects at least 2 arguments, 0 provided" "" { 
target *-*-* } .-1 }
bar(1);  // { dg-error "no matching" }
-  // { dg-message "candidate expects at least 2 arguments, 1 provided" "" { 
target *-*-* } .-1 }
bar(1, 2);
bar(1, 2, 3);
  }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-57397-2.C 

Re: [PATCH] c++: unifying identical tmpls from current inst [PR108347]

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/13/23 13:53, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk?

-- >8 --

Here more_specialized_partial_spec considers the two partial
specializations to be unordered ultimately because unify for identical
parm=arg=A::C returns failure due to C being dependent.

This patch fixes this by relaxing unify's early-exit identity test to
also accept dependent decls; we can't deduce anything further from them
anyway.


OK.


In passing this patch removes the CONST_DECL case of unify:
we should never see the CONST_DECL version of a template parameter here,
and for other CONST_DECLs (such as enumerators) it seems we can rely on
them already having been folded to their DECL_INITIAL.


Hmm, I think I'd prefer to add a gcc_unreachable in case we decide to 
defer that folding at some point.


Jason



Re: [PATCH] c++: optimize unification of class specializations [PR89231]

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/13/23 13:53, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


OK.


-- >8 --

Since the LHS of a qualified-id is a non-deduced context, it effectively
means we can't deduce from outer template arguments of a class template
specialization.  And checking for equality between the TI_TEMPLATE of a
class specialization parm/arg already implies that the outer template
arguments are the same.  Hence recursing into outer template arguments
during unification of class specializations is redundant, so this patch
makes unify recurse only into innermost arguments.

This incidentally fixes the testcase from PR89231 because there
more_specialized_partial_inst considers the two partial specializations
to be unordered ultimately because unify for identical
parm=arg=A::Collect gets confused when it recurses into
parm=arg={Ps...} since the level of Ps doesn't match the innermost level
of tparms that we're actually deducing.

PR c++/89231

gcc/cp/ChangeLog:

* pt.cc (try_class_unification): Strengthen TI_TEMPLATE equality
test by not calling most_general_template.  Only unify the
innermost levels of template arguments.
(unify) : Only unify the innermost levels of
template arguments.  Don't unify template arguments if the
template is not primary.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/variadic-partial3.C: New test.
---
  gcc/cp/pt.cc  | 17 +++--
  .../g++.dg/cpp0x/variadic-partial3.C  | 19 +++
  2 files changed, 30 insertions(+), 6 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 838179d5fe3..c88e9cd0fa6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23999,8 +23999,7 @@ try_class_unification (tree tparms, tree targs, tree 
parm, tree arg,
  return NULL_TREE;
else if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
  /* Matches anything.  */;
-  else if (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
-  != most_general_template (CLASSTYPE_TI_TEMPLATE (parm)))
+  else if (CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
  return NULL_TREE;
  
/* We need to make a new template argument vector for the call to

@@ -24041,8 +24040,10 @@ try_class_unification (tree tparms, tree targs, tree 
parm, tree arg,
if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
  err = unify_bound_ttp_args (tparms, targs, parm, arg, explain_p);
else
-err = unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
-CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p);
+err = unify (tparms, targs,
+INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
+INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (arg)),
+UNIFY_ALLOW_NONE, explain_p);
  
return err ? NULL_TREE : arg;

  }
@@ -25167,11 +25168,15 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
/* There's no chance of unification succeeding.  */
return unify_type_mismatch (explain_p, parm, arg);
  
-	  return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),

-   CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p);
+ if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+   return unify (tparms, targs,
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (t)),
+ UNIFY_ALLOW_NONE, explain_p);
}
else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
return unify_type_mismatch (explain_p, parm, arg);
+
return unify_success (explain_p);
  
  case METHOD_TYPE:

diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C 
b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
new file mode 100644
index 000..5af60711320
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
@@ -0,0 +1,19 @@
+// PR c++/89231
+// { dg-do compile { target c++11 } }
+
+template
+struct A {
+  template
+  struct Collect { };
+
+  template>
+  struct Seq;
+
+  template
+  struct Seq> : Seq> { };
+
+  template
+  struct Seq<0, I, Collect> : Collect { };
+};
+
+A::Seq<4> test;




Re: [PATCH] c++: overeager type completion in convert_to_void [PR111419]

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/15/23 12:03, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

Here convert_to_void always completes the type of an INDIRECT_REF or
VAR_DECL expression, but according to [expr.context] an lvalue-to-rvalue
conversion is applied to a discarded-value expression only if "the
expression is a glvalue of volatile-qualified type".  This patch restricts
convert_to_void's type completion accordingly.

PR c++/111419

gcc/cp/ChangeLog:

* cvt.cc (convert_to_void) : Only call
complete_type if the type is volatile and the INDIRECT_REF
isn't an implicit one.


Hmm, what does implicit have to do with it?  The expression forms listed 
in https://eel.is/c++draft/expr.context#2 include "id-expression"...



diff --git a/gcc/testsuite/g++.dg/expr/discarded1a.C 
b/gcc/testsuite/g++.dg/expr/discarded1a.C
new file mode 100644
index 000..5516ff46fe9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/discarded1a.C
@@ -0,0 +1,16 @@
+// PR c++/111419
+
+struct Incomplete;
+
+template struct Holder { T t; }; // { dg-error "incomplete" }
+
+extern volatile Holder a;
+extern volatile Holder& b;
+extern volatile Holder* c;
+
+int main() {
+  a; // { dg-message "required from here" }
+  b; // { dg-warning "implicit dereference will not access object" }
+ // { dg-bogus "required from here" "" { target *-*-* } .-1 }


...so it seems to me this line should get the lvalue-rvalue conversion 
(and not the warning about no access).



+  *c; // { dg-message "required from here" }
+}




Re: [PATCH] c++: visibility wrt template and ptrmem targs [PR70413]

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/15/23 12:03, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


OK.


-- >8 --

When constraining the visibility of an instantiation, we weren't
properly considering the visibility of PTRMEM_CST and TEMPLATE_DECL
template arguments.

PR c++/70413

gcc/cp/ChangeLog:

* decl2.cc (min_vis_expr_r): Handle PTRMEM_CST and TEMPLATE_DECL.

gcc/testsuite/ChangeLog:

* g++.dg/abi/no-linkage-expr2.C: New test.
* g++.dg/abi/no-linkage-expr3.C: New test.
---
  gcc/cp/decl2.cc | 18 ++
  gcc/testsuite/g++.dg/abi/no-linkage-expr2.C | 15 +++
  gcc/testsuite/g++.dg/abi/no-linkage-expr3.C | 17 +
  3 files changed, 46 insertions(+), 4 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/abi/no-linkage-expr2.C
  create mode 100644 gcc/testsuite/g++.dg/abi/no-linkage-expr3.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index b402befba6d..5006372a646 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2582,7 +2582,10 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
int *vis_p = (int *)data;
int tpvis = VISIBILITY_DEFAULT;
  
-  switch (TREE_CODE (*tp))

+  tree t = *tp;
+  if (TREE_CODE (t) == PTRMEM_CST)
+t = PTRMEM_CST_MEMBER (t);
+  switch (TREE_CODE (t))
  {
  case CAST_EXPR:
  case IMPLICIT_CONV_EXPR:
@@ -2593,15 +2596,22 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
  case NEW_EXPR:
  case CONSTRUCTOR:
  case LAMBDA_EXPR:
-  tpvis = type_visibility (TREE_TYPE (*tp));
+  tpvis = type_visibility (TREE_TYPE (t));
break;
  
+case TEMPLATE_DECL:

+  t = DECL_TEMPLATE_RESULT (t);
+  /* Fall through.  */
  case VAR_DECL:
  case FUNCTION_DECL:
-  if (! TREE_PUBLIC (*tp))
+  if (! TREE_PUBLIC (t))
tpvis = VISIBILITY_ANON;
else
-   tpvis = DECL_VISIBILITY (*tp);
+   tpvis = DECL_VISIBILITY (t);
+  break;
+
+case FIELD_DECL:
+  tpvis = type_visibility (DECL_CONTEXT (t));
break;
  
  default:

diff --git a/gcc/testsuite/g++.dg/abi/no-linkage-expr2.C 
b/gcc/testsuite/g++.dg/abi/no-linkage-expr2.C
new file mode 100644
index 000..db23570bb08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no-linkage-expr2.C
@@ -0,0 +1,15 @@
+// PR c++/70413
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler-not "weak.*_Z" } }
+
+namespace {
+  template struct A;
+  template using B = int;
+}
+
+template class Q> void f() { }
+
+int main() {
+  f();
+  f();
+}
diff --git a/gcc/testsuite/g++.dg/abi/no-linkage-expr3.C 
b/gcc/testsuite/g++.dg/abi/no-linkage-expr3.C
new file mode 100644
index 000..a2db1a45c74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no-linkage-expr3.C
@@ -0,0 +1,17 @@
+// PR c++/70413
+// { dg-final { scan-assembler-not "weak.*_Z" } }
+
+namespace {
+  struct A {
+void f();
+int m;
+  };
+}
+
+template void g() { }
+template void h() { }
+
+int main() {
+  g<::f>();
+  h<::m>();
+}




Re: [PATCH] c++: constness of decltype of NTTP object [PR98820]

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/15/23 13:55, Patrick Palka wrote:

This corrects decltype of a (class) NTTP object as per
[dcl.type.decltype]/1.2 and [temp.param]/6 in the type-dependent case.
In the non-dependent case (nontype-class8.C) we resolve the decltype
ahead of time, and finish_decltype_type already made sure to drop the
const VIEW_CONVERT_EXPR wrapper around the TEMPLATE_PARM_INDEX.


Hmm, seems like dropping the VIEW_CONVERT_EXPR is wrong in this case? 
I'm not sure why I added that.


Jason



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

2023-09-16 Thread Jason Merrill via Gcc-patches

On 9/15/23 16:32, Marek Polacek wrote:

On Fri, Sep 15, 2023 at 02:08:46PM -0400, Jason Merrill wrote:

On 9/13/23 20:02, Marek Polacek wrote:

On Wed, Sep 13, 2023 at 05:57:47PM -0400, Jason Merrill wrote:

On 9/13/23 16:56, Marek Polacek wrote:

On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:

On 9/8/23 14:24, Marek Polacek wrote:

+  switch (TREE_CODE (stmt))
+{
+/* Unfortunately we must handle code like
+false ? bar () : 42
+   where we have to check bar too.  */
+case COND_EXPR:
+  if (cp_fold_immediate_r (_OPERAND (stmt, 1), walk_subtrees, data))
+   return error_mark_node;
+  if (TREE_OPERAND (stmt, 2)
+ && cp_fold_immediate_r (_OPERAND (stmt, 2), walk_subtrees, data))
+   return error_mark_node;


Is this necessary?  Doesn't walk_tree already walk into the arms of
COND_EXPR?


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


Ah.  But in that case I guess we need to walk into the arms, not just check
the top-level expression in them.

Arg, of course.  I was fooled into thinking that it would recurse, but
you're right.  Fixed by using cp_walk_tree as I intended.  Tested in
consteval34.C.


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


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


Callers of cp_fold_immediate don't need this because cp_fold_r isn't
involved, so it isn't folding anything.


This is true.
  

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


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


Ah, that's a good point.  With the recursive walk in 
cp_fold_immediate_r, I suppose we could suppress it when called from 
cp_fold_immediate with a new fold_flag?  That would still allow for 
cp_walk_tree_without_duplicates.


Incidentally, I notice you check for null op2 of COND_EXPR, should 
probably also check op1.


Jason



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

2023-09-15 Thread Jason Merrill via Gcc-patches

On 9/13/23 20:02, Marek Polacek wrote:

On Wed, Sep 13, 2023 at 05:57:47PM -0400, Jason Merrill wrote:

On 9/13/23 16:56, Marek Polacek wrote:

On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:

On 9/8/23 14:24, Marek Polacek wrote:

+  switch (TREE_CODE (stmt))
+{
+/* Unfortunately we must handle code like
+false ? bar () : 42
+   where we have to check bar too.  */
+case COND_EXPR:
+  if (cp_fold_immediate_r (_OPERAND (stmt, 1), walk_subtrees, data))
+   return error_mark_node;
+  if (TREE_OPERAND (stmt, 2)
+ && cp_fold_immediate_r (_OPERAND (stmt, 2), walk_subtrees, data))
+   return error_mark_node;


Is this necessary?  Doesn't walk_tree already walk into the arms of
COND_EXPR?


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


Ah.  But in that case I guess we need to walk into the arms, not just check
the top-level expression in them.
  
Arg, of course.  I was fooled into thinking that it would recurse, but

you're right.  Fixed by using cp_walk_tree as I intended.  Tested in
consteval34.C.


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


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


Callers of cp_fold_immediate don't need this because cp_fold_r isn't 
involved, so it isn't folding anything.


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


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



+  break;
+
case PTRMEM_CST:
  if (TREE_CODE (PTRMEM_CST_MEMBER (stmt)) == FUNCTION_DECL
  && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (stmt)))
{
- if (!data->pset.add (stmt))
+ if (!data->pset.add (stmt) && (complain & tf_error))
error_at (PTRMEM_CST_LOCATION (stmt),
  "taking address of an immediate function %qD",
  PTRMEM_CST_MEMBER (stmt));
  stmt = *stmt_p = build_zero_cst (TREE_TYPE (stmt));


It looks like this will overwrite *stmt_p even if we didn't give an error.


I suppose that could result in missing errors, adjusted.  And there's no
point in setting stmt.

- break;
+ return error_mark_node;
}
  break;
+/* Expand immediate invocations.  */
+case CALL_EXPR:
+case AGGR_INIT_EXPR:
+  if (tree fn = cp_get_callee (stmt))
+   if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P (fn))
+ if (tree fndecl = cp_get_fndecl_from_callee (fn, /*fold*/false))
+   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ {
+   *stmt_p = stmt = cxx_constant_value (stmt, complain);


Likewise.


I think we have to keep setting *stmt_p to actually evaluate consteval
functions.


But only when it succeeds; we don't want to set it to error_mark_node if we
aren't complaining.


Hmm, probably not.  Fixed, thanks.

+   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ {
+   stmt = cxx_constant_value (stmt, complain);
+   if (stmt == error_mark_node && (complain & tf_error))
+ return error_mark_node;
+   *stmt_p = stmt;
+ }


This seems backwards; like with the ADDR_EXPR/PTRMEM_CST cases, I think 
we want to return error_mark_node regardless of complain, but only set 
*stmt_p when complaining.


Jason



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

2023-09-13 Thread Jason Merrill via Gcc-patches

On 9/13/23 16:56, Marek Polacek wrote:

On Tue, Sep 12, 2023 at 05:26:25PM -0400, Jason Merrill wrote:

On 9/8/23 14:24, Marek Polacek wrote:
  

+  switch (TREE_CODE (stmt))
+{
+/* Unfortunately we must handle code like
+false ? bar () : 42
+   where we have to check bar too.  */
+case COND_EXPR:
+  if (cp_fold_immediate_r (_OPERAND (stmt, 1), walk_subtrees, data))
+   return error_mark_node;
+  if (TREE_OPERAND (stmt, 2)
+ && cp_fold_immediate_r (_OPERAND (stmt, 2), walk_subtrees, data))
+   return error_mark_node;


Is this necessary?  Doesn't walk_tree already walk into the arms of
COND_EXPR?


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


Ah.  But in that case I guess we need to walk into the arms, not just 
check the top-level expression in them.


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



+  break;
+
   case PTRMEM_CST:
 if (TREE_CODE (PTRMEM_CST_MEMBER (stmt)) == FUNCTION_DECL
  && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (stmt)))
{
- if (!data->pset.add (stmt))
+ if (!data->pset.add (stmt) && (complain & tf_error))
error_at (PTRMEM_CST_LOCATION (stmt),
  "taking address of an immediate function %qD",
  PTRMEM_CST_MEMBER (stmt));
  stmt = *stmt_p = build_zero_cst (TREE_TYPE (stmt));


It looks like this will overwrite *stmt_p even if we didn't give an error.


I suppose that could result in missing errors, adjusted.  And there's no
point in setting stmt.
  

- break;
+ return error_mark_node;
}
 break;
+/* Expand immediate invocations.  */
+case CALL_EXPR:
+case AGGR_INIT_EXPR:
+  if (tree fn = cp_get_callee (stmt))
+   if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P (fn))
+ if (tree fndecl = cp_get_fndecl_from_callee (fn, /*fold*/false))
+   if (DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ {
+   *stmt_p = stmt = cxx_constant_value (stmt, complain);


Likewise.


I think we have to keep setting *stmt_p to actually evaluate consteval
functions.


But only when it succeeds; we don't want to set it to error_mark_node if 
we aren't complaining.


Jason



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

2023-09-12 Thread Jason Merrill via Gcc-patches

On 9/8/23 14:24, Marek Polacek wrote:

On Thu, Sep 07, 2023 at 02:32:51PM -0400, Jason Merrill wrote:

On 9/7/23 11:23, Marek Polacek wrote:

On Tue, Sep 05, 2023 at 04:36:34PM -0400, Jason Merrill wrote:

On 9/5/23 15:59, Marek Polacek wrote:

On Tue, Sep 05, 2023 at 10:52:04AM -0400, Jason Merrill wrote:

On 9/1/23 13:23, Marek Polacek wrote:

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

-- >8 --

In the review of P2564:

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

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

The main drawback seems to be that cp_fold_r doesn't process as much
code as we did before: uninstantiated templates


That's acceptable, it's an optional diagnostic.


and things like "false ? foo () : 1".


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


Unfortunately we had already thrown the dead branch away when we got to
cp_fold_r.  I wonder if we have to adjust cxx_eval_conditional_expression
to call cp_fold_r on the dead branch too,


Hmm, I guess so.


perhaps with a new ff_ flag to skip the whole second switch in cp_fold_r?


Or factor out the immediate function handling to a separate walk function
that cp_fold_r also calls?


I did that.

But then it's possible that the in_immediate_context checks have to stay.


We can just not do the walk in immediate (or mce_true) context, like we
currently avoid calling cp_fold_function.


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

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


I disagree; the call is in a manifestly constant-evaluated expression, and
so is now considered an immediate function context, and we should accept
that example.


Ack.  I was still living in pre-P2564 world.
  

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


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


I think it will given the above comment.


Correct.  For instance, in:

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

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

   static_assert (foo (false) == 2);

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


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


Can't we check for mce_true here instead of looking at the call chain?


Yes.
  

+/* A wrapper around cp_fold_immediate_r.  */
+
+void
+cp_fold_immediate (tree *tp)
+{


Maybe return early if consteval isn't supported in the active standard?


Absolutely.

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

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

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

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

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

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

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

which were deemed ill-formed.

gcc/cp/ChangeLog:

* call.cc (build_over_call): Set ADDR_EXPR_DENOTES_CALL_P.  Don't handle
immediate_invocation_p here.
* constexpr.cc (in_immediate_context): New overload.
(cxx_eval_call_expression): Use mce_true for DECL_IMMEDIATE_FUNCTION_P.
(cxx_eval_conditional_expression): Call cp_fold_immediate.
* cp-gimplify.cc (maybe_replace_decl): Make 

[PATCH RFC] diagnostic: add permerror variants with opt

2023-09-12 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu.  Does this approach make sense to you?  Or do you
have another idea?

Perhaps the warn_system_headers adjustment should also be part of this?

-- 8< --

In the discussion of promoting some pedwarns to be errors by default, rather
than move them all into -fpermissive it seems to me to make sense to follow
the -Wnarrowing pattern of turning pedantic_errors on by default for them
like I've previously done for -Wnarrowing.  This way will also work with
-fpermissive, but users can still use -Wno-error=narrowing to downgrade that
specific diagnostic rather than everything affected by -fpermissive.

gcc/ChangeLog:

* diagnostic.cc (permerror): Add new overloads.
* diagnostic-core.h (permerror): Declare them.

gcc/cp/ChangeLog:

* typeck2.cc (check_narrowing): Use permerror.
---
 gcc/diagnostic-core.h |  3 +++
 gcc/cp/typeck2.cc |  9 +++--
 gcc/diagnostic.cc | 39 +++
 3 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index c9e27fd2e6e..2d9909f18bd 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -105,6 +105,9 @@ extern bool pedwarn (rich_location *, int, const char *, 
...)
 extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
 extern bool permerror (rich_location *, const char *,
   ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern bool permerror (location_t, int, const char *, ...) 
ATTRIBUTE_GCC_DIAG(3,4);
+extern bool permerror (rich_location *, int, const char *,
+  ...) ATTRIBUTE_GCC_DIAG(3,4);
 extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void sorry_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
 extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index cd1ea045720..1cbab70f513 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1109,15 +1109,12 @@ check_narrowing (tree type, tree init, tsubst_flags_t 
complain,
   else if (complain & tf_error)
{
  int savederrorcount = errorcount;
- if (!flag_permissive)
-   global_dc->pedantic_errors = 1;
  auto s = make_temp_override (global_dc->dc_warn_system_headers, true);
- pedwarn (loc, OPT_Wnarrowing,
-  "narrowing conversion of %qE from %qH to %qI",
-  init, ftype, type);
+ permerror (loc, OPT_Wnarrowing,
+"narrowing conversion of %qE from %qH to %qI",
+init, ftype, type);
  if (errorcount == savederrorcount)
ok = true;
- global_dc->pedantic_errors = flag_pedantic_errors;
}
 }
 
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 65c0cfbf11a..4195a01aa09 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -2054,6 +2054,45 @@ permerror (rich_location *richloc, const char *gmsgid, 
...)
   return ret;
 }
 
+/* Similar to the above, but controlled by a flag other than -fpermissive.
+   As above, an error by default or a warning with -fpermissive, but this
+   diagnostic can also be downgraded by -Wno-error=opt.  */
+
+bool
+permerror (location_t location, int opt, const char *gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, gmsgid);
+  rich_location richloc (line_table, location);
+  bool pe = global_dc->pedantic_errors;
+  if (!global_dc->permissive)
+global_dc->pedantic_errors = true;
+  bool ret = diagnostic_impl (, NULL, opt, gmsgid, , DK_PEDWARN);
+  global_dc->pedantic_errors = pe;
+  va_end (ap);
+  return ret;
+}
+
+/* Same as "permerror" above, but at RICHLOC.  */
+
+bool
+permerror (rich_location *richloc, int opt, const char *gmsgid, ...)
+{
+  gcc_assert (richloc);
+
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, gmsgid);
+  bool pe = global_dc->pedantic_errors;
+  if (!global_dc->permissive)
+global_dc->pedantic_errors = true;
+  bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, , DK_PEDWARN);
+  global_dc->pedantic_errors = pe;
+  va_end (ap);
+  return ret;
+}
+
 /* A hard error: the code is definitely ill-formed, and an object file
will not be produced.  */
 void

base-commit: f73d2d61a5926f42e9e5d771d23868787ef9d800
-- 
2.39.3



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

2023-09-12 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

The argument might not already be an integer.

PR c++/111357

gcc/cp/ChangeLog:

* pt.cc (expand_integer_pack): Convert argument to int.

gcc/testsuite/ChangeLog:

* g++.dg/ext/integer-pack7.C: New test.
---
 gcc/cp/pt.cc |  2 ++
 gcc/testsuite/g++.dg/ext/integer-pack7.C | 38 
 2 files changed, 40 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/integer-pack7.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 838179d5fe3..b583c11eb99 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -3793,6 +3793,8 @@ expand_integer_pack (tree call, tree args, tsubst_flags_t 
complain,
 }
   else
 {
+  hi = perform_implicit_conversion_flags (integer_type_node, hi, complain,
+ LOOKUP_IMPLICIT);
   hi = instantiate_non_dependent_expr (hi, complain);
   hi = cxx_constant_value (hi, complain);
   int len = valid_constant_size_p (hi) ? tree_to_shwi (hi) : -1;
diff --git a/gcc/testsuite/g++.dg/ext/integer-pack7.C 
b/gcc/testsuite/g++.dg/ext/integer-pack7.C
new file mode 100644
index 000..95b1195bef4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/integer-pack7.C
@@ -0,0 +1,38 @@
+// PR c++/111357
+// { dg-do compile { target c++11 } }
+
+namespace std {
+  template
+struct integer_sequence
+{ };
+
+  template
+using make_integer_sequence
+  = integer_sequence<_Tp, __integer_pack(_Num)...>;
+}
+
+using std::integer_sequence;
+using std::make_integer_sequence;
+
+template
+void g(integer_sequence)
+{}
+
+template
+struct c1
+{
+  static constexpr int value = 1;
+  constexpr operator int() { return value; }
+};
+template
+struct R
+{
+   using S = make_integer_sequence{}>;
+
+   R() noexcept(noexcept(g(S(
+   {}
+};
+int main()
+{
+R();
+}

base-commit: ea5abbb263315e558c876b50c9371b90ddd5e028
-- 
2.39.3



[pushed] c++: ICE with -fno-exceptions and array init [PR107198]

2023-09-12 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

The removed line no longer has an effect on anew5.C error recovery, and
removing it improves error recovery for this testcase.

PR c++/107198

gcc/cp/ChangeLog:

* typeck2.cc (process_init_constructor_array): Use VEC_INIT_EXPR
regardless of seen_error.

gcc/testsuite/ChangeLog:

* g++.dg/eh/no-exceptions1.C: New test.
---
 gcc/cp/typeck2.cc|  1 -
 gcc/testsuite/g++.dg/eh/no-exceptions1.C | 19 +++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/eh/no-exceptions1.C

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 582a73bb053..cd1ea045720 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1683,7 +1683,6 @@ process_init_constructor_array (tree type, tree init, int 
nested, int flags,
if (next)
  {
if (next != error_mark_node
-   && ! seen_error () // Improves error-recovery on anew5.C.
&& (initializer_constant_valid_p (next, TREE_TYPE (next))
!= null_pointer_node))
  {
diff --git a/gcc/testsuite/g++.dg/eh/no-exceptions1.C 
b/gcc/testsuite/g++.dg/eh/no-exceptions1.C
new file mode 100644
index 000..4b77064c646
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/no-exceptions1.C
@@ -0,0 +1,19 @@
+// PR c++/107198
+// { dg-additional-options -fno-exceptions }
+
+struct A {
+  A() { throw 0; } // { dg-error disabled }
+  A(int i) { throw i; }
+  A(const A&) { throw 10; }
+};
+
+void try_idx (int i)
+{
+  int t = 10;
+  try {
+struct X {
+  A e1[2], e2;
+}
+x2[3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+  } catch (int x) { t = x; }   // { dg-prune-output "not declared" }
+}

base-commit: 27e2e7c93e48bcbb63877cc5964fae8dba47d706
-- 
2.39.3



Re: [PATCH] c++: cache conversion function lookup

2023-09-07 Thread Jason Merrill via Gcc-patches

On 9/7/23 16:12, Patrick Palka wrote:

On Thu, 7 Sep 2023, Jason Merrill wrote:


On 9/6/23 18:07, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  This cache apparently has a 98% hit rate for TYPE_HAS_CONVERSION
types on some test files.


Does it make a measurable difference in compile time?


Admittedly this optimization was probably more justified with the older
version of the PR99599 patch that added another lookup_conversions call.
Compile time for this standalone patch in the noise according to my
experiments, but I did measure a ~1MB/0.2% decrease in memory usage for
range-v3's zip.cpp.  This is because lookup_conversions_r allocates a
new list each time it's called (on a TYPE_HAS_CONVERSION type) even in
the simple case of no inheritance etc.  Maybe lookup_conversions_r's
(relatively complicated) implementation could be improved in the
simple/common case...


+/* A cache of the result of lookup_conversions.  */
+
+static GTY((cache)) type_tree_cache_map *lookup_conversions_cache;


This should probably be (deletable) rather than (cache)?


Ack.  Is that because of PCH concerns or because the cache is
purely an optimization and so has no semantic effect?


The latter.  Really, (cache) is a terrible name, it should only be used 
when it's impractical to recompute the value.


Jason



Re: [PATCH] c++: cache conversion function lookup

2023-09-07 Thread Jason Merrill via Gcc-patches

On 9/6/23 18:07, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  This cache apparently has a 98% hit rate for TYPE_HAS_CONVERSION
types on some test files.


Does it make a measurable difference in compile time?


+/* A cache of the result of lookup_conversions.  */
+
+static GTY((cache)) type_tree_cache_map *lookup_conversions_cache;


This should probably be (deletable) rather than (cache)?

Jason



Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-09-07 Thread Jason Merrill via Gcc-patches

On 9/6/23 18:09, Patrick Palka wrote:

On Mon, 28 Aug 2023, Jason Merrill wrote:


On 8/24/23 09:31, Patrick Palka wrote:

On Wed, 23 Aug 2023, Jason Merrill wrote:


On 8/21/23 21:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

+ /* We're checking only non-instantiating conversions.
+A conversion may instantiate only if it's to/from a
+class type that has a constructor template/conversion
+function template.  */
+ tree parm_nonref = non_reference (parm);
+ tree type_nonref = non_reference (type);
+
+ if (CLASS_TYPE_P (parm_nonref))
+   {
+ if (!COMPLETE_TYPE_P (parm_nonref)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
+   return unify_success (explain_p);
+
+ tree ctors = get_class_binding (parm_nonref,
+ complete_ctor_identifier);
+ for (tree ctor : lkp_range (ctors))
+   if (TREE_CODE (ctor) == TEMPLATE_DECL)
+ return unify_success (explain_p);


Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?


Done; all dups of this PR seem to use tag types that are aggregates, so this
seems like a good simplification.  I also made us punt if the arg type has a
constrained non-template conversion function.



Also, instantiation can also happen when checking for conversion to a
pointer
or reference to base class.


Oops, I suppose we just need to strip pointer types upfront as well.  The
!COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
sure we deem a potential derived-to-base conversion unsafe if appropriate
IIUC.

How does the following look?

-- >8 --

Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs
[PR99599]

PR c++/99599

gcc/cp/ChangeLog:

* config-lang.in (gtfiles): Add search.cc.
* pt.cc (check_non_deducible_conversions): Add bool parameter
passed down to check_non_deducible_conversion.
(fn_type_unification): Call check_non_deducible_conversions
an extra time before satisfaction with noninst_only_p=true.
(check_non_deducible_conversion): Add bool parameter controlling
whether to compute only conversions that are guaranteed to
not induce template instantiation.
* search.cc (conversions_cache): Define.
(lookup_conversions): Use it to cache the lookup.  Improve cache
rate by considering TYPE_MAIN_VARIANT of the type.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-nondep4.C: New test.
---
   gcc/cp/config-lang.in |  1 +
   gcc/cp/pt.cc  | 81 +--
   gcc/cp/search.cc  | 14 +++-
   gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C | 21 +
   4 files changed, 110 insertions(+), 7 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C

@@ -22921,6 +22933,65 @@ check_non_deducible_conversion (tree parm, tree
arg, unification_kind_t strict,
   {
 bool ok = false;
 tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
+  if (conv_p && *conv_p)
+   {
+ /* This conversion was already computed earlier (when
+computing only non-instantiating conversions).  */
+ gcc_checking_assert (!noninst_only_p);
+ return unify_success (explain_p);
+   }
+  if (noninst_only_p)
+   {
+ /* We're checking only non-instantiating conversions.
+Computing a conversion may induce template instantiation
+only if ... */


Let's factor this whole block out into another function.


Sounds good.



Incidentally, CWG1092 is a related problem with defaulted functions, which I
dealt with in a stricter way: when LOOKUP_DEFAULTED we ignore a conversion
from the parameter being 

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

2023-09-07 Thread Jason Merrill via Gcc-patches

On 9/7/23 11:23, Marek Polacek wrote:

On Tue, Sep 05, 2023 at 04:36:34PM -0400, Jason Merrill wrote:

On 9/5/23 15:59, Marek Polacek wrote:

On Tue, Sep 05, 2023 at 10:52:04AM -0400, Jason Merrill wrote:

On 9/1/23 13:23, Marek Polacek wrote:

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

-- >8 --

In the review of P2564:

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

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

The main drawback seems to be that cp_fold_r doesn't process as much
code as we did before: uninstantiated templates


That's acceptable, it's an optional diagnostic.


and things like "false ? foo () : 1".


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


Unfortunately we had already thrown the dead branch away when we got to
cp_fold_r.  I wonder if we have to adjust cxx_eval_conditional_expression
to call cp_fold_r on the dead branch too,


Hmm, I guess so.


perhaps with a new ff_ flag to skip the whole second switch in cp_fold_r?


Or factor out the immediate function handling to a separate walk function
that cp_fold_r also calls?


I did that.
  

But then it's possible that the in_immediate_context checks have to stay.


We can just not do the walk in immediate (or mce_true) context, like we
currently avoid calling cp_fold_function.


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

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


I disagree; the call is in a manifestly constant-evaluated expression, 
and so is now considered an immediate function context, and we should 
accept that example.



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


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


I think it will given the above comment.


diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 0ca4370deab..397d5c7ec3f 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2311,6 +2311,29 @@ cxx_dynamic_cast_fn_p (tree fndecl)
  && CP_DECL_CONTEXT (fndecl) == abi_node);
  }
  
+/* Return true if we are in the body of a consteval function. > +   This is in addition to in_immediate_context because that

+   uses current_function_decl which may not be available.  CTX is
+   the current constexpr context.  */
+
+static bool
+in_immediate_context (const constexpr_ctx *ctx)
+{
+  if (in_immediate_context ())
+return true;


Can't we check for mce_true here instead of looking at the call chain?


+/* A wrapper around cp_fold_immediate_r.  */
+
+void
+cp_fold_immediate (tree *tp)
+{


Maybe return early if consteval isn't supported in the active standard?

Jason



[pushed] c++: [[no_unique_address]] and cv-qualified type

2023-09-05 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

We were checking for overlap using same_type_p and therefore allocating two
Empty subobjects at the same offset because one was cv-qualified.

This gives the warning at the location of the class name rather than the
member declaration, but this should be a rare enough issue that it doesn't
seem worth trying to be more precise.

gcc/ChangeLog:

* common.opt: Update -fabi-version=19.

gcc/cp/ChangeLog:

* class.cc (check_subobject_offset): Check
same_type_ignoring_top_level_qualifiers_p.

gcc/testsuite/ChangeLog:

* g++.dg/abi/no_unique_address8.C: New test.
* g++.dg/abi/no_unique_address8a.C: New test.
---
 gcc/common.opt|  1 +
 gcc/cp/class.cc   | 28 +++--
 gcc/testsuite/g++.dg/abi/no_unique_address8.C | 30 ++
 .../g++.dg/abi/no_unique_address8a.C  | 31 +++
 4 files changed, 88 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/no_unique_address8.C
 create mode 100644 gcc/testsuite/g++.dg/abi/no_unique_address8a.C

diff --git a/gcc/common.opt b/gcc/common.opt
index 3e1939293e8..f137a1f81ac 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1011,6 +1011,7 @@ Driver Undocumented
 ; Default in G++ 13.
 ;
 ; 19: Emits ABI tags if needed in structured binding mangled names.
+; Ignores cv-quals on [[no_unique_object]] members.
 ; Default in G++ 14.
 ;
 ; Additional positive integers will be assigned as new versions of
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 778759237dc..9139a0075ab 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -4053,9 +4053,33 @@ check_subobject_offset (tree type, tree offset, 
splay_tree offsets)
   if (!n)
 return 0;
 
+  enum { ignore, fast, slow, warn }
+  cv_check = (abi_version_crosses (19) ? slow
+ : abi_version_at_least (19) ? fast
+ : ignore);
   for (t = (tree) n->value; t; t = TREE_CHAIN (t))
-if (same_type_p (TREE_VALUE (t), type))
-  return 1;
+{
+  tree elt = TREE_VALUE (t);
+
+  if (same_type_p (elt, type))
+   return 1;
+
+  if (cv_check != ignore
+ && same_type_ignoring_top_level_qualifiers_p (elt, type))
+   {
+ if (cv_check == fast)
+   return 1;
+ cv_check = warn;
+   }
+}
+
+  if (cv_check == warn)
+{
+  warning (OPT_Wabi, "layout of %qs member of type %qT changes in %qs",
+  "[[no_unique_address]]", type, "-fabi-version=19");
+  if (abi_version_at_least (19))
+   return 1;
+}
 
   return 0;
 }
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address8.C 
b/gcc/testsuite/g++.dg/abi/no_unique_address8.C
new file mode 100644
index 000..6aa2bba7810
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address8.C
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=19 -Wabi=18" }
+
+#include 
+
+#define NOUNIQUE [[no_unique_address]]
+
+struct Empty { };
+#define CHECK_DISTINCT(type, field1, field2) static_assert(offsetof(type, 
field1) != offsetof(type, field2))
+
+struct A1 {
+NOUNIQUE Empty a;
+Empty b;
+};
+CHECK_DISTINCT(A1, a, b);
+struct A2 {
+NOUNIQUE const Empty a;
+const Empty b;
+};
+CHECK_DISTINCT(A2, a, b);
+struct A3 {// { dg-warning "layout" }
+NOUNIQUE const Empty a;
+Empty b;
+};
+CHECK_DISTINCT(A3, a, b);
+struct A4 {// { dg-warning "layout" }
+NOUNIQUE Empty a;
+const Empty b;
+};
+CHECK_DISTINCT(A4, a, b);
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address8a.C 
b/gcc/testsuite/g++.dg/abi/no_unique_address8a.C
new file mode 100644
index 000..c5d48088529
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address8a.C
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=18 -Wabi=19" }
+
+#include 
+
+#define NOUNIQUE [[no_unique_address]]
+
+struct Empty { };
+#define CHECK_DISTINCT(type, field1, field2) static_assert(offsetof(type, 
field1) != offsetof(type, field2))
+#define CHECK_SAME(type, field1, field2) static_assert(offsetof(type, field1) 
== offsetof(type, field2))
+
+struct A1 {
+NOUNIQUE Empty a;
+Empty b;
+};
+CHECK_DISTINCT(A1, a, b);
+struct A2 {
+NOUNIQUE const Empty a;
+const Empty b;
+};
+CHECK_DISTINCT(A2, a, b);
+struct A3 {// { dg-warning "layout" }
+NOUNIQUE const Empty a;
+Empty b;
+};
+CHECK_SAME(A3, a, b);
+struct A4 {// { dg-warning "layout" }
+NOUNIQUE Empty a;
+const Empty b;
+};
+CHECK_SAME(A4, a, b);

base-commit: 244d1321340116b7780e78096356f69662fd0e18
-- 
2.39.3



Re: [PATCH] c++: Additional warning for name-hiding [PR12341]

2023-09-05 Thread Jason Merrill via Gcc-patches

On 9/4/23 13:18, priour...@gmail.com wrote:

From: benjamin priour 

Hi,

This patch was the first I wrote and had been
at that time returned to me because ill-formatted.

Getting busy with other things, I forgot about it.
I've now fixed the formatting.

Succesfully regstrapped on x86_64-linux-gnu off trunk
a7d052b3200c7928d903a0242b8cfd75d131e374.
Is it OK for trunk ?

Thanks,
Benjamin.

Patch below.
---

Add a new warning for name-hiding. When a class's field
is named similarly to one inherited, a warning should
be issued.
This new warning is controlled by the existing Wshadow.

gcc/cp/ChangeLog:

PR c++/12341
* search.cc (lookup_member):
New optional parameter to preempt processing the
inheritance tree deeper than necessary.
(lookup_field): Likewise.
(dfs_walk_all): Likewise.
* cp-tree.h: Update the above declarations.
* class.cc: (warn_name_hiding): New function.
(finish_struct_1): Call warn_name_hiding if -Wshadow.

gcc/testsuite/ChangeLog:

PR c++/12341
* g++.dg/pr12341-1.C: New file.
* g++.dg/pr12341-2.C: New file.

Signed-off-by: benjamin priour 
---
  gcc/cp/class.cc  | 75 
  gcc/cp/cp-tree.h |  9 ++--
  gcc/cp/search.cc | 28 
  gcc/testsuite/g++.dg/pr12341-1.C | 65 +++
  gcc/testsuite/g++.dg/pr12341-2.C | 34 +++
  5 files changed, 200 insertions(+), 11 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/pr12341-1.C
  create mode 100644 gcc/testsuite/g++.dg/pr12341-2.C

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 778759237dc..b1c59c392a0 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -3080,6 +3080,79 @@ warn_hidden (tree t)
}
  }
  
+/* Warn about non-static fields name hiding.  */

+
+static void
+warn_name_hiding (tree t)
+{
+  if (is_empty_class (t) || CLASSTYPE_NEARLY_EMPTY_P (t))
+return;
+
+  for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
+{
+  /* Skip if field is not an user-defined non-static data member.  */
+  if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
+   continue;
+
+  unsigned j;
+  tree name = DECL_NAME (field);
+  /* Skip if field is anonymous.  */
+  if (!name || !identifier_p (name))
+   continue;
+
+  auto_vec base_vardecls;
+  tree binfo;
+  tree base_binfo;
+  /* Iterate through all of the base classes looking for possibly
+shadowed non-static data members.  */
+  for (binfo = TYPE_BINFO (t), j = 0;
+  BINFO_BASE_ITERATE (binfo, j, base_binfo); j++)


Rather than iterate through the bases here, maybe add a mode to 
lookup_member/lookup_field_r that skips the most derived type, e.g. by 
adding that as a flag in lookup_field_info?


Probably instead of the once_suffices stuff?


+ if (base_vardecl)
+   {
+ auto_diagnostic_group d;
+ if (warning_at (location_of (field), OPT_Wshadow,
+ "%qD might shadow %qD", field, base_vardecl))


Why "might"?  We can give a correct answer, we shouldn't settle for an 
approximation.


Jason



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

2023-09-05 Thread Jason Merrill via Gcc-patches

On 9/5/23 15:59, Marek Polacek wrote:

On Tue, Sep 05, 2023 at 10:52:04AM -0400, Jason Merrill wrote:

On 9/1/23 13:23, Marek Polacek wrote:

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

-- >8 --

In the review of P2564:

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

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

The main drawback seems to be that cp_fold_r doesn't process as much
code as we did before: uninstantiated templates


That's acceptable, it's an optional diagnostic.


and things like "false ? foo () : 1".


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


Unfortunately we had already thrown the dead branch away when we got to
cp_fold_r.  I wonder if we have to adjust cxx_eval_conditional_expression
to call cp_fold_r on the dead branch too,


Hmm, I guess so.


perhaps with a new ff_ flag to skip the whole second switch in cp_fold_r?


Or factor out the immediate function handling to a separate walk 
function that cp_fold_r also calls?



But then it's possible that the in_immediate_context checks have to stay.


We can just not do the walk in immediate (or mce_true) context, like we 
currently avoid calling cp_fold_function.  For mce_unknown I guess we'd 
want to set *non_constant_p instead of giving an error.


Jason



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

2023-09-05 Thread Jason Merrill via Gcc-patches

On 9/1/23 20:00, Marek Polacek wrote:

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

-- >8 --

When verify_constant complains, it's pretty terse.  Consider

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

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

With this patch, we say:

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

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

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8bd5c4a47f8..6d5aed82377 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3381,6 +3381,54 @@ ok:
  }
  }
  
+/* *TP was not deemed constant by reduced_constant_expression_p.  Explain

+   why and suggest what could be done about it.  */
+
+static tree
+verify_constant_explain_r (tree *tp, int *, void *)
+{
+  bool ref_p = false;


I think you'll want something along the lines of

  /* No need to look into types or unevaluated operands.  */
  if (TYPE_P (init) || unevaluated_p (code))
{
  *walk_subtrees = false;
  return NULL_TREE;
}

(from find_uninit_fields_r).

OK with that change.

Jason



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

2023-09-05 Thread Jason Merrill via Gcc-patches

On 9/1/23 13:23, Marek Polacek wrote:

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

-- >8 --

In the review of P2564:

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

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

The main drawback seems to be that cp_fold_r doesn't process as much
code as we did before: uninstantiated templates


That's acceptable, it's an optional diagnostic.


and things like "false ? foo () : 1".


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



diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8bd5c4a47f8..af4f98b1fe1 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3135,6 +3135,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
  unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
  
+	  /* Make sure we fold std::is_constant_evaluated to true in an

+immediate function.  */
+ if (immediate_invocation_p (fun))


I think this should just check DECL_IMMEDIATE_FUNCTION_P, the context 
doesn't matter.



+   call_ctx.manifestly_const_eval = mce_true;
+
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 206e791fcfd..29132aad158 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1058,9 +1058,21 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
}
break;
  
+/* Expand immediate invocations.  */

+case CALL_EXPR:
+case AGGR_INIT_EXPR:
+  if (!in_immediate_context ())


As you mentioned in your followup, we shouldn't need to check this 
because we don't call cp_fold_r in immediate context.



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


Likewise.


diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 799183dc646..7dfb6de2da3 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -3254,7 +3254,7 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_)
 variables.  */
  
  static tree

-bot_replace (tree* t, int* walk_subtrees, void* data_)
+bot_replace (tree* t, int*, void* data_)


Generally we keep the parameter name as a comment like
int */*walk_subtrees*/


diff --git a/gcc/testsuite/g++.dg/cpp23/consteval-if2.C 
b/gcc/testsuite/g++.dg/cpp23/consteval-if2.C
index d1845da9e58..9fa95295c43 100644
--- a/gcc/testsuite/g++.dg/cpp23/consteval-if2.C
+++ b/gcc/testsuite/g++.dg/cpp23/consteval-if2.C
@@ -65,7 +65,7 @@ qux (int x)
int r = 0;
if not consteval// { dg-warning "'if consteval' only available with" "" 
{ target c++20_only } }
  {
-  r += foo (x);// { dg-error "'x' is not a constant expression" }
+  r += foo (x);// { dg-error "'x' is not a constant expression" "" { 
xfail *-*-* } }


This whole function should have a comment that these errors are not 
required because qux is never instantiated.



diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval11.C 
b/gcc/testsuite/g++.dg/cpp2a/consteval11.C
index 2f68ec0f892..9fd32dcab7b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/consteval11.C
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval11.C
@@ -5,25 +5,25 @@ consteval int bar (int i) { if (i != 1) throw 1; return 0; }  // { 
dg-error "is n
  
  constexpr int a = bar (1);

  constexpr int b = bar (2);// { dg-message "in 'constexpr' expansion 
of" }
-constexpr int c = 0 ? bar (3) : 1; // { dg-message "in 'constexpr' expansion 
of" }
+constexpr int c = 0 ? bar (3) : 1;


As discussed above, we need to keep this diagnostic and the others like it.

Let's also add a test with the

template 
constexpr bool is_not(T t, F f) {
return not f(t);
}

consteval bool is_even(int i) { return i % 2 == 0; }

static_assert(is_not(5, is_even)); // ok

example from the paper.

Jason



Re: [PATCH] c++, v2: Diagnose [basic.scope.block]/2 violations even in compound-stmt of function-try-block [PR52953]

2023-09-05 Thread Jason Merrill via Gcc-patches

On 9/1/23 09:24, Jakub Jelinek wrote:

On Thu, Aug 31, 2023 at 03:52:22PM -0400, Jason Merrill wrote:

On 8/31/23 03:20, Jakub Jelinek wrote:

As the following testcase shows, while check_local_shadow diagnoses most of
the [basic.scope.block]/2 violations, it doesn't diagnose when parameter's
name is redeclared inside of the compound-stmt of a function-try-block.

There is in that case an extra scope (sk_try with parent artificial
sk_block with for FUNCTION_NEEDS_BODY_BLOCK another sk_block and only then
sk_function_param).

The following patch fixes that.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-08-31  Jakub Jelinek  

PR c++/52953
* cp-tree.h (struct language_function): Add x_in_function_try_block
member.


How about adding a flag to cp_binding_level instead?  Maybe to mark the
artificial sk_block level as such, which we could use for both this case and
the FUNCTION_NEEDS_BODY_BLOCK cases.


So like this?

It actually changes behaviour on the
void foo (int x) try {} catch (int x) {} case, where previously
this triggered the
|| (TREE_CODE (old) == PARM_DECL
&& (current_binding_level->kind == sk_catch
|| current_binding_level->level_chain->kind == sk_catch)
&& in_function_try_handler))
 {
   auto_diagnostic_group d;
   if (permerror (DECL_SOURCE_LOCATION (decl),
  "redeclaration of %q#D", decl))
 inform (DECL_SOURCE_LOCATION (old),
 "%q#D previously declared here", old);
diagnostics (note, just the current_binding_level->kind == sk_catch
case), while now it triggers already the earlier
   if (b->kind == sk_function_parms)
 {
   error_at (DECL_SOURCE_LOCATION (decl),
 "declaration of %q#D shadows a parameter", decl);
   inform (DECL_SOURCE_LOCATION (old),
   "%q#D previously declared here", old);
error.  If you think it is important to differentiate that,
I guess I could guard the while (b->artificial) loop with say
+ if (!in_function_try_handler
+ || current_binding_level->kind != sk_catch)
while (b->artificial)
  b = b->level_chain;
and adjust the 2 testcases.


I don't mind the change of diagnostic.  Can we remove the 
in_function_try_handler test, then, if it's no longer reachable?  OK 
with that change.



Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
or with modification?

2023-09-01  Jakub Jelinek  

PR c++/52953
* name-lookup.h (struct cp_binding_level): Add artificial bit-field.
Formatting fixes.
* name-lookup.cc (check_local_shadow): Skip artificial bindings when
checking if parameter scope is parent scope.  Don't special case
FUNCTION_NEEDS_BODY_BLOCK.
* decl.cc (begin_function_body): Set
current_binding_level->artificial.
* semantics.cc (begin_function_try_block): Likewise.

* g++.dg/diagnostic/redeclaration-3.C: New test.
* g++.dg/parse/pr31952-3.C: Expect different diagnostic wording.

--- gcc/cp/name-lookup.h.jj 2023-08-21 11:57:33.105460770 +0200
+++ gcc/cp/name-lookup.h2023-09-01 10:15:20.137943395 +0200
@@ -292,11 +292,11 @@ struct GTY(()) cp_binding_level {
only valid if KIND == SK_TEMPLATE_PARMS.  */
BOOL_BITFIELD explicit_spec_p : 1;
  
-  /* true means make a BLOCK for this level regardless of all else.  */

+  /* True means make a BLOCK for this level regardless of all else.  */
unsigned keep : 1;
  
/* Nonzero if this level can safely have additional

-  cleanup-needing variables added to it.  */
+ cleanup-needing variables added to it.  */
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
  
@@ -308,9 +308,13 @@ struct GTY(()) cp_binding_level {

unsigned defining_class_p : 1;
  
/* True for SK_FUNCTION_PARMS of a requires-expression.  */

-  unsigned requires_expression: 1;
+  unsigned requires_expression : 1;
  
-  /* 22 bits left to fill a 32-bit word.  */

+  /* True for artificial blocks which should be ignored when finding
+ parent scope.  */
+  unsigned artificial : 1;
+
+  /* 21 bits left to fill a 32-bit word.  */
  };
  
  /* The binding level currently in effect.  */

--- gcc/cp/name-lookup.cc.jj2023-08-31 14:31:06.055762306 +0200
+++ gcc/cp/name-lookup.cc   2023-09-01 10:21:03.658118594 +0200
@@ -3146,8 +3146,10 @@ check_local_shadow (tree decl)
 them there.  */
  cp_binding_level *b = current_binding_level->level_chain;
  
-	  if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))

-   /* Skip the ctor/dtor cleanup level.  */
+ /* Skip artificially added scopes which aren't present
+in the C++ standard, e.g. for function-try-block or
+ctor/dtor cleanups.  */
+ while 

Re: [PATCH] c++, v2: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]

2023-09-05 Thread Jason Merrill via Gcc-patches

On 9/1/23 09:34, Jakub Jelinek wrote:

On Thu, Aug 31, 2023 at 05:46:28PM -0400, Jason Merrill wrote:

I've suggested this to Core.


Thanks.


So, I'm not really sure what to do.  Intuitively the patch seems right
because even block externs redeclare stuff and change meaning of the
identifiers and void foo () { int i; extern int i (int); } is rejected
by all compilers.


I think this direction makes sense, though we might pedwarn on these rather
than error to reduce possible breakage.


It wasn't clear to me whether you want to make those pedwarns just for the
DECL_EXTERNAL cases, ones that actually changed, or all others as well
(which were errors or permerrors depending on the case).
I've implemented the former, kept existing behavior of !DECL_EXTERNAL.


2023-08-31  Jakub Jelinek  

PR c++/52953
* name-lookup.cc (check_local_shadow): Defer punting on
DECL_EXTERNAL (decl) from the start of function to right before
the -Wshadow* checks.


Don't we want to consider externs for the -Wshadow* checks as well?


I think that is a good idea (though dunno how much it will trigger in
real-world), but there is one case I've excluded, the global variable
shadowing case, because warning that
int z;
void foo () { extern int z; z = 1; }
shadows the global var would be incorrect, it is the same var.
It is true that
int y; namespace N { void bar () { extern int y; y = 1; } }
shadows ::y but it is unclear how to differentiate those two cases with
the information we have at check_local_shadow time.

I've also found one spot which wasn't using auto_diagnostic_group d;
on a pair of error_at/inform.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


OK.


2023-09-01  Jakub Jelinek  

PR c++/52953
* name-lookup.cc (check_local_shadow): Don't punt early for
DECL_EXTERNAL decls, instead just disable the shadowing of namespace
decls check for those and emit a pedwarn rather than error_at for
those.  Add missing auto_diagnostic_group.  Formatting fix.

* g++.dg/diagnostic/redeclaration-4.C: New test.
* g++.dg/diagnostic/redeclaration-5.C: New test.
* g++.dg/warn/Wshadow-19.C: New test.

--- gcc/cp/name-lookup.cc.jj2023-09-01 10:21:03.658118594 +0200
+++ gcc/cp/name-lookup.cc   2023-09-01 11:30:10.868516494 +0200
@@ -3096,10 +3096,6 @@ check_local_shadow (tree decl)
if (TREE_CODE (decl) == PARM_DECL && !DECL_CONTEXT (decl))
  return;
  
-  /* External decls are something else.  */

-  if (DECL_EXTERNAL (decl))
-return;
-
tree old = NULL_TREE;
cp_binding_level *old_scope = NULL;
if (cxx_binding *binding = outer_binding (DECL_NAME (decl), NULL, true))
@@ -3130,11 +3126,9 @@ check_local_shadow (tree decl)
  && DECL_CONTEXT (old) == lambda_function (current_lambda_expr ())
  && TREE_CODE (old) == PARM_DECL
  && DECL_NAME (decl) != this_identifier)
-   {
- error_at (DECL_SOURCE_LOCATION (old),
-   "lambda parameter %qD "
-   "previously declared as a capture", old);
-   }
+   error_at (DECL_SOURCE_LOCATION (old),
+ "lambda parameter %qD "
+ "previously declared as a capture", old);
  return;
}
/* Don't complain if it's from an enclosing function.  */
@@ -3156,10 +3150,18 @@ check_local_shadow (tree decl)
 in the outermost block of the function definition.  */
  if (b->kind == sk_function_parms)
{
- error_at (DECL_SOURCE_LOCATION (decl),
-   "declaration of %q#D shadows a parameter", decl);
- inform (DECL_SOURCE_LOCATION (old),
- "%q#D previously declared here", old);
+ auto_diagnostic_group d;
+ bool emit = true;
+ if (DECL_EXTERNAL (decl))
+   emit = pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+   "declaration of %q#D shadows a parameter",
+   decl);
+ else
+   error_at (DECL_SOURCE_LOCATION (decl),
+ "declaration of %q#D shadows a parameter", decl);
+ if (emit)
+   inform (DECL_SOURCE_LOCATION (old),
+   "%q#D previously declared here", old);
  return;
}
}
@@ -3185,10 +3187,16 @@ check_local_shadow (tree decl)
   && (old_scope->kind == sk_cond || old_scope->kind == sk_for))
{
  auto_diagnostic_group d;
- error_at (DECL_SOURCE_LOCATION (decl),
-   "redeclaration of %q#D", decl);
- inform (DECL_SOURCE_LOCATION (old),
- "%q#D previously declared here", old);
+ bool emit = true;
+ if (DECL_EXTERNAL (decl))
+   emit = pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+  

Re: [RFC PATCH] c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]

2023-08-31 Thread Jason Merrill via Gcc-patches

On 8/31/23 04:08, Jakub Jelinek wrote:

Hi!

C++17 had in [basic.block.scope]/2
"A parameter name shall not be redeclared in the outermost block of the function
definition nor in the outermost block of any handler associated with a
function-try-block."
and in [basic.block.scope]/4 similar rule for selection/iteration
statements.  My reading of that is that it applied even for block local
externs in all those spots, while they declare something at namespace scope,
the redeclaration happens in that outermost block etc. and introduces names
into that.
Those wordings seemed to have been moved somewhere else in C++20, but what's
worse, they were moved back and completely rewritten in
P1787R6: Declarations and where to find them
which has been applied as a DR (but admittedly, we don't claim yet to
implement that).
The current wording at https://eel.is/c++draft/basic.scope#block-2
and https://eel.is/c++draft/basic.scope#scope-2.10 seem to imply at least
to me that it doesn't apply to extern block local decls because their
target scope is the namespace scope and [basic.scope.block]/2 says
"and whose target scope is the block scope"...
Now, it is unclear if that is actually the intent or not.


Yes, I suspect that should be

If a declaration that is not a name-independent declaration and 
whose target scope isthat binds a name in the 
block scope S of a


which seems to also be needed to prohibit the already-diagnosed

void f(int i) { union { int i; }; }
void g(int i) { enum { i }; }

I've suggested this to Core.


There seems to be quite large implementation divergence on this as well.

Unpatched g++ e.g. on the redeclaration-5.C testcase diagnoses just
lines 55,58,67,70 (i.e. where the previous declaration is in for's
condition).

clang++ trunk diagnoses just lines 8 and 27, i.e. redeclaration in the
function body vs. parameter both in normal fn and lambda (but not e.g.
function-try-block and others, including ctors, but it diagnoses those
for non-extern decls).

ICC 19 diagnoses lines 8,32,38,41,45,52,55,58,61,64,67,70,76.

And MSCV trunk diagnoses 8,27,32,38,41,45,48,52,55,58,67,70,76,87,100,137
although the last 4 are just warnings.

g++ with the patch diagnoses
8,15,27,32,38,41,45,48,52,55,58,61,64,67,70,76,87,100,121,137
as the dg-error directives test.

So, I'm not really sure what to do.  Intuitively the patch seems right
because even block externs redeclare stuff and change meaning of the
identifiers and void foo () { int i; extern int i (int); } is rejected
by all compilers.


I think this direction makes sense, though we might pedwarn on these 
rather than error to reduce possible breakage.



2023-08-31  Jakub Jelinek  

PR c++/52953
* name-lookup.cc (check_local_shadow): Defer punting on
DECL_EXTERNAL (decl) from the start of function to right before
the -Wshadow* checks.


Don't we want to consider externs for the -Wshadow* checks as well?

Jason



Re: [PATCH] c++: Diagnose [basic.scope.block]/2 violations even in compound-stmt of function-try-block [PR52953]

2023-08-31 Thread Jason Merrill via Gcc-patches

On 8/31/23 03:20, Jakub Jelinek wrote:

Hi!

As the following testcase shows, while check_local_shadow diagnoses most of
the [basic.scope.block]/2 violations, it doesn't diagnose when parameter's
name is redeclared inside of the compound-stmt of a function-try-block.

There is in that case an extra scope (sk_try with parent artificial
sk_block with for FUNCTION_NEEDS_BODY_BLOCK another sk_block and only then
sk_function_param).

The following patch fixes that.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-08-31  Jakub Jelinek  

PR c++/52953
* cp-tree.h (struct language_function): Add x_in_function_try_block
member.


How about adding a flag to cp_binding_level instead?  Maybe to mark the 
artificial sk_block level as such, which we could use for both this case 
and the FUNCTION_NEEDS_BODY_BLOCK cases.


Jason



Re: [PATCH] c++, v3: Fix up mangling of function/block scope static structured bindings and emit abi tags [PR111069]

2023-08-31 Thread Jason Merrill via Gcc-patches

On 8/31/23 15:14, Jakub Jelinek wrote:

On Thu, Aug 31, 2023 at 01:11:57PM -0400, Jason Merrill wrote:

2023-08-28  Jakub Jelinek  

PR c++/111069
gcc/
* common.opt (fabi-version=): Document version 19.
* doc/invoke.texi (-fabi-version=): Likewise.
gcc/c-family/
* c-opts.cc (c_common_post_options): Change latest_abi_version to 19.
gcc/cp/
* cp-tree.h (determine_local_discriminator): Add NAME argument with
NULL_TREE default.
(struct cp_decomp): New type.


Maybe cp_finish_decomp should take this as well?  And tsubst_decomp_names,
and various other functions with decomp_first_name/decomp_cnt parms?


Ok, done below.


+  if (tree tags = get_abi_tags (decl))
+{
+  /* We didn't emit ABI tags for structured bindings before ABI 19.  */
+  if (!G.need_abi_warning
+  && abi_warn_or_compat_version_crosses (19))
+   G.need_abi_warning = 1;


In general we should probably only warn about mangling changes if
TREE_PUBLIC (decl).


I have done that but I think it ought to be unnecessary, because
check_abi_tags starts with
   if (!TREE_PUBLIC (decl))
 /* No need to worry about things local to this TU.  */
 return NULL_TREE;

Here is an updated patch, so far just tested with
make check-g++ GXX_TESTSUITE_STDS=98,11,14,17,20,2b,2c 
RUNTESTFLAGS="dg.exp='*decomp*'"
ok for trunk if it passes full bootstrap/regtest?


OK.


2023-08-31  Jakub Jelinek  

PR c++/111069
gcc/
* common.opt (fabi-version=): Document version 19.
* doc/invoke.texi (-fabi-version=): Likewise.
gcc/c-family/
* c-opts.cc (c_common_post_options): Change latest_abi_version to 19.
gcc/cp/
* cp-tree.h (determine_local_discriminator): Add NAME argument with
NULL_TREE default.
(struct cp_decomp): New type.
(cp_finish_decl): Add DECOMP argument defaulted to nullptr.
(cp_maybe_mangle_decomp): Remove declaration.
(cp_finish_decomp): Add cp_decomp * argument, remove tree and unsigned
args.
(cp_convert_range_for): Likewise.
* decl.cc (determine_local_discriminator): Add NAME argument, use it
if non-NULL, otherwise compute it the old way.
(maybe_commonize_var): Don't return early for structured bindings.
(cp_finish_decl): Add DECOMP argument, if non-NULL, call
cp_maybe_mangle_decomp.
(cp_maybe_mangle_decomp): Make it static with a forward declaration.
Call determine_local_discriminator.  Replace FIRST and COUNT arguments
with DECOMP argument.
(cp_finish_decomp): Replace FIRST and COUNT arguments with DECOMP
argument.
* mangle.cc (find_decomp_unqualified_name): Remove.
(write_unqualified_name): Don't call find_decomp_unqualified_name.
(mangle_decomp): Handle mangling of static function/block scope
structured bindings.  Don't call decl_mangling_context twice.  Call
check_abi_tags, call write_abi_tags for abi version >= 19 and emit
-Wabi warnings if needed.
(write_guarded_var_name): Handle structured bindings.
(mangle_ref_init_variable): Use write_guarded_var_name.
* parser.cc (cp_parser_range_for): Adjust do_range_for_auto_deduction
and cp_convert_range_for callers.
(do_range_for_auto_deduction): Replace DECOMP_FIRST_NAME and
DECOMP_CNT arguments with DECOMP.  Adjust cp_finish_decomp caller.
(cp_convert_range_for): Replace DECOMP_FIRST_NAME and
DECOMP_CNT arguments with DECOMP.  Don't call cp_maybe_mangle_decomp,
adjust cp_finish_decl and cp_finish_decomp callers.
(cp_parser_decomposition_declaration): Don't call
cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp
callers.
(cp_convert_omp_range_for): Adjust do_range_for_auto_deduction
and cp_finish_decomp callers.
(cp_finish_omp_range_for): Don't call cp_maybe_mangle_decomp,
adjust cp_finish_decl and cp_finish_decomp callers.
* pt.cc (tsubst_omp_for_iterator): Adjust tsubst_decomp_names
caller.
(tsubst_decomp_names): Replace FIRST and CNT arguments with DECOMP.
(tsubst_expr): Don't call cp_maybe_mangle_decomp, adjust
tsubst_decomp_names, cp_finish_decl, cp_finish_decomp and
cp_convert_range_for callers.
gcc/testsuite/
* g++.dg/cpp2a/decomp8.C: New test.
* g++.dg/cpp2a/decomp9.C: New test.
* g++.dg/abi/macro0.C: Expect __GXX_ABI_VERSION 1019 rather than
1018.

--- gcc/common.opt.jj   2023-08-28 13:55:55.670370386 +0200
+++ gcc/common.opt  2023-08-31 19:53:31.186280641 +0200
@@ -1010,6 +1010,9 @@ Driver Undocumented
  ; 18: Corrects errors in mangling of lambdas with additional context.
  ; Default in G++ 13.
  ;
+; 19: Emits ABI tags if needed in structured binding mangled names.
+; Default in G++ 14.
+;
  ; Additional positive integers will be assigned as new versions of
  ; the 

Re: [PATCH] c++, v2: Fix up mangling of function/block scope static structured bindings and emit abi tags [PR111069]

2023-08-31 Thread Jason Merrill via Gcc-patches

On 8/28/23 09:58, Jakub Jelinek wrote:

Hi!

On Thu, Aug 24, 2023 at 06:39:10PM +0200, Jakub Jelinek via Gcc-patches wrote:

Maybe do this in mangle_decomp, based on the actual mangling in process
instead of this pseudo-mangling?


Not sure that is possible, for 2 reasons:
1) determine_local_discriminator otherwise works on DECL_NAME, not mangled
names, so if one uses (albeit implementation reserved)
_ZZN1N3fooI1TB3bazEEivEDC1h1iEB6foobar and similar identifiers, they
could clash with the counting of the structured bindings


I guess, but those names are reserved so that we don't need to worry 
about that.



2) seems the local discriminator counting shouldn't take into account
details like abi tags, e.g. if I have:


Right, you'd need to use the partial mangled name before the ABI tags, 
e.g. with get_identifier_with_length (obstack_base, obstack_object_size).


But the way you have it is fine too.


The following updated patch handles everything except it leaves for the
above 2 reasons the determination of local discriminator where it was.
I had to add a new (defaulted) argument to cp_finish_decl and do
cp_maybe_mangle_decomp from there, so that it is after e.g. auto type
deduction and maybe_commonize_var (which had to be changed as well) and
spots in cp_finish_decl where we need or might need mangled names already.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

There is one difference between g++ with this patch and clang++,
g++ uses
_ZZ3barI1TB3quxEivEDC1o1pEB3qux
while clang++ uses
_ZZ3barI1TB3quxEivEDC1o1pE
but from what I can see, such a difference is there also when just using
normal local decls:
struct [[gnu::abi_tag ("foobar")]] S { int i; };
struct [[gnu::abi_tag ("qux")]] T { int i; S j; int k; };

inline int
foo ()
{
   static S c;
   static T d;
   return ++c.i + ++d.i;
}

template 
inline int
bar ()
{
   static S c;
   static T d;
   return ++c.i + ++d.i;
}

int (*p) () = 
int (*q) () = ;
where both compilers mangle c in foo as:
_ZZ3foovE1cB6foobar
and d in there as
_ZZ3foovE1dB3qux
and similarly both compilers mangle c in bar as
_ZZ3barI1TB3quxEivE1cB6foobar
but g++ mangles d in bar as
_ZZ3barI1TB3quxEivE1dB3qux
while clang++ mangles it as just
_ZZ3barI1TB3quxEivE1d
No idea what is right or wrong according to Itanium mangling.


I think g++ is right.

This has to do with the ABI "If part of a declaration's type is not 
represented in the mangling, i.e. the type of a variable or a return 
type that is not represented in the mangling of a function, any ABI tags 
on that type (or components of a compound type) that are not also 
present in a mangled part of the type are applied to the name of the 
declaration."


Here the type of bar::d is not mangled, so the tags of T are applied to 
the name d.


I guess clang interpreted the above as "any ABI tags on that type that 
are not already present in the mangled name...", which would also be a 
reasonable rule but is not the actual rule in the ABI.



2023-08-28  Jakub Jelinek  

PR c++/111069
gcc/
* common.opt (fabi-version=): Document version 19.
* doc/invoke.texi (-fabi-version=): Likewise.
gcc/c-family/
* c-opts.cc (c_common_post_options): Change latest_abi_version to 19.
gcc/cp/
* cp-tree.h (determine_local_discriminator): Add NAME argument with
NULL_TREE default.
(struct cp_decomp): New type.


Maybe cp_finish_decomp should take this as well?  And 
tsubst_decomp_names, and various other functions with 
decomp_first_name/decomp_cnt parms?



+  if (tree tags = get_abi_tags (decl))
+{
+  /* We didn't emit ABI tags for structured bindings before ABI 19.  */
+  if (!G.need_abi_warning
+  && abi_warn_or_compat_version_crosses (19))
+   G.need_abi_warning = 1;


In general we should probably only warn about mangling changes if 
TREE_PUBLIC (decl).


Jason



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

2023-08-30 Thread Jason Merrill via Gcc-patches

On 8/29/23 09:35, Nathaniel Shead wrote:

This is an attempt to improve the constexpr machinery's handling of
union lifetime by catching more cases that cause UB. Is this approach
OK?

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


I guess the simplest would be

(TYPE_HAS_TRIVIAL_DFLT (t) && locate_ctor (t))

because locate_ctor returns null for a deleted default ctor.  It would 
be good to make this a separate predicate.



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


Perhaps, but what you have here is fine.  Another possibility would be 
to just have a vec of the refs and extract the index from the ref later 
as needed.


Jason



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

2023-08-30 Thread Jason Merrill via Gcc-patches

On 8/29/23 15:01, Marek Polacek wrote:

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


OK.


-- >8 --

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

and while we detect

   constinit int fn();

we weren't detecting

   using F = int();
   constinit F f;

PR c++/73

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index bea0ee92106..a0e8a24efc0 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -14639,6 +14639,9 @@ grokdeclarator (const cp_declarator *declarator,
"storage class % invalid for "
"function %qs", name);
  }
+   else if (constinit_p)
+ error_at (declspecs->locations[ds_constinit],
+   "% specifier invalid for function %qs", name);
  
  if (virt_specifiers)

error ("virt-specifiers in %qs not allowed outside a class "
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit19.C 
b/gcc/testsuite/g++.dg/cpp2a/constinit19.C
new file mode 100644
index 000..5be610a18a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit19.C
@@ -0,0 +1,5 @@
+// PR c++/73
+// { dg-do compile { target c++20 } }
+
+using Function = int();
+constinit Function f; // { dg-error ".constinit. specifier invalid for 
function" }

base-commit: fce74ce2535aa3b7648ba82e7e61eb77d0175546




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

2023-08-29 Thread Jason Merrill via Gcc-patches

On 8/28/23 19:09, Marek Polacek wrote:

On Mon, Aug 28, 2023 at 06:27:26PM -0400, Jason Merrill wrote:

On 8/25/23 12:44, Marek Polacek wrote:

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

-- >8 --

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

PR c++/91319

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index eeb22e44fb4..b3d5c65b469 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -25718,6 +25718,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
 tree designator;
 tree initializer;
 bool clause_non_constant_p;
+  bool direct_p = false;
 location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 /* Handle the C++20 syntax, '. id ='.  */
@@ -25740,6 +25741,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
  if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
/* Consume the `='.  */
cp_lexer_consume_token (parser->lexer);
+ else
+   direct_p = true;
}
 /* Also, if the next token is an identifier and the following one is a
 colon, we are looking at the GNU designated-initializer
@@ -25817,6 +25820,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
 if (clause_non_constant_p && non_constant_p)
*non_constant_p = true;
+  if (TREE_CODE (initializer) == CONSTRUCTOR)
+   CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p;


Why |= rather than = ?


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


What is setting it earlier?

The patch is OK with a comment explaining that.

Jason



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

2023-08-29 Thread Jason Merrill via Gcc-patches

On 8/28/23 19:24, Marek Polacek wrote:

On Fri, Aug 25, 2023 at 08:34:37PM -0400, Jason Merrill wrote:

On 8/25/23 19:37, Marek Polacek wrote:

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

-- >8 --

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

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

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

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

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..09ebcf6a115 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8459,12 +8459,21 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
if (pedwarn (loc, 0, "converting to %qT from initializer list "
 "would use explicit constructor %qD",
 totype, convfn))
- inform (loc, "in C++11 and above a default constructor "
- "can be explicit");
+ {
+   inform (loc, "in C++11 and above a default constructor "
+   "can be explicit");
+   inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
+   convfn);


I'd swap these two informs.


Done.
  

+++ b/gcc/testsuite/g++.dg/diagnostic/explicit.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+struct S {
+  explicit S(int) { }
+  explicit operator bool() const { return true; } // { dg-message "explicit 
conversion function was not considered" }
+  explicit operator int() const { return 42; } // { dg-message "explicit conversion 
function was not considered" }
+};
+
+void
+g ()
+{
+  S s = {1}; // { dg-error "would use explicit constructor" }
+  bool b = S{1}; // { dg-error "cannot convert .S. to .bool. in 
initialization" }
+  int i;
+  i = S{2}; // { dg-error "cannot convert .S. to .int. in assignment" }
+}


Let's also test other copy-initialization contexts: parameter passing,
return, throw, aggregate member initialization.


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

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

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

but #2 isn't a viable candidate so this would take more effort to handle.


True, copy-initialization is different when the types are the same.


We just say about #1 that "candidate expects 0 arguments, 1 provided".

clang++ says

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


That would be better; in add_candidates when we see an explicit 
constructor we could add it to bad_fns instead of ignoring it.  But that 
doesn't need to be part of this patch.



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

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

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

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

explicit.C:13:12: error: cannot convert 'S' to 'bool' in initialization
13 |   bool b 

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

2023-08-29 Thread Jason Merrill via Gcc-patches

On 8/23/23 15:49, Marek Polacek wrote:

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

-- >8 --

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


Great, thanks!


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

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

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

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

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

which hopefully makes it clear what's going on.

Implementing this proposal has been tricky.  One problem was delayed
instantiation: instantiating a function can set off a domino effect
where one call promotes a function to consteval but that then means
that another function should also be promoted, etc.


What I expected was that we would instantiate when we see a call, i.e. 
immediate_invocation_p would instantiate its argument if it's an 
immediate-escalating function.  But...



I previously thought that I could get past that by implementing the propagation 
in
cp_gimplify_expr at which point we have already instantiated everything
via instantiate_pending_templates.


...this sounds like a clever way to avoid the problems we tend to see 
with eager instantiation (e.g. constexpr-inst1.C).  It still seems 
promising to me.



But I realized that we don't gimplify e.g.

   static auto p = 


Indeed, just cp_fully_fold_init them, at least until we build the global 
init function.



and so we'd never detect taking the address of a consteval function.
Therefore this patch instantiates immediate-escalating functions
beforehand.


Relatedly, in one of the testcases you have


+template 
+constexpr int f2(T);
+
+// ??? clang++ emits
+// error: immediate function 'f2' used before it is defined
+// error: immediate function 'f2' used before it is defined
+// but at this point we don't know that f2 will be updated to consteval?
+auto a2 = ;
+auto b2 = ;
+
+template 
+constexpr int f2(T t) {
+return id(t);


This is a case where we can't immediately resolve the question anyway, 
we need to remember where we've seen bare references to 
immediate-escalating functions outside of other immediate-escalating (or 
already immediate) functions, and complain later if they became 
consteval when instantiated.


I don't see why this is a significant obstacle to doing escalation late.


* cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.


Is this flag just for rejecting consteval-prop10.C?  I think we should 
not try to reject it.  This came up previously in the context of my 
patch for CWG2631, at which point I argued to CWG that it should be 
allowed, but nobody responded.  I'll ping that thread now, but in the 
mean time let's not go out of our way to reject this testcase that seems 
to me pretty clearly allowed by the current wording: that expression 
invokes an immediate function, so it's an immediate invocation.



diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 673ec91d60e..31f78b71fe1 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9735,7 +9735,9 @@ build_trivial_dtor_call (tree instance, bool no_ptr_deref)
  
  /* Return true if in an immediate function context, or an unevaluated operand,

 or a default argument/member initializer, or a subexpression of an 
immediate
-   invocation.  */
+   invocation.
+   ??? P2564 says that "a subexpression of a manifestly constant-evaluated
+   expression or conversion" is also an immediate function context.  */


Yes, that was to allow the consteval-prop2.C

  static_assert(is_not(5, is_even));

Since the operand of static_assert is manifestly constant-evaluated, 
it's OK that we name consteval is_even there.


We currently use this function to trigger evaluating immediate 
evaluations, and later (through immediate_invocation_p) to trigger 
errors, and other constant-evaluation happens between those two, so in 
most cases it's OK that this function does not identify that situation.


But there's another example in the paper, that this patch doesn't handle:

consteval int g(int p) { return p; }
template constexpr auto f(T) { 

Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-08-28 Thread Jason Merrill via Gcc-patches

On 8/24/23 09:31, Patrick Palka wrote:

On Wed, 23 Aug 2023, Jason Merrill wrote:


On 8/21/23 21:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

+ /* We're checking only non-instantiating conversions.
+A conversion may instantiate only if it's to/from a
+class type that has a constructor template/conversion
+function template.  */
+ tree parm_nonref = non_reference (parm);
+ tree type_nonref = non_reference (type);
+
+ if (CLASS_TYPE_P (parm_nonref))
+   {
+ if (!COMPLETE_TYPE_P (parm_nonref)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
+   return unify_success (explain_p);
+
+ tree ctors = get_class_binding (parm_nonref,
+ complete_ctor_identifier);
+ for (tree ctor : lkp_range (ctors))
+   if (TREE_CODE (ctor) == TEMPLATE_DECL)
+ return unify_success (explain_p);


Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?


Done; all dups of this PR seem to use tag types that are aggregates, so this
seems like a good simplification.  I also made us punt if the arg type has a
constrained non-template conversion function.



Also, instantiation can also happen when checking for conversion to a pointer
or reference to base class.


Oops, I suppose we just need to strip pointer types upfront as well.  The
!COMPLETE_TYPE_P && CLASSTYPE_TEMPLATE_INSTANTIATION tests will then make
sure we deem a potential derived-to-base conversion unsafe if appropriate
IIUC.

How does the following look?

-- >8 --

Subject: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

PR c++/99599

gcc/cp/ChangeLog:

* config-lang.in (gtfiles): Add search.cc.
* pt.cc (check_non_deducible_conversions): Add bool parameter
passed down to check_non_deducible_conversion.
(fn_type_unification): Call check_non_deducible_conversions
an extra time before satisfaction with noninst_only_p=true.
(check_non_deducible_conversion): Add bool parameter controlling
whether to compute only conversions that are guaranteed to
not induce template instantiation.
* search.cc (conversions_cache): Define.
(lookup_conversions): Use it to cache the lookup.  Improve cache
rate by considering TYPE_MAIN_VARIANT of the type.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-nondep4.C: New test.
---
  gcc/cp/config-lang.in |  1 +
  gcc/cp/pt.cc  | 81 +--
  gcc/cp/search.cc  | 14 +++-
  gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C | 21 +
  4 files changed, 110 insertions(+), 7 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-nondep4.C

@@ -22921,6 +22933,65 @@ check_non_deducible_conversion (tree parm, tree arg, 
unification_kind_t strict,
  {
bool ok = false;
tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
+  if (conv_p && *conv_p)
+   {
+ /* This conversion was already computed earlier (when
+computing only non-instantiating conversions).  */
+ gcc_checking_assert (!noninst_only_p);
+ return unify_success (explain_p);
+   }
+  if (noninst_only_p)
+   {
+ /* We're checking only non-instantiating conversions.
+Computing a conversion may induce template instantiation
+only if ... */


Let's factor this whole block out into another function.

Incidentally, CWG1092 is a related problem with defaulted functions, 
which I dealt with in a stricter way: when LOOKUP_DEFAULTED we ignore a 
conversion from the parameter being copied to a non-reference-related 
type.  As a follow-on, it might make sense to use this test there as well?


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

2023-08-28 Thread Jason Merrill via Gcc-patches

On 8/25/23 12:33, Patrick Palka wrote:

Boostrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


OK.


-- >8 --

This replaces manual memory management via conversion_obstack_alloc(0)
and obstack_free with the recently added conversion_obstack_sentinel,
and also uses the latter in build_user_type_conversion and
build_operator_new_call.

gcc/cp/ChangeLog:

* call.cc (build_user_type_conversion): Free allocated
conversions.
(build_converted_constant_expr_internal): Use
conversion_obstack_sentinel instead.
(perform_dguide_overload_resolution): Likewise.
(build_new_function_call): Likewise.
(build_operator_new_call): Free allocated conversions.
(build_op_call): Use conversion_obstack_sentinel instead.
(build_conditional_expr): Use conversion_obstack_sentinel
instead, and hoist it out to the outermost scope.
(build_new_op): Use conversion_obstack_sentinel instead
and set it up before the first goto.  Remove second unneeded goto.
(build_op_subscript): Use conversion_obstack_sentinel instead.
(ref_conv_binds_to_temporary): Likewise.
(build_new_method_call): Likewise.
(can_convert_arg): Likewise.
(can_convert_arg_bad): Likewise.
(perform_implicit_conversion_flags): Likewise.
(perform_direct_initialization_if_possible): Likewise.
(initialize_reference): Likewise.
---
  gcc/cp/call.cc | 107 ++---
  1 file changed, 22 insertions(+), 85 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 673ec91d60e..432ac99b4bb 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -4646,6 +4646,9 @@ build_user_type_conversion (tree totype, tree expr, int 
flags,
tree ret;
  
auto_cond_timevar tv (TV_OVERLOAD);

+
+  conversion_obstack_sentinel cos;
+
cand = build_user_type_conversion_1 (totype, expr, flags, complain);
  
if (cand)

@@ -4698,15 +4701,13 @@ build_converted_constant_expr_internal (tree type, tree 
expr,
int flags, tsubst_flags_t complain)
  {
conversion *conv;
-  void *p;
tree t;
location_t loc = cp_expr_loc_or_input_loc (expr);
  
if (error_operand_p (expr))

  return error_mark_node;
  
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */

-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
  
conv = implicit_conversion (type, TREE_TYPE (expr), expr,

  /*c_cast_p=*/false, flags, complain);
@@ -4815,9 +4816,6 @@ build_converted_constant_expr_internal (tree type, tree 
expr,
expr = error_mark_node;
  }
  
-  /* Free all the conversions we allocated.  */

-  obstack_free (_obstack, p);
-
return expr;
  }
  
@@ -4985,8 +4983,7 @@ perform_dguide_overload_resolution (tree dguides, const vec *args,
  
gcc_assert (deduction_guide_p (OVL_FIRST (dguides)));
  
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */

-  void *p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
  
z_candidate *cand = perform_overload_resolution (dguides, args, ,

   _viable_p, complain);
@@ -4999,9 +4996,6 @@ perform_dguide_overload_resolution (tree dguides, const 
vec *args,
else
  result = cand->fn;
  
-  /* Free all the conversions we allocated.  */

-  obstack_free (_obstack, p);
-
return result;
  }
  
@@ -5015,7 +5009,6 @@ build_new_function_call (tree fn, vec **args,

  {
struct z_candidate *candidates, *cand;
bool any_viable_p;
-  void *p;
tree result;
  
if (args != NULL && *args != NULL)

@@ -5028,8 +5021,7 @@ build_new_function_call (tree fn, vec **args,
if (flag_tm)
  tm_malloc_replacement (fn);
  
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */

-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
  
cand = perform_overload_resolution (fn, *args, , _viable_p,

  complain);
@@ -5061,9 +5053,6 @@ build_new_function_call (tree fn, vec **args,
  == BUILT_IN_NORMAL)
 result = coro_validate_builtin_call (result);
  
-  /* Free all the conversions we allocated.  */

-  obstack_free (_obstack, p);
-
return result;
  }
  
@@ -5108,6 +5097,8 @@ build_operator_new_call (tree fnname, vec **args,

if (*args == NULL)
  return error_mark_node;
  
+  conversion_obstack_sentinel cos;

+
/* Based on:
  
 [expr.new]

@@ -5234,7 +5225,6 @@ build_op_call (tree obj, vec **args, 
tsubst_flags_t complain)
tree fns, convs, first_mem_arg = NULL_TREE;
bool any_viable_p;
tree result = NULL_TREE;
-  void *p;
  
auto_cond_timevar tv (TV_OVERLOAD);
  
@@ -5273,8 +5263,7 @@ build_op_call (tree obj, vec **args, tsubst_flags_t complain)

return error_mark_node;
  }
  
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */


Re: [PATCH] c++: more dummy non_constant_p arg avoidance

2023-08-28 Thread Jason Merrill via Gcc-patches

On 8/25/23 13:41, Patrick Palka wrote:

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?  This
reduces calls to is_rvalue_constant_expression from
cp_parser_constant_expression by 10% for stdc++.h.


OK.


-- >8 --

As a follow-up to Marek's r14-3088-ga263152643bbec, this patch makes
us avoid passing an effectively dummy non_constant_p argument in two
more spots in the parser.

gcc/cp/ChangeLog:

* parser.cc (cp_parser_parenthesized_expression_list_elt): Pass
nullptr as non_constant_p to cp_parser_braced_list if our
non_constant_p is null.
(cp_parser_initializer_list): Likewise to
cp_parser_initializer_clause.
---
  gcc/cp/parser.cc | 11 ---
  1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 774706ac607..a8cc91059c1 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -8099,7 +8099,10 @@ cp_parser_parenthesized_expression_list_elt (cp_parser 
*parser, bool cast_p,
/* A braced-init-list.  */
cp_lexer_set_source_position (parser->lexer);
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
-  expr = cp_parser_braced_list (parser, _non_constant_p);
+  expr = cp_parser_braced_list (parser,
+   (non_constant_p != nullptr
+   ? _non_constant_p
+   : nullptr));
if (non_constant_p && expr_non_constant_p)
*non_constant_p = true;
  }
@@ -25812,9 +25815,11 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
  
/* Parse the initializer.  */

initializer = cp_parser_initializer_clause (parser,
- _non_constant_p);
+ (non_constant_p != nullptr
+  ? _non_constant_p
+  : nullptr));
/* If any clause is non-constant, so is the entire initializer.  */
-  if (clause_non_constant_p && non_constant_p)
+  if (non_constant_p && clause_non_constant_p)
*non_constant_p = true;
  
/* If we have an ellipsis, this is an initializer pack




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

2023-08-28 Thread Jason Merrill via Gcc-patches

On 8/25/23 12:44, Marek Polacek wrote:

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

-- >8 --

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

PR c++/91319

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index eeb22e44fb4..b3d5c65b469 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -25718,6 +25718,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
tree designator;
tree initializer;
bool clause_non_constant_p;
+  bool direct_p = false;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
  
/* Handle the C++20 syntax, '. id ='.  */

@@ -25740,6 +25741,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
  if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
/* Consume the `='.  */
cp_lexer_consume_token (parser->lexer);
+ else
+   direct_p = true;
}
/* Also, if the next token is an identifier and the following one is a
 colon, we are looking at the GNU designated-initializer
@@ -25817,6 +25820,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* 
non_constant_p,
if (clause_non_constant_p && non_constant_p)
*non_constant_p = true;
  
+  if (TREE_CODE (initializer) == CONSTRUCTOR)

+   CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p;


Why |= rather than = ?

Jason



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

2023-08-25 Thread Jason Merrill via Gcc-patches

On 8/25/23 19:37, Marek Polacek wrote:

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

-- >8 --

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

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

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

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

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..09ebcf6a115 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8459,12 +8459,21 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
if (pedwarn (loc, 0, "converting to %qT from initializer list "
 "would use explicit constructor %qD",
 totype, convfn))
- inform (loc, "in C++11 and above a default constructor "
- "can be explicit");
+ {
+   inform (loc, "in C++11 and above a default constructor "
+   "can be explicit");
+   inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
+   convfn);


I'd swap these two informs.


+++ b/gcc/testsuite/g++.dg/diagnostic/explicit.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+struct S {
+  explicit S(int) { }
+  explicit operator bool() const { return true; } // { dg-message "explicit 
conversion function was not considered" }
+  explicit operator int() const { return 42; } // { dg-message "explicit conversion 
function was not considered" }
+};
+
+void
+g ()
+{
+  S s = {1}; // { dg-error "would use explicit constructor" }
+  bool b = S{1}; // { dg-error "cannot convert .S. to .bool. in 
initialization" }
+  int i;
+  i = S{2}; // { dg-error "cannot convert .S. to .int. in assignment" }
+}


Let's also test other copy-initialization contexts: parameter passing, 
return, throw, aggregate member initialization.


Jason



Re: [PATCH] c++: Fix up mangling of function/block scope static structured bindings [PR111069]

2023-08-23 Thread Jason Merrill via Gcc-patches

On 8/22/23 04:12, Jakub Jelinek wrote:

As can be seen on the testcase, we weren't correctly mangling
static/thread_local structured bindings (C++20 feature) at function/block
scope.  The following patch fixes that by using what write_local_name
does for those cases (note, structured binding mandling doesn't use the
standard path because it needs to pass a list of all the identifiers in
the structured binding to the mangling).  In addition to that it fixes
mangling of various helpers which use write_guarded_name (_ZGV*, _ZTH*,
_ZTW*) and kills find_decomp_unqualified_name which for the local names
would be too hard to implement and uses write_guarded_name for structured
binding related _ZGR* names as well.
All the mangled names on the testcase match now clang++ and my expectations.
Because the old mangled names were plain wrong (they mangled the same as
structured binding at global scope and resulted in assembly errors if there
was more than one static structured binding with the same identifiers in
the same (or another) function, I think we don't need to play with another
mangling ABI level which turns on/off the old broken way, unsure whether
we should backport the patch to 13 branch though.


Probably not.


BTW, I think we should also handle ABI tags in mangle_decomp which we
currently don't do, but guess that should be subject to another mangling ABI
version.


I'd be surprised if this would affect any real code, but I suppose so. 
In any case I'd like to fix this at the same time as the local statics, 
to avoid changing their mangled name twice.



@@ -9049,6 +9050,25 @@ cp_maybe_mangle_decomp (tree decl, tree
tree d = first;
for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
v[count - i - 1] = d;
+  if (DECL_FUNCTION_SCOPE_P (decl))
+   {
+ size_t sz = 3;
+ for (unsigned int i = 0; i < count; ++i)
+   sz += IDENTIFIER_LENGTH (DECL_NAME (v[i])) + 1;
+ char *name = XALLOCAVEC (char, sz);
+ name[0] = 'D';
+ name[1] = 'C';
+ char *p = name + 2;
+ for (unsigned int i = 0; i < count; ++i)
+   {
+ size_t len = IDENTIFIER_LENGTH (DECL_NAME (v[i]));
+ *p++ = ' ';
+ memcpy (p, IDENTIFIER_POINTER (DECL_NAME (v[i])), len);
+ p += len;
+   }
+ *p = '\0';
+ determine_local_discriminator (decl, get_identifier (name));
+   }


Maybe do this in mangle_decomp, based on the actual mangling in process 
instead of this pseudo-mangling?



@@ -4564,6 +4519,13 @@ write_guarded_var_name (const tree varia
  /* The name of a guard variable for a reference temporary should refer
 to the reference, not the temporary.  */
  write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
+  else if (DECL_DECOMPOSITION_P (variable)
+  && DECL_NAME (variable) == NULL_TREE
+  && startswith (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)),
+ "_Z"))


Maybe add a startswith overload that takes an identifier?


@@ -4630,7 +4592,10 @@ mangle_ref_init_variable (const tree var
start_mangling (variable);
write_string ("_ZGR");
check_abi_tags (variable);
-  write_name (variable, /*ignore_local_scope=*/0);
+  if (DECL_DECOMPOSITION_P (variable))
+write_guarded_var_name (variable);
+  else
+write_name (variable, /*ignore_local_scope=*/0);


Why not use write_guarded_name unconditionally?

Jason



Re: [PATCH] c++: refine CWG 2369 satisfaction vs non-dep convs [PR99599]

2023-08-23 Thread Jason Merrill via Gcc-patches

On 8/21/23 21:51, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look like
a reasonable approach?  I didn't observe any compile time/memory impact
of this change.

-- >8 --

As described in detail in the PR, CWG 2369 has the surprising
consequence of introducing constraint recursion in seemingly valid and
innocent code.

This patch attempts to fix this surpising behavior for the majority
of problematic use cases.  Rather than checking satisfaction before
_all_ non-dependent conversions, as specified by the CWG issue,
this patch makes us first check "safe" non-dependent conversions,
then satisfaction, then followed by "unsafe" non-dependent conversions.
In this case, a conversion is "safe" if computing it is guaranteed
to not induce template instantiation.  This patch heuristically
determines "safety" by checking for a constructor template or conversion
function template in the (class) parm or arg types respectively.
If neither type has such a member, then computing the conversion
should not induce instantiation (modulo satisfaction checking of
non-template constructor and conversion functions I suppose).

+ /* We're checking only non-instantiating conversions.
+A conversion may instantiate only if it's to/from a
+class type that has a constructor template/conversion
+function template.  */
+ tree parm_nonref = non_reference (parm);
+ tree type_nonref = non_reference (type);
+
+ if (CLASS_TYPE_P (parm_nonref))
+   {
+ if (!COMPLETE_TYPE_P (parm_nonref)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (parm_nonref))
+   return unify_success (explain_p);
+
+ tree ctors = get_class_binding (parm_nonref,
+ complete_ctor_identifier);
+ for (tree ctor : lkp_range (ctors))
+   if (TREE_CODE (ctor) == TEMPLATE_DECL)
+ return unify_success (explain_p);


Today we discussed maybe checking CLASSTYPE_NON_AGGREGATE?

Also, instantiation can also happen when checking for conversion to a 
pointer or reference to base class.


Jason



Re: [PATCH] debug/111080 - avoid outputting debug info for unused restrict qualified type

2023-08-23 Thread Jason Merrill via Gcc-patches

On 8/21/23 05:11, Richard Biener wrote:

The following applies some maintainance with respect to type qualifiers
and kinds added by later DWARF standards to prune_unused_types_walk.
The particular case in the bug is not handling (thus marking required)
all restrict qualified type DIEs.  I've found more DW_TAG_*_type that
are unhandled, looked up the DWARF docs and added them as well based
on common sense.

Bootstrapped and tested on x86_64-unknown-linux-gnu, OK?


OK.


Thanks,
Richard.

PR debug/111080
* dwarf2out.cc (prune_unused_types_walk): Handle
DW_TAG_restrict_type, DW_TAG_shared_type, DW_TAG_atomic_type,
DW_TAG_immutable_type, DW_TAG_coarray_type, DW_TAG_unspecified_type
and DW_TAG_dynamic_type as to only output them when referenced.

* gcc.dg/debug/dwarf2/pr111080.c: New testcase.
---
  gcc/dwarf2out.cc |  7 +++
  gcc/testsuite/gcc.dg/debug/dwarf2/pr111080.c | 18 ++
  2 files changed, 25 insertions(+)
  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/pr111080.c

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index fa0fe4c41bb..69018bde238 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -30141,8 +30141,13 @@ prune_unused_types_walk (dw_die_ref die)
  case DW_TAG_reference_type:
  case DW_TAG_rvalue_reference_type:
  case DW_TAG_volatile_type:
+case DW_TAG_restrict_type:
+case DW_TAG_shared_type:
+case DW_TAG_atomic_type:
+case DW_TAG_immutable_type:
  case DW_TAG_typedef:
  case DW_TAG_array_type:
+case DW_TAG_coarray_type:
  case DW_TAG_friend:
  case DW_TAG_enumeration_type:
  case DW_TAG_subroutine_type:
@@ -30151,6 +30156,8 @@ prune_unused_types_walk (dw_die_ref die)
  case DW_TAG_subrange_type:
  case DW_TAG_ptr_to_member_type:
  case DW_TAG_file_type:
+case DW_TAG_unspecified_type:
+case DW_TAG_dynamic_type:
/* Type nodes are useful only when other DIEs reference them --- don't
 mark them.  */
/* FALLTHROUGH */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr111080.c 
b/gcc/testsuite/gcc.dg/debug/dwarf2/pr111080.c
new file mode 100644
index 000..3949d7e7c64
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr111080.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-save-temps -gdwarf-3 -dA" } */
+
+struct foo {
+int field_number_1;
+int field_number_2;
+int field_number_3;
+int field_number_4;
+int field_number_5;
+};
+
+typedef int fun_t(struct foo *restrict);
+
+int main() {
+return 0;
+}
+
+/* { dg-final { scan-assembler-not "DW_TAG_structure_type" } } */




Re: [PATCH v7 2/4] p1689r5: initial support

2023-08-23 Thread Jason Merrill via Gcc-patches

On 7/2/23 12:32, Ben Boeckel wrote:

This patch implements support for [P1689R5][] to communicate to a build
system the C++20 module dependencies to build systems so that they may
build `.gcm` files in the proper order.

Support is communicated through the following three new flags:

- `-fdeps-format=` specifies the format for the output. Currently named
   `p1689r5`.

- `-fdeps-file=` specifies the path to the file to write the format to.

- `-fdeps-target=` specifies the `.o` that will be written for the TU
   that is scanned. This is required so that the build system can
   correlate the dependency output with the actual compilation that will
   occur.

CMake supports this format as of 17 Jun 2022 (to be part of 3.25.0)
using an experimental feature selection (to allow for future usage
evolution without committing to how it works today). While it remains
experimental, docs may be found in CMake's documentation for
experimental features.

Future work may include using this format for Fortran module
dependencies as well, however this is still pending work.

[P1689R5]: https://isocpp.org/files/papers/P1689R5.html
[cmake-experimental]: 
https://gitlab.kitware.com/cmake/cmake/-/blob/master/Help/dev/experimental.rst

TODO:

- header-unit information fields

Header units (including the standard library headers) are 100%
unsupported right now because the `-E` mechanism wants to import their
BMIs. A new mode (i.e., something more workable than existing `-E`
behavior) that mocks up header units as if they were imported purely
from their path and content would be required.

- non-utf8 paths

The current standard says that paths that are not unambiguously
represented using UTF-8 are not supported (because these cases are rare
and the extra complication is not worth it at this time). Future
versions of the format might have ways of encoding non-UTF-8 paths. For
now, this patch just doesn't support non-UTF-8 paths (ignoring the
"unambiguously representable in UTF-8" case).

- figure out why junk gets placed at the end of the file

Sometimes it seems like the file gets a lot of `NUL` bytes appended to
it. It happens rarely and seems to be the result of some
`ftruncate`-style call which results in extra padding in the contents.
Noting it here as an observation at least.


Thank you for your patience, just a few tweaks left and I think we can 
put this all in this week or next.



diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index aef703f8111..141cfd60eda 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -302,6 +302,9 @@ typedef CPPCHAR_SIGNED_T cppchar_signed_t;
  /* Style of header dependencies to generate.  */
  enum cpp_deps_style { DEPS_NONE = 0, DEPS_USER, DEPS_SYSTEM };
  
+/* Structured format of module dependencies to generate.  */

+enum cpp_fdeps_format { DEPS_FMT_NONE = 0, DEPS_FMT_P1689R5 };


These should be FDEPS_FMT_* or just FDEPS_*.


@@ -395,10 +423,16 @@ make_write (const cpp_reader *pfile, FILE *fp, unsigned 
int colmax)
   if (colmax && colmax < 34)
 colmax = 34;
 
+  /* Write out C++ modules information if no other `-fdeps-format=`

+ option is given. */
+  cpp_fdeps_format fdeps_format = CPP_OPTION (pfile, deps.fdeps_format);
+  bool write_make_modules_deps = fdeps_format == DEPS_FMT_NONE &&
+CPP_OPTION (pfile, deps.modules);


We typically format an expression like this as:


+  bool write_make_modules_deps = (fdeps_format == FDEPS_FMT_NONE
+ && CPP_OPTION (pfile, deps.modules));



@@ -473,6 +507,117 @@ deps_write (const cpp_reader *pfile, FILE *fp, unsigned 
int colmax)
   make_write (pfile, fp, colmax);
 }
 
+static void

+p1689r5_write_filepath (const char *name, FILE *fp)


This and the other p1689r5 functions need more comments, at least one at 
the top explaining their purpose.


Jason



Re: [PATCH v7 1/4] driver: add a spec function to join arguments

2023-08-23 Thread Jason Merrill via Gcc-patches

On 7/2/23 12:32, Ben Boeckel wrote:

When passing `-o` flags to other options, the typical `-o foo` spelling
leaves a leading whitespace when replacing elsewhere. This ends up
creating flags spelled as `-some-option-with-arg= foo.ext` which doesn't
parse properly. When attempting to make a spec function to just remove
the leading whitespace, the argument splitting ends up masking the
whitespace. However, the intended extension *also* ends up being its own
argument.


Odd.  I looked into this to figure out what was going on, and now I 
understand: when process_brace_body handles e.g. %{o*:-fjoined=%.x%*}, 
first it replaces $* with the rest of the flag, i.e. "", resulting in 
-fjoined=, and then adds the argument as a separate argument to the 
result of substitution.  This seems strange, but works fine for the 
existing uses that build one Separate switch from another.


The other oddity you mention comes from

  /* End of string.  If we are processing a spec function, we need to   
 end any pending argument.  */

  if (processing_spec_function)
end_going_arg ();


so that when give_switch calls do_spec_1 twice for the basename and 
suffix, they end up as separate arguments to the spec function.  I don't 
know the purpose of this code; it doesn't seem to have been necessary 
for the if-exists spec function that was added in the same patch 
(r59241).  Removing this doesn't seem to break anything for me.


The join function works around both of these issues.  But I notice that 
the use of reconcat is a memory leak, and since we have the obstack 
available I've tweaked the function to use it.  I also added some 
documentation.


Joseph, any thoughts on these issues or the workaround?

JasonFrom ca7c76c5b44e76e8596bf8db68d6210fd9ddf113 Mon Sep 17 00:00:00 2001
From: Ben Boeckel 
Date: Sun, 2 Jul 2023 12:32:08 -0400
Subject: [PATCH] driver: add a spec function to join arguments
To: gcc-patches@gcc.gnu.org

When passing `-o` flags to other options, the typical `-o foo` spelling
leaves a leading whitespace when replacing elsewhere. This ends up
creating flags spelled as `-some-option-with-arg= foo.ext` which doesn't
parse properly. When attempting to make a spec function to just remove
the leading whitespace, the argument splitting ends up masking the
whitespace. However, the intended extension *also* ends up being its own
argument. To perform the desired behavior, the arguments need to be
concatenated together.

gcc/:

	* gcc.cc (join_spec_func): Add a spec function to join all
	arguments.
	* doc/invoke.texi: Document it.

Signed-off-by: Ben Boeckel 
Co-authored-by: Jason Merrill 
---
 gcc/doc/invoke.texi | 10 ++
 gcc/gcc.cc  | 23 +++
 2 files changed, 33 insertions(+)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ef3f4098986..7c475ee5c82 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -35236,6 +35236,16 @@ usage:
 -l%:if-exists-then-else(%:getenv(VSB_DIR rtnet.h) rtnet net)
 @end smallexample
 
+@item @code{join}
+The @code{join} spec function returns the concatenation of its
+arguments.  This is currently used to build e.g. @samp{-fjoined=foo.b}
+from @samp{-fseparate foo.a}, as the behavior of @samp{%*} without this
+function produces the broken @samp{-fjoined= foo.b} instead.
+
+@smallexample
+%@{-fseparate*:-fjoined=%:join(%.b%*)@}
+@end smallexample
+
 @item @code{sanitize}
 The @code{sanitize} spec function takes no arguments.  It returns non-NULL if
 any address, thread or undefined behavior sanitizers are active.
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index fdfac0b4fe4..4c4e81dee50 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -447,6 +447,7 @@ static const char *greater_than_spec_func (int, const char **);
 static const char *debug_level_greater_than_spec_func (int, const char **);
 static const char *dwarf_version_greater_than_spec_func (int, const char **);
 static const char *find_fortran_preinclude_file (int, const char **);
+static const char *join_spec_func (int, const char **);
 static char *convert_white_space (char *);
 static char *quote_spec (char *);
 static char *quote_spec_arg (char *);
@@ -1772,6 +1773,7 @@ static const struct spec_function static_spec_functions[] =
   { "debug-level-gt",		debug_level_greater_than_spec_func },
   { "dwarf-version-gt",		dwarf_version_greater_than_spec_func },
   { "fortran-preinclude-file",	find_fortran_preinclude_file},
+  { "join",			join_spec_func},
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -10975,6 +10977,27 @@ find_fortran_preinclude_file (int argc, const char **argv)
   return result;
 }
 
+/* The function takes any number of arguments and joins them together.
+
+   This seems to be necessary to build "-fjoined=foo.b" from "-fseparate foo.a"
+   with a %{fseparate*:-fjoined=%.b$*} rule without adding undesired spaces:
+   when doing $* replacement we first replace $* with the rest of the switch
+   

[pushed 2/2] c++: maybe_substitute_reqs_for fix

2023-08-22 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

While working on PR109751 I found that maybe_substitute_reqs_for was doing
the wrong thing for a non-template friend, substituting in the template args
of the scope's original template rather than those of the instantiation.
This didn't end up being necessary to fix the PR, but it's still an
improvement.

gcc/cp/ChangeLog:

* pt.cc (outer_template_args): Handle non-template argument.
* constraint.cc (maybe_substitute_reqs_for): Pass decl to it.
* cp-tree.h (outer_template_args): Adjust.
---
 gcc/cp/cp-tree.h |  2 +-
 gcc/cp/constraint.cc |  2 +-
 gcc/cp/pt.cc | 12 +++-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 356d7ffb6d6..eb901683b6d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7083,7 +7083,7 @@ extern tree maybe_set_retval_sentinel (void);
 extern tree template_parms_to_args (tree);
 extern tree template_parms_level_to_args   (tree);
 extern tree generic_targs_for  (tree);
-extern tree outer_template_args(tree);
+extern tree outer_template_args(const_tree);
 
 /* in expr.cc */
 extern tree cplus_expand_constant  (tree);
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..c9e4e7043cd 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1339,7 +1339,7 @@ maybe_substitute_reqs_for (tree reqs, const_tree decl)
   if (DECL_UNIQUE_FRIEND_P (decl) && DECL_TEMPLATE_INFO (decl))
 {
   tree tmpl = DECL_TI_TEMPLATE (decl);
-  tree outer_args = outer_template_args (tmpl);
+  tree outer_args = outer_template_args (decl);
   processing_template_decl_sentinel s;
   if (PRIMARY_TEMPLATE_P (tmpl)
  || uses_template_parms (outer_args))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f4e77d172b9..c017591f235 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4966,19 +4966,21 @@ generic_targs_for (tree tmpl)
 }
 
 /* Return the template arguments corresponding to the template parameters of
-   TMPL's enclosing scope.  When TMPL is a member of a partial specialization,
+   DECL's enclosing scope.  When DECL is a member of a partial specialization,
this returns the arguments for the partial specialization as opposed to 
those
for the primary template, which is the main difference between this function
-   and simply using e.g. the TYPE_TI_ARGS of TMPL's DECL_CONTEXT.  */
+   and simply using e.g. the TYPE_TI_ARGS of DECL's DECL_CONTEXT.  */
 
 tree
-outer_template_args (tree tmpl)
+outer_template_args (const_tree decl)
 {
-  tree ti = get_template_info (DECL_TEMPLATE_RESULT (tmpl));
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
+decl = DECL_TEMPLATE_RESULT (decl);
+  tree ti = get_template_info (decl);
   if (!ti)
 return NULL_TREE;
   tree args = TI_ARGS (ti);
-  if (!PRIMARY_TEMPLATE_P (tmpl))
+  if (!PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)))
 return args;
   if (TMPL_ARGS_DEPTH (args) == 1)
 return NULL_TREE;
-- 
2.39.3



[pushed 1/2] c++: constrained hidden friends [PR109751]

2023-08-22 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

r13-4035 avoided a problem with overloading of constrained hidden friends by
checking satisfaction, but checking satisfaction early is inconsistent with
the usual late checking and can lead to hard errors, so let's not do that
after all.

We were wrongly treating the different instantiations of the same friend
template as the same function because maybe_substitute_reqs_for was failing
to actually substitute in the case of a non-template friend.  But we don't
actually need to do the substitution anyway, because [temp.friend] says that
such a friend can't be the same as any other declaration.

After fixing that, instead of a redefinition error we got an ambiguous
overload error, fixed by allowing constrained hidden friends to coexist
until overload resolution, at which point they probably won't be in the same
ADL overload set anyway.

And we avoid mangling collisions by following the proposed mangling for
these friends as a member function with an extra 'F' before the name.  I
demangle this by just adding [friend] to the name of the function because
it's not feasible to reconstruct the actual scope of the function since the
mangling ABI doesn't distinguish between class and namespace scopes.

PR c++/109751

gcc/cp/ChangeLog:

* cp-tree.h (member_like_constrained_friend_p): Declare.
* decl.cc (member_like_constrained_friend_p): New.
(function_requirements_equivalent_p): Check it.
(duplicate_decls): Check it.
(grokfndecl): Check friend template constraints.
* mangle.cc (decl_mangling_context): Check it.
(write_unqualified_name): Check it.
* pt.cc (uses_outer_template_parms_in_constraints): Fix for friends.
(tsubst_friend_function): Don't check satisfaction.

include/ChangeLog:

* demangle.h (enum demangle_component_type): Add
DEMANGLE_COMPONENT_FRIEND.

libiberty/ChangeLog:

* cp-demangle.c (d_make_comp): Handle DEMANGLE_COMPONENT_FRIEND.
(d_count_templates_scopes): Likewise.
(d_print_comp_inner): Likewise.
(d_unqualified_name): Handle member-like friend mangling.
* testsuite/demangle-expected: Add test.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-friend11.C: Now works.  Add template.
* g++.dg/cpp2a/concepts-friend15.C: New test.
---
 gcc/cp/cp-tree.h  |  3 +-
 include/demangle.h|  2 +
 gcc/cp/decl.cc| 49 ++-
 gcc/cp/mangle.cc  | 10 
 gcc/cp/pt.cc  | 14 --
 .../g++.dg/cpp2a/concepts-friend11.C  | 26 ++
 .../g++.dg/cpp2a/concepts-friend11a.C | 15 ++
 .../g++.dg/cpp2a/concepts-friend15.C  | 22 +
 libiberty/cp-demangle.c   | 17 +++
 libiberty/testsuite/demangle-expected |  3 ++
 10 files changed, 145 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-friend11a.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-friend15.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d051ee85f70..356d7ffb6d6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6859,6 +6859,7 @@ extern void note_break_stmt   (void);
 extern bool note_iteration_stmt_body_start (void);
 extern void note_iteration_stmt_body_end   (bool);
 extern void determine_local_discriminator  (tree);
+extern bool member_like_constrained_friend_p   (tree);
 extern bool fns_correspond (tree, tree);
 extern int decls_match (tree, tree, bool = true);
 extern bool maybe_version_functions(tree, tree, bool);
@@ -7385,7 +7386,7 @@ extern tree lookup_template_function  (tree, 
tree);
 extern tree lookup_template_variable   (tree, tree, tsubst_flags_t);
 extern bool uses_template_parms(tree);
 extern bool uses_template_parms_level  (tree, int);
-extern bool uses_outer_template_parms_in_constraints (tree);
+extern bool uses_outer_template_parms_in_constraints (tree, tree = NULL_TREE);
 extern bool need_generic_capture   (void);
 extern tree instantiate_class_template (tree);
 extern tree instantiate_template   (tree, tree, tsubst_flags_t);
diff --git a/include/demangle.h b/include/demangle.h
index 769137e03e5..f062d7731c6 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -448,6 +448,8 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_TRANSACTION_SAFE,
   /* A cloned function.  */
   DEMANGLE_COMPONENT_CLONE,
+  /* A member-like friend function.  */
+  DEMANGLE_COMPONENT_FRIEND,
   DEMANGLE_COMPONENT_NOEXCEPT,
   DEMANGLE_COMPONENT_THROW_SPEC,
 
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 62c34bf9abe..bea0ee92106 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -951,6 

Re: [PATCH v4] c++: extend cold, hot attributes to classes

2023-08-22 Thread Jason Merrill via Gcc-patches

On 8/15/23 09:41, Javier Martinez wrote:
On Mon, Aug 14, 2023 at 8:32 PM Jason Merrill > wrote:

 > I think you also want to check for ATTR_FLAG_TYPE_IN_PLACE.
 > [...]
 > > +  propagate_class_warmth_attribute (t);
 > Maybe call this in check_bases_and_members instead?

Yes, that is sensible. Done.


You still need an update to doc/extend.texi for this additional use of 
the attribute.  Sorry I didn't think of that before.



+ warning (OPT_Wattributes, "ignoring attribute %qE because it "
+   "conflicts with attribute %qs", name, "cold");

...

+ warning (OPT_Wattributes, "ignoring attribute %qE because it "
+   "conflicts with attribute %qs", name, "hot");


Function arguments continuing on the next line should line up with the '('.


+  tree class_has_cold_attr = lookup_attribute ("cold",
+   TYPE_ATTRIBUTES (t));
+  tree class_has_hot_attr = lookup_attribute ("hot",
+   TYPE_ATTRIBUTES (t));


...so I'd suggest reformatting these lines as:

   tree class_has_cold_attr
 = lookup_attribute ("cold", TYPE_ATTRIBUTES (t));
   tree class_has_hot_attr
 = lookup_attribute ("hot", TYPE_ATTRIBUTES (t));


+   decl_attributes (,
+   tree_cons (get_identifier ("cold"), NULL, NULL), 0);


...and maybe use a local variable for the result of tree_cons.


+  if (has_cold_attr || has_hot_attr)
+{
+
+  /* Transparently ignore the new warmth attribute if it


Unnecessary blank line.

Jason



Re: [PATCH v3] c++: extend cold, hot attributes to classes

2023-08-14 Thread Jason Merrill via Gcc-patches

On 8/11/23 09:18, Javier Martinez wrote:

Hi Jason,

Regarding the initialization example - no, the set of classes that we 
consider cold is more loosely defined.


On Thu, Aug 10, 2023 at 11:01 PM Jason Merrill > wrote:

 > Yes, but that's because the implicit op== isn't declared lazily like
 > some other special member functions (CLASSTYPE_LAZY_*/lazily_declare_fn)
 > which can happen after the class is complete.

I see, thanks. I have fixed this now by injecting it directly from 
lazily_declare_fn, works well. Doing it from grokclassfn instead seems 
to be a nuisance because the explicit method attribute might be 
processed after the class-propagated attribute is injected, which is the 
wrong way around for the desired precedence.


 > I think it would work to check for (flags & (ATTR_FLAG_FUNCTION_NEXT |
 > ATTR_FLAG_DECL_NEXT)) and return without warning in that case.  You'd
 > still set *no_add_attr.

Correct, done.

I have added the patch as an attachment, if it garbles it then I will 
use git-send-email next time.


That worked fine, thanks.


@@ -1110,6 +1110,28 @@ handle_hot_attribute (tree *node, tree name, tree 
ARG_UNUSED (args),
 {
   /* Attribute hot processing is done later with lookup_attribute.  */
 }
+  else if ((TREE_CODE (*node) == RECORD_TYPE
+   || TREE_CODE (*node) == UNION_TYPE)
+ && c_dialect_cxx ())


I think you also want to check for ATTR_FLAG_TYPE_IN_PLACE.


@@ -7866,6 +7891,10 @@ finish_struct (tree t, tree attributes)
   && !LAMBDA_TYPE_P (t))
 add_stmt (build_min (TAG_DEFN, t));
 
+  /* This must be done after all lazily declared special member functions

+ have been injected.  */
+  propagate_class_warmth_attribute (t);


Maybe call this in check_bases_and_members instead?

Jason



Re: [PATCH v1] c++: follow DR 2386 and update implementation of get_tuple_size [PR110216]

2023-08-14 Thread Jason Merrill via Gcc-patches

On 8/12/23 04:16, gnaggnoyil wrote:

DR 2386 updated the tuple_size requirements for structured binding and
it now requires tuple_size to be considered only if
std::tuple_size names a complete class type with member value. GCC
before this patch does not follow the updated requrements, and this
patch is intended to implement it.

DR 2386
PR c++/110216

gcc/cp/ChangeLog:

* decl.cc (get_tuple_size): Update implemetation to follow DR 2386.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/decomp10.C: Update expected error message for DR 2386.
* g++.dg/cpp1z/pr110216.C: New test.

Signed-off-by: gnaggnoyil 


Pushed, thanks!

Note that the GCC DCO policy (https://gcc.gnu.org/dco.html) requires 
real names in the sign-off; in this case I've applied the patch anyway 
because it is small enough that it's not legally significant for copyright.


I think if you want to contribute larger patches under this pseudonym, 
you should file a copyright assignment with the FSF, which explicitly 
allows this.  "If a contributor wants the FSF to publish only a 
pseudonym, that is ok. The contributor should say this, and state the 
desired pseudonym, when answering the request- form. The actual legal 
papers will use the real name, but the FSF will publish only the 
pseudonym."[2]


Thanks again,
Jason

[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/Documentation/process?id=d4563201f33a022fc0353033d9dfeb1606a88330

[2] https://www.gnu.org/prep/maintain/maintain.html#Copyright-Papers



[pushed] c++: -fconcepts and __cpp_concepts

2023-08-14 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Since -fconcepts no longer implies -fconcepts-ts, we shouldn't advertise TS
support with __cpp_concepts=201507L.  Also fix one case where -std=c++14
-fconcepts wasn't working (as found by range-v3 calendar).  Fixing other
cases is not a priority, probably better to reject that flag combination if
there are further issues.

gcc/c-family/ChangeLog:

* c-cppbuiltin.cc (c_cpp_builtins): Adjust __cpp_concepts.

gcc/cp/ChangeLog:

* parser.cc (cp_parser_simple_type_specifier): Handle -std=c++14
-fconcepts.
---
 gcc/c-family/c-cppbuiltin.cc | 2 +-
 gcc/cp/parser.cc | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 6bd4c1261a7..f2b12fd63db 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1089,7 +1089,7 @@ c_cpp_builtins (cpp_reader *pfile)
}
   if (flag_concepts)
 {
- if (cxx_dialect >= cxx20)
+ if (cxx_dialect >= cxx20 || !flag_concepts_ts)
cpp_define (pfile, "__cpp_concepts=202002L");
   else
 cpp_define (pfile, "__cpp_concepts=201507L");
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 2d27376d988..7f646704d3f 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -20017,12 +20017,13 @@ cp_parser_simple_type_specifier (cp_parser* parser,
   /* Otherwise, look for a type-name.  */
   if (!type)
{
- if (cxx_dialect >= cxx17)
+ if (cxx_dialect >= cxx17 || flag_concepts)
cp_parser_parse_tentatively (parser);
 
  type = cp_parser_type_name (parser, (qualified_p && typename_p));
 
- if (cxx_dialect >= cxx17 && !cp_parser_parse_definitely (parser))
+ if ((cxx_dialect >= cxx17 || flag_concepts)
+ && !cp_parser_parse_definitely (parser))
type = NULL_TREE;
}
 

base-commit: 2d2b05f0691799f03062bf5c436462f14cad3e7c
-- 
2.39.3



Re: [PATCH] tree-pretty-print: delimit TREE_VEC with braces

2023-08-11 Thread Jason Merrill via Gcc-patches

On 8/11/23 13:35, Patrick Palka wrote:

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?


OK.


-- >8 --

This makes the generic pretty printer print braces around a TREE_VEC
like we do for CONSTRUCTOR.  This should improve readability of nested
TREE_VECs in particular.

gcc/ChangeLog:

* tree-pretty-print.cc (dump_generic_node) :
Delimit output with braces.
---
  gcc/tree-pretty-print.cc | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc
index 51a213529d1..579037b32c2 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -1900,6 +1900,7 @@ dump_generic_node (pretty_printer *pp, tree node, int 
spc, dump_flags_t flags,
  case TREE_VEC:
{
size_t i;
+   pp_left_brace (pp);
if (TREE_VEC_LENGTH (node) > 0)
  {
size_t len = TREE_VEC_LENGTH (node);
@@ -1913,6 +1914,7 @@ dump_generic_node (pretty_printer *pp, tree node, int 
spc, dump_flags_t flags,
dump_generic_node (pp, TREE_VEC_ELT (node, len - 1), spc,
   flags, false);
  }
+   pp_right_brace (pp);
}
break;
  




Re: [PATCH] c, c++, v2: Accept __builtin_classify_type (typename)

2023-08-11 Thread Jason Merrill via Gcc-patches

On 8/11/23 04:48, Jakub Jelinek wrote:

On Fri, Aug 11, 2023 at 01:13:32AM +0200, Jakub Jelinek wrote:

Looking at the first uses of the builtin back in 90s in va*.h, it certainly
relied on array/function decay there (the macros would abort e.g. on
array_type_class, function_type_class and various other return values).
Looking at older versions of tgmath.h, I see just checks for 8/9 (i.e.
real/complex) and those woiuldn't be affected by any promotions/decay.
But newer versions of tgmath.h before __builtin_tgmath do check also for
1 and they would be upset if char wasn't promoted to int (including latest
glibc).
systemtap macros also use __builtin_classify_type and do check for pointers
but those seems to be prepared to handle even arrays.


So to sum it up, I think at least the original use of the builtin had a
strong reason to do the array to pointer etc. decay and argument promotion,
because that is what happens with the varargs too and the builtin is still
documented in the internals manual just for that purpose.  It is true GCC
doesn't use the builtin for that reason anymore, but there are numerous
uses in the wild, some might cope well with changing the behavior, others
less so.


+   cp_evaluated ev;
+   ++cp_unevaluated_operand;
+   ++c_inhibit_evaluation_warnings;


These three lines seem unnecessary for parsing a type.


I had a quick look at this and a reason to do at least some of this
is e.g. array types, __builtin_classify_type (int [foo () + whatever])
will not really evaluate foo () + whatever, all it will care about is that
it is an array, so emiting evaluation warnings for it would be weird.
cp_unevaluated_operand is harder to find out what all the effects are,
but e.g. warnings for missing member initializers in such expressions
isn't needed either.


Fair enough.  But you should only need a single line

cp_unevaluated ev;

The C++ bits are OK with that change.

Jason



Re: [PATCH] c++: bogus warning w/ deduction guide in anon ns [PR106604]

2023-08-11 Thread Jason Merrill via Gcc-patches

On 8/11/23 09:54, Patrick Palka wrote:

On Thu, 10 Aug 2023, Jason Merrill wrote:


On 8/10/23 16:40, Patrick Palka wrote:

On Thu, 10 Aug 2023, Jason Merrill wrote:


On 8/10/23 12:09, Patrick Palka wrote:

Booststrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for
trunk and perhaps 13?

-- >8 --

We shouldn't issue a "declared static but never defined" warning
for a deduction guide (declared in an anonymous namespace).

PR c++/106604

gcc/cp/ChangeLog:

* decl.cc (wrapup_namespace_globals): Don't issue a
-Wunused-function warning for a deduction guide.


Maybe instead of special casing this here we could set DECL_INITIAL on
deduction guides so they look defined?


That seems to work, but it requires some tweaks in duplicate_decls to keep
saying "declared" instead of "defined" when diagnosing a deduction guide
redeclaration.  I'm not sure which approach is preferable?


I'm not sure it matters which we say; the restriction that you can't repeat a
deduction guide makes it more like a definition anyway (even if [basic.def]
disagrees).  Is the diagnostic worse apart from that word?


Ah, makes sense.  So we can also remove the special case for them in the
redeclaration checking code after we give them a dummy DECL_INITIAL.
Like so?


OK, thanks.


Here's a before/after for the diagnostic with the below patch:

Before

src/gcc/testsuite/g++.dg/cpp1z/class-deduction74.C:11:1: error: deduction guide 
‘S()-> S’ redeclared
11 | S() -> S; // { dg-error "redefinition" }
   | ^
src/gcc/testsuite/g++.dg/cpp1z/class-deduction74.C:10:1: note: ‘S()-> S’ 
previously declared here
10 | S() -> S; // { dg-message "previously defined here|old 
declaration" }
   | ^

After

src/gcc/testsuite/g++.dg/cpp1z/class-deduction74.C:11:1: error: redefinition of 
‘S()-> S’
11 | S() -> S; // { dg-error "redefinition" }
   | ^
src/gcc/testsuite/g++.dg/cpp1z/class-deduction74.C:10:1: note: ‘S()-> S’ 
previously defined here
10 | S() -> S; // { dg-message "previously defined here|old 
declaration" }
   | ^

-- >8 --

Subject: [PATCH] c++: bogus warning w/ deduction guide in anon ns [PR106604]

Here we're unintentionally issuing a "declared static but never defined"
warning for a deduction guide declared in an anonymous namespace.
This patch fixes this by giving deduction guides a dummy DECL_INITIAL,
which suppresses the warning and also allows us to simplify redeclaration
checking for them.

Co-authored-by: Jason Merrill 

PR c++/106604

gcc/cp/ChangeLog:

* decl.cc (redeclaration_error_message): Remove special handling
for deduction guides.
(grokfndecl): Give deduction guides a dummy DECL_INITIAL.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/class-deduction74.C: Expect "defined" instead
of "declared" in diagnostics for a repeated deduction guide.
* g++.dg/cpp1z/class-deduction116.C: New test.
---
  gcc/cp/decl.cc  | 14 ++
  gcc/testsuite/g++.dg/cpp1z/class-deduction116.C |  8 
  gcc/testsuite/g++.dg/cpp1z/class-deduction74.C  | 14 +++---
  3 files changed, 21 insertions(+), 15 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction116.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 792ab330dd0..3ada5516c58 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -3297,10 +3297,6 @@ redeclaration_error_message (tree newdecl, tree olddecl)
}
}
  
-  if (deduction_guide_p (olddecl)

- && deduction_guide_p (newdecl))
-   return G_("deduction guide %q+D redeclared");
-
/* [class.compare.default]: A definition of a comparison operator as
 defaulted that appears in a class shall be the first declaration of
 that function.  */
@@ -3355,10 +3351,6 @@ redeclaration_error_message (tree newdecl, tree olddecl)
}
}
  
-  if (deduction_guide_p (olddecl)

- && deduction_guide_p (newdecl))
-   return G_("deduction guide %q+D redeclared");
-
/* Core issue #226 (C++11):
  
 If a friend function template declaration specifies a

@@ -10352,6 +10344,12 @@ grokfndecl (tree ctype,
DECL_CXX_DESTRUCTOR_P (decl) = 1;
DECL_NAME (decl) = dtor_identifier;
break;
+case sfk_deduction_guide:
+  /* Give deduction guides a definition even though they don't really
+have one: the restriction that you can't repeat a deduction guide
+makes them more like a definition anyway.  */
+  DECL_INITIAL (decl) = void_node;
+  break;
  default:
break;
  }
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction116.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction116.C
new file mode 100644
index 000..00f6d5fef41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction116.C
@@ -0,0 +1,8 @@
+// PR c++/106604
+// { dg-do compile { target c++17 } }
+// { dg-additional-options 

Re: [PATCH] c, c++, v2: Accept __builtin_classify_type (typename)

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 11:35, Jakub Jelinek wrote:

Hi!

I'd like to ping this patch.  Reposting it as I found a typo in the
documentation - s/builtin-in/built-in/.  Bootstrapped/regtested again
on x86_64-linux and i686-linux, ok for trunk?

On Mon, Jun 12, 2023 at 09:57:17PM +0200, Jakub Jelinek via Gcc-patches wrote:

As mentioned in my stdckdint.h mail, __builtin_classify_type has
a problem that argument promotion (the argument is passed to ...
prototyped builtin function) means that certain type classes will
simply never appear.
I think it is too late to change how it behaves, lots of code in the
wild might rely on the current behavior.


Hmm, you really think there's any code at all in the wild relying on 
__builtin_classify_type + array/function decay?  It's a (previously) 
undocumented built-in, I wouldn't expect anyone outside the project to 
be using it.  So at first glance I'd be inclined to fix it whether or 
not we also allow it to accept a type.  But I don't actually know how 
it's used, so could well be wrong...



--- gcc/cp/parser.cc.jj 2023-06-06 20:02:35.631211230 +0200
+++ gcc/cp/parser.cc2023-06-12 16:19:04.892202240 +0200
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.
  #include "c-family/known-headers.h"
  #include "contracts.h"
  #include "bitmap.h"
+#include "builtins.h"
  
  

  /* The lexer.  */
@@ -7850,6 +7851,50 @@ cp_parser_postfix_expression (cp_parser
  = parser->non_integral_constant_expression_p;
parser->integral_constant_expression_p = false;
  }
+   else if (TREE_CODE (stripped_expression) == FUNCTION_DECL
+&& fndecl_built_in_p (stripped_expression,
+  BUILT_IN_CLASSIFY_TYPE))
+ {
+   /* __builtin_classify_type (type)  */
+   auto cl1 = make_temp_override
+(parser->type_definition_forbidden_message,
+ G_("types may not be defined in "
+"%<__builtin_classify_type%> calls"));
+   auto cl2 = make_temp_override
+(parser->type_definition_forbidden_message_arg,
+ NULL);
+   auto cl3 = make_temp_override (parser->in_type_id_in_expr_p,
+  true);
+   cp_evaluated ev;
+   ++cp_unevaluated_operand;
+   ++c_inhibit_evaluation_warnings;


These three lines seem unnecessary for parsing a type.


+   tentative_firewall firewall (parser);


I think you only need a tentative_firewall if you're going to call 
cp_parser_commit_to_tentative_parse yourself, which you don't.


Jason



Re: [PATCH] c++: dependently scoped template-id in type-req [PR110927]

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 12:08, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk and perhaps 13?


OK.


-- >8 --

Here we're incorrectly rejecting the first type-requirement at parse
time with

   concepts-requires35.C:14:56: error: ‘typename A::B’ is not a template 
[-fpermissive]

We also incorrectly reject the second type-requirement at satisfaction time
with

   concepts-requires35.C:17:34: error: ‘typename A::B’ names ‘template 
struct A::B’, which is not a type

and similarly for the third type-requirement.  This seems to happen only
within a type-requirement; if we instead use e.g. an alias template then
it works as expected.

The difference ultimately seems to be that during parsing of a
using-declaration, we pass check_dependency_p=true to
cp_parser_nested_name_specifier_opt whereas during parsing of a
type-requirement we pass check_dependency_p=false.  Passing =false causes
cp_parser_template_id for the dependently-scoped template-id B to
return a TYPE_DECL of TYPENAME_TYPE (sometimes with TYPENAME_IS_CLASS_P
unexpectedly set for the last two type-requirements) whereas passing
=true causes it to return a TEMPLATE_ID_EXPR.

The simplest fix therefore seems to be to pass check_dependency_p=true
from cp_parser_type_requirement, matching the behavior of
cp_parser_elaborated_type_specifier.

PR c++/110927

gcc/cp/ChangeLog:

* parser.cc (cp_parser_type_requirement): Pass
check_dependency_p=true instead of =false.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-requires35.C: New test.
---
  gcc/cp/parser.cc  |  4 +--
  .../g++.dg/cpp2a/concepts-requires35.C| 28 +++
  2 files changed, 30 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires35.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 589ac879c6d..2d27376d988 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -30977,7 +30977,7 @@ cp_parser_type_requirement (cp_parser *parser)
cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
cp_parser_nested_name_specifier_opt (parser,
 /*typename_keyword_p=*/true,
-   /*check_dependency_p=*/false,
+  /*check_dependency_p=*/true,
 /*type_p=*/true,
 /*is_declaration=*/false);
  
@@ -30987,7 +30987,7 @@ cp_parser_type_requirement (cp_parser *parser)

cp_lexer_consume_token (parser->lexer);
type = cp_parser_template_id (parser,
  /*template_keyword_p=*/true,
-/*check_dependency=*/false,
+   /*check_dependency_p=*/true,
  /*tag_type=*/none_type,
  /*is_declaration=*/false);
type = make_typename_type (parser->scope, type, typename_type,
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires35.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-requires35.C
new file mode 100644
index 000..1dad931c01a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires35.C
@@ -0,0 +1,28 @@
+// PR c++/110927
+// { dg-do compile { target c++20 } }
+
+template
+struct A {
+  template struct B { using type = B; };
+
+  template using type = U;
+};
+
+template<> struct A { };
+
+template
+concept C1 = requires { typename A::template B::type; };
+
+template
+concept C2 = requires { typename A::template B; };
+
+template
+concept C3 = requires { typename A::template type; };
+
+static_assert(C1);
+static_assert(C2);
+static_assert(C3);
+
+static_assert(!C1);
+static_assert(!C2);
+static_assert(!C3);




Re: [PATCH] c++: recognize in-class var tmpl partial spec [PR71954]

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 12:08, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk?


OK.


-- >8 --

This makes us recognize variable template partial specializations
defined directly inside the class body.  It seems to suffice to call
check_explicit_specialization when we see a static TEMPLATE_ID_EXPR data
member, which sets SET_DECL_TEMPLATE_SPECIALIZATION and which we
otherwise don't call (for out-of-class partial specializations we call
it from from grokvardecl which is used only for out-of-class definitions).
We also need to make finish_member_template_decl return NULL_TREE for
such partial specializations (matching its behavior class template
partial specializations) so that its caller doesn't try to call
finish_member_declaration on it.

PR c++/71954

gcc/cp/ChangeLog:

* decl.cc (grokdeclarator): Use 'dname' instead of
'unqualified_id' when building the VAR_DECL for a static data
member.  Call check_explicit_specialization for a
TEMPLATE_ID_EXPR such member.
* pt.cc (finish_member_template_decl): Return NULL_TREE
instead of 'decl' when DECL_TEMPLATE_SPECIALIZATION is not
set.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/var-templ84.C: New test.
* g++.dg/cpp1y/var-templ84a.C: New test.
---
  gcc/cp/decl.cc| 11 ++-
  gcc/cp/pt.cc  |  2 +-
  gcc/testsuite/g++.dg/cpp1y/var-templ84.C  | 12 
  gcc/testsuite/g++.dg/cpp1y/var-templ84a.C | 19 +++
  4 files changed, 42 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ84.C
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ84a.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9fe3a0b98fd..2b3fb313166 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -14440,7 +14440,16 @@ grokdeclarator (const cp_declarator *declarator,
/* C++ allows static class members.  All other work
   for this is done by grokfield.  */
decl = build_lang_decl_loc (id_loc, VAR_DECL,
-   unqualified_id, type);
+   dname, type);
+   if (unqualified_id
+   && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
+ {
+   decl = check_explicit_specialization (unqualified_id, decl,
+ template_count,
+ concept_p * 8);
+   if (decl == error_mark_node)
+ return error_mark_node;
+ }
set_linkage_for_static_data_member (decl);
if (concept_p)
  error_at (declspecs->locations[ds_concept],
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 2706fa619bf..a4809f034dc 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -314,7 +314,7 @@ finish_member_template_decl (tree decl)
  return DECL_TI_TEMPLATE (decl);
}
else
-   return decl;
+   return NULL_TREE;
  }
else
  error_at (DECL_SOURCE_LOCATION (decl),
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ84.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ84.C
new file mode 100644
index 000..39c2a0dc0cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ84.C
@@ -0,0 +1,12 @@
+// PR c++/71954
+// { dg-do compile { target c++14 } }
+
+struct A {
+  template static const int var = 0;
+  template static const int var = 1;
+  template static const int var = 2;
+};
+
+static_assert(A::var == 0, "");
+static_assert(A::var == 1, "");
+static_assert(A::var == 2, "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ84a.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ84a.C
new file mode 100644
index 000..4aa3a2a7245
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ84a.C
@@ -0,0 +1,19 @@
+// PR c++/71954
+// A version of var-templ84.C where the partial specializations depend on
+// outer template parameters.
+// { dg-do compile { target c++14 } }
+
+template
+struct A {
+  template static const int var = 0;
+  template static const int var = 1;
+  template static const int var = 2;
+};
+
+static_assert(A::var == 0, "");
+static_assert(A::var == 1, "");
+static_assert(A::var == 2, "");
+
+static_assert(A::var == 0, "");
+static_assert(A::var == 0, "");
+static_assert(A::var == 0, "");




Re: [PATCH] c++: bogus warning w/ deduction guide in anon ns [PR106604]

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 16:40, Patrick Palka wrote:

On Thu, 10 Aug 2023, Jason Merrill wrote:


On 8/10/23 12:09, Patrick Palka wrote:

Booststrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk and perhaps 13?

-- >8 --

We shouldn't issue a "declared static but never defined" warning
for a deduction guide (declared in an anonymous namespace).

PR c++/106604

gcc/cp/ChangeLog:

* decl.cc (wrapup_namespace_globals): Don't issue a
-Wunused-function warning for a deduction guide.


Maybe instead of special casing this here we could set DECL_INITIAL on
deduction guides so they look defined?


That seems to work, but it requires some tweaks in duplicate_decls to keep
saying "declared" instead of "defined" when diagnosing a deduction guide
redeclaration.  I'm not sure which approach is preferable?


I'm not sure it matters which we say; the restriction that you can't 
repeat a deduction guide makes it more like a definition anyway (even if 
[basic.def] disagrees).  Is the diagnostic worse apart from that word?


Jason



Re: [PATCH] c++: improve debug_tree for templated types/decls

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 16:59, Patrick Palka wrote:

On Tue, 8 Aug 2023, Jason Merrill wrote:


On 7/31/23 20:34, Patrick Palka wrote:

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

-- >8 --

gcc/cp/ChangeLog:

* ptree.cc (cxx_print_decl): Check for DECL_LANG_SPECIFIC and
TS_DECL_COMMON only when necessary.  Print DECL_TEMPLATE_INFO
for all decls that have it, not just VAR_DECL or FUNCTION_DECL.
Also print DECL_USE_TEMPLATE.
(cxx_print_type): Print TYPE_TEMPLATE_INFO.
: Don't print TYPE_TI_ARGS
anymore.
: Print TEMPLATE_TYPE_PARM_INDEX
instead of printing the index, level and original level
individually.
---
   gcc/cp/ptree.cc | 32 +---
   1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/gcc/cp/ptree.cc b/gcc/cp/ptree.cc
index 33af7b81f58..13306fc8762 100644
--- a/gcc/cp/ptree.cc
+++ b/gcc/cp/ptree.cc
@@ -38,10 +38,6 @@ cxx_print_decl (FILE *file, tree node, int indent)
 return;
   }
   -  if (!CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON)
-  || !DECL_LANG_SPECIFIC (node))
-return;
-
 if (TREE_CODE (node) == FUNCTION_DECL)
   {
 int flags = TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE
@@ -106,7 +102,10 @@ cxx_print_decl (FILE *file, tree node, int indent)
 need_indent = false;
   }
   -  if (DECL_EXTERNAL (node) && DECL_NOT_REALLY_EXTERN (node))
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON)
+  && DECL_LANG_SPECIFIC (node)
+  && DECL_EXTERNAL (node)
+  && DECL_NOT_REALLY_EXTERN (node))
   {
 if (need_indent)
indent_to (file, indent + 3);
@@ -115,6 +114,7 @@ cxx_print_decl (FILE *file, tree node, int indent)
   }
   if (TREE_CODE (node) == FUNCTION_DECL
+  && DECL_LANG_SPECIFIC (node)
 && DECL_PENDING_INLINE_INFO (node))
   {
 if (need_indent)
@@ -124,27 +124,29 @@ cxx_print_decl (FILE *file, tree node, int indent)
 need_indent = false;
   }
 -  if (VAR_OR_FUNCTION_DECL_P (node)
+  if (DECL_LANG_SPECIFIC (node)


Hmm, won't this crash on a non-COMMON decl?


Oops yes, I overlooked that DECL_LANG_SPECIFIC requires DECL_COMMON.  So
we should just move the early exit test down a bit.




 && DECL_TEMPLATE_INFO (node))


We also need to constrain the kinds of decls that we test
DECL_TEMPLATE_INFO on according to template_info_decl_check.

-- >8 --

Subject: [PATCH] c++: improve debug_tree for templated types/decls

gcc/cp/ChangeLog:

* ptree.cc (cxx_print_decl): Check for DECL_LANG_SPECIFIC and
TS_DECL_COMMON only when necessary.  Print DECL_TEMPLATE_INFO
for all decls that have it, not just VAR_DECL or FUNCTION_DECL.
Also print DECL_USE_TEMPLATE.
(cxx_print_type): Print TYPE_TEMPLATE_INFO.
: Don't print TYPE_TI_ARGS
anymore.
: Print TEMPLATE_TYPE_PARM_INDEX
instead of printing the index, level and original level
individually.


OK.

Jason



Re: [RFC PATCH v2] c++: extend cold, hot attributes to classes

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 14:06, Javier Martinez wrote:


Thanks for the comments, Jason.
v2: + Fix formatting, remove unnecessarily warning.

On Tue, Aug 8, 2023 at 10:28 PM Jason Merrill > wrote:

 > Seems reasonable, but how do you expect this to be used?
We have large applications where some large classes are known to be used 
only at startup. Marking every member function as cold is impractical so 
we would mark those classes as cold.


Sure, though I think of the cold attribute as being primarily to mark 
unlikely paths in otherwise hot code; is this a


if (!initialized)
  do_initialization();

kind of situation?


 > I think doing this here will miss lazily-declared special member
 > functions; I wonder if you want to copy the attribute in grokclassfn
 > instead?
I think they are being handled correctly with the current patch. 
Considered the following program:


class __attribute((cold)) Foo {
public:
     int m_x, m_y;
     auto operator<=>(const Foo&) const = default;
};

int main(void) {
     Foo a{1,1};
     Foo b{1,2};

     std::set s; // OK
     s.insert(a);     // OK

     std::cout << std::boolalpha
         << (a == b) << ' '
         << (a != b) << ' '
         << (a <  b) << ' '
         << (a <= b) << ' '
         << (a >  b) << ' '
         << (a >= b) << ' '
         << std::endl;
}

Per the rules for any operator<=> overload, a defaulted <=> overload 
will also allow the type to be compared with <, <=, >, and >=. If 
operator<=> is defaulted and operator== is not declared at all, then 
operator== is implicitly defaulted.

The GIMPLE dump shows:
 > __attribute__((cold))
 > struct strong_ordering Foo::operator<=> (const struct Foo * const 
this, const struct Foo & D.64195)

 > __attribute__((cold))
 > bool Foo::operator== (const struct Foo * const this, const struct Foo 
& D.64206)


I think this makes sense as add_implicitly_declared_members is called 
before my injection via finish_struct_1 -> check_bases_and_members.


Yes, but that's because the implicit op== isn't declared lazily like 
some other special member functions (CLASSTYPE_LAZY_*/lazily_declare_fn) 
which can happen after the class is complete.



---

I would like some comment on the implications of:
-  { "cold",       0, 0, true,  false, false, false,
+  { "cold",      0, 0, false,  false, false, false,

As I am now introducing a new warning that I cannot explain in an old test:
testsuite/g++.dg/Wmissing-attributes.C:55:22: warning: 'hot' attribute 
ignored [-Wattributes]


 > template <>
 > void*
 > ATTR ((hot)) ATTR ((alloc_size (1))) ATTR ((malloc))
 > missing_all(int);   // T = char, same as above


I think this is because attributes in that position appertain to the 
return type rather than the declaration.  At attribs.cc:753, if an 
attribute has decl_required true and we try to apply it to a return 
type, we pass it along to the declaration instead; if you change the 
true to false we will try to apply it to void* directly and fail.


I think it would work to check for (flags & (ATTR_FLAG_FUNCTION_NEXT | 
ATTR_FLAG_DECL_NEXT)) and return without warning in that case.  You'd 
still set *no_add_attr.


BTW the patch got garbled this time, probably safer to make it an 
attachment if you're using gmail.


Jason



Re: [PATCH] c++: bogus warning w/ deduction guide in anon ns [PR106604]

2023-08-10 Thread Jason Merrill via Gcc-patches

On 8/10/23 12:09, Patrick Palka wrote:

Booststrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk and perhaps 13?

-- >8 --

We shouldn't issue a "declared static but never defined" warning
for a deduction guide (declared in an anonymous namespace).

PR c++/106604

gcc/cp/ChangeLog:

* decl.cc (wrapup_namespace_globals): Don't issue a
-Wunused-function warning for a deduction guide.


Maybe instead of special casing this here we could set DECL_INITIAL on 
deduction guides so they look defined?



gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/class-deduction116.C: New test.
---
  gcc/cp/decl.cc  | 1 +
  gcc/testsuite/g++.dg/cpp1z/class-deduction116.C | 8 
  2 files changed, 9 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction116.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 792ab330dd0..9fe3a0b98fd 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -856,6 +856,7 @@ wrapup_namespace_globals ()
  && !TREE_PUBLIC (decl)
  && !DECL_ARTIFICIAL (decl)
  && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
+ && !deduction_guide_p (decl)
  && !warning_suppressed_p (decl, OPT_Wunused_function))
warning_at (DECL_SOURCE_LOCATION (decl),
OPT_Wunused_function,
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction116.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction116.C
new file mode 100644
index 000..00f6d5fef41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction116.C
@@ -0,0 +1,8 @@
+// PR c++/106604
+// { dg-do compile { target c++17 } }
+// { dg-additional-options "-Wunused-function" }
+
+namespace {
+  template struct A { A(...); };
+  A(bool) -> A; // { dg-bogus "never defined" }
+}




Re: [PATCH] preprocessor: c++: Support `#pragma GCC target' macros [PR87299]

2023-08-08 Thread Jason Merrill via Gcc-patches

On 7/31/23 22:22, Lewis Hyatt via Gcc-patches wrote:

`#pragma GCC target' is not currently handled in preprocess-only mode (e.g.,
when running gcc -E or gcc -save-temps). As noted in the PR, this means that
if the target pragma defines any macros, those macros are not effective in
preprocess-only mode. Similarly, such macros are not effective when
compiling with C++ (even when compiling without -save-temps), because C++
does not process the pragma until after all tokens have been obtained from
libcpp, at which point it is too late for macro expansion to take place.

Since r13-1544 and r14-2893, there is a general mechanism to handle pragmas
under these conditions as well, so resolve the PR by using the new "early
pragma" support.

toplev.cc required some changes because the target-specific handlers for
`#pragma GCC target' may call target_reinit(), and toplev.cc was not expecting
that function to be called in preprocess-only mode.

I added some additional testcases from the PR for x86. The other targets
that support `#pragma GCC target' (aarch64, arm, nios2, powerpc, s390)
already had tests verifying that the pragma sets macros as expected; here I
have added -save-temps to some of them, to test that it now works in
preprocess-only mode as well.

gcc/c-family/ChangeLog:

PR preprocessor/87299
* c-pragma.cc (init_pragma): Register `#pragma GCC target' and
related pragmas in preprocess-only mode, and enable early handling.
(c_reset_target_pragmas): New function refactoring code from...
(handle_pragma_reset_options): ...here.
* c-pragma.h (c_reset_target_pragmas): Declare.

gcc/cp/ChangeLog:

PR preprocessor/87299
* parser.cc (cp_lexer_new_main): Call c_reset_target_pragmas ()
after preprocessing is complete, before starting compilation.

gcc/ChangeLog:

PR preprocessor/87299
* toplev.cc (no_backend): New static global.
(finalize): Remove argument no_backend, which is now a
static global.
(process_options): Likewise.
(do_compile): Likewise.
(target_reinit): Don't do anything in preprocess-only mode.
(toplev::main): Adapt to no_backend change.
(toplev::finalize): Likewise.

gcc/testsuite/ChangeLog:

PR preprocessor/87299
* c-c++-common/pragma-target-1.c: New test.
* c-c++-common/pragma-target-2.c: New test.
* g++.target/i386/pr87299-1.C: New test.
* g++.target/i386/pr87299-2.C: New test.
* gcc.target/i386/pr87299-1.c: New test.
* gcc.target/i386/pr87299-2.c: New test.
* gcc.target/s390/target-attribute/tattr-2.c: Add -save-temps to the
options, to test preprocess-only mode as well.
* gcc.target/aarch64/pragma_cpp_predefs_1.c: Likewise.
* gcc.target/arm/pragma_arch_attribute.c: Likewise.
* gcc.target/nios2/custom-fp-2.c: Likewise.
* gcc.target/powerpc/float128-3.c: Likewise.
---

Notes:
 Hello-
 
 This patch fixes the PR by enabling early pragma handling for `#pragma GCC

 target' and related pragmas such as `#pragma GCC push_options'. I did not
 need to touch any target-specific code, however I did need to make a change
 to toplev.cc, affecting all targets, to make it safe to call 
target_reinit()
 in preprocess-only mode. (Otherwise, it would be necessary to modify the
 implementation of target pragmas in every target, to avoid this code path.)
 That was the only complication I ran into.
 
 Regarding testing, I did: (thanks to GCC compile farm for the non-x86

 targets)
 
 bootstrap + regtest all languages - x86_64-pc-linux-gnu

 bootstrap + regtest c/c++ - powerpc64le-unknown-linux-gnu,
 aarch64-unknown-linux-gnu
 
 The following backends also implement this pragma so ought to be tested:

 arm
 nios2
 s390
 
 I am not able to test those directly. I did add coverage to their testsuites

 (basically, adding -save-temps to any existing test, causes it to test the
 pragma in preprocess-only mode.) Then, I verified on x86_64 with a cross
 compiler, that the modified testcases fail before the patch and pass
 afterwards. nios2 is an exception, it does not set any libcpp macros when
 handling the pragma, so there is nothing to test, but I did verify that
 processing the pragma in preprocess-only mode does not cause any problems.
 The cross compilers tested were targets arm-unknown-linux-gnueabi,
 nios2-unknown-linux, and s390-ibm-linux.
 
 Please let me know if it looks OK? Thanks!


The c-family and C++ changes look good.  David, any comments on the 
toplev changes?


Jason



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

2023-08-08 Thread Jason Merrill via Gcc-patches

On 7/31/23 17:52, Marek Polacek wrote:

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

-- >8 --

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

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


Nice!  OK, thanks.

Jason



Re: [PATCH] c++: improve debug_tree for templated types/decls

2023-08-08 Thread Jason Merrill via Gcc-patches

On 7/31/23 20:34, Patrick Palka wrote:

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

-- >8 --

gcc/cp/ChangeLog:

* ptree.cc (cxx_print_decl): Check for DECL_LANG_SPECIFIC and
TS_DECL_COMMON only when necessary.  Print DECL_TEMPLATE_INFO
for all decls that have it, not just VAR_DECL or FUNCTION_DECL.
Also print DECL_USE_TEMPLATE.
(cxx_print_type): Print TYPE_TEMPLATE_INFO.
: Don't print TYPE_TI_ARGS
anymore.
: Print TEMPLATE_TYPE_PARM_INDEX
instead of printing the index, level and original level
individually.
---
  gcc/cp/ptree.cc | 32 +---
  1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/gcc/cp/ptree.cc b/gcc/cp/ptree.cc
index 33af7b81f58..13306fc8762 100644
--- a/gcc/cp/ptree.cc
+++ b/gcc/cp/ptree.cc
@@ -38,10 +38,6 @@ cxx_print_decl (FILE *file, tree node, int indent)
return;
  }
  
-  if (!CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON)

-  || !DECL_LANG_SPECIFIC (node))
-return;
-
if (TREE_CODE (node) == FUNCTION_DECL)
  {
int flags = TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE
@@ -106,7 +102,10 @@ cxx_print_decl (FILE *file, tree node, int indent)
need_indent = false;
  }
  
-  if (DECL_EXTERNAL (node) && DECL_NOT_REALLY_EXTERN (node))

+  if (CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON)
+  && DECL_LANG_SPECIFIC (node)
+  && DECL_EXTERNAL (node)
+  && DECL_NOT_REALLY_EXTERN (node))
  {
if (need_indent)
indent_to (file, indent + 3);
@@ -115,6 +114,7 @@ cxx_print_decl (FILE *file, tree node, int indent)
  }
  
if (TREE_CODE (node) == FUNCTION_DECL

+  && DECL_LANG_SPECIFIC (node)
&& DECL_PENDING_INLINE_INFO (node))
  {
if (need_indent)
@@ -124,27 +124,29 @@ cxx_print_decl (FILE *file, tree node, int indent)
need_indent = false;
  }

-  if (VAR_OR_FUNCTION_DECL_P (node)

+  if (DECL_LANG_SPECIFIC (node)


Hmm, won't this crash on a non-COMMON decl?


&& DECL_TEMPLATE_INFO (node))
-print_node (file, "template-info", DECL_TEMPLATE_INFO (node),
-   indent + 4);
+{
+  print_node (file, "template-info", DECL_TEMPLATE_INFO (node),
+ indent + 4);
+  indent_to (file, indent + 3);
+  fprintf (file, " use_template=%d", DECL_USE_TEMPLATE (node));
+}
  }
  
  void

  cxx_print_type (FILE *file, tree node, int indent)
  {
+  if (TYPE_LANG_SPECIFIC (node)
+  && TYPE_TEMPLATE_INFO (node))
+print_node (file, "template-info", TYPE_TEMPLATE_INFO (node), indent + 4);
+
switch (TREE_CODE (node))
  {
  case BOUND_TEMPLATE_TEMPLATE_PARM:
-  print_node (file, "args", TYPE_TI_ARGS (node), indent + 4);
-  gcc_fallthrough ();
-
  case TEMPLATE_TYPE_PARM:
  case TEMPLATE_TEMPLATE_PARM:
-  indent_to (file, indent + 3);
-  fprintf (file, "index %d level %d orig_level %d",
-  TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
-  TEMPLATE_TYPE_ORIG_LEVEL (node));
+  print_node (file, "tpi", TEMPLATE_TYPE_PARM_INDEX (node), indent + 4);
return;
  
  case FUNCTION_TYPE:




Re: [PATCH 04/14] c++: use _P() defines from tree.h

2023-08-08 Thread Jason Merrill via Gcc-patches

On 8/2/23 12:51, Patrick Palka via Gcc-patches wrote:

On Thu, Jun 1, 2023 at 2:11 PM Bernhard Reutner-Fischer
 wrote:


Hi David, Patrick,

On Thu, 1 Jun 2023 18:33:46 +0200
Bernhard Reutner-Fischer  wrote:


On Thu, 1 Jun 2023 11:24:06 -0400
Patrick Palka  wrote:


On Sat, May 13, 2023 at 7:26 PM Bernhard Reutner-Fischer via
Gcc-patches  wrote:



diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 131b212ff73..19dfb3ed782 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -1173,7 +1173,7 @@ build_cplus_array_type (tree elt_type, tree index_type, 
int dependent)
  }

/* Avoid spurious warnings with VLAs (c++/54583).  */
-  if (TYPE_SIZE (t) && EXPR_P (TYPE_SIZE (t)))
+  if (CAN_HAVE_LOCATION_P (TYPE_SIZE (t)))


Hmm, this change seems undesirable...


mhm, yes that is misleading. I'll prepare a patch to revert this.
Let me have a look if there were other such CAN_HAVE_LOCATION_P changes
that we'd want to revert.


Sorry for that!
I'd revert the hunk above and the one in gcc-rich-location.cc
(maybe_range_label_for_tree_type_mismatch::get_text), please see
attached. Bootstrap running, ok for trunk if it passes?


LGTM!


Yes, OK.

Jason



Re: [RFC] c++: extend cold, hot attributes to classes

2023-08-08 Thread Jason Merrill via Gcc-patches

On 8/3/23 07:07, Javier Martinez via Gcc-patches wrote:

Most code is cold. This patch extends support for attribute ((cold)) to C++
Classes, Unions, and Structs (RECORD_TYPES and UNION_TYPES) to benefit from
encapsulation - reducing the verbosity of using the attribute where
deserved. The ((hot)) attribute is also extended for its semantic relation.
What is the sentiment on this use-case?


Seems reasonable, but how do you expect this to be used?


for gcc/c-family/ChangeLog

 * c-attribs.c (attribute_spec): Remove decl_required
 field for "hot" and "cold" attributes.
 (handle_cold_attribute): remove warning on RECORD_TYPE
 and UNION_TYPE when c_dialect_cxx.
 (handle_cold_attribute): remove warning on RECORD_TYPE
 and UNION_TYPE when c_dialect_cxx.

for gcc/cp/ChangeLog

 * class.c (finish_struct) propagate hot and cold
 attributes to all FUNCTION_DECL when the class
 itself is marked hot or cold.

for  gcc/testsuite/ChangeLog

 * g++.dg/ext/attr-hotness.C: New.


Signed-off-by: Javier Martinez 

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index dc9579c..815df66 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -398,10 +398,10 @@ const struct attribute_spec
c_common_attribute_table[] =
{ "alloc_size",  1, 2, false, true, true, false,
handle_alloc_size_attribute,
attr_alloc_exclusions },
-  { "cold",   0, 0, true,  false, false, false,
+  { "cold",   0, 0, false,  false, false, false,
handle_cold_attribute,
attr_cold_hot_exclusions },
-  { "hot",0, 0, true,  false, false, false,
+  { "hot",0, 0, false,  false, false, false,
handle_hot_attribute,
attr_cold_hot_exclusions },
{ "no_address_safety_analysis",
@@ -837,22 +837,23 @@ handle_noreturn_attribute (tree *node, tree name,
tree ARG_UNUSED (args),

  static tree
  handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-  int ARG_UNUSED (flags), bool *no_add_attrs)
+   int ARG_UNUSED (flags), bool *no_add_attrs)


Try to avoid unnecessary whitespace changes.


  {
-  if (TREE_CODE (*node) == FUNCTION_DECL
-  || TREE_CODE (*node) == LABEL_DECL)
+  if ( (TREE_CODE (*node) == FUNCTION_DECL ||
+TREE_CODE (*node) == LABEL_DECL)
+  || ((TREE_CODE(*node) == RECORD_TYPE ||
+   TREE_CODE(*node) == UNION_TYPE) && c_dialect_cxx()))


In GCC we generally put a space before '(', not after it.
https://www.gnu.org/prep/standards/html_node/Formatting.html#Formatting


  {
/* Attribute hot processing is done later with lookup_attribute.  */
  }
else
  {
warning (OPT_Wattributes, "%qE attribute ignored", name);
-  *no_add_attrs = true;
+  *no_add_attrs = true;


More unnecessary reformatting.


  }

return NULL_TREE;
  }
-


We want to keep this newline between this function and the comment for 
the next function.



  /* Handle a "cold" and attribute; arguments as in
 struct attribute_spec.handler.  */

@@ -860,15 +861,17 @@ static tree
  handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 int ARG_UNUSED (flags), bool *no_add_attrs)
  {
-  if (TREE_CODE (*node) == FUNCTION_DECL
-  || TREE_CODE (*node) == LABEL_DECL)
+  if ( (TREE_CODE (*node) == FUNCTION_DECL ||
+TREE_CODE (*node) == LABEL_DECL)
+  || ((TREE_CODE(*node) == RECORD_TYPE ||
+   TREE_CODE(*node) == UNION_TYPE) && c_dialect_cxx()))


As above.


  {
/* Attribute cold processing is done later with lookup_attribute.  */
  }
else
  {
warning (OPT_Wattributes, "%qE attribute ignored", name);
-  *no_add_attrs = true;
+  *no_add_attrs = true;


As above.


  }

return NULL_TREE;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 07abe52..70f734f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7540,6 +7540,35 @@ finish_struct (tree t, tree attributes)
&& !LAMBDA_TYPE_P (t))
  add_stmt (build_min (TAG_DEFN, t));

+


Unnecessary extra blank line.


+  /* classes marked with hotness attributes propagate the attribute to


Capitalize the beginning of the comment.


+  all methods. We propagate these here as there is a guarantee that
+  TYPE_FIELDS is populated, as opposed from within decl_attributes. */
+
+  tree has_cold_attr = lookup_attribute("cold", TYPE_ATTRIBUTES(t));
+  tree has_hot_attr = lookup_attribute("hot", TYPE_ATTRIBUTES(t));
+
+  if ( has_cold_attr || has_hot_attr ) {
+
+/* hoisted out of the loop */
+tree attr_cold_id = get_identifier("cold");
+tree attr_hot_id = get_identifier("hot");


More space before parenthesis.


+
+for (tree f = TYPE_FIELDS (t); f; f = DECL_CHAIN (f))
+  {
+if (TREE_CODE (f) == FUNCTION_DECL) {
+  /* decl_attributes will take care of conflicts,
+  also prioritizing 

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

2023-08-08 Thread Jason Merrill via Gcc-patches

On 8/7/23 22:48, Nathaniel Shead wrote:

Sorry, noticed I provided the wrong version of the test. Here is the
correct version (not relying on 'namespace std' being implicitly
defined). Bootstrapped + regtested on x86_64-pc-linux-gnu.


Pushed, thanks!


-- 8< --

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

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

PR c++/100482

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

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

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d7ef5b34d42..119a14d03b9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -16506,10 +16506,6 @@ cp_parser_decltype_expr (cp_parser *parser,
expr = cp_parser_lookup_name_simple (parser, expr,
 id_expr_start_token->location);
  
-  if (expr && TREE_CODE (expr) == TEMPLATE_DECL)

-   /* A template without args is not a complete id-expression.  */
-   expr = error_mark_node;
-
if (expr
&& expr != error_mark_node
&& TREE_CODE (expr) != TYPE_DECL
@@ -16530,13 +16526,17 @@ cp_parser_decltype_expr (cp_parser *parser,
 _msg,
   id_expr_start_token->location));
  
-  if (expr == error_mark_node)

-/* We found an id-expression, but it was something that we
-   should not have found. This is an error, not something
-   we can recover from, so note that we found an
-   id-expression and we'll recover as gracefully as
-   possible.  */
-id_expression_or_member_access_p = true;
+ if (error_msg)
+   {
+ /* We found an id-expression, but it was something that we
+should not have found. This is an error, not something
+we can recover from, so report the error we found and
+we'll recover as gracefully as possible.  */
+ cp_parser_parse_definitely (parser);
+ cp_parser_error (parser, error_msg);
+ id_expression_or_member_access_p = true;
+ return error_mark_node;
+   }
  }
  
if (expr

diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C 
b/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
new file mode 100644
index 000..1df8b162743
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-100482.C
@@ -0,0 +1,12 @@
+// PR c++/100482
+// { dg-do compile { target c++11 } }
+
+namespace N {}
+decltype(N) x;   // { dg-error "expected primary-expression" }
+
+struct S {};
+decltype(S) y;  // { dg-error "argument to .decltype. must be an expression" }
+
+template 
+struct U {};
+decltype(U) z;  // { dg-error "missing template arguments" }




Re: [PATCH] c++: follow DR 2386 and update implementation of get_tuple_size [PR110216]

2023-08-08 Thread Jason Merrill via Gcc-patches

On 8/6/23 14:15, gnaggnoyil wrote:

DR 2386 updated the tuple_size requirements for structured binding and
it now requires tuple_size to be considered only if
std::tuple_size names a complete class type with member value. GCC
before this patch does not follow the updated requrements, and this
patch is intended to implement it.

DR 2386
PR c++/110216

gcc/cp/ChangeLog:

* decl.cc (get_tuple_size): Update implemetation to follow DR 2386.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/pr110216.C: New test.


Thanks!  Unfortunately, I see that this patch causes a testsuite failure 
in cpp1z/decomp10.C.  This seems to be an intended change of behavior, 
but please also update that testcase, and remember to run the testsuite 
before submitting a patch.


Jason



Re: [PATCH v2] c-family: Implement pragma_lex () for preprocess-only mode

2023-07-29 Thread Jason Merrill via Gcc-patches

On 7/28/23 07:14, Lewis Hyatt wrote:

On Thu, Jul 27, 2023 at 06:18:33PM -0700, Jason Merrill wrote:

On 7/27/23 18:59, Lewis Hyatt wrote:

In order to support processing #pragma in preprocess-only mode (-E or
-save-temps for gcc/g++), we need a way to obtain the #pragma tokens from
libcpp. In full compilation modes, this is accomplished by calling
pragma_lex (), which is a symbol that must be exported by the frontend, and
which is currently implemented for C and C++. Neither of those frontends
initializes its parser machinery in preprocess-only mode, and consequently
pragma_lex () does not work in this case.

Address that by adding a new function c_init_preprocess () for the frontends
to implement, which arranges for pragma_lex () to work in preprocess-only
mode, and adjusting pragma_lex () accordingly.

In preprocess-only mode, the preprocessor is accustomed to controlling the
interaction with libcpp, and it only knows about tokens that it has called
into libcpp itself to obtain. Since it still needs to see the tokens
obtained by pragma_lex () so that they can be streamed to the output, also
adjust c_lex_with_flags () and related functions in c-family/c-lex.cc to
inform the preprocessor about any tokens it won't be aware of.

Currently, there is one place where we are already supporting #pragma in
preprocess-only mode, namely the handling of `#pragma GCC diagnostic'.  That
was done by directly interfacing with libcpp, rather than making use of
pragma_lex (). Now that pragma_lex () works, that code is no longer
necessary; remove it.

gcc/c-family/ChangeLog:

* c-common.h (c_init_preprocess): Declare.
(c_lex_enable_token_streaming): Declare.
* c-opts.cc (c_common_init): Call c_init_preprocess ().
* c-lex.cc (stream_tokens_to_preprocessor): New static variable.
(c_lex_enable_token_streaming): New function.
(cb_def_pragma): Add a comment.
(get_token): New function wrapping cpp_get_token.
(c_lex_with_flags): Use the new wrapper function to support
obtaining tokens in preprocess_only mode.
(lex_string): Likewise.
* c-ppoutput.cc (preprocess_file): Call c_lex_enable_token_streaming
when needed.
* c-pragma.cc (pragma_diagnostic_lex_normal): Rename to...
(pragma_diagnostic_lex): ...this.
(pragma_diagnostic_lex_pp): Remove.
(handle_pragma_diagnostic_impl): Call pragma_diagnostic_lex () in
all modes.
(c_pp_invoke_early_pragma_handler): Adapt to support pragma_lex ()
usage.
* c-pragma.h (pragma_lex_discard_to_eol): Declare.

gcc/c/ChangeLog:

* c-parser.cc (pragma_lex_discard_to_eol): New function.
(c_init_preprocess): New function.

gcc/cp/ChangeLog:

* parser.cc (c_init_preprocess): New function.
(maybe_read_tokens_for_pragma_lex): New function.
(pragma_lex): Support preprocess-only mode.
(pragma_lex_discard_to_eol): New function.
---

Notes:
  Hello-
  Here is version 2 of the patch, incorporating Jason's feedback from
  https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625591.html
  Thanks again, please let me know if it's OK? Bootstrap + regtest all
  languages on x86-64 Linux looks good.
  -Lewis

   gcc/c-family/c-common.h|  4 +++
   gcc/c-family/c-lex.cc  | 49 +
   gcc/c-family/c-opts.cc |  1 +
   gcc/c-family/c-ppoutput.cc | 17 +---
   gcc/c-family/c-pragma.cc   | 56 ++
   gcc/c-family/c-pragma.h|  2 ++
   gcc/c/c-parser.cc  | 21 ++
   gcc/cp/parser.cc   | 45 ++
   8 files changed, 138 insertions(+), 57 deletions(-)

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index b5ef5ff6b2c..2fe2f194660 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -990,6 +990,9 @@ extern void c_parse_file (void);
   extern void c_parse_final_cleanups (void);
+/* This initializes for preprocess-only mode.  */
+extern void c_init_preprocess (void);
+
   /* These macros provide convenient access to the various _STMT nodes.  */
   /* Nonzero if a given STATEMENT_LIST represents the outermost binding
@@ -1214,6 +1217,7 @@ extern tree c_build_bind_expr (location_t, tree, tree);
   /* In c-lex.cc.  */
   extern enum cpp_ttype
   conflict_marker_get_final_tok_kind (enum cpp_ttype tok1_kind);
+extern void c_lex_enable_token_streaming (bool enabled);
   /* In c-pch.cc  */
   extern void pch_init (void);
diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index dcd061c7cb1..ac4c018d863 100644
--- a/gcc/c-family/c-lex.cc
+++ b/gcc/c-family/c-lex.cc
@@ -57,6 +57,17 @@ static void cb_ident (cpp_reader *, unsigned int, const 
cpp_string *);
   static void cb_def_pragma (cpp_reader *, unsigned int);
   static void cb_define (cpp_reader *, unsigned int, cpp_hashnode *);
   static void cb_undef (cpp_reader *, unsigned int, 

Re: [PATCH] c++: devirtualization of array destruction [PR110057]

2023-07-28 Thread Jason Merrill via Gcc-patches

On 7/26/23 20:06, Ng YongXiang wrote:

Hi Jason,

I've made the following changes.

1. Add pr83054-2.C
2. Move the devirt tests to tree-ssa.
3. Remove dg do run for devirt tests
4. Add // PR c++/110057
5. Generate commit message with git gcc-commit-mklog
6. Check commit format with git gcc-verify

Thanks!


Thanks.  I added a comment and fixed another test that was breaking with 
the patch; here's what I pushed.


JasonFrom a47e615fbf9c6f4b24e5032df5d720b6bf9b63b5 Mon Sep 17 00:00:00 2001
From: Ng YongXiang 
Date: Thu, 27 Jul 2023 08:06:14 +0800
Subject: [PATCH] c++: devirtualization of array destruction [PR110057]
To: gcc-patches@gcc.gnu.org

	PR c++/110057
	PR ipa/83054

gcc/cp/ChangeLog:

	* init.cc (build_vec_delete_1): Devirtualize array destruction.

gcc/testsuite/ChangeLog:

	* g++.dg/warn/pr83054.C: Remove devirtualization warning.
	* g++.dg/lto/pr89335_0.C: Likewise.
	* g++.dg/tree-ssa/devirt-array-destructor-1.C: New test.
	* g++.dg/tree-ssa/devirt-array-destructor-2.C: New test.
	* g++.dg/warn/pr83054-2.C: New test.

Signed-off-by: Ng Yong Xiang 
---
 gcc/cp/init.cc| 11 +++--
 gcc/testsuite/g++.dg/lto/pr89335_0.C  |  2 +-
 .../tree-ssa/devirt-array-destructor-1.C  | 28 
 .../tree-ssa/devirt-array-destructor-2.C  | 29 
 gcc/testsuite/g++.dg/warn/pr83054-2.C | 44 +++
 gcc/testsuite/g++.dg/warn/pr83054.C   |  2 +-
 6 files changed, 110 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-1.C
 create mode 100644 gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-2.C
 create mode 100644 gcc/testsuite/g++.dg/warn/pr83054-2.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index ff5014ca576..3b9a7783391 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4116,8 +4116,8 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type,
   if (type_build_dtor_call (type))
 	{
 	  tmp = build_delete (loc, ptype, base, sfk_complete_destructor,
-			  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
-			  complain);
+			  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR|LOOKUP_NONVIRTUAL,
+			  1, complain);
 	  if (tmp == error_mark_node)
 	return error_mark_node;
 	}
@@ -4146,9 +4146,12 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type,
   if (tmp == error_mark_node)
 return error_mark_node;
   body = build_compound_expr (loc, body, tmp);
+  /* [expr.delete]/3: "In an array delete expression, if the dynamic type of
+ the object to be deleted is not similar to its static type, the behavior
+ is undefined."  So we can set LOOKUP_NONVIRTUAL.  */
   tmp = build_delete (loc, ptype, tbase, sfk_complete_destructor,
-		  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
-		  complain);
+		  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR|LOOKUP_NONVIRTUAL,
+		  1, complain);
   if (tmp == error_mark_node)
 return error_mark_node;
   body = build_compound_expr (loc, body, tmp);
diff --git a/gcc/testsuite/g++.dg/lto/pr89335_0.C b/gcc/testsuite/g++.dg/lto/pr89335_0.C
index 95bf4b3b0cb..76382f8d742 100644
--- a/gcc/testsuite/g++.dg/lto/pr89335_0.C
+++ b/gcc/testsuite/g++.dg/lto/pr89335_0.C
@@ -9,7 +9,7 @@ public:
   virtual ~Container ();
 };
 
-class List : public Container // { dg-lto-message "final would enable devirtualization" }
+class List : public Container
 {
 };
 
diff --git a/gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-1.C b/gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-1.C
new file mode 100644
index 000..ce8dc2a57cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-1.C
@@ -0,0 +1,28 @@
+// PR c++/110057
+/* { dg-do-compile } */
+/* Virtual calls should be devirtualized because we know dynamic type of object in array at compile time */
+/* { dg-options "-O3 -fdump-tree-optimized -fno-inline"  } */
+
+class A
+{
+public:
+  virtual ~A()
+  {
+  }
+};
+
+class B : public A
+{
+public:
+  virtual ~B()
+  {
+  }
+};
+
+int main()
+{
+  B b[10];
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-2.C b/gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-2.C
new file mode 100644
index 000..6b44dc1a4ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/devirt-array-destructor-2.C
@@ -0,0 +1,29 @@
+// PR c++/110057
+/* { dg-do-compile } */
+/* Virtual calls should be devirtualized because we know dynamic type of object in array at compile time */
+/* { dg-options "-O3 -fdump-tree-optimized -fno-inline"  } */
+
+class A
+{
+public:
+  virtual ~A()
+  {
+  }
+};
+
+class B : public A
+{
+public:
+  virtual ~B()
+  {
+  }
+};
+
+int main()
+{
+  B* ptr = new B[10];
+  delete[] ptr;
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
diff --git a/gcc/testsuite/g++.dg/warn/pr83054-2.C b/gcc/testsuite/g++.dg/warn/pr83054-2.C
new file 

Re: [PATCH v2] c-family: Implement pragma_lex () for preprocess-only mode

2023-07-27 Thread Jason Merrill via Gcc-patches

On 7/27/23 18:59, Lewis Hyatt wrote:

In order to support processing #pragma in preprocess-only mode (-E or
-save-temps for gcc/g++), we need a way to obtain the #pragma tokens from
libcpp. In full compilation modes, this is accomplished by calling
pragma_lex (), which is a symbol that must be exported by the frontend, and
which is currently implemented for C and C++. Neither of those frontends
initializes its parser machinery in preprocess-only mode, and consequently
pragma_lex () does not work in this case.

Address that by adding a new function c_init_preprocess () for the frontends
to implement, which arranges for pragma_lex () to work in preprocess-only
mode, and adjusting pragma_lex () accordingly.

In preprocess-only mode, the preprocessor is accustomed to controlling the
interaction with libcpp, and it only knows about tokens that it has called
into libcpp itself to obtain. Since it still needs to see the tokens
obtained by pragma_lex () so that they can be streamed to the output, also
adjust c_lex_with_flags () and related functions in c-family/c-lex.cc to
inform the preprocessor about any tokens it won't be aware of.

Currently, there is one place where we are already supporting #pragma in
preprocess-only mode, namely the handling of `#pragma GCC diagnostic'.  That
was done by directly interfacing with libcpp, rather than making use of
pragma_lex (). Now that pragma_lex () works, that code is no longer
necessary; remove it.

gcc/c-family/ChangeLog:

* c-common.h (c_init_preprocess): Declare.
(c_lex_enable_token_streaming): Declare.
* c-opts.cc (c_common_init): Call c_init_preprocess ().
* c-lex.cc (stream_tokens_to_preprocessor): New static variable.
(c_lex_enable_token_streaming): New function.
(cb_def_pragma): Add a comment.
(get_token): New function wrapping cpp_get_token.
(c_lex_with_flags): Use the new wrapper function to support
obtaining tokens in preprocess_only mode.
(lex_string): Likewise.
* c-ppoutput.cc (preprocess_file): Call c_lex_enable_token_streaming
when needed.
* c-pragma.cc (pragma_diagnostic_lex_normal): Rename to...
(pragma_diagnostic_lex): ...this.
(pragma_diagnostic_lex_pp): Remove.
(handle_pragma_diagnostic_impl): Call pragma_diagnostic_lex () in
all modes.
(c_pp_invoke_early_pragma_handler): Adapt to support pragma_lex ()
usage.
* c-pragma.h (pragma_lex_discard_to_eol): Declare.

gcc/c/ChangeLog:

* c-parser.cc (pragma_lex_discard_to_eol): New function.
(c_init_preprocess): New function.

gcc/cp/ChangeLog:

* parser.cc (c_init_preprocess): New function.
(maybe_read_tokens_for_pragma_lex): New function.
(pragma_lex): Support preprocess-only mode.
(pragma_lex_discard_to_eol): New function.
---

Notes:
 Hello-
 
 Here is version 2 of the patch, incorporating Jason's feedback from

 https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625591.html
 
 Thanks again, please let me know if it's OK? Bootstrap + regtest all

 languages on x86-64 Linux looks good.
 
 -Lewis


  gcc/c-family/c-common.h|  4 +++
  gcc/c-family/c-lex.cc  | 49 +
  gcc/c-family/c-opts.cc |  1 +
  gcc/c-family/c-ppoutput.cc | 17 +---
  gcc/c-family/c-pragma.cc   | 56 ++
  gcc/c-family/c-pragma.h|  2 ++
  gcc/c/c-parser.cc  | 21 ++
  gcc/cp/parser.cc   | 45 ++
  8 files changed, 138 insertions(+), 57 deletions(-)

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index b5ef5ff6b2c..2fe2f194660 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -990,6 +990,9 @@ extern void c_parse_file (void);
  
  extern void c_parse_final_cleanups (void);
  
+/* This initializes for preprocess-only mode.  */

+extern void c_init_preprocess (void);
+
  /* These macros provide convenient access to the various _STMT nodes.  */
  
  /* Nonzero if a given STATEMENT_LIST represents the outermost binding

@@ -1214,6 +1217,7 @@ extern tree c_build_bind_expr (location_t, tree, tree);
  /* In c-lex.cc.  */
  extern enum cpp_ttype
  conflict_marker_get_final_tok_kind (enum cpp_ttype tok1_kind);
+extern void c_lex_enable_token_streaming (bool enabled);
  
  /* In c-pch.cc  */

  extern void pch_init (void);
diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index dcd061c7cb1..ac4c018d863 100644
--- a/gcc/c-family/c-lex.cc
+++ b/gcc/c-family/c-lex.cc
@@ -57,6 +57,17 @@ static void cb_ident (cpp_reader *, unsigned int, const 
cpp_string *);
  static void cb_def_pragma (cpp_reader *, unsigned int);
  static void cb_define (cpp_reader *, unsigned int, cpp_hashnode *);
  static void cb_undef (cpp_reader *, unsigned int, cpp_hashnode *);
+
+/* Flag to remember if we are in a mode (such as flag_preprocess_only) in 

Re: [PATCH v5 4/5] c++modules: report imported CMI files as dependencies

2023-07-27 Thread Jason Merrill via Gcc-patches

On 7/23/23 20:26, Ben Boeckel wrote:

On Fri, Jul 21, 2023 at 16:23:07 -0400, Nathan Sidwell wrote:

It occurs to me that the model I am envisioning is similar to CMake's object
libraries.  Object libraries are a convenient name for a bunch of object files.
IIUC they're linked by naming the individual object files (or I think the could
be implemented as a static lib linked with --whole-archive path/to/libfoo.a
-no-whole-archive.  But for this conversation consider them a bunch of separate
object files with a convenient group name.


Yes, `--whole-archive` would work great if it had any kind of
portability across CMake's platform set.


Consider also that object libraries could themselves contain object libraries (I
don't know of they can, but it seems like a useful concept).  Then one could
create an object library from a collection of object files and object libraries
(recursively).  CMake would handle the transitive gtaph.


I think this detail is relevant, but you can use
`$` as an `INTERFACE` sources and it would act
like that, but it is an explicit thing. Instead, `OBJECT` libraries
*only* provide their objects to targets that *directly* link them. If
not, given this:

 A (OBJECT library)
 B (library of some kind; links PUBLIC to A)
 C (links to B)

If `A` has things like linker flags (or, more likely, libraries) as part
of its usage requirements, C will get them on is link line. However, if
OBJECT files are transitive in the same way, the linker (on most
platforms at least) chokes because it now has duplicates of all of A's
symbols: those from the B library and those from A's objects on the link
line.


Now, allow an object library to itself have some kind of tangible, on-disk
representation.  *BUT* not like a static library -- it doesn't include the
object files.


Now that immediately maps onto modules.

CMI: Object library
Direct imports: Direct object libraries of an object library

This is why I don't understand the need explicitly indicate the indirect imports
of a CMI.  CMake knows them, because it knows the graph.


Sure, *CMake* knows them, but the *build tool* needs to be told
(typically `make` or `ninja`) because it is what is actually executing
the build graph. The way this is communicated is via `-MF` files and
that's what I'm providing in this patch. Note that `ninja` does not
allow rules to specify such dependencies for other rules than the one it
is reading the file for.


But since the direct imports need to be rebuilt themselves if the 
transitive imports change, the build graph should be the same whether or 
not the transitive imports are repeated?  Either way, if a transitive 
import changes you need to rebuild the direct import and then the importer.


I guess it shouldn't hurt to have the transitive imports in the -MF 
file, as long as they aren't also in the p1689 file, so I'm not 
particularly opposed to this change, but I don't see how it makes a 
practical difference.


Jason



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

2023-07-26 Thread Jason Merrill via Gcc-patches

On 6/30/23 03:05, Nathaniel Shead wrote:

On Thu, Jun 29, 2023 at 01:43:07PM -0400, Jason Merrill wrote:

On 6/24/23 09:24, Nathaniel Shead wrote:

On Fri, Jun 23, 2023 at 11:59:51AM -0400, Patrick Palka wrote:

Hi,

On Sat, 22 Apr 2023, Nathaniel Shead via Gcc-patches wrote:


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

-- 8< --

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


Thanks very much for the patch!  Some minor comments below.



PR 103497


We should include the bug component name when referring to the PR in the
commit message (i.e. PR c++/103497) so that upon pushing the patch the
post-commit hook automatically adds a comment to the PR reffering to the
commit.  I could be wrong but AFAIK the hook only performs this when the
component name is included.


Thanks for the review! Fixed.



gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

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

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e5f032f2330..1415e07e152 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -19884,6 +19884,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
   {
 type = saved_checks_value (token->u.tree_check_value);
+  /* Within a function parameter declaration, decltype(auto) is always an
+error.  */
+  if (parser->auto_is_implicit_function_template_parm_p
+ && TREE_CODE (type) == TEMPLATE_TYPE_PARM


We could check is_auto (type) here instead, to avoid any confusion with
checking AUTO_IS_DECLTYPE for a non-auto TEMPLATE_TYPE_PARM.


+ && AUTO_IS_DECLTYPE (type))
+   {
+ error_at (token->location,
+   "cannot declare a parameter with %");
+ type = error_mark_node;
+   }
 if (decl_specs)
{
  cp_parser_set_decl_spec_type (decl_specs, type,
diff --git a/gcc/testsuite/g++.dg/pr103497.C b/gcc/testsuite/g++.dg/pr103497.C
new file mode 100644
index 000..bcd421c2907
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103497.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++14 } }
+
+void foo(decltype(auto)... args);  // { dg-error "parameter with 
.decltype.auto..|no parameter packs" }


I noticed for

void foo(decltype(auto) arg);

we already issue an identical error from grokdeclarator.  Perhaps we could
instead extend the error handling there to detect decltype(auto)... as well,
rather than adding new error handling in cp_parser_simple_type_specifier?


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

Regtested on x86_64-pc-linux-gnu.

-- 8< --

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

PR c++/103497

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

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

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 60f107d50c4..aaf691fce68 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -14044,6 +14044,9 @@ grokdeclarator (const cp_declarator *declarator,
error ("cannot use %<::%> in parameter declaration");
 tree auto_node = type_uses_auto (type);
+  if (!auto_node && parameter_pack_p)
+   auto_node = type_uses_auto (PACK_EXPANSION_PATTERN (type));


Hmm, I wonder if type_uses_auto should look into PACK_EXPANSION_PATTERN
itself.  Would that break anything?


I gave that a try and it seems to work fine.

Regtested on x86_64-pc-linux-gnu.


Pushed, thanks.


-- 8< --

This patch ensures 'type_uses_auto' also checks for usages of 'auto' in
parameter packs.

PR c++/103497

gcc/cp/ChangeLog:

* pt.cc (type_uses_auto): Check inside parameter packs.

gcc/testsuite/ChangeLog:

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

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

Re: [PATCH] c-family: Implement pragma_lex () for preprocess-only mode

2023-07-26 Thread Jason Merrill via Gcc-patches

On 6/30/23 18:59, Lewis Hyatt wrote:

In order to support processing #pragma in preprocess-only mode (-E or
-save-temps for gcc/g++), we need a way to obtain the #pragma tokens from
libcpp. In full compilation modes, this is accomplished by calling
pragma_lex (), which is a symbol that must be exported by the frontend, and
which is currently implemented for C and C++. Neither of those frontends
initializes its parser machinery in preprocess-only mode, and consequently
pragma_lex () does not work in this case.

Address that by adding a new function c_init_preprocess () for the frontends
to implement, which arranges for pragma_lex () to work in preprocess-only
mode, and adjusting pragma_lex () accordingly.

In preprocess-only mode, the preprocessor is accustomed to controlling the
interaction with libcpp, and it only knows about tokens that it has called
into libcpp itself to obtain. Since it still needs to see the tokens
obtained by pragma_lex () so that they can be streamed to the output, also
add a new libcpp callback, on_token_lex (), that ensures the preprocessor
sees these tokens too.

Currently, there is one place where we are already supporting #pragma in
preprocess-only mode, namely the handling of `#pragma GCC diagnostic'.  That
was done by directly interfacing with libcpp, rather than making use of
pragma_lex (). Now that pragma_lex () works, that code is no longer
necessary; remove it.

gcc/c-family/ChangeLog:

* c-common.h (c_init_preprocess): Declare new function.
* c-opts.cc (c_common_init): Call it.
* c-pragma.cc (pragma_diagnostic_lex_normal): Rename to...
(pragma_diagnostic_lex): ...this.
(pragma_diagnostic_lex_pp): Remove.
(handle_pragma_diagnostic_impl): Call pragma_diagnostic_lex () in
all modes.
(c_pp_invoke_early_pragma_handler): Adapt to support pragma_lex ()
usage.
* c-pragma.h (pragma_lex_discard_to_eol): Declare new function.

gcc/c/ChangeLog:

* c-parser.cc (pragma_lex): Support preprocess-only mode.
(pragma_lex_discard_to_eol): New function.
(c_init_preprocess): New function.

gcc/cp/ChangeLog:

* parser.cc (c_init_preprocess): New function.
(maybe_read_tokens_for_pragma_lex): New function.
(pragma_lex): Support preprocess-only mode.
(pragma_lex_discard_to_eol): New funtion.

libcpp/ChangeLog:

* include/cpplib.h (struct cpp_callbacks): Add new callback
on_token_lex.
* macro.cc (cpp_get_token_1): Support new callback.
---

Notes:
 Hello-
 
 In r13-1544, I added support for processing `#pragma GCC diagnostic' in

 preprocess-only mode. Because pragma_lex () doesn't work in that mode, in
 that patch I called into libcpp directly to obtain the tokens needed to
 process the pragma. As part of the review, Jason noted that it would
 probably be better to make pragma_lex () usable in preprocess-only mode, 
and
 we decided just to add a comment about that for the time being, and to go
 ahead and implement that in the future, if it became necessary to support
 other pragmas during preprocessing.
 
 I think now is a good time to proceed with that plan, because I would like

 to fix PR87299, which is about another pragma (#pragma GCC target) not
 working in preprocess-only mode. This patch makes the necessary changes for
 pragma_lex () to work in preprocess-only mode.
 
 I have also added a new callback, on_token_lex (), to libcpp. This is so the

 preprocessor can see and stream out all the tokens that pragma_lex () gets
 from libcpp, since it won't otherwise see them.  This seemed the simplest
 approach to me. Another possibility would be to add a wrapper function in
 c-family/c-lex.cc, which would call cpp_get_token_with_location(), and then
 also stream the token in preprocess-only mode, and then change all calls
 into libcpp in that file to use the wrapper function.  The libcpp callback
 seemed cleaner to me FWIW.


I think the other way sounds better to me; there are only three calls to 
cpp_get_... in c_lex_with_flags.


The rest of the patch looks good.

Jason



Re: [PATCH 1/2][frontend] Add novector C++ pragma

2023-07-26 Thread Jason Merrill via Gcc-patches

On 7/26/23 15:32, Tamar Christina wrote:

+
+   cp_token *tok = pragma_tok;
+
+   do
  {
-   tok = cp_lexer_consume_token (parser->lexer);
-   ivdep = cp_parser_pragma_ivdep (parser, tok);
-   tok = cp_lexer_peek_token (the_parser->lexer);
+   switch (cp_parser_pragma_kind (tok))
+ {
+   case PRAGMA_IVDEP:
+ {
+   if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+   ivdep = cp_parser_pragma_ivdep (parser, tok);
+   tok = cp_lexer_peek_token (the_parser->lexer);
+   break;
+ }
+   case PRAGMA_UNROLL:
+ {
+   if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+   unroll = cp_parser_pragma_unroll (parser, tok);
+   tok = cp_lexer_peek_token (the_parser->lexer);
+   break;
+ }
+   case PRAGMA_NOVECTOR:
+ {
+   if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+   novector = cp_parser_pragma_novector (parser, tok);
+   tok = cp_lexer_peek_token (the_parser->lexer);
+   break;
+ }
+   default:
+ gcc_unreachable ();


This unreachable seems to assert that if a pragma follows one of these
pragmas, it must be another one of these pragmas?  That seems wrong;
instead of hitting gcc_unreachable() in that case we should fall through to the
diagnostic below.



Ah, good should. Since it has to exit two levels I had to introduce a bool
for controlling the loop iterations.  New patch below.

Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.

Ok for master?


OK.


Thanks,
Tamar

gcc/cp/ChangeLog:

* cp-tree.h (RANGE_FOR_NOVECTOR): New.
(cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt,
finish_for_cond): Add novector param.
* init.cc (build_vec_init): Default novector to false.
* method.cc (build_comparison_op): Likewise.
* parser.cc (cp_parser_statement): Likewise.
(cp_parser_for, cp_parser_c_for, cp_parser_range_for,
cp_convert_range_for, cp_parser_iteration_statement,
cp_parser_omp_for_loop, cp_parser_pragma): Support novector.
(cp_parser_pragma_novector): New.
* pt.cc (tsubst_expr): Likewise.
* semantics.cc (finish_while_stmt_cond, finish_do_stmt,
finish_for_cond): Likewise.

gcc/ChangeLog:

* doc/extend.texi: Document it.

gcc/testsuite/ChangeLog:

* g++.dg/vect/vect.exp (support vect- prefix).
* g++.dg/vect/vect-novector-pragma.cc: New test.

--- inline copy of patch ---

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 
8398223311194837441107cb335d497ff5f5ec1c..bece7bff1f01a23cfc94386fd3295a0be8c462fe
 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5377,6 +5377,7 @@ get_vec_init_expr (tree t)
  #define RANGE_FOR_UNROLL(NODE)TREE_OPERAND (RANGE_FOR_STMT_CHECK 
(NODE), 4)
  #define RANGE_FOR_INIT_STMT(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 
5)
  #define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE))
+#define RANGE_FOR_NOVECTOR(NODE) TREE_LANG_FLAG_5 (RANGE_FOR_STMT_CHECK (NODE))
  
  /* STMT_EXPR accessor.  */

  #define STMT_EXPR_STMT(NODE)  TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0)
@@ -7286,7 +7287,7 @@ extern bool maybe_clone_body  (tree);
  
  /* In parser.cc */

  extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool,
- unsigned short);
+ unsigned short, bool);
  extern void cp_convert_omp_range_for (tree &, vec *, tree &,
  tree &, tree &, tree &, tree &, tree &);
  extern void cp_finish_omp_range_for (tree, tree);
@@ -7609,16 +7610,19 @@ extern void begin_else_clause   (tree);
  extern void finish_else_clause(tree);
  extern void finish_if_stmt(tree);
  extern tree begin_while_stmt  (void);
-extern void finish_while_stmt_cond (tree, tree, bool, unsigned short);
+extern void finish_while_stmt_cond (tree, tree, bool, unsigned short,
+bool);
  extern void finish_while_stmt (tree);
  extern tree begin_do_stmt (void);
  extern void finish_do_body(tree);
-extern void finish_do_stmt (tree, tree, bool, unsigned short);
+extern void finish_do_stmt (tree, tree, bool, unsigned short,
+bool);
  extern tree finish_return_stmt(tree);
  extern tree begin_for_scope   (tree *);

Re: [PATCH v2][RFC] c-family: Implement __has_feature and __has_extension [PR60512]

2023-07-26 Thread Jason Merrill via Gcc-patches

On 6/28/23 06:35, Alex Coplan wrote:

Hi,

This patch implements clang's __has_feature and __has_extension in GCC.
This is a v2 of the original RFC posted here:

https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617878.html

Changes since v1:
  - Follow the clang behaviour where -pedantic-errors means that
__has_extension behaves exactly like __has_feature.
  - We're now more conservative with reporting C++ features as extensions
available in C++98. For features where we issue a pedwarn in C++98
mode, we no longer report these as available extensions for C++98.
  - Switch to using a hash_map to store the features. As well as ensuring
lookup is constant time, this allows us to dynamically register
features (right now based on frontend, but later we could allow the
target to register additional features).
  - Also implement some Objective-C features, add a langhook to dispatch
to each frontend to allow it to register language-specific features.


Hmm, it seems questionable to use a generic langhook for something that 
the generic code doesn't care about, only the c-family front ends.  A 
common pattern in c-family is to declare a signature in c-common.h and 
define it differently for the various front-ends, i.e. in the *-lang.cc 
files.



There is an outstanding question around what to do with
cxx_binary_literals in the C frontend for C2x. Should we introduce a new
c_binary_literals feature that is a feature in C2x and an extension
below that, or should we just continue using the cxx_binary_literals
feature and mark that as a standard feature in C2x? See the comment in
c_feature_table in the patch.


What does clang do here?


There is also some doubt over what to do with the undocumented "tls"
feature.  In clang this is gated on whether the target supports TLS, but
in clang (unlike GCC) it is a hard error to use TLS when the target
doesn't support it.  In GCC I believe you can always use TLS, you just
get emulated TLS in the case that the target doesn't support it
natively.  So in this patch GCC always reports having the "tls" feature.
Would appreciate if anyone has feedback on this aspect.


Hmm, I don't think GCC always supports TLS, given that the testsuite has 
a predicate to check for that support (and others to check for emulated 
or native support).


But I think it's right to report having "tls" for emulated support.


I know Iain was concerned that it should be possible to have
target-specific features. Hopefully it is clear that the design in this
patch is more amenable in this. I think for Darwin it should be possible
to add a targetcm hook to register additional features (either passing
through a callback to allow the target code to add to the hash_map, or
exposing a separate langhook that the target can call to register
features).


The design seems a bit complicated still, with putting a callback into 
the map.  Do we need the callbacks?  Do we expect the value of 
__has_feature to change at different points in compilation?  Does that 
happen in clang?



Bootstrapped/regtested on aarch64-linux-gnu and x86_64-apple-darwin. Any
thoughts?


Most of the patch needs more comments, particularly before various 
top-level definitions.


Jason



Re: [PATCH] c++: constexpr empty subobject confusion [PR110197]

2023-07-26 Thread Jason Merrill via Gcc-patches

On 7/26/23 12:57, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/13 (later)?


OK.


-- >8 --

Now that init_subob_ctx no longer sets new_ctx.ctor for a subobject of
empty type, it seems we need to ensure its callers cxx_eval_bare_aggregate
and cxx_eval_vec_init_1 consistently omit entries for such subobjects in
the parent ctx->ctor.  We also need to allow cxx_eval_array_reference
to synthesize an empty element object even if the array CONSTRUCTOR
has CONSTRUCTOR_NO_CLEARING set.

PR c++/110197

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_array_reference): Return a synthesized
empty subobject even if CONSTRUCTOR_NO_CLEARING is set.
(cxx_eval_bare_aggregate): Set 'no_slot' to true more generally
whenever new_ctx.ctor is empty, i.e. for any subobject of empty
type.
(cxx_eval_vec_init_1): Define 'no_slot' as above and use it
accordingly.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-empty18.C: New test.
* g++.dg/cpp0x/constexpr-empty19.C: New test.
---
  gcc/cp/constexpr.cc   | 23 +--
  .../g++.dg/cpp0x/constexpr-empty18.C  |  7 ++
  .../g++.dg/cpp0x/constexpr-empty19.C  | 12 ++
  3 files changed, 35 insertions(+), 7 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-empty18.C
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-empty19.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index f2fcb54626d..da2c3116810 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4297,6 +4297,9 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
  
/* Not found.  */
  
+  if (is_really_empty_class (elem_type, /*ignore_vptr*/false))

+return build_constructor (elem_type, NULL);
+
if (TREE_CODE (ary) == CONSTRUCTOR
&& CONSTRUCTOR_NO_CLEARING (ary))
  {
@@ -4314,9 +4317,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
   directly for non-aggregates to avoid creating a garbage CONSTRUCTOR.  */
tree val;
constexpr_ctx new_ctx;
-  if (is_really_empty_class (elem_type, /*ignore_vptr*/false))
-return build_constructor (elem_type, NULL);
-  else if (CP_AGGREGATE_TYPE_P (elem_type))
+  if (CP_AGGREGATE_TYPE_P (elem_type))
  {
tree empty_ctor = build_constructor (init_list_type_node, NULL);
val = digest_init (elem_type, empty_ctor, tf_warning_or_error);
@@ -5095,9 +5096,9 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
FOR_EACH_CONSTRUCTOR_ELT (v, i, index, value)
  {
tree orig_value = value;
-  /* Like in cxx_eval_store_expression, omit entries for empty fields.  */
-  bool no_slot = TREE_CODE (type) == RECORD_TYPE && is_empty_field (index);
init_subob_ctx (ctx, new_ctx, index, value);
+  /* Like in cxx_eval_store_expression, omit entries for empty fields.  */
+  bool no_slot = new_ctx.ctor == NULL_TREE;
int pos_hint = -1;
if (new_ctx.ctor != ctx->ctor && !no_slot)
{
@@ -5261,7 +5262,8 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree 
atype, tree init,
bool reuse = false;
constexpr_ctx new_ctx;
init_subob_ctx (ctx, new_ctx, idx, pre_init ? init : elttype);
-  if (new_ctx.ctor != ctx->ctor)
+  bool no_slot = new_ctx.ctor == NULL_TREE;
+  if (new_ctx.ctor != ctx->ctor && !no_slot)
{
  if (zeroed_out)
CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = false;
@@ -5306,7 +5308,14 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree 
atype, tree init,
}
if (*non_constant_p)
break;
-  if (new_ctx.ctor != ctx->ctor)
+  if (no_slot)
+   {
+ /* This is an initializer for an empty subobject; now that we've
+checked that it's constant, we can ignore it.  */
+ gcc_checking_assert (i == 0);
+ break;
+   }
+  else if (new_ctx.ctor != ctx->ctor)
{
  /* We appended this element above; update the value.  */
  gcc_assert ((*p)->last().index == idx);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty18.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty18.C
new file mode 100644
index 000..4bb9e3dcb64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty18.C
@@ -0,0 +1,7 @@
+// PR c++/110197
+// { dg-do compile { target c++11 } }
+
+struct A { constexpr A(int) { } };
+struct B { A a; };
+constexpr B f(int n) { return B{A{n}}; }
+constexpr B b = f(1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty19.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty19.C
new file mode 100644
index 000..5ad67682c5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty19.C
@@ -0,0 +1,12 @@
+// PR c++/110197
+// { dg-do compile { target c++11 } }
+
+struct A {
+  constexpr A() : A(__builtin_is_constant_evaluated()) { }
+  constexpr A(int) { }
+};
+constexpr 

Re: [PATCH] c++: unifying REAL_CSTs [PR110809]

2023-07-26 Thread Jason Merrill via Gcc-patches

On 7/26/23 12:57, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/13 (after the branch is unfrozen)?


OK.


-- >8 --

This teaches unify how to compare two REAL_CSTs.

PR c++/110809

gcc/cp/ChangeLog:

* pt.cc (unify) : Generalize to handle
REAL_CST as well.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/nontype-float3.C: New test.
---
  gcc/cp/pt.cc|  5 +++--
  gcc/testsuite/g++.dg/cpp2a/nontype-float3.C | 12 
  2 files changed, 15 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-float3.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d342ab5929a..1e09f304490 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24890,12 +24890,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
/* Types INTEGER_CST and MINUS_EXPR can come from array bounds.  */
/* Type INTEGER_CST can come from ordinary constant template args.  */
  case INTEGER_CST:
+case REAL_CST:
while (CONVERT_EXPR_P (arg))
arg = TREE_OPERAND (arg, 0);
  
-  if (TREE_CODE (arg) != INTEGER_CST)

+  if (TREE_CODE (arg) != TREE_CODE (parm))
return unify_template_argument_mismatch (explain_p, parm, arg);
-  return (tree_int_cst_equal (parm, arg)
+  return (simple_cst_equal (parm, arg)
  ? unify_success (explain_p)
  : unify_template_argument_mismatch (explain_p, parm, arg));
  
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-float3.C b/gcc/testsuite/g++.dg/cpp2a/nontype-float3.C

new file mode 100644
index 000..044fb99905a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-float3.C
@@ -0,0 +1,12 @@
+// PR c++/110809
+// { dg-do compile { target c++20 } }
+
+template struct A { };
+
+template void f(A);
+template void f(A);
+
+int main() {
+  f(A{});
+  f(A{}); // { dg-error "no match" }
+}




[pushed] c++: member vs global template [PR106310]

2023-07-26 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

For backward compatibility we still want to allow patterns like
this->A::foo, but the template keyword in a qualified name is
specifically to specify that a dependent name is a template, so don't look
in the enclosing scope at all.

Also fix handling of dependent bases: if member lookup in the current
instantiation fails and we have dependent bases, the lookup is dependent.
We were already handling that for the case where lookup in the enclosing
scope also fails, but we also want it to affect that lookup itself.

PR c++/106310

gcc/cp/ChangeLog:

* parser.cc (cp_parser_template_name): Skip non-member
lookup after the template keyword.
(cp_parser_lookup_name): Pass down template_keyword_p.

gcc/testsuite/ChangeLog:

* g++.dg/template/template-keyword4.C: New test.
---
 gcc/cp/parser.cc  | 20 ---
 .../g++.dg/template/template-keyword4.C   | 18 +
 2 files changed, 31 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/template-keyword4.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 5e2b5cba57e..571997733be 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2748,7 +2748,7 @@ static tree cp_parser_objc_struct_declaration
 /* Utility Routines */
 
 static cp_expr cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
+  (cp_parser *, tree, enum tag_types, int, bool, bool, tree *, location_t);
 static tree cp_parser_lookup_name_simple
   (cp_parser *, tree, location_t);
 static tree cp_parser_maybe_treat_template_as_class
@@ -18771,7 +18771,7 @@ cp_parser_template_name (cp_parser* parser,
   /* Look up the name.  */
   decl = cp_parser_lookup_name (parser, identifier,
tag_type,
-   /*is_template=*/true,
+   /*is_template=*/1 + template_keyword_p,
/*is_namespace=*/false,
check_dependency_p,
/*ambiguous_decls=*/NULL,
@@ -31173,7 +31173,7 @@ prefer_type_arg (tag_types tag_type)
refer to types are ignored.
 
If IS_TEMPLATE is TRUE, bindings that do not refer to templates are
-   ignored.
+   ignored.  If IS_TEMPLATE IS 2, the 'template' keyword was specified.
 
If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
are ignored.
@@ -31188,7 +31188,7 @@ prefer_type_arg (tag_types tag_type)
 static cp_expr
 cp_parser_lookup_name (cp_parser *parser, tree name,
   enum tag_types tag_type,
-  bool is_template,
+  int is_template,
   bool is_namespace,
   bool check_dependency,
   tree *ambiguous_decls,
@@ -31372,7 +31372,14 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   else
decl = NULL_TREE;
 
-  if (!decl)
+  /* If we didn't find a member and have dependent bases, the member lookup
+is now dependent.  */
+  if (!dep && !decl && any_dependent_bases_p (object_type))
+   dep = true;
+
+  if (dep && is_template == 2)
+   /* The template keyword specifies a dependent template.  */;
+  else if (!decl)
/* Look it up in the enclosing context.  DR 141: When looking for a
   template-name after -> or ., only consider class templates.  */
decl = lookup_name (name, is_namespace ? LOOK_want::NAMESPACE
@@ -31400,8 +31407,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 
   /* If we know we're looking for a type (e.g. A in p->A::x),
 mock up a typename.  */
-  if (!decl && object_type && tag_type != none_type
- && dependentish_scope_p (object_type))
+  if (!decl && dep && tag_type != none_type)
{
  tree type = build_typename_type (object_type, name, name,
   typename_type);
diff --git a/gcc/testsuite/g++.dg/template/template-keyword4.C 
b/gcc/testsuite/g++.dg/template/template-keyword4.C
new file mode 100644
index 000..a7ab9bb8ca6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/template-keyword4.C
@@ -0,0 +1,18 @@
+// PR c++/106310
+
+template 
+struct set{};
+
+template< typename T >
+struct Base
+{
+  template< int > int set(T const &);
+};
+
+template< typename T >
+struct Derived : Base< T >
+{
+  void f(T const ) {
+this->template set< 0 >(arg);
+  }
+};

base-commit: 21da32d995c8b574c929ec420cd3b0fcfe6fa4fe
-- 
2.39.3



Re: [PATCH] c++: devirtualization of array destruction [PR110057]

2023-07-26 Thread Jason Merrill via Gcc-patches

On 7/26/23 12:00, Ng YongXiang wrote:

Hi Jason,

Thanks for the reply and review. I've attached an updated patch with the 
change log and sign off.


The change made in gcc/testsuite/g++.dg/warn/pr83054.C is because I 
think there is no more warning since we have already devirtualized the 
destruction for the array.


Makes sense, and it's good to have your adjusted testcase in the 
testsuite, it should just be a new one (maybe pr83054-2.C).


Apologies for the poor formatting. It is my first time contributing. Do 
let me know if there's any stuff I've missed and feel free to modify the 
patch where you deem necessary.


No worries!

The ChangeLog entries still need some adjustment, according to git 
gcc-verify (from contrib/gcc-git-customization.sh, see 
https://gcc.gnu.org/gitwrite.html):


ERR: line should start with a tab: "* init.c: Call non virtual 
destructor of objects in array"
ERR: line should start with a tab: "* 
g++.dg/devirt-array-destructor-1.C: New."
ERR: line should start with a tab: "* 
g++.dg/devirt-array-destructor-2.C: New."
ERR: line should start with a tab: "* g++.dg/warn/pr83054.C: 
Remove expected warnings caused by devirtualization"
ERR: PR 110057 in subject but not in changelog: "c++: devirtualization 
of array destruction [PR110057]"


git gcc-commit-mklog (also from gcc-git-customization.sh) makes 
generating ChangeLog entries a lot simpler.



* g++.dg/devirt-array-destructor-1.C: New.


Tests that look at tree-optimization dump files should go in the 
g++.dg/tree-ssa subdirectory.



+/* { dg-do run } */


It seems unnecessary to execute these tests, I'd think the default of { 
dg-do compile } would be fine.


It's also good to have a

// PR c++/110057

line at the top of the testcase for future reference.  gcc-commit-mklog 
also uses that to add the PR number to the ChangeLog.


Jason



Re: [PATCH] - Devirtualization of array destruction (C++) - 110057

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/12/23 10:10, Ng YongXiang via Gcc-patches wrote:

Component:
c++

Bug ID:
110057

Bugzilla link:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110057

Description:
Array should not call virtual destructor of object when array is destructed

ChangeLog:

2023-07-12  Ng YongXiang  PR c++
* Devirtualize auto generated destructor calls of arraycp/*
init.c: Call non virtual destructor of objects in arraytestsuite/
   * g++.dg/devirt-array-destructor-1.C: New.*
g++.dg/devirt-array-destructor-2.C: New.


On Wed, Jul 12, 2023 at 5:02 PM Xi Ruoyao  wrote:


On Wed, 2023-07-12 at 16:58 +0800, Ng YongXiang via Gcc-patches wrote:

I'm writing to seek for a review for an issue I filed some time ago.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110057 . A proposed patch

is

attached in the bug tracker as well.


You should send the patch to gcc-patches@gcc.gnu.org for a review, see
https://gcc.gnu.org/contribute.html for the details.  Generally we
consider patches attached in bugzilla as drafts.


Thanks!  The change makes sense under 
https://eel.is/c++draft/expr.delete#3.sentence-2 , but please look again 
at contribute.html.


In particular, the Legal section; you don't seem to have a copyright 
assignment with the FSF, nor do I see a DCO certification 
(https://gcc.gnu.org/dco.html) in your patch.


Like the examples in contribute.html, the subject line should be more 
like "[PATCH] c++: devirtualization of array destruction [PR110057]"


The ChangeLog entry should be in the commit message.


 * g++.dg/warn/pr83054.C: Change expected number of devirtualized calls


This isn't just changing the expected number, it's also changing the 
array from a local variable to dynamically allocated, which is a big 
change to what's being tested.  If you want to test the dynamic case, 
please add a new test instead of making this change.



diff --git a/gcc/testsuite/g++.dg/warn/pr83054.C 
b/gcc/testsuite/g++.dg/warn/pr83054.C
index 5285f94acee..7cd0951713d 100644
--- a/gcc/testsuite/g++.dg/warn/pr83054.C
+++ b/gcc/testsuite/g++.dg/warn/pr83054.C
@@ -10,7 +10,7 @@
 #endif
 
 extern "C" int printf (const char *, ...);

-struct foo // { dg-warning "final would enable devirtualization of 5 calls" }
+struct foo // { dg-warning "final would enable devirtualization of 1 call" }
 {
   static int count;
   void print (int i, int j) { printf ("foo[%d][%d] = %d\n", i, j, x); }
@@ -29,19 +29,15 @@ int foo::count;
 
 int main ()

 {
-  {
-foo array[3][3];
-for (int i = 0; i < 3; i++)
-  {
-   for (int j = 0; j < 3; j++)
- {
-   printf("[%d][%d] = %x\n", i, j, (void *)[i][j]);
- }
-  }
-  // The count should be nine, if not, fail the test.
-  if (foo::count != 9)
-   return 1;
-  }
+  foo* arr[9];
+  for (int i = 0; i < 9; ++i)
+arr[i] = new foo();
+  if (foo::count != 9)
+return 1;
+  for (int i = 0; i < 9; ++i)
+arr[i]->print(i / 3, i % 3);
+  for (int i = 0; i < 9; ++i)
+delete arr[i];





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

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/25/23 16:30, Marek Polacek wrote:

On Tue, Jul 25, 2023 at 04:24:39PM -0400, Jason Merrill wrote:

On 7/25/23 15:59, Marek Polacek wrote:

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


Looks good.  Please do update the other callers as well, while you're
looking at this.


Thanks.  Can I push this part first?


Ah, sure.  I had thought the other callers would be trivial to add.

Jason



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

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/22/23 11:12, Nathaniel Shead wrote:

This is an update of the patch series at
https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625050.html


I applied the patches, with an addition to the first patch to fix 
constexpr-mutable3.C in C++11 mode, which was not part of the default 
std set.  And fixed the testsuite to run that test (and others that test 
c++11_only behavior) in C++11 mode.  Thanks!


FWIW, I test C++ patches with GXX_TESTSUITE_STDS=98,11,14,17,20,impcx 
for more coverage.



Changes since v4:

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

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

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

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

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





[pushed] testsuite: run C++11 tests in C++11 mode

2023-07-25 Thread Jason Merrill via Gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

A recent change missed updating constexpr-mutable3.C because it wasn't run
in C++11 mode even though it checks the behavior for { target c++11_only }.

gcc/testsuite/ChangeLog:

* lib/g++-dg.exp (g++-dg-runtest): Check for c++11_only.
---
 gcc/testsuite/lib/g++-dg.exp | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/lib/g++-dg.exp b/gcc/testsuite/lib/g++-dg.exp
index 046d63170c8..142c52c8426 100644
--- a/gcc/testsuite/lib/g++-dg.exp
+++ b/gcc/testsuite/lib/g++-dg.exp
@@ -55,13 +55,16 @@ proc g++-dg-runtest { testcases flags default-extra-flags } 
{
} else {
# If the test requires a newer C++ version than which
# is tested by default, use that C++ version for that
-   # single test.  This should be updated or commented
-   # out whenever the default std_list is updated or newer
-   # C++ effective target is added.
+   # single test.  Or if a test checks behavior specifically for
+   # one C++ version, include that version in the default list.
+   # These should be adjusted whenever the default std_list is
+   # updated or newer C++ effective target is added.
if [search_for $test "\{ dg-do * \{ target c++23"] {
set std_list { 23 26 }
} elseif [search_for $test "\{ dg-do * \{ target c++26"] {
set std_list { 26 }
+   } elseif [search_for $test "c++11_only"] {
+   set std_list { 98 11 14 20 }
} else {
set std_list { 98 14 17 20 }
}

base-commit: 50656980497d77ac12a5e7179013a6af09ba32f7
-- 
2.39.3



Re: [PATCH 1/2][frontend] Add novector C++ pragma

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/19/23 11:15, Tamar Christina wrote:

Hi All,

FORTRAN currently has a pragma NOVECTOR for indicating that vectorization should
not be applied to a particular loop.

ICC/ICX also has such a pragma for C and C++ called #pragma novector.

As part of this patch series I need a way to easily turn off vectorization of
particular loops, particularly for testsuite reasons.

This patch proposes a #pragma GCC novector that does the same for C++
as gfortan does for FORTRAN and what ICX/ICX does for C++.

I added only some basic tests here, but the next patch in the series uses this
in the testsuite in about ~800 tests.

Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/cp/ChangeLog:

* cp-tree.def (RANGE_FOR_STMT): Update comment.
* cp-tree.h (RANGE_FOR_NOVECTOR): New.
(cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt,
finish_for_cond): Add novector param.
* init.cc (build_vec_init): Default novector to false.
* method.cc (build_comparison_op): Likewise.
* parser.cc (cp_parser_statement): Likewise.
(cp_parser_for, cp_parser_c_for, cp_parser_range_for,
cp_convert_range_for, cp_parser_iteration_statement,
cp_parser_omp_for_loop, cp_parser_pragma): Support novector.
(cp_parser_pragma_novector): New.
* pt.cc (tsubst_expr): Likewise.
* semantics.cc (finish_while_stmt_cond, finish_do_stmt,
finish_for_cond): Likewise.

gcc/ChangeLog:

* doc/extend.texi: Document it.

gcc/testsuite/ChangeLog:

* g++.dg/vect/vect.exp (support vect- prefix).
* g++.dg/vect/vect-novector-pragma.cc: New test.

--- inline copy of patch --
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 
0e66ca70e00caa1dc4beada1024ace32954e2aaf..c13c8ea98a523c4ef1c55a11e02d5da9db7e367e
 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -305,8 +305,8 @@ DEFTREECODE (IF_STMT, "if_stmt", tcc_statement, 4)
  
  /* Used to represent a range-based `for' statement. The operands are

 RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, RANGE_FOR_SCOPE,
-   RANGE_FOR_UNROLL, and RANGE_FOR_INIT_STMT, respectively.  Only used in
-   templates.  */
+   RANGE_FOR_UNROLL, RANGE_FOR_NOVECTOR and RANGE_FOR_INIT_STMT,
+   respectively.  Only used in templates.  */


This change is unnecessary; RANGE_FOR_NOVECTOR is a flag, not an operand.


  DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 6)
  
  /* Used to represent an expression statement.  Use `EXPR_STMT_EXPR' to

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 
dd3665c8ccf48a8a0b1ba2c06400fe50999ea240..8776e8f4cf8266ee715c3e7f943602fdb1acaf79
 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -13658,7 +13660,13 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree 
init, bool ivdep,
   "% pragma");
condition = error_mark_node;
  }
-  finish_for_cond (condition, stmt, ivdep, unroll);
+  else if (novector)
+{
+  cp_parser_error (parser, "missing loop condition in loop with "
+  "% pragma");
+  condition = error_mark_node;
+}


Why is it a problem for a loop with novector to have no condition?  This 
error makes sense for the other pragmas that want to optimize based on 
the condition, it seems unneeded for this pragma.



+
+   cp_token *tok = pragma_tok;
+
+   do
  {
-   tok = cp_lexer_consume_token (parser->lexer);
-   ivdep = cp_parser_pragma_ivdep (parser, tok);
-   tok = cp_lexer_peek_token (the_parser->lexer);
+   switch (cp_parser_pragma_kind (tok))
+ {
+   case PRAGMA_IVDEP:
+ {
+   if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+   ivdep = cp_parser_pragma_ivdep (parser, tok);
+   tok = cp_lexer_peek_token (the_parser->lexer);
+   break;
+ }
+   case PRAGMA_UNROLL:
+ {
+   if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+   unroll = cp_parser_pragma_unroll (parser, tok);
+   tok = cp_lexer_peek_token (the_parser->lexer);
+   break;
+ }
+   case PRAGMA_NOVECTOR:
+ {
+   if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+   novector = cp_parser_pragma_novector (parser, tok);
+   tok = cp_lexer_peek_token (the_parser->lexer);
+   break;
+ }
+   default:
+ gcc_unreachable ();


This unreachable seems to assert that if a pragma follows one of these 
pragmas, it must be another one of these pragmas?  That seems wrong; 
instead of hitting gcc_unreachable() in that case we should 

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

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/25/23 15:55, Marek Polacek wrote:

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


OK.


-- >8 --

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

PR c++/108960

gcc/cp/ChangeLog:

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

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

+ shouldn't be set.  For instance, we may be called while doing a partial
+ substitution of a template variable, but the type of the variable
+ template may be auto, in which case we will call do_auto_deduction
+ in mark_used (which clears tf_partial) and the auto must be properly
+ reduced at that time for the deduction to work.  */
+  complain &= tf_warning_or_error;
+
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
  
if (modules_p ())


base-commit: 6e424febfbcb27c21a7fe3a137e614765f9cf9d2




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

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/25/23 15:59, Marek Polacek wrote:

On Fri, Jul 21, 2023 at 01:44:17PM -0400, Jason Merrill wrote:

On 7/20/23 17:58, Marek Polacek wrote:

On Thu, Jul 20, 2023 at 03:51:32PM -0400, Marek Polacek wrote:

On Thu, Jul 20, 2023 at 02:37:07PM -0400, Jason Merrill wrote:

On 7/20/23 14:13, Marek Polacek wrote:

On Wed, Jul 19, 2023 at 10:11:27AM -0400, Patrick Palka wrote:

On Tue, 18 Jul 2023, Marek Polacek via Gcc-patches wrote:


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


Looks reasonable to me.


Thanks.

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


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


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


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


It was for the C++98 notion of constant-expression, which was more of a
parser-level notion, and has been supplanted by the C++11 version.  I'm
happy to remove it, and therefore remove the is_rvalue_constant_expression
call.


Wonderful.  I'll do that next.


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


Sure, we would need to use the C++11 code for C++98 mode, which is likely
fine but is more uncertain.

It's probably simpler to just ignore n_i_c_e_p for C++11 and up, along with
Patrick's suggestion of allowing null non_constant_p with true
allow_non_constant_p.


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


Looks good.  Please do update the other callers as well, while you're 
looking at this.



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

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

gcc/cp/ChangeLog:

* parser.cc (cp_parser_constant_expression): Allow non_constant_p to be
nullptr even when allow_non_constant_p is true.  Don't call
_rvalue_constant_expression when not necessary.  Move local variable
declarations closer to their first use.
(cp_parser_static_assert): Don't pass a dummy down to
cp_parser_constant_expression.
---
  gcc/cp/parser.cc | 24 +++-
  1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 5e2b5cba57e..efaa806f107 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -10734,11 +10734,6 @@ cp_parser_constant_expression (cp_parser* parser,
   bool *non_constant_p /* = NULL */,
   bool strict_p /* = false */)
  {
-  bool saved_integral_constant_expression_p;
-  bool saved_allow_non_integral_constant_expression_p;
-  bool saved_non_integral_constant_expression_p;
-  cp_expr expression;
-
/* It might seem that we could simply parse the
   conditional-expression, and then check to see if it were
   TREE_CONSTANT.  However, an expression that is TREE_CONSTANT is
@@ -10757,10 +10752,12 @@ cp_parser_constant_expression (cp_parser* parser,
   will fold this operation to an INTEGER_CST for `3'.  */
  
/* Save the old settings.  */

-  saved_integral_constant_expression_p = 
parser->integral_constant_expression_p;
-  saved_allow_non_integral_constant_expression_p
+  bool saved_integral_constant_expression_p
+= parser->integral_constant_expression_p;
+  bool saved_allow_non_integral_constant_expression_p
  = parser->allow_non_integral_constant_expression_p;
-  

Re: [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566]

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/24/23 13:03, Patrick Palka wrote:

On Fri, 21 Jul 2023, Jason Merrill wrote:

On 7/21/23 14:34, Patrick Palka wrote:

(This is a follow-up of
https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624951.html)

Bootstrapped and regtested on x86_64-pc-linux-gnu, how does this look?

-- >8 --

The previous fix doesn't work for partially instantiated ttps primarily
because most_general_template doesn't work for them.  This patch fixes
this by giving such ttps a DECL_TEMPLATE_INFO (extending the
r11-734-g2fb595f8348e16 fix) with which we can obtain the original ttp.

This patch additionally makes us be more careful about using the correct
amount of levels from the scope of a ttp argument during
coerce_template_template_parms.

PR c++/110566

gcc/cp/ChangeLog:

* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
on the DECL_TEMPLATE_RESULT of a reduced template template
parameter.
(add_defaults_to_ttp): Also update DECL_TEMPLATE_INFO of the
ttp's DECL_TEMPLATE_RESULT.
(coerce_template_template_parms): Make sure 'scope_args' has
the right amount of levels for the ttp argument.
(most_general_template): Handle template template parameters.

gcc/testsuite/ChangeLog:

* g++.dg/template/ttp39.C: New test.
---
   gcc/cp/pt.cc  | 46 ---
   gcc/testsuite/g++.dg/template/ttp39.C | 16 ++
   2 files changed, 57 insertions(+), 5 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e0ed4bc8bbb..be7119dd9a0 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4570,8 +4570,14 @@ reduce_template_parm_level (tree index, tree type,
int levels, tree args,
  TYPE_DECL, DECL_NAME (decl), type);
  DECL_TEMPLATE_RESULT (decl) = inner;
  DECL_ARTIFICIAL (inner) = true;
- DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
-   (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
+ tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
+ args, complain);
+ DECL_TEMPLATE_PARMS (decl) = parms;
+ retrofit_lang_decl (inner);
+ tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
+ DECL_TEMPLATE_INFO (inner)
+   = build_template_info (DECL_TI_TEMPLATE (orig_inner),
+  template_parms_to_args (parms));


Should we assert that orig_inner doesn't have its own DECL_TEMPLATE_INFO?  I'm
wondering if it's possible to reduce the level of a TTP more than once.


It's possible for a ttp belonging to a nested generic lambda:

   template
   void f() {
 [](auto) {
   [] class TT>() {
   };
 }(0);
   }

   template void f();




}
   /* Attach the TPI to the decl.  */
@@ -7936,6 +7942,19 @@ add_defaults_to_ttp (tree otmpl)
}
   }
   +  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
+  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);


Hmm, here we're assuming that all TTPs have DECL_TEMPLATE_INFO?


I figured it's a reasonable assumption since all "formal" ttps
originally start out with DECL_TEMPLATE_INFO (via process_template_parm).
Though I realized I missed adjusting rewrite_template_parm to set
DECL_TEMPLATE_INFO on the new ttp, which the below patch fixes (and
adds a testcase that we'd otherwise segfualt on).




+  tree gen_ntmpl;
+  if (gen_otmpl == otmpl)
+gen_ntmpl = ntmpl;
+  else
+gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
+
+  tree nresult = copy_node (oresult);


Another fixed bug: since we build the new DECL_TEMPLATE_RESULT via
copy_node, we need to avoid sharing its DECL_LANG_SPECIFIC with the
old decl.


+  DECL_TEMPLATE_INFO (nresult) = copy_node (DECL_TEMPLATE_INFO (oresult));
+  DECL_TI_TEMPLATE (nresult) = gen_ntmpl;
+  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
+
 hash_map_safe_put (defaulted_ttp_cache, otmpl, ntmpl);
 return ntmpl;
   }
@@ -8121,15 +8140,29 @@ coerce_template_template_parms (tree parm_tmpl,
 OUTER_ARGS are not the right outer levels in this case, as they are
 the args we're building up for PARM, and for the coercion we want the
 args for ARG.  If DECL_CONTEXT isn't set for a template template
-parameter, we can assume that it's in the current scope.  In that
case
-we might end up adding more levels than needed, but that shouldn't be
-a problem; any args we need to refer to are at the right level.  */
+parameter, we can assume that it's in the current scope.  */
 tree ctx = DECL_CONTEXT (arg_tmpl);
 if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
ctx = current_scope ();
 tree scope_args = NULL_TREE;
 if (tree tinfo = get_template_info (ctx))
scope_args = TI_ARGS (tinfo);
+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
+   {
+ int level = 

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

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/25/23 12:59, Marek Polacek wrote:

On Tue, Jul 25, 2023 at 11:15:07AM -0400, Jason Merrill wrote:

On 7/24/23 18:37, Marek Polacek wrote:

On Sat, Jul 22, 2023 at 12:28:59AM -0400, Jason Merrill wrote:

On 7/21/23 18:38, Marek Polacek wrote:

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

-- >8 --

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

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

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

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

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


...and this code doesn't also clear(/set) new_ctx.object like everywhere
else in constexpr.cc that sets new_ctx.ctor.  Fixing that should make the
testcase work.


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

...except it should work to always clear the object, like below.

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

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

had the right type.


Indeed, and using it rather than building a new one seems like a valid
optimization for trunk.

Agreed, I kept it.


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


It looks like init == ctx->ctor only happens only with this new testcase.
I'm not sure it's worth it adding code for such a rare case?

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

PR c++/110382

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fb94f3cefcb..518b7c7a2d5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4291,7 +4291,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
  else
val = build_value_init (elem_type, tf_warning_or_error);
-  if (!SCALAR_TYPE_P (elem_type))
+  if (!SCALAR_TYPE_P (elem_type)
+  /* Create a new constructor only if we don't already have one that
+is suitable.  */
+  && !(ctx->ctor && same_type_p (elem_type, TREE_TYPE (ctx->ctor


We generally use same_type_ignoring_top_level_qualifiers_p in the constexpr
code.


True, changed.

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

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

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

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

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

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

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

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

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

had the right type.

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

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

PR c++/110382

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-110382.C: New test.
---
   gcc/cp/constexpr.cc   | 17 +++--
   gcc/testsuite/g++.dg/cpp1y/constexpr-110382.C | 17 +
   2 files changed, 32 insertions(+), 2 deletions(-)
   

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

2023-07-25 Thread Jason Merrill via Gcc-patches

On 7/24/23 18:37, Marek Polacek wrote:

On Sat, Jul 22, 2023 at 12:28:59AM -0400, Jason Merrill wrote:

On 7/21/23 18:38, Marek Polacek wrote:

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

-- >8 --

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

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

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

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

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


...and this code doesn't also clear(/set) new_ctx.object like everywhere
else in constexpr.cc that sets new_ctx.ctor.  Fixing that should make the
testcase work.


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

...except it should work to always clear the object, like below.
  

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

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

had the right type.


Indeed, and using it rather than building a new one seems like a valid
optimization for trunk.
  
Agreed, I kept it.



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


It looks like init == ctx->ctor only happens only with this new testcase.
I'm not sure it's worth it adding code for such a rare case?
  

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

PR c++/110382

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fb94f3cefcb..518b7c7a2d5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4291,7 +4291,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
 else
   val = build_value_init (elem_type, tf_warning_or_error);
-  if (!SCALAR_TYPE_P (elem_type))
+  if (!SCALAR_TYPE_P (elem_type)
+  /* Create a new constructor only if we don't already have one that
+is suitable.  */
+  && !(ctx->ctor && same_type_p (elem_type, TREE_TYPE (ctx->ctor


We generally use same_type_ignoring_top_level_qualifiers_p in the constexpr
code.


True, changed.

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

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

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

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

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

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

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

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

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

had the right type.

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

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

PR c++/110382

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc 

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

2023-07-21 Thread Jason Merrill via Gcc-patches

On 7/21/23 18:38, Marek Polacek wrote:

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

-- >8 --

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

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

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

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

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


...and this code doesn't also clear(/set) new_ctx.object like everywhere 
else in constexpr.cc that sets new_ctx.ctor.  Fixing that should make 
the testcase work.



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

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

had the right type.


Indeed, and using it rather than building a new one seems like a valid 
optimization for trunk.


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



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

PR c++/110382

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fb94f3cefcb..518b7c7a2d5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4291,7 +4291,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
else
  val = build_value_init (elem_type, tf_warning_or_error);
  
-  if (!SCALAR_TYPE_P (elem_type))

+  if (!SCALAR_TYPE_P (elem_type)
+  /* Create a new constructor only if we don't already have one that
+is suitable.  */
+  && !(ctx->ctor && same_type_p (elem_type, TREE_TYPE (ctx->ctor


We generally use same_type_ignoring_top_level_qualifiers_p in the 
constexpr code.


Jason



  1   2   3   4   5   6   7   8   9   10   >