Re: configure adds -std=gnu++11 to CXX variable

2024-05-29 Thread Jason Merrill via Gcc
On Wed, May 29, 2024 at 1:34 PM Tom Tromey  wrote:
> > "Jason" == Jason Merrill  writes:
>
> Jason> Thanks, though I don't think all that code needs to go;
> Jason> AC_PROG_CXX_STDCXX_EDITION_TRY still looks useful for a project that
> Jason> relies on features from a particular standard.  We just don't want
> Jason> AC_PROG_CXX to invoke it.
>
> I didn't read the macro but there's also config/ax_cxx_compile_stdcxx.m4.
> gdb uses this to make sure C++17 is available.

Good point, that's what GCC uses as well.

Jason



[gcc r15-902] c++: pragma target and static init [PR109753]

2024-05-29 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:eff00046409a7289bfdc1861e68b532895f91c0e

commit r15-902-geff00046409a7289bfdc1861e68b532895f91c0e
Author: Jason Merrill 
Date:   Wed Feb 14 17:18:17 2024 -0500

c++: pragma target and static init [PR109753]

 #pragma target and optimize should also apply to implicitly-generated
 functions like static initialization functions and defaulted special member
 functions.

The handle_optimize_attribute change is necessary to avoid regressing
g++.dg/opt/pr105306.C; maybe_clone_body creates a cgraph_node for the ~B
alias before handle_optimize_attribute, and the alias never goes through
finalize_function, so we need to adjust semantic_interposition somewhere
else.

PR c++/109753

gcc/c-family/ChangeLog:

* c-attribs.cc (handle_optimize_attribute): Set
cgraph_node::semantic_interposition.

gcc/cp/ChangeLog:

* decl.cc (start_preparsed_function): Call decl_attributes.

gcc/testsuite/ChangeLog:

* g++.dg/opt/always_inline1.C: New test.

Diff:
---
 gcc/c-family/c-attribs.cc | 4 
 gcc/cp/decl.cc| 3 +++
 gcc/testsuite/g++.dg/opt/always_inline1.C | 8 
 3 files changed, 15 insertions(+)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 04e39b41bdf..605469dd7dd 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -5971,6 +5971,10 @@ handle_optimize_attribute (tree *node, tree name, tree 
args,
   if (prev_target_node != target_node)
DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
 
+  /* Also update the cgraph_node, if it's already built.  */
+  if (cgraph_node *cn = cgraph_node::get (*node))
+   cn->semantic_interposition = flag_semantic_interposition;
+
   /* Restore current options.  */
   cl_optimization_restore (_options, _options_set,
   _opts);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index a992d54dc8f..d481e1ec074 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17832,6 +17832,9 @@ start_preparsed_function (tree decl1, tree attrs, int 
flags)
doing_friend = true;
 }
 
+  /* Adjust for #pragma target/optimize.  */
+  decl_attributes (, NULL_TREE, 0);
+
   if (DECL_DECLARED_INLINE_P (decl1)
   && lookup_attribute ("noinline", attrs))
 warning_at (DECL_SOURCE_LOCATION (decl1), 0,
diff --git a/gcc/testsuite/g++.dg/opt/always_inline1.C 
b/gcc/testsuite/g++.dg/opt/always_inline1.C
new file mode 100644
index 000..a042a1cf0c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/always_inline1.C
@@ -0,0 +1,8 @@
+// PR c++/109753
+// { dg-do compile { target x86_64-*-* } }
+
+#pragma GCC target("avx2")
+struct aa {
+__attribute__((__always_inline__)) aa() {}
+};
+aa _M_impl;


[gcc r15-900] c++: add module extensions

2024-05-29 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:ff41abdca0ab9993b6170b9b1f46b3a40921f1b0

commit r15-900-gff41abdca0ab9993b6170b9b1f46b3a40921f1b0
Author: Jason Merrill 
Date:   Thu May 16 16:09:12 2024 -0400

c++: add module extensions

There is a trend in the broader C++ community to use a different extension
for module interface units, even though (in GCC) they are compiled in the
same way as other source files.  Let's recognize these extensions as C++.

.ixx is the MSVC standard, while the .c*m are supported by Clang.  libc++
standard headers use .cppm, as their other source files use .cpp.
Perhaps libstdc++ might use .ccm for parallel consistency?

One issue with .c++m is that libcpp/mkdeps.cc has been using it for the
phony dependencies to express module dependencies, so I'm changing mkdeps to
something less likely to be an actual file, ".c++-module".

gcc/cp/ChangeLog:

* lang-specs.h: Add module interface extensions.

gcc/ChangeLog:

* doc/invoke.texi: Update module extension docs.

libcpp/ChangeLog:

* mkdeps.cc (make_write): Change .c++m to .c++-module.

gcc/testsuite/ChangeLog:

* g++.dg/modules/dep-1_a.C
* g++.dg/modules/dep-1_b.C
* g++.dg/modules/dep-2.C: Change .c++m to .c++-module.

Diff:
---
 gcc/doc/invoke.texi| 20 ++--
 gcc/cp/lang-specs.h|  6 ++
 gcc/testsuite/g++.dg/modules/dep-1_a.C |  4 ++--
 gcc/testsuite/g++.dg/modules/dep-1_b.C |  8 
 gcc/testsuite/g++.dg/modules/dep-2.C   |  4 ++--
 libcpp/mkdeps.cc   | 13 ++---
 6 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 2cba380718b..517a782987d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -2317,9 +2317,12 @@ other language.
 C++ source files conventionally use one of the suffixes @samp{.C},
 @samp{.cc}, @samp{.cpp}, @samp{.CPP}, @samp{.c++}, @samp{.cp}, or
 @samp{.cxx}; C++ header files often use @samp{.hh}, @samp{.hpp},
-@samp{.H}, or (for shared template code) @samp{.tcc}; and
-preprocessed C++ files use the suffix @samp{.ii}.  GCC recognizes
-files with these names and compiles them as C++ programs even if you
+@samp{.H}, or (for shared template code) @samp{.tcc};
+preprocessed C++ files use the suffix @samp{.ii}; and C++20 module interface
+units sometimes use @samp{.ixx}, @samp{.cppm}, @samp{.cxxm}, @samp{.c++m},
+or @samp{.ccm}.
+
+GCC recognizes files with these names and compiles them as C++ programs even 
if you
 call the compiler the same way as for compiling C programs (usually
 with the name @command{gcc}).
 
@@ -37705,13 +37708,10 @@ Modular compilation is @emph{not} enabled with just 
the
 version selected, although in pre-C++20 versions, it is of course an
 extension.
 
-No new source file suffixes are required or supported.  If you wish to
-use a non-standard suffix (@pxref{Overall Options}), you also need
-to provide a @option{-x c++} option too.@footnote{Some users like to
-distinguish module interface files with a new suffix, such as naming
-the source @code{module.cppm}, which involves
-teaching all tools about the new suffix.  A different scheme, such as
-naming @code{module-m.cpp} would be less invasive.}
+No new source file suffixes are required.  A few suffixes preferred
+for module interface units by other compilers (e.g. @samp{.ixx},
+@samp{.cppm}) are supported, but files with these suffixes are treated
+the same as any other C++ source file.
 
 Compiling a module interface unit produces an additional output (to
 the assembly or object file), called a Compiled Module Interface
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index 7a7f5ff0ab5..e5651567a2d 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -39,6 +39,12 @@ along with GCC; see the file COPYING3.  If not see
   {".HPP", "@c++-header", 0, 0, 0},
   {".tcc", "@c++-header", 0, 0, 0},
   {".hh",  "@c++-header", 0, 0, 0},
+  /* Module interface unit.  Should there also be a .C counterpart?  */
+  {".ixx", "@c++", 0, 0, 0}, /* MSVC */
+  {".cppm", "@c++", 0, 0, 0}, /* Clang/libc++ */
+  {".cxxm", "@c++", 0, 0, 0},
+  {".c++m", "@c++", 0, 0, 0},
+  {".ccm", "@c++", 0, 0, 0},
   {"@c++-header",
   "%{E|M|MM:cc1plus -E %{fmodules-ts:-fdirectives-only -fmodule-header}"
   "  %(cpp_options) %2 %(cpp_debug_options)}"
diff --git a/gcc/testsuite/g++.dg/modules/dep-1_a.C 
b/gcc/testsuite/g++.dg/modules/dep-1_a.C
index 5ec5dd30f6d..3e92eeaef9f 100644
--- a/gcc/testsuite/g++.dg/modules/dep-1_a.C
+++ b/gcc/testsuite/g++.dg/modules/dep-1_a.C
@@ -4,6 +4,6 @@ export module m:part;
 // { dg-module-cmi m:part }
 
 // All The Backslashes!
-// { dg-final { scan-file dep-1_a.d {\nm:part\.c\+\+m: gcm.cache/m-part\.gcm} 
} }
+// { dg-final { scan-file dep-1_a.d {\nm:part\.c\+\+-module: 
gcm.cache/m-part\.gcm} } }
 // { dg-final { 

[gcc r15-897] c-family: add hints for strerror

2024-05-29 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:19c491d1848a8410559247183597096778967edf

commit r15-897-g19c491d1848a8410559247183597096778967edf
Author: Oskari Pirhonen 
Date:   Tue Feb 27 19:13:30 2024 -0600

c-family: add hints for strerror

Add proper hints for implicit declaration of strerror.

The results could be confusing depending on the other included headers.
These example messages are from compiling a trivial program to print the
string for an errno value. It only includes stdio.h (cstdio for C++).

Before:
$ /tmp/gcc-master/bin/gcc test.c -o test_c
test.c: In function ‘main’:
test.c:4:20: warning: implicit declaration of function ‘strerror’; did you 
mean ‘perror’? [-Wimplicit-function-declaration]
4 | printf("%s\n", strerror(0));
  |^~~~
  |perror

$ /tmp/gcc-master/bin/g++ test.cpp -o test_cpp
test.cpp: In function ‘int main()’:
test.cpp:4:20: error: ‘strerror’ was not declared in this scope; did you 
mean ‘stderr’?
4 | printf("%s\n", strerror(0));
  |^~~~
  |stderr

After:
$ /tmp/gcc-known-headers/bin/gcc test.c -o test_c
test.c: In function ‘main’:
test.c:4:20: warning: implicit declaration of function ‘strerror’ 
[-Wimplicit-function-declaration]
4 | printf("%s\n", strerror(0));
  |^~~~
test.c:2:1: note: ‘strerror’ is defined in header ‘’; this is 
probably fixable by adding ‘#include ’
1 | #include 
  +++ |+#include 
2 |

$ /tmp/gcc-known-headers/bin/g++ test.cpp -o test_cpp
test.cpp: In function ‘int main()’:
test.cpp:4:20: error: ‘strerror’ was not declared in this scope
4 | printf("%s\n", strerror(0));
  |^~~~
test.cpp:2:1: note: ‘strerror’ is defined in header ‘’; this is 
probably fixable by adding ‘#include ’
1 | #include 
  +++ |+#include 
2 |

gcc/c-family/ChangeLog:

* known-headers.cc (get_stdlib_header_for_name): Add strerror.

gcc/testsuite/ChangeLog:

* g++.dg/spellcheck-stdlib.C: Add check for strerror.
* gcc.dg/spellcheck-stdlib-2.c: New test.

Signed-off-by: Oskari Pirhonen 

Diff:
---
 gcc/c-family/known-headers.cc  | 1 +
 gcc/testsuite/g++.dg/spellcheck-stdlib.C   | 2 ++
 gcc/testsuite/gcc.dg/spellcheck-stdlib-2.c | 8 
 3 files changed, 11 insertions(+)

diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc
index dbc42eacde1..871fd714eb5 100644
--- a/gcc/c-family/known-headers.cc
+++ b/gcc/c-family/known-headers.cc
@@ -182,6 +182,7 @@ get_stdlib_header_for_name (const char *name, enum stdlib 
lib)
 {"strchr", {"", ""} },
 {"strcmp", {"", ""} },
 {"strcpy", {"", ""} },
+{"strerror", {"", ""} },
 {"strlen", {"", ""} },
 {"strncat", {"", ""} },
 {"strncmp", {"", ""} },
diff --git a/gcc/testsuite/g++.dg/spellcheck-stdlib.C 
b/gcc/testsuite/g++.dg/spellcheck-stdlib.C
index fd0f3a9b8c9..33718b8034e 100644
--- a/gcc/testsuite/g++.dg/spellcheck-stdlib.C
+++ b/gcc/testsuite/g++.dg/spellcheck-stdlib.C
@@ -104,6 +104,8 @@ void test_cstring (char *dest, char *src)
   // { dg-message "'#include '" "" { target *-*-* } .-1 }
   strcpy(dest, "test"); // { dg-error "was not declared" }
   // { dg-message "'#include '" "" { target *-*-* } .-1 }
+  strerror(0); // { dg-error "was not declared" }
+  // { dg-message "'#include '" "" { target *-*-* } .-1 }
   strlen("test"); // { dg-error "was not declared" }
   // { dg-message "'#include '" "" { target *-*-* } .-1 }
   strncat(dest, "test", 3); // { dg-error "was not declared" }
diff --git a/gcc/testsuite/gcc.dg/spellcheck-stdlib-2.c 
b/gcc/testsuite/gcc.dg/spellcheck-stdlib-2.c
new file mode 100644
index 000..4762e2ddbbd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/spellcheck-stdlib-2.c
@@ -0,0 +1,8 @@
+/* { dg-options "-Wimplicit-function-declaration" } */
+
+/* Missing .  */
+void test_string_h (void)
+{
+  strerror (0); /* { dg-error "implicit declaration of function 'strerror'" } 
*/
+  /* { dg-message "'strerror' is defined in header ''" "" { target 
*-*-* } .-1 } */
+}


Re: configure adds -std=gnu++11 to CXX variable

2024-05-28 Thread Jason Merrill via Gcc
On Tue, May 28, 2024 at 12:49 PM Paul Eggert  wrote:
>
> On 2024-05-28 08:02, Jakub Jelinek wrote:
> > even for C GCC updates the default
>
> True, but C seems to be different, in that using a later-than-default
> -std=whatever is more likely to help than hurt, because the C
> standardization folks are more careful about compatibility. That's what
> I've been experiencing with -std=gnu23, for example, even though C23 has
> lots of changes from C17.
>
>
> >> > Autoconf should go back to its 2.69 behavior and not mess with the C++
> >> > version as that's more likely to hurt than help.
> >
> > Yes.
>
> OK, thanks, I installed the attached.

Thanks, though I don't think all that code needs to go;
AC_PROG_CXX_STDCXX_EDITION_TRY still looks useful for a project that
relies on features from a particular standard.  We just don't want
AC_PROG_CXX to invoke it.

Jason



Re: configure adds -std=gnu++11 to CXX variable

2024-05-28 Thread Jason Merrill via Gcc
On Tue, May 28, 2024 at 10:36 AM Paul Eggert  wrote:
>
> On 2024-05-28 01:20, Jonathan Wakely wrote:
> > I am not aware of any distro ever changing the default -std setting for g++
> > or clang++. Are you attempting to solve a non-problem, but introducing new
> > ones?
>
> If it's a non-problem for C++, why does Autoconf upgrade to C++11 when
> the default is C++98? Autoconf has done so since Autoconf 2.70 (2020),
> with nobody complaining as far as I know.
>
> Was the Autoconf 2.70 change done so late that it had no practical
> effect, because no distro was defaulting to C++98 any more?

Yes, the GCC default changed from C++98 to C++14 in GCC 6 (2016).

> If so, it sounds like Autoconf should go back to its 2.69 behavior and not 
> mess
> with the C++ version as that's more likely to hurt than help.

Not by default, certainly.

> For background on that Autoconf 2.70 change, see this 2013 thread:
>
> https://lists.gnu.org/r/autoconf/2013-01/msg00016.html
>



[gcc r11-11448] c++: unroll pragma in templates [PR111529]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:a644775c363979bc25951532819ffa0f244b82f4

commit r11-11448-ga644775c363979bc25951532819ffa0f244b82f4
Author: Jason Merrill 
Date:   Fri Sep 22 12:10:11 2023 +0100

c++: unroll pragma in templates [PR111529]

We were failing to handle ANNOTATE_EXPR in tsubst_copy_and_build, leading to
problems with substitution of any wrapped expressions.

Let's also not tell users that lambda templates are available in C++14.

PR c++/111529

gcc/cp/ChangeLog:

* parser.c (cp_parser_lambda_declarator_opt): Don't suggest
-std=c++14 for lambda templates.
* pt.c (tsubst_expr): Move ANNOTATE_EXPR handling...
(tsubst_copy_and_build): ...here.

gcc/testsuite/ChangeLog:

* g++.dg/ext/unroll-4.C: New test.

(cherry picked from commit 9c62af101e11e1cce573c2b3d2e18b403412dbc8)

Diff:
---
 gcc/cp/parser.c |  2 +-
 gcc/cp/pt.c | 14 +++---
 gcc/testsuite/g++.dg/ext/unroll-4.C | 16 
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0619b834cf4..4f75f19ac50 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11310,7 +11310,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
   if (cxx_dialect < cxx14)
pedwarn (parser->lexer->next_token->location, 0,
 "lambda templates are only available with "
-"%<-std=c++14%> or %<-std=gnu++14%>");
+"%<-std=c++20%> or %<-std=gnu++20%>");
   else if (cxx_dialect < cxx20)
pedwarn (parser->lexer->next_token->location, OPT_Wpedantic,
 "lambda templates are only available with "
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 07515f63d29..8d39473de9e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19367,13 +19367,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl,
RECUR (TREE_OPERAND (t, 1)),
complain));
 
-case ANNOTATE_EXPR:
-  tmp = RECUR (TREE_OPERAND (t, 0));
-  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
- TREE_TYPE (tmp), tmp,
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2;
-
 case PREDICT_EXPR:
   RETURN (add_stmt (copy_node (t)));
 
@@ -21123,6 +21116,13 @@ tsubst_copy_and_build (tree t,
 with constant operands.  */
   RETURN (t);
 
+case ANNOTATE_EXPR:
+  op1 = RECUR (TREE_OPERAND (t, 0));
+  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
+ TREE_TYPE (op1), op1,
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2;
+
 case NON_LVALUE_EXPR:
 case VIEW_CONVERT_EXPR:
   if (location_wrapper_p (t))
diff --git a/gcc/testsuite/g++.dg/ext/unroll-4.C 
b/gcc/testsuite/g++.dg/ext/unroll-4.C
new file mode 100644
index 000..1d1643a6bd9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/unroll-4.C
@@ -0,0 +1,16 @@
+// PR c++/111529
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -w }
+
+template 
+void f() {
+  []() {
+#pragma GCC unroll 9
+for (int i = 1; i; --i) {
+}
+  };
+}
+
+int main() {
+  f<0>();
+}


[gcc r11-11449] c++: array of PMF [PR113598]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:38de942670ad39c60ba4feae893d11843e0aebe8

commit r11-11449-g38de942670ad39c60ba4feae893d11843e0aebe8
Author: Jason Merrill 
Date:   Thu Jan 25 12:02:07 2024 -0500

c++: array of PMF [PR113598]

Here AGGREGATE_TYPE_P includes pointers to member functions, which is not
what we want.  Instead we should use class||array, as elsewhere in the
function.

PR c++/113598

gcc/cp/ChangeLog:

* init.c (build_vec_init): Don't use {} for PMF.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-pmf2.C: New test.

(cherry picked from commit 136a828754ff65079a83482b49d54bd5bc64)

Diff:
---
 gcc/cp/init.c  |  4 +++-
 gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C | 12 
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 08b26ba9a17..b6e63ee8f28 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -4479,7 +4479,9 @@ build_vec_init (tree base, tree maxindex, tree init,
 But for non-classes, that's the same as value-initialization.  */
   if (empty_list)
{
- if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type))
+ if (cxx_dialect >= cxx11
+ && (CLASS_TYPE_P (type)
+ || TREE_CODE (type) == ARRAY_TYPE))
{
  init = build_constructor (init_list_type_node, NULL);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C
new file mode 100644
index 000..59c3698a9f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C
@@ -0,0 +1,12 @@
+// PR c++/113598
+// { dg-additional-options -w }
+
+struct Cpu
+{
+  int op_nop();
+};
+typedef int(Cpu::*OpCode)();
+void f()
+{
+  new OpCode[256]{::op_nop};
+}


[gcc r11-11447] c++: __is_constructible ref binding [PR100667]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:16046a075cb54c90609825e30b2ab45a03395ca1

commit r11-11447-g16046a075cb54c90609825e30b2ab45a03395ca1
Author: Jason Merrill 
Date:   Wed Mar 27 16:14:01 2024 -0400

c++: __is_constructible ref binding [PR100667]

The requirement that a type argument be complete is excessive in the case of
direct reference binding to the same type, which does not rely on any
properties of the type.  This is LWG 2939.

PR c++/100667

gcc/cp/ChangeLog:

* semantics.c (same_type_ref_bind_p): New.
(finish_trait_expr): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_constructible8.C: New test.

(cherry picked from commit 8bb3ef3f6e335e8794590fb712a2661d11d21973)

Diff:
---
 gcc/cp/semantics.c   | 41 ++--
 gcc/testsuite/g++.dg/ext/is_constructible8.C | 16 +++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 385e108a1c8..57e71ec3a3c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -10570,6 +10570,38 @@ check_trait_type (tree type)
   return !!complete_type_or_else (strip_array_types (type), NULL_TREE);
 }
 
+/* True iff the conversion (if any) would be a direct reference
+   binding, not requiring complete types.  This is LWG2939.  */
+
+static bool
+same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2)
+{
+  tree from, to;
+  switch (kind)
+{
+  /* These put the target type first.  */
+case CPTK_IS_CONSTRUCTIBLE:
+case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+  to = type1;
+  from = type2;
+  break;
+
+default:
+  gcc_unreachable ();
+}
+
+  if (TREE_CODE (to) != REFERENCE_TYPE || !from)
+return false;
+  if (TREE_CODE (from) == TREE_VEC && TREE_VEC_LENGTH (from) == 1)
+from = TREE_VEC_ELT (from, 0);
+  else if (TREE_CODE (from) == TREE_LIST && !TREE_CHAIN (from))
+from = TREE_VALUE (from);
+  return (TYPE_P (from)
+ && (same_type_ignoring_top_level_qualifiers_p
+ (non_reference (to), non_reference (from;
+}
+
 /* Process a trait expression.  */
 
 tree
@@ -10619,10 +10651,15 @@ finish_trait_expr (location_t loc, cp_trait_kind 
kind, tree type1, tree type2)
 case CPTK_IS_CONSTRUCTIBLE:
   break;
 
-case CPTK_IS_TRIVIALLY_ASSIGNABLE:
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
-case CPTK_IS_NOTHROW_ASSIGNABLE:
 case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+  /* Don't check completeness for direct reference binding.  */;
+  if (same_type_ref_bind_p (kind, type1, type2))
+   break;
+  gcc_fallthrough ();
+
+case CPTK_IS_NOTHROW_ASSIGNABLE:
+case CPTK_IS_TRIVIALLY_ASSIGNABLE:
   if (!check_trait_type (type1)
  || !check_trait_type (type2))
return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible8.C 
b/gcc/testsuite/g++.dg/ext/is_constructible8.C
new file mode 100644
index 000..4b8204c0768
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible8.C
@@ -0,0 +1,16 @@
+// PR c++/100667
+// { dg-do compile { target c++11 } }
+
+struct T;
+
+#define SA(X) static_assert ((X), #X);
+
+SA (__is_constructible(T&&, T));
+SA (__is_constructible(const T&, T));
+SA (!__is_constructible(T&, T));
+SA (__is_nothrow_constructible(T&&, T));
+SA (__is_nothrow_constructible(const T&, T));
+SA (!__is_nothrow_constructible(T&, T));
+SA (__is_trivially_constructible(T&&, T));
+SA (__is_trivially_constructible(const T&, T));
+SA (!__is_trivially_constructible(T&, T));


[gcc r12-10470] c++: __is_constructible ref binding [PR100667]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:ba57a52dbf6a64ba66f72c20064c5c0e8cc9dbbb

commit r12-10470-gba57a52dbf6a64ba66f72c20064c5c0e8cc9dbbb
Author: Jason Merrill 
Date:   Wed Mar 27 16:14:01 2024 -0400

c++: __is_constructible ref binding [PR100667]

The requirement that a type argument be complete is excessive in the case of
direct reference binding to the same type, which does not rely on any
properties of the type.  This is LWG 2939.

PR c++/100667

gcc/cp/ChangeLog:

* semantics.cc (same_type_ref_bind_p): New.
(finish_trait_expr): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_constructible8.C: New test.

(cherry picked from commit 8bb3ef3f6e335e8794590fb712a2661d11d21973)

Diff:
---
 gcc/cp/semantics.cc  | 41 ++--
 gcc/testsuite/g++.dg/ext/is_constructible8.C | 16 +++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index e5db5189f33..0672d6c5b68 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12034,6 +12034,38 @@ check_trait_type (tree type)
   return !!complete_type_or_else (strip_array_types (type), NULL_TREE);
 }
 
+/* True iff the conversion (if any) would be a direct reference
+   binding, not requiring complete types.  This is LWG2939.  */
+
+static bool
+same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2)
+{
+  tree from, to;
+  switch (kind)
+{
+  /* These put the target type first.  */
+case CPTK_IS_CONSTRUCTIBLE:
+case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+  to = type1;
+  from = type2;
+  break;
+
+default:
+  gcc_unreachable ();
+}
+
+  if (TREE_CODE (to) != REFERENCE_TYPE || !from)
+return false;
+  if (TREE_CODE (from) == TREE_VEC && TREE_VEC_LENGTH (from) == 1)
+from = TREE_VEC_ELT (from, 0);
+  else if (TREE_CODE (from) == TREE_LIST && !TREE_CHAIN (from))
+from = TREE_VALUE (from);
+  return (TYPE_P (from)
+ && (same_type_ignoring_top_level_qualifiers_p
+ (non_reference (to), non_reference (from;
+}
+
 /* Process a trait expression.  */
 
 tree
@@ -12083,10 +12115,15 @@ finish_trait_expr (location_t loc, cp_trait_kind 
kind, tree type1, tree type2)
 case CPTK_IS_CONSTRUCTIBLE:
   break;
 
-case CPTK_IS_TRIVIALLY_ASSIGNABLE:
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
-case CPTK_IS_NOTHROW_ASSIGNABLE:
 case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+  /* Don't check completeness for direct reference binding.  */;
+  if (same_type_ref_bind_p (kind, type1, type2))
+   break;
+  gcc_fallthrough ();
+
+case CPTK_IS_NOTHROW_ASSIGNABLE:
+case CPTK_IS_TRIVIALLY_ASSIGNABLE:
   if (!check_trait_type (type1)
  || !check_trait_type (type2))
return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible8.C 
b/gcc/testsuite/g++.dg/ext/is_constructible8.C
new file mode 100644
index 000..4b8204c0768
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible8.C
@@ -0,0 +1,16 @@
+// PR c++/100667
+// { dg-do compile { target c++11 } }
+
+struct T;
+
+#define SA(X) static_assert ((X), #X);
+
+SA (__is_constructible(T&&, T));
+SA (__is_constructible(const T&, T));
+SA (!__is_constructible(T&, T));
+SA (__is_nothrow_constructible(T&&, T));
+SA (__is_nothrow_constructible(const T&, T));
+SA (!__is_nothrow_constructible(T&, T));
+SA (__is_trivially_constructible(T&&, T));
+SA (__is_trivially_constructible(const T&, T));
+SA (!__is_trivially_constructible(T&, T));


[gcc r12-10469] c++: fix PR111529 backport

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:6a5dcdb7ae6bbd9c5a273ceadc7f7c7cd8a6c8ec

commit r12-10469-g6a5dcdb7ae6bbd9c5a273ceadc7f7c7cd8a6c8ec
Author: Jason Merrill 
Date:   Fri May 24 11:19:29 2024 -0400

c++: fix PR111529 backport

r12-10468-g19827831516023 added the ANNOTATE_EXPR in the wrong place,
leading to ICEs on several testcases.

gcc/cp/ChangeLog:

* pt.cc (tsubst_copy_and_build): Move ANNOTATE_EXPR out of
fallthrough path.

Diff:
---
 gcc/cp/pt.cc | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1dcdaad571a..d6cdab5ad80 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21535,6 +21535,13 @@ tsubst_copy_and_build (tree t,
 with constant operands.  */
   RETURN (t);
 
+case ANNOTATE_EXPR:
+  op1 = RECUR (TREE_OPERAND (t, 0));
+  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
+ TREE_TYPE (op1), op1,
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2;
+
 case NON_LVALUE_EXPR:
 case VIEW_CONVERT_EXPR:
   if (location_wrapper_p (t))
@@ -21544,13 +21551,6 @@ tsubst_copy_and_build (tree t,
  EXPR_LOCATION (t)));
   /* fallthrough.  */
 
-case ANNOTATE_EXPR:
-  op1 = RECUR (TREE_OPERAND (t, 0));
-  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
- TREE_TYPE (op1), op1,
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2;
-
 default:
   /* Handle Objective-C++ constructs, if appropriate.  */
   {


[gcc r14-10242] c++: deleting array temporary [PR115187]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:9031c027827bff44e1b55c366fc7034c43501b4c

commit r14-10242-g9031c027827bff44e1b55c366fc7034c43501b4c
Author: Jason Merrill 
Date:   Wed May 22 18:41:27 2024 -0400

c++: deleting array temporary [PR115187]

Decaying the array temporary to a pointer and then deleting that crashes in
verify_gimple_stmt, because the TARGET_EXPR is first evaluated inside the
TRY_FINALLY_EXPR, but the cleanup point is outside.  Fixed by using
get_target_expr instead of save_expr.

I also adjust the stabilize_expr comment to prevent me from again thinking
it's a suitable replacement.

PR c++/115187

gcc/cp/ChangeLog:

* init.cc (build_delete): Use get_target_expr instead of save_expr.
* tree.cc (stabilize_expr): Update comment.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/array-prvalue3.C: New test.

Diff:
---
 gcc/cp/init.cc  | 9 -
 gcc/cp/tree.cc  | 6 +-
 gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C | 8 
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index e758a8c8568..c5ba82c8664 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -5222,9 +5222,13 @@ build_delete (location_t loc, tree otype, tree addr,
   addr = convert_force (build_pointer_type (type), addr, 0, complain);
 }
 
+  tree addr_expr = NULL_TREE;
   if (deleting)
 /* We will use ADDR multiple times so we must save it.  */
-addr = save_expr (addr);
+{
+  addr_expr = get_target_expr (addr);
+  addr = TARGET_EXPR_SLOT (addr_expr);
+}
 
   bool virtual_p = false;
   if (type_build_dtor_call (type))
@@ -5343,6 +5347,9 @@ build_delete (location_t loc, tree otype, tree addr,
   if (!integer_nonzerop (ifexp))
 expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
 
+  if (addr_expr)
+expr = cp_build_compound_expr (addr_expr, expr, tf_none);
+
   protected_set_expr_location (expr, loc);
   return expr;
 }
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 9d37d255d8d..41fdf67f757 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5952,7 +5952,11 @@ decl_storage_duration (tree decl)
*INITP) an expression that will perform the pre-evaluation.  The
value returned by this function is a side-effect free expression
equivalent to the pre-evaluated expression.  Callers must ensure
-   that *INITP is evaluated before EXP.  */
+   that *INITP is evaluated before EXP.
+
+   Note that if EXPR is a glvalue, the return value is a glvalue denoting the
+   same address; this function does not guard against modification of the
+   stored value like save_expr or get_target_expr do.  */
 
 tree
 stabilize_expr (tree exp, tree* initp)
diff --git a/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C 
b/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C
new file mode 100644
index 000..f264e46084a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C
@@ -0,0 +1,8 @@
+// PR c++/115187
+// { dg-do compile { target c++17 } }
+
+void f() {
+  using T = int[2];
+  delete T{};  // { dg-warning "deleting array" }
+  // { dg-warning "unallocated object" "" { target *-*-* } .-1 }
+}


[gcc r11-11446] c++: binding reference to comma expr [PR114561]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:b35afe75674ff9f79cf9685d099bc80f10442216

commit r11-11446-gb35afe75674ff9f79cf9685d099bc80f10442216
Author: Jason Merrill 
Date:   Tue Apr 2 10:52:28 2024 -0400

c++: binding reference to comma expr [PR114561]

We represent a reference binding where the referent type is more qualified
by a ck_ref_bind around a ck_qual.  We performed the ck_qual and then tried
to undo it with STRIP_NOPS, but that doesn't work if the conversion is
buried in COMPOUND_EXPR.  So instead let's avoid performing that fake
conversion in the first place.

PR c++/114561
PR c++/114562

gcc/cp/ChangeLog:

* call.c (convert_like_internal): Avoid adding qualification
conversion in direct reference binding.

gcc/testsuite/ChangeLog:

* g++.dg/conversion/ref10.C: New test.
* g++.dg/conversion/ref11.C: New test.

(cherry picked from commit 5d7e9a35024f065b25f61747859c7cb7a770c92b)

Diff:
---
 gcc/cp/call.c   | 23 +--
 gcc/testsuite/g++.dg/conversion/ref10.C |  5 +
 gcc/testsuite/g++.dg/conversion/ref11.C | 33 +
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7c3ce1693e1..fbe29f38384 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7816,7 +7816,15 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   break;
 };
 
-  expr = convert_like (next_conversion (convs), expr, fn, argnum,
+  conversion *nc = next_conversion (convs);
+  if (convs->kind == ck_ref_bind && nc->kind == ck_qual
+  && !convs->need_temporary_p)
+/* direct_reference_binding might have inserted a ck_qual under
+   this ck_ref_bind for the benefit of conversion sequence ranking.
+   Don't actually perform that conversion.  */
+nc = next_conversion (nc);
+
+  expr = convert_like (nc, expr, fn, argnum,
   convs->kind == ck_ref_bind
   ? issue_conversion_warnings : false,
   c_cast_p, complain & ~tf_no_cleanup);
@@ -7897,19 +7905,6 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   {
tree ref_type = totype;
 
-   /* direct_reference_binding might have inserted a ck_qual under
-  this ck_ref_bind for the benefit of conversion sequence ranking.
-  Ignore the conversion; we'll create our own below.  */
-   if (next_conversion (convs)->kind == ck_qual
-   && !convs->need_temporary_p)
- {
-   gcc_assert (same_type_p (TREE_TYPE (expr),
-next_conversion (convs)->type));
-   /* Strip the cast created by the ck_qual; cp_build_addr_expr
-  below expects an lvalue.  */
-   STRIP_NOPS (expr);
- }
-
if (convs->bad_p && !next_conversion (convs)->bad_p)
  {
tree extype = TREE_TYPE (expr);
diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C 
b/gcc/testsuite/g++.dg/conversion/ref10.C
new file mode 100644
index 000..1913f733a6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref10.C
@@ -0,0 +1,5 @@
+// PR c++/114561
+
+void create(void* u) {
+  const void* const& r = ( (void)0, u );
+}
diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C 
b/gcc/testsuite/g++.dg/conversion/ref11.C
new file mode 100644
index 000..bb9b835034c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref11.C
@@ -0,0 +1,33 @@
+// PR c++/114562
+// { dg-do compile { target c++11 } }
+
+template 
+struct Optional {
+  Optional(T&&);
+};
+
+struct MyClass {
+  MyClass(Optional);
+};
+
+// const void* NONE = nullptr; // Correct Error
+void* NONE = nullptr; // Crash
+
+void beforeParam();
+
+template
+struct Create {
+  template  static T create(U &&) noexcept;
+};
+
+
+template 
+template
+T Create::create(U && u) noexcept {
+  return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue 
reference" }
+  // return T( (u) ); // Correct Error
+}
+
+void test_func() {
+  Create::create(NONE);
+}


[gcc r12-10468] c++: unroll pragma in templates [PR111529]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:19827831516023f2dff449af0b228b2d60190a28

commit r12-10468-g19827831516023f2dff449af0b228b2d60190a28
Author: Jason Merrill 
Date:   Fri Sep 22 12:10:11 2023 +0100

c++: unroll pragma in templates [PR111529]

We were failing to handle ANNOTATE_EXPR in tsubst_copy_and_build, leading to
problems with substitution of any wrapped expressions.

Let's also not tell users that lambda templates are available in C++14.

PR c++/111529

gcc/cp/ChangeLog:

* parser.cc (cp_parser_lambda_declarator_opt): Don't suggest
-std=c++14 for lambda templates.
* pt.cc (tsubst_expr): Move ANNOTATE_EXPR handling...
(tsubst_copy_and_build): ...here.

gcc/testsuite/ChangeLog:

* g++.dg/ext/unroll-4.C: New test.

(cherry picked from commit 9c62af101e11e1cce573c2b3d2e18b403412dbc8)

Diff:
---
 gcc/cp/parser.cc|  7 ++-
 gcc/cp/pt.cc| 14 +++---
 gcc/testsuite/g++.dg/ext/unroll-4.C | 16 
 3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 194f9b07d83..9c1bd32cff1 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -11513,11 +11513,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
  an opening angle if present.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
 {
-  if (cxx_dialect < cxx14)
-   pedwarn (parser->lexer->next_token->location, OPT_Wc__14_extensions,
-"lambda templates are only available with "
-"%<-std=c++14%> or %<-std=gnu++14%>");
-  else if (pedantic && cxx_dialect < cxx20)
+  if (cxx_dialect < cxx20
+ && (pedantic || cxx_dialect < cxx14))
pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions,
 "lambda templates are only available with "
 "%<-std=c++20%> or %<-std=gnu++20%>");
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ed4dbe06179..1dcdaad571a 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19616,13 +19616,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl,
templated_operator_saved_lookups (t),
complain));
 
-case ANNOTATE_EXPR:
-  tmp = RECUR (TREE_OPERAND (t, 0));
-  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
- TREE_TYPE (tmp), tmp,
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2;
-
 case PREDICT_EXPR:
   RETURN (add_stmt (copy_node (t)));
 
@@ -21551,6 +21544,13 @@ tsubst_copy_and_build (tree t,
  EXPR_LOCATION (t)));
   /* fallthrough.  */
 
+case ANNOTATE_EXPR:
+  op1 = RECUR (TREE_OPERAND (t, 0));
+  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
+ TREE_TYPE (op1), op1,
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2;
+
 default:
   /* Handle Objective-C++ constructs, if appropriate.  */
   {
diff --git a/gcc/testsuite/g++.dg/ext/unroll-4.C 
b/gcc/testsuite/g++.dg/ext/unroll-4.C
new file mode 100644
index 000..d488aca974e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/unroll-4.C
@@ -0,0 +1,16 @@
+// PR c++/111529
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -Wno-c++20-extensions }
+
+template 
+void f() {
+  []() {
+#pragma GCC unroll 9
+for (int i = 1; i; --i) {
+}
+  };
+}
+
+int main() {
+  f<0>();
+}


[gcc r12-10467] c++: array of PMF [PR113598]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:419b5e17eace9b6b985b9853db0dc1a5478375b6

commit r12-10467-g419b5e17eace9b6b985b9853db0dc1a5478375b6
Author: Jason Merrill 
Date:   Thu Jan 25 12:02:07 2024 -0500

c++: array of PMF [PR113598]

Here AGGREGATE_TYPE_P includes pointers to member functions, which is not
what we want.  Instead we should use class||array, as elsewhere in the
function.

PR c++/113598

gcc/cp/ChangeLog:

* init.cc (build_vec_init): Don't use {} for PMF.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-pmf2.C: New test.

(cherry picked from commit 136a828754ff65079a83482b49d54bd5bc64)

Diff:
---
 gcc/cp/init.cc |  4 +++-
 gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C | 12 
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 36a5d7c4849..a0a28f2a002 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4760,7 +4760,9 @@ build_vec_init (tree base, tree maxindex, tree init,
 But for non-classes, that's the same as value-initialization.  */
   if (empty_list)
{
- if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type))
+ if (cxx_dialect >= cxx11
+ && (CLASS_TYPE_P (type)
+ || TREE_CODE (type) == ARRAY_TYPE))
{
  init = build_constructor (init_list_type_node, NULL);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C
new file mode 100644
index 000..0fac8333c75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C
@@ -0,0 +1,12 @@
+// PR c++/113598
+// { dg-additional-options -Wno-c++11-extensions }
+
+struct Cpu
+{
+  int op_nop();
+};
+typedef int(Cpu::*OpCode)();
+void f()
+{
+  new OpCode[256]{::op_nop};
+}


[gcc r12-10466] c++: binding reference to comma expr [PR114561]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:7076c565e22281e193aeafafbf40676426a64b75

commit r12-10466-g7076c565e22281e193aeafafbf40676426a64b75
Author: Jason Merrill 
Date:   Tue Apr 2 10:52:28 2024 -0400

c++: binding reference to comma expr [PR114561]

We represent a reference binding where the referent type is more qualified
by a ck_ref_bind around a ck_qual.  We performed the ck_qual and then tried
to undo it with STRIP_NOPS, but that doesn't work if the conversion is
buried in COMPOUND_EXPR.  So instead let's avoid performing that fake
conversion in the first place.

PR c++/114561
PR c++/114562

gcc/cp/ChangeLog:

* call.cc (convert_like_internal): Avoid adding qualification
conversion in direct reference binding.

gcc/testsuite/ChangeLog:

* g++.dg/conversion/ref10.C: New test.
* g++.dg/conversion/ref11.C: New test.

(cherry picked from commit 5d7e9a35024f065b25f61747859c7cb7a770c92b)

Diff:
---
 gcc/cp/call.cc  | 23 +--
 gcc/testsuite/g++.dg/conversion/ref10.C |  5 +
 gcc/testsuite/g++.dg/conversion/ref11.C | 33 +
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 4f4cee5b95c..6fd6da4b2dd 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8135,7 +8135,15 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   break;
 };
 
-  expr = convert_like (next_conversion (convs), expr, fn, argnum,
+  conversion *nc = next_conversion (convs);
+  if (convs->kind == ck_ref_bind && nc->kind == ck_qual
+  && !convs->need_temporary_p)
+/* direct_reference_binding might have inserted a ck_qual under
+   this ck_ref_bind for the benefit of conversion sequence ranking.
+   Don't actually perform that conversion.  */
+nc = next_conversion (nc);
+
+  expr = convert_like (nc, expr, fn, argnum,
   convs->kind == ck_ref_bind
   ? issue_conversion_warnings : false,
   c_cast_p, complain & ~tf_no_cleanup);
@@ -8216,19 +8224,6 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   {
tree ref_type = totype;
 
-   /* direct_reference_binding might have inserted a ck_qual under
-  this ck_ref_bind for the benefit of conversion sequence ranking.
-  Ignore the conversion; we'll create our own below.  */
-   if (next_conversion (convs)->kind == ck_qual
-   && !convs->need_temporary_p)
- {
-   gcc_assert (same_type_p (TREE_TYPE (expr),
-next_conversion (convs)->type));
-   /* Strip the cast created by the ck_qual; cp_build_addr_expr
-  below expects an lvalue.  */
-   STRIP_NOPS (expr);
- }
-
if (convs->bad_p && !next_conversion (convs)->bad_p)
  {
tree extype = TREE_TYPE (expr);
diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C 
b/gcc/testsuite/g++.dg/conversion/ref10.C
new file mode 100644
index 000..1913f733a6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref10.C
@@ -0,0 +1,5 @@
+// PR c++/114561
+
+void create(void* u) {
+  const void* const& r = ( (void)0, u );
+}
diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C 
b/gcc/testsuite/g++.dg/conversion/ref11.C
new file mode 100644
index 000..bb9b835034c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref11.C
@@ -0,0 +1,33 @@
+// PR c++/114562
+// { dg-do compile { target c++11 } }
+
+template 
+struct Optional {
+  Optional(T&&);
+};
+
+struct MyClass {
+  MyClass(Optional);
+};
+
+// const void* NONE = nullptr; // Correct Error
+void* NONE = nullptr; // Crash
+
+void beforeParam();
+
+template
+struct Create {
+  template  static T create(U &&) noexcept;
+};
+
+
+template 
+template
+T Create::create(U && u) noexcept {
+  return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue 
reference" }
+  // return T( (u) ); // Correct Error
+}
+
+void test_func() {
+  Create::create(NONE);
+}


[gcc r13-8799] c++: unroll pragma in templates [PR111529]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:53cdaa755de57e57ba9e787f232adc3cfde88209

commit r13-8799-g53cdaa755de57e57ba9e787f232adc3cfde88209
Author: Jason Merrill 
Date:   Fri Sep 22 12:10:11 2023 +0100

c++: unroll pragma in templates [PR111529]

We were failing to handle ANNOTATE_EXPR in tsubst_copy_and_build, leading to
problems with substitution of any wrapped expressions.

Let's also not tell users that lambda templates are available in C++14.

PR c++/111529

gcc/cp/ChangeLog:

* parser.cc (cp_parser_lambda_declarator_opt): Don't suggest
-std=c++14 for lambda templates.
* pt.cc (tsubst_expr): Move ANNOTATE_EXPR handling...
(tsubst_copy_and_build): ...here.

gcc/testsuite/ChangeLog:

* g++.dg/ext/unroll-4.C: New test.

(cherry picked from commit 9c62af101e11e1cce573c2b3d2e18b403412dbc8)

Diff:
---
 gcc/cp/parser.cc|  7 ++-
 gcc/cp/pt.cc| 14 +++---
 gcc/testsuite/g++.dg/ext/unroll-4.C | 16 
 3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4e67da6ff3a..a9241bd7e7a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -11558,11 +11558,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
  an opening angle if present.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
 {
-  if (cxx_dialect < cxx14)
-   pedwarn (parser->lexer->next_token->location, OPT_Wc__14_extensions,
-"lambda templates are only available with "
-"%<-std=c++14%> or %<-std=gnu++14%>");
-  else if (pedantic && cxx_dialect < cxx20)
+  if (cxx_dialect < cxx20
+ && (pedantic || cxx_dialect < cxx14))
pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions,
 "lambda templates are only available with "
 "%<-std=c++20%> or %<-std=gnu++20%>");
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3af705c647a..5a6bf80c3d4 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19926,13 +19926,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
templated_operator_saved_lookups (t),
complain));
 
-case ANNOTATE_EXPR:
-  tmp = RECUR (TREE_OPERAND (t, 0));
-  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
- TREE_TYPE (tmp), tmp,
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2;
-
 case PREDICT_EXPR:
   RETURN (add_stmt (copy_node (t)));
 
@@ -21862,6 +21855,13 @@ tsubst_copy_and_build (tree t,
RETURN (op);
   }
 
+case ANNOTATE_EXPR:
+  op1 = RECUR (TREE_OPERAND (t, 0));
+  RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
+ TREE_TYPE (op1), op1,
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2;
+
 default:
   /* Handle Objective-C++ constructs, if appropriate.  */
   {
diff --git a/gcc/testsuite/g++.dg/ext/unroll-4.C 
b/gcc/testsuite/g++.dg/ext/unroll-4.C
new file mode 100644
index 000..d488aca974e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/unroll-4.C
@@ -0,0 +1,16 @@
+// PR c++/111529
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -Wno-c++20-extensions }
+
+template 
+void f() {
+  []() {
+#pragma GCC unroll 9
+for (int i = 1; i; --i) {
+}
+  };
+}
+
+int main() {
+  f<0>();
+}


[gcc r13-8798] c++: array of PMF [PR113598]

2024-05-24 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:5f1457841abc2fd8657a52d1371c983ac010f1cc

commit r13-8798-g5f1457841abc2fd8657a52d1371c983ac010f1cc
Author: Jason Merrill 
Date:   Thu Jan 25 12:02:07 2024 -0500

c++: array of PMF [PR113598]

Here AGGREGATE_TYPE_P includes pointers to member functions, which is not
what we want.  Instead we should use class||array, as elsewhere in the
function.

PR c++/113598

gcc/cp/ChangeLog:

* init.cc (build_vec_init): Don't use {} for PMF.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-pmf2.C: New test.

(cherry picked from commit 136a828754ff65079a83482b49d54bd5bc64)

Diff:
---
 gcc/cp/init.cc |  4 +++-
 gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C | 12 
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 78e992af171..4977ce34398 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4859,7 +4859,9 @@ build_vec_init (tree base, tree maxindex, tree init,
 But for non-classes, that's the same as value-initialization.  */
   if (empty_list)
{
- if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type))
+ if (cxx_dialect >= cxx11
+ && (CLASS_TYPE_P (type)
+ || TREE_CODE (type) == ARRAY_TYPE))
{
  init = build_constructor (init_list_type_node, NULL);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C
new file mode 100644
index 000..0fac8333c75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C
@@ -0,0 +1,12 @@
+// PR c++/113598
+// { dg-additional-options -Wno-c++11-extensions }
+
+struct Cpu
+{
+  int op_nop();
+};
+typedef int(Cpu::*OpCode)();
+void f()
+{
+  new OpCode[256]{::op_nop};
+}


[gcc r15-796] c++: deleting array temporary [PR115187]

2024-05-23 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:ed63cd2aa5b114565fe5499c3a6bf8da5e8e48ba

commit r15-796-ged63cd2aa5b114565fe5499c3a6bf8da5e8e48ba
Author: Jason Merrill 
Date:   Wed May 22 18:41:27 2024 -0400

c++: deleting array temporary [PR115187]

Decaying the array temporary to a pointer and then deleting that crashes in
verify_gimple_stmt, because the TARGET_EXPR is first evaluated inside the
TRY_FINALLY_EXPR, but the cleanup point is outside.  Fixed by using
get_target_expr instead of save_expr.

I also adjust the stabilize_expr comment to prevent me from again thinking
it's a suitable replacement.

PR c++/115187

gcc/cp/ChangeLog:

* init.cc (build_delete): Use get_target_expr instead of save_expr.
* tree.cc (stabilize_expr): Update comment.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1z/array-prvalue3.C: New test.

Diff:
---
 gcc/cp/init.cc  | 9 -
 gcc/cp/tree.cc  | 6 +-
 gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C | 8 
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 906e401974c..52396d87a8c 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -5228,9 +5228,13 @@ build_delete (location_t loc, tree otype, tree addr,
   addr = convert_force (build_pointer_type (type), addr, 0, complain);
 }
 
+  tree addr_expr = NULL_TREE;
   if (deleting)
 /* We will use ADDR multiple times so we must save it.  */
-addr = save_expr (addr);
+{
+  addr_expr = get_target_expr (addr);
+  addr = TARGET_EXPR_SLOT (addr_expr);
+}
 
   bool virtual_p = false;
   if (type_build_dtor_call (type))
@@ -5349,6 +5353,9 @@ build_delete (location_t loc, tree otype, tree addr,
   if (!integer_nonzerop (ifexp))
 expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
 
+  if (addr_expr)
+expr = cp_build_compound_expr (addr_expr, expr, tf_none);
+
   protected_set_expr_location (expr, loc);
   return expr;
 }
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 4d87661b4ad..0485a618c6c 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5924,7 +5924,11 @@ decl_storage_duration (tree decl)
*INITP) an expression that will perform the pre-evaluation.  The
value returned by this function is a side-effect free expression
equivalent to the pre-evaluated expression.  Callers must ensure
-   that *INITP is evaluated before EXP.  */
+   that *INITP is evaluated before EXP.
+
+   Note that if EXPR is a glvalue, the return value is a glvalue denoting the
+   same address; this function does not guard against modification of the
+   stored value like save_expr or get_target_expr do.  */
 
 tree
 stabilize_expr (tree exp, tree* initp)
diff --git a/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C 
b/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C
new file mode 100644
index 000..f264e46084a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C
@@ -0,0 +1,8 @@
+// PR c++/115187
+// { dg-do compile { target c++17 } }
+
+void f() {
+  using T = int[2];
+  delete T{};  // { dg-warning "deleting array" }
+  // { dg-warning "unallocated object" "" { target *-*-* } .-1 }
+}


[gcc r15-495] c++: ICE in build_deduction_guide for invalid template [PR105760]

2024-05-14 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:0003e469d4664397b65080a66ad7d6557bd7ffce

commit r15-495-g0003e469d4664397b65080a66ad7d6557bd7ffce
Author: Simon Martin 
Date:   Mon May 6 15:20:10 2024 +0200

c++: ICE in build_deduction_guide for invalid template [PR105760]

We currently ICE upon the following invalid snippet because we fail to
properly handle tsubst_arg_types returning error_mark_node in
build_deduction_guide.

== cut ==
template
struct A { A(Ts...); };
A a;
== cut ==

This patch fixes this, and has been successfully tested on 
x86_64-pc-linux-gnu.

PR c++/105760

gcc/cp/ChangeLog:

* pt.cc (build_deduction_guide): Check for error_mark_node
result from tsubst_arg_types.

gcc/testsuite/ChangeLog:

* g++.dg/parse/error66.C: New test.

Diff:
---
 gcc/cp/pt.cc | 2 ++
 gcc/testsuite/g++.dg/parse/error66.C | 6 ++
 2 files changed, 8 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 4b71e199d27f..32640f8e946d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30031,6 +30031,8 @@ build_deduction_guide (tree type, tree ctor, tree 
outer_args, tsubst_flags_t com
 references to members of an unknown specialization.  */
  cp_evaluated ev;
  fparms = tsubst_arg_types (fparms, targs, NULL_TREE, complain, ctor);
+if (fparms == error_mark_node)
+  ok = false;
  fargs = tsubst (fargs, targs, complain, ctor);
  if (ci)
{
diff --git a/gcc/testsuite/g++.dg/parse/error66.C 
b/gcc/testsuite/g++.dg/parse/error66.C
new file mode 100644
index ..82f4b8b8a530
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error66.C
@@ -0,0 +1,6 @@
+// PR c++/105760
+// { dg-do compile { target c++17 } }
+
+template // { dg-error "must be at the end of the template 
parameter list" }
+struct A { A(Ts...); };
+A a;


[gcc r15-494] c++ comment adjustments for 114935

2024-05-14 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:1288283051435c6b23473448aa21fa9ca53fabac

commit r15-494-g1288283051435c6b23473448aa21fa9ca53fabac
Author: Jason Merrill 
Date:   Tue May 14 17:37:08 2024 -0400

c++ comment adjustments for 114935

gcc/cp/ChangeLog:

* decl.cc (wrap_cleanups_r): Clarify comment.
* init.cc (build_vec_init): Update comment.

Diff:
---
 gcc/cp/decl.cc | 10 +-
 gcc/cp/init.cc | 10 --
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 3fc8835154d9..a139b293e00c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8028,11 +8028,11 @@ wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void 
*data)
Unfortunately, there's no way to express this properly in terms of
nesting, as the regions for the temporaries overlap the region for the
variable itself; if there are two temporaries, the variable needs to be
-   the first thing destroyed if either of them throws.  However, we only
-   want to run the variable's cleanup if it actually got constructed.  So
-   we need to guard the temporary cleanups with the variable's cleanup if
-   they are run on the normal path, but not if they are run on the
-   exceptional path.  We implement this by telling
+   the first thing destroyed if either of the temporary destructors throws.
+   However, we only want to run the variable's cleanup if it actually got
+   constructed.  So we need to guard the temporary cleanups with the
+   variable's cleanup if they are run on the normal path, but not if they
+   are run on the exceptional path.  We implement this by telling
honor_protect_cleanup_actions to strip the variable cleanup from the
exceptional path.
 
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 7bb98f445c37..906e401974cb 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4685,8 +4685,14 @@ build_vec_init (tree base, tree maxindex, tree init,
 for any temporaries in the initialization are naturally within our
 cleanup region, so we don't want wrap_temporary_cleanups to do
 anything for arrays.  But if the array is a subobject, we need to
-tell split_nonconstant_init how to turn off this cleanup in favor of
-the cleanup for the complete object.  */
+tell split_nonconstant_init or cp_genericize_target_expr how to turn
+off this cleanup in favor of the cleanup for the complete object.
+
+??? For an array temporary such as an initializer_list backing array,
+it would avoid redundancy to leave this cleanup active, clear
+CLEANUP_EH_ONLY, and not build another cleanup for the temporary
+itself.  But that breaks when gimplify_target_expr adds a clobber
+cleanup that runs before the build_vec_init cleanup.  */
   if (cleanup_flags)
vec_safe_push (*cleanup_flags, build_tree_list (iterator, maxindex));
 }


[gcc r14-10165] c++: initializer_list and EH [PR114935]

2024-05-03 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:3b4d6b6ecd79df790bf0938dab1f51094f94d777

commit r14-10165-g3b4d6b6ecd79df790bf0938dab1f51094f94d777
Author: Jason Merrill 
Date:   Fri May 3 09:52:46 2024 -0400

c++: initializer_list and EH [PR114935]

When we initialize an array of a type with a non-trivial destructor, such as
the backing array for the initializer_list, we have a cleanup to destroy any
constructed elements if a later constructor throws.  When the array being
created is a variable, the end of that EH region naturally coincides with
the beginning of the EH region for the cleanup for the variable as a whole.

But if the array is a temporary, or a subobject of one, the array cleanup
region lasts for the rest of the full-expression, along with the normal
cleanup for the TARGET_EXPR.  As a result, when tata throws we clean it up
twice.  Before r14-1705 we avoided this by disabling the array cleanup in
split_nonconstant_init, but after that we don't go through
split_nonconstant_init, so let's handle it in cp_genericize_target_expr.

PR c++/114935

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_genericize_init): Add flags parm.
(cp_genericize_init_expr): Pass nullptr.
(cp_genericize_target_expr): Handle cleanup flags.
* typeck2.cc (build_disable_temp_cleanup): Factor out of...
(split_nonconstant_init): ...here.
* cp-tree.h (build_disable_temp_cleanup): Declare.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-eh1.C: New test.

(cherry picked from commit 8f3afb83c879f1bfa722a963a07c06aaf174ef72)

Diff:
---
 gcc/cp/cp-tree.h  |  1 +
 gcc/cp/cp-gimplify.cc | 18 
 gcc/cp/typeck2.cc | 34 ++-
 gcc/testsuite/g++.dg/cpp0x/initlist-eh1.C | 25 +++
 4 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bafdf63dc63..a226a0a9fb6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8406,6 +8406,7 @@ extern int abstract_virtuals_error
(abstract_class_use, tree,
 tsubst_flags_t = 
tf_warning_or_error);
 
 extern tree store_init_value   (tree, tree, vec**, int);
+extern tree build_disable_temp_cleanup (tree);
 extern tree split_nonconstant_init (tree, tree);
 extern bool check_narrowing(tree, tree, tsubst_flags_t,
 bool = false);
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index ab5acd18c99..5cbdf0ea498 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1063,11 +1063,11 @@ any_non_eliding_target_exprs (tree ctor)
the result.  */
 
 static void
-cp_genericize_init (tree *replace, tree from, tree to)
+cp_genericize_init (tree *replace, tree from, tree to, vec** flags)
 {
   tree init = NULL_TREE;
   if (TREE_CODE (from) == VEC_INIT_EXPR)
-init = expand_vec_init_expr (to, from, tf_warning_or_error);
+init = expand_vec_init_expr (to, from, tf_warning_or_error, flags);
   else if (TREE_CODE (from) == CONSTRUCTOR
   && TREE_SIDE_EFFECTS (from)
   && ((flag_exceptions
@@ -1101,7 +1101,7 @@ cp_genericize_init_expr (tree *stmt_p)
   /* Return gets confused if we clobber its INIT_EXPR this soon.  */
   && TREE_CODE (to) != RESULT_DECL)
 from = TARGET_EXPR_INITIAL (from);
-  cp_genericize_init (stmt_p, from, to);
+  cp_genericize_init (stmt_p, from, to, nullptr);
 }
 
 /* For a TARGET_EXPR, change the TARGET_EXPR_INITIAL.  We will need to use
@@ -1112,9 +1112,19 @@ cp_genericize_target_expr (tree *stmt_p)
 {
   iloc_sentinel ils = EXPR_LOCATION (*stmt_p);
   tree slot = TARGET_EXPR_SLOT (*stmt_p);
+  vec *flags = make_tree_vector ();
   cp_genericize_init (_EXPR_INITIAL (*stmt_p),
- TARGET_EXPR_INITIAL (*stmt_p), slot);
+ TARGET_EXPR_INITIAL (*stmt_p), slot, );
   gcc_assert (!DECL_INITIAL (slot));
+  for (tree f : flags)
+{
+  /* Once initialization is complete TARGET_EXPR_CLEANUP becomes active, so
+disable any subobject cleanups.  */
+  tree d = build_disable_temp_cleanup (f);
+  auto  = TARGET_EXPR_INITIAL (*stmt_p);
+  r = add_stmt_to_compound (r, d);
+}
+  release_tree_vector (flags);
 }
 
 /* Similar to if (target_expr_needs_replace) replace_decl, but TP is the
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 2985bfdf9ec..06bad4d3303 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -466,6 +466,25 @@ maybe_push_temp_cleanup (tree sub, vec **flags)
 }
 }
 
+/* F is something added to a cleanup flags vec by maybe_push_temp_cleanup or
+   build_vec_init.  Return the code to disable the cleanup it controls.  */
+
+tree
+build_disable_temp_cleanup (tree f)

[gcc r15-138] c++: initializer_list and EH [PR114935]

2024-05-03 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:8f3afb83c879f1bfa722a963a07c06aaf174ef72

commit r15-138-g8f3afb83c879f1bfa722a963a07c06aaf174ef72
Author: Jason Merrill 
Date:   Fri May 3 09:52:46 2024 -0400

c++: initializer_list and EH [PR114935]

When we initialize an array of a type with a non-trivial destructor, such as
the backing array for the initializer_list, we have a cleanup to destroy any
constructed elements if a later constructor throws.  When the array being
created is a variable, the end of that EH region naturally coincides with
the beginning of the EH region for the cleanup for the variable as a whole.

But if the array is a temporary, or a subobject of one, the array cleanup
region lasts for the rest of the full-expression, along with the normal
cleanup for the TARGET_EXPR.  As a result, when tata throws we clean it up
twice.  Before r14-1705 we avoided this by disabling the array cleanup in
split_nonconstant_init, but after that we don't go through
split_nonconstant_init, so let's handle it in cp_genericize_target_expr.

PR c++/114935

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_genericize_init): Add flags parm.
(cp_genericize_init_expr): Pass nullptr.
(cp_genericize_target_expr): Handle cleanup flags.
* typeck2.cc (build_disable_temp_cleanup): Factor out of...
(split_nonconstant_init): ...here.
* cp-tree.h (build_disable_temp_cleanup): Declare.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-eh1.C: New test.

Diff:
---
 gcc/cp/cp-tree.h  |  1 +
 gcc/cp/cp-gimplify.cc | 18 
 gcc/cp/typeck2.cc | 34 ++-
 gcc/testsuite/g++.dg/cpp0x/initlist-eh1.C | 25 +++
 4 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1ba7054f8bc..52d6841559c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8411,6 +8411,7 @@ extern int abstract_virtuals_error
(abstract_class_use, tree,
 tsubst_flags_t = 
tf_warning_or_error);
 
 extern tree store_init_value   (tree, tree, vec**, int);
+extern tree build_disable_temp_cleanup (tree);
 extern tree split_nonconstant_init (tree, tree);
 extern bool check_narrowing(tree, tree, tsubst_flags_t,
 bool = false);
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index ab5acd18c99..5cbdf0ea498 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1063,11 +1063,11 @@ any_non_eliding_target_exprs (tree ctor)
the result.  */
 
 static void
-cp_genericize_init (tree *replace, tree from, tree to)
+cp_genericize_init (tree *replace, tree from, tree to, vec** flags)
 {
   tree init = NULL_TREE;
   if (TREE_CODE (from) == VEC_INIT_EXPR)
-init = expand_vec_init_expr (to, from, tf_warning_or_error);
+init = expand_vec_init_expr (to, from, tf_warning_or_error, flags);
   else if (TREE_CODE (from) == CONSTRUCTOR
   && TREE_SIDE_EFFECTS (from)
   && ((flag_exceptions
@@ -1101,7 +1101,7 @@ cp_genericize_init_expr (tree *stmt_p)
   /* Return gets confused if we clobber its INIT_EXPR this soon.  */
   && TREE_CODE (to) != RESULT_DECL)
 from = TARGET_EXPR_INITIAL (from);
-  cp_genericize_init (stmt_p, from, to);
+  cp_genericize_init (stmt_p, from, to, nullptr);
 }
 
 /* For a TARGET_EXPR, change the TARGET_EXPR_INITIAL.  We will need to use
@@ -1112,9 +1112,19 @@ cp_genericize_target_expr (tree *stmt_p)
 {
   iloc_sentinel ils = EXPR_LOCATION (*stmt_p);
   tree slot = TARGET_EXPR_SLOT (*stmt_p);
+  vec *flags = make_tree_vector ();
   cp_genericize_init (_EXPR_INITIAL (*stmt_p),
- TARGET_EXPR_INITIAL (*stmt_p), slot);
+ TARGET_EXPR_INITIAL (*stmt_p), slot, );
   gcc_assert (!DECL_INITIAL (slot));
+  for (tree f : flags)
+{
+  /* Once initialization is complete TARGET_EXPR_CLEANUP becomes active, so
+disable any subobject cleanups.  */
+  tree d = build_disable_temp_cleanup (f);
+  auto  = TARGET_EXPR_INITIAL (*stmt_p);
+  r = add_stmt_to_compound (r, d);
+}
+  release_tree_vector (flags);
 }
 
 /* Similar to if (target_expr_needs_replace) replace_decl, but TP is the
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 2985bfdf9ec..06bad4d3303 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -466,6 +466,25 @@ maybe_push_temp_cleanup (tree sub, vec **flags)
 }
 }
 
+/* F is something added to a cleanup flags vec by maybe_push_temp_cleanup or
+   build_vec_init.  Return the code to disable the cleanup it controls.  */
+
+tree
+build_disable_temp_cleanup (tree f)
+{
+  tree d = f;
+  tree i = boolean_false_node;
+  if (TREE_CODE (f) == 

[gcc r13-8669] c++: alias CTAD and template template parm [PR114377]

2024-05-01 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:60e1e13f458f1fcfb05a30ace57fa682461e2732

commit r13-8669-g60e1e13f458f1fcfb05a30ace57fa682461e2732
Author: centurion 
Date:   Wed Mar 27 18:36:37 2024 +

c++: alias CTAD and template template parm [PR114377]

To match all the other places that pull a _TEMPLATE_PARM out of a
_DECL (get_template_parm_index, etc.).

This change is too small to be legally significant for copyright.

PR c++/114377

gcc/cp/ChangeLog:

* pt.cc (find_template_parameter_info::found): Use TREE_TYPE for
TEMPLATE_DECL instead of DECL_INITIAL.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias19.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 801e82acd6b4f0cf863529875947e394899ea7b9)

Diff:
---
 gcc/cp/pt.cc |  3 ++-
 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C | 15 +++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a768d11c82f..fa660fcf49e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10917,7 +10917,8 @@ find_template_parameter_info::found (tree parm)
 {
   if (TREE_CODE (parm) == TREE_LIST)
 parm = TREE_VALUE (parm);
-  if (TREE_CODE (parm) == TYPE_DECL)
+  if (TREE_CODE (parm) == TYPE_DECL
+  || TREE_CODE (parm) == TEMPLATE_DECL)
 parm = TREE_TYPE (parm);
   else
 parm = DECL_INITIAL (parm);
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C
new file mode 100644
index 000..1ea79bd7691
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C
@@ -0,0 +1,15 @@
+// PR c++/114377
+// { dg-do compile { target c++20 } }
+
+template  typename Iterator>
+struct K {};
+
+template 
+class Foo {};
+
+template  typename TTP>
+using Bar = Foo>;
+
+void s() {
+Bar(1); // { dg-error "failed|no match" }
+}


[gcc r13-8668] c++: binding reference to comma expr [PR114561]

2024-05-01 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:7bc362ea61e5bf552356aa862beb7845fe50a47c

commit r13-8668-g7bc362ea61e5bf552356aa862beb7845fe50a47c
Author: Jason Merrill 
Date:   Tue Apr 2 10:52:28 2024 -0400

c++: binding reference to comma expr [PR114561]

We represent a reference binding where the referent type is more qualified
by a ck_ref_bind around a ck_qual.  We performed the ck_qual and then tried
to undo it with STRIP_NOPS, but that doesn't work if the conversion is
buried in COMPOUND_EXPR.  So instead let's avoid performing that fake
conversion in the first place.

PR c++/114561
PR c++/114562

gcc/cp/ChangeLog:

* call.cc (convert_like_internal): Avoid adding qualification
conversion in direct reference binding.

gcc/testsuite/ChangeLog:

* g++.dg/conversion/ref10.C: New test.
* g++.dg/conversion/ref11.C: New test.

(cherry picked from commit 5d7e9a35024f065b25f61747859c7cb7a770c92b)

Diff:
---
 gcc/cp/call.cc  | 23 +--
 gcc/testsuite/g++.dg/conversion/ref10.C |  5 +
 gcc/testsuite/g++.dg/conversion/ref11.C | 33 +
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index d012680f185..b10bdc62d38 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8632,7 +8632,15 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   break;
 };
 
-  expr = convert_like (next_conversion (convs), expr, fn, argnum,
+  conversion *nc = next_conversion (convs);
+  if (convs->kind == ck_ref_bind && nc->kind == ck_qual
+  && !convs->need_temporary_p)
+/* direct_reference_binding might have inserted a ck_qual under
+   this ck_ref_bind for the benefit of conversion sequence ranking.
+   Don't actually perform that conversion.  */
+nc = next_conversion (nc);
+
+  expr = convert_like (nc, expr, fn, argnum,
   convs->kind == ck_ref_bind
   ? issue_conversion_warnings : false,
   c_cast_p, /*nested_p=*/true, complain & ~tf_no_cleanup);
@@ -8710,19 +8718,6 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   {
tree ref_type = totype;
 
-   /* direct_reference_binding might have inserted a ck_qual under
-  this ck_ref_bind for the benefit of conversion sequence ranking.
-  Ignore the conversion; we'll create our own below.  */
-   if (next_conversion (convs)->kind == ck_qual
-   && !convs->need_temporary_p)
- {
-   gcc_assert (same_type_p (TREE_TYPE (expr),
-next_conversion (convs)->type));
-   /* Strip the cast created by the ck_qual; cp_build_addr_expr
-  below expects an lvalue.  */
-   STRIP_NOPS (expr);
- }
-
if (convs->bad_p && !next_conversion (convs)->bad_p)
  {
tree extype = TREE_TYPE (expr);
diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C 
b/gcc/testsuite/g++.dg/conversion/ref10.C
new file mode 100644
index 000..1913f733a6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref10.C
@@ -0,0 +1,5 @@
+// PR c++/114561
+
+void create(void* u) {
+  const void* const& r = ( (void)0, u );
+}
diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C 
b/gcc/testsuite/g++.dg/conversion/ref11.C
new file mode 100644
index 000..bb9b835034c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref11.C
@@ -0,0 +1,33 @@
+// PR c++/114562
+// { dg-do compile { target c++11 } }
+
+template 
+struct Optional {
+  Optional(T&&);
+};
+
+struct MyClass {
+  MyClass(Optional);
+};
+
+// const void* NONE = nullptr; // Correct Error
+void* NONE = nullptr; // Crash
+
+void beforeParam();
+
+template
+struct Create {
+  template  static T create(U &&) noexcept;
+};
+
+
+template 
+template
+T Create::create(U && u) noexcept {
+  return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue 
reference" }
+  // return T( (u) ); // Correct Error
+}
+
+void test_func() {
+  Create::create(NONE);
+}


[gcc r13-8667] c++: __is_constructible ref binding [PR100667]

2024-05-01 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:19821ce86afa0f4ce0d2312b16864c809e605be9

commit r13-8667-g19821ce86afa0f4ce0d2312b16864c809e605be9
Author: Jason Merrill 
Date:   Wed Mar 27 16:14:01 2024 -0400

c++: __is_constructible ref binding [PR100667]

The requirement that a type argument be complete is excessive in the case of
direct reference binding to the same type, which does not rely on any
properties of the type.  This is LWG 2939.

PR c++/100667

gcc/cp/ChangeLog:

* semantics.cc (same_type_ref_bind_p): New.
(finish_trait_expr): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_constructible8.C: New test.

(cherry picked from commit 8bb3ef3f6e335e8794590fb712a2661d11d21973)

Diff:
---
 gcc/cp/semantics.cc  | 50 ++--
 gcc/testsuite/g++.dg/ext/is_constructible8.C | 31 +
 2 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 3bf478fd68c..079ad5c93bf 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12176,6 +12176,47 @@ check_trait_type (tree type, int kind = 1)
   return true;
 }
 
+/* True iff the conversion (if any) would be a direct reference
+   binding, not requiring complete types.  This is LWG2939.  */
+
+static bool
+same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2)
+{
+  tree from, to;
+  switch (kind)
+{
+  /* These put the target type first.  */
+case CPTK_IS_CONSTRUCTIBLE:
+case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
+case CPTK_REF_CONVERTS_FROM_TEMPORARY:
+  to = type1;
+  from = type2;
+  break;
+
+  /* These put it second.  */
+case CPTK_IS_CONVERTIBLE:
+case CPTK_IS_NOTHROW_CONVERTIBLE:
+  to = type2;
+  from = type1;
+  break;
+
+default:
+  gcc_unreachable ();
+}
+
+  if (TREE_CODE (to) != REFERENCE_TYPE || !from)
+return false;
+  if (TREE_CODE (from) == TREE_VEC && TREE_VEC_LENGTH (from) == 1)
+from = TREE_VEC_ELT (from, 0);
+  else if (TREE_CODE (from) == TREE_LIST && !TREE_CHAIN (from))
+from = TREE_VALUE (from);
+  return (TYPE_P (from)
+ && (same_type_ignoring_top_level_qualifiers_p
+ (non_reference (to), non_reference (from;
+}
+
 /* Process a trait expression.  */
 
 tree
@@ -12241,14 +12282,19 @@ finish_trait_expr (location_t loc, cp_trait_kind 
kind, tree type1, tree type2)
return error_mark_node;
   break;
 
-case CPTK_IS_TRIVIALLY_ASSIGNABLE:
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
-case CPTK_IS_NOTHROW_ASSIGNABLE:
 case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
 case CPTK_IS_CONVERTIBLE:
 case CPTK_IS_NOTHROW_CONVERTIBLE:
 case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
 case CPTK_REF_CONVERTS_FROM_TEMPORARY:
+  /* Don't check completeness for direct reference binding.  */;
+  if (same_type_ref_bind_p (kind, type1, type2))
+   break;
+  gcc_fallthrough ();
+
+case CPTK_IS_NOTHROW_ASSIGNABLE:
+case CPTK_IS_TRIVIALLY_ASSIGNABLE:
   if (!check_trait_type (type1)
  || !check_trait_type (type2))
return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible8.C 
b/gcc/testsuite/g++.dg/ext/is_constructible8.C
new file mode 100644
index 000..a27ec6eddd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible8.C
@@ -0,0 +1,31 @@
+// PR c++/100667
+// { dg-do compile { target c++11 } }
+
+struct T;
+
+#define SA(X) static_assert ((X), #X);
+
+SA (__is_constructible(T&&, T));
+SA (__is_constructible(const T&, T));
+SA (!__is_constructible(T&, T));
+SA (__is_nothrow_constructible(T&&, T));
+SA (__is_nothrow_constructible(const T&, T));
+SA (!__is_nothrow_constructible(T&, T));
+SA (__is_trivially_constructible(T&&, T));
+SA (__is_trivially_constructible(const T&, T));
+SA (!__is_trivially_constructible(T&, T));
+
+SA (__is_convertible(T, T&&));
+SA (__is_convertible(T, const T&));
+SA (!__is_convertible(T, T&));
+SA (__is_nothrow_convertible(T, T&&));
+SA (__is_nothrow_convertible(T, const T&));
+SA (!__is_nothrow_convertible(T, T&));
+
+// All false because either the conversion fails or it doesn't bind a temporary
+SA (!__reference_constructs_from_temporary (T&&, T));
+SA (!__reference_constructs_from_temporary (const T&, T));
+SA (!__reference_constructs_from_temporary (T&, T));
+SA (!__reference_converts_from_temporary (T&&, T));
+SA (!__reference_converts_from_temporary (const T&, T));
+SA (!__reference_converts_from_temporary (T&, T));


Re: Updated Sourceware infrastructure plans

2024-05-01 Thread Jason Merrill via Gcc

On 5/1/24 12:15, Jeff Law wrote:



On 4/22/24 9:24 PM, Tom Tromey wrote:

Jason> Someone mentioned earlier that gerrit was previously tried
Jason> unsuccessfully.

We tried it and gdb and then abandoned it.  We tried to integrate it
into the traditional gdb development style, having it send email to
gdb-patches.  I found these somewhat hard to read and in the end we
agreed not to use it.

I've come around again to thinking we should probably abandon email
instead.  For me the main benefit is that gerrit has patch tracking,
unlike our current system, where losing patches is fairly routine.

Jason> I think this is a common pattern in GCC at least: someone has an
Jason> idea for a workflow improvement, and gets it working, but it
Jason> isn't widely adopted.

It essentially has to be mandated, IMO.

For GCC this seems somewhat harder since the community is larger, so
there's more people to convince.
I tend to think it's the principal reviewers that will drive this.  If 
several of the key folks indicated they were going to use system XYZ, 
whatever it is, that would drive everyone to that system.


We're currently using patchwork to track patches tagged with RISC-V.  We 
don't do much review with patchwork.  In that model patchwork ultimately 
just adds overhead as I'm constantly trying to figure out what patches 
have been integrated vs what are still outstanding.


Patchwork definitely isn't the answer IMHO.  Nor is gitlab MRs which we 
use heavily internally.  But boy I want to get away from email and to a 
pull request kind of flow.


Do you (or others) have any thoughts about GitLab FOSS?

Jason



[gcc r15-95] c++: drop in-charge for dtors without vbases

2024-05-01 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:a12cae973900f118436ef85c1197e91bf0428280

commit r15-95-ga12cae973900f118436ef85c1197e91bf0428280
Author: Jason Merrill 
Date:   Tue Dec 12 18:07:28 2023 -0500

c++: drop in-charge for dtors without vbases

Constructors and destructors use the in-charge parameter to decide whether
they're responsible for recursing into virtual bases.  Historically all
destructors had this parameter in order to also distinguish the deleting
destructor.  But r151673 in GCC 4.5 changed the deleting destructor to just
call the complete destructor and then operator delete, making the in-charge
parameter no longer relevant for destructors in classes without virtual
bases.  Having it causes confusion in constexpr evaluation, which assumes
that clones will have the same parameters as the cloned 'tor.

gcc/cp/ChangeLog:

* cp-tree.h (base_ctor_identifier): Adjust comment.
* call.cc (in_charge_arg_for_name): Abort on deleting dtor.
* decl2.cc (maybe_retrofit_in_chrg): Don't add it for
destructors without vbases, either.
* constexpr.cc (cxx_eval_call_expression): Remove workaround.

gcc/testsuite/ChangeLog:

* g++.dg/debug/dwarf2/array-3.C: No more 'int' for in-chrg parm.
* g++.dg/debug/dwarf2/array-4.C: Likewise.

Diff:
---
 gcc/cp/cp-tree.h|  3 +--
 gcc/cp/call.cc  |  4 +++-
 gcc/cp/constexpr.cc | 20 +++-
 gcc/cp/decl2.cc | 12 
 gcc/testsuite/g++.dg/debug/dwarf2/array-3.C |  6 +++---
 gcc/testsuite/g++.dg/debug/dwarf2/array-4.C |  2 +-
 6 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1938ada0268..5d1bd6ba493 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -289,8 +289,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 /* The name of a constructor that does not construct virtual base classes.  */
 #define base_ctor_identifier   
cp_global_trees[CPTI_BASE_CTOR_IDENTIFIER]
 /* The name of a destructor that takes an in-charge parameter to
-   decide whether or not to destroy virtual base classes and whether
-   or not to delete the object.  */
+   decide whether or not to destroy virtual base classes.  */
 #define dtor_identifier
cp_global_trees[CPTI_DTOR_IDENTIFIER]
 /* The name of a destructor that destroys virtual base classes.  */
 #define complete_dtor_identifier   
cp_global_trees[CPTI_COMPLETE_DTOR_IDENTIFIER]
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index dbdd7c29fe8..7c4ecf08c4b 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -11167,7 +11167,9 @@ in_charge_arg_for_name (tree name)
   if (name == complete_dtor_identifier)
return integer_two_node;
   else if (name == deleting_dtor_identifier)
-   return integer_three_node;
+   /* The deleting dtor should now be handled by
+  build_delete_destructor_body.  */
+   gcc_unreachable ();
   gcc_checking_assert (name == base_dtor_identifier);
 }
 
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8078b31544d..50f799d7ff7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3243,19 +3243,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
tree t,
  ctx->global->put_value (remapped, arg);
  remapped = DECL_CHAIN (remapped);
}
- for (; remapped; remapped = TREE_CHAIN (remapped))
-   if (DECL_NAME (remapped) == in_charge_identifier)
- {
-   /* FIXME destructors unnecessarily have in-charge parameters
-  even in classes without vbases, map it to 0 for now.  */
-   gcc_assert (!CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun)));
-   ctx->global->put_value (remapped, integer_zero_node);
- }
-   else
- {
-   gcc_assert (seen_error ());
-   *non_constant_p = true;
- }
+ if (remapped)
+   {
+ /* We shouldn't have any parms without args, but fail gracefully
+in error recovery.  */
+ gcc_checking_assert (seen_error ());
+ *non_constant_p = true;
+   }
  /* Add the RESULT_DECL to the values map, too.  */
  gcc_assert (!DECL_BY_REFERENCE (res));
  ctx->global->put_value (res, NULL_TREE);
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 806a2a4bc69..b8dc55b51d9 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -275,11 +275,8 @@ build_artificial_parm (tree fn, tree name, tree type)
   return parm;
 }
 
-/* Constructors for types with virtual baseclasses need an "in-charge" flag
-   saying whether this constructor is responsible for initialization of
-   virtual baseclasses or not.  All destructors also need this "in-charge"
-   flag, which 

[gcc r15-91] c++: const void* memchr [PR113706]

2024-05-01 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:c3bc2787b8beb7aae67fdf2a7f7271a9a4edca7c

commit r15-91-gc3bc2787b8beb7aae67fdf2a7f7271a9a4edca7c
Author: Jason Merrill 
Date:   Mon Feb 12 18:24:00 2024 -0500

c++: const void* memchr [PR113706]

The C++ standard specifies that the  functions have const and
non-const overloads, unlike C's single function with const argument and
non-const return.  Many systems don't actually implement this, but only add
an overload with non-const argument, so both end up having non-const return.
Solaris  does what the standard says, but we were penalizing it by
not recognizing the const overload as the built-in memchr.

PR c++/113706

gcc/cp/ChangeLog:

* decl.cc (decls_match): Handle memchr return type being
const-qualified.

gcc/testsuite/ChangeLog:

* g++.dg/opt/const-builtin1.C: New test.
* c-c++-common/pr103798-2.c: Remove xfail.

Diff:
---
 gcc/cp/decl.cc| 10 ++
 gcc/testsuite/c-c++-common/pr103798-2.c   |  3 +--
 gcc/testsuite/g++.dg/opt/const-builtin1.C | 33 +++
 3 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d88e0698652..df855334133 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1156,6 +1156,16 @@ decls_match (tree newdecl, tree olddecl, bool 
record_versions /* = true */)
   tree r2 = fndecl_declared_return_type (olddecl);
   tree r1 = fndecl_declared_return_type (newdecl);
 
+  /* For memchr et al, allow const void* return type (as specified by C++)
+when we expect void* (as in C).  */
+  if (DECL_IS_UNDECLARED_BUILTIN (olddecl)
+ && DECL_EXTERN_C_P (olddecl)
+ && !same_type_p (r1, r2)
+ && TREE_CODE (r1) == POINTER_TYPE
+ && TREE_CODE (r2) == POINTER_TYPE
+ && comp_ptr_ttypes (TREE_TYPE (r1), TREE_TYPE (r2)))
+   r2 = r1;
+
   tree p1 = TYPE_ARG_TYPES (f1);
   tree p2 = TYPE_ARG_TYPES (f2);
 
diff --git a/gcc/testsuite/c-c++-common/pr103798-2.c 
b/gcc/testsuite/c-c++-common/pr103798-2.c
index 83cdfaa1660..e7e99c3679e 100644
--- a/gcc/testsuite/c-c++-common/pr103798-2.c
+++ b/gcc/testsuite/c-c++-common/pr103798-2.c
@@ -27,5 +27,4 @@ main ()
  return 0;
 }
 
-/* See PR c++/113706 for the xfail.  */
-/* { dg-final { scan-assembler-not "memchr" { xfail { c++ && { *-*-solaris2* 
*-*-vxworks* } } } } } */
+/* { dg-final { scan-assembler-not "memchr" } } */
diff --git a/gcc/testsuite/g++.dg/opt/const-builtin1.C 
b/gcc/testsuite/g++.dg/opt/const-builtin1.C
new file mode 100644
index 000..8b9987271c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/const-builtin1.C
@@ -0,0 +1,33 @@
+// PR c++/113706
+/* A variant of the pr103798-2.c test with const void * memchr return type, as
+   specified by the C++ standard.  */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */
+
+extern "C" const void *memchr (const void *, int, __SIZE_TYPE__); // { 
dg-bogus "built-in" }
+
+__attribute__ ((weak))
+int
+f (int a)
+{
+   return memchr ("aE", a, 2) != 0;
+}
+
+__attribute__ ((weak))
+int
+g (char a)
+{
+  return a == 'a' || a == 'E';
+}
+
+int
+main ()
+{
+ for (int i = 0; i < 255; i++)
+   if (f (i + 256) != g (i + 256))
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "memchr" } } */


Re: 1.76% performance loss in VRP due to inlining

2024-04-30 Thread Jason Merrill via Gcc

On 4/30/24 12:22, Jakub Jelinek wrote:

On Tue, Apr 30, 2024 at 03:09:51PM -0400, Jason Merrill via Gcc wrote:

On Fri, Apr 26, 2024 at 5:44 AM Aldy Hernandez via Gcc  wrote:


In implementing prange (pointer ranges), I have found a 1.74% slowdown
in VRP, even without any code path actually using the code.  I have
tracked this down to irange::get_bitmask() being compiled differently
with and without the bare bones patch.  With the patch,
irange::get_bitmask() has a lot of code inlined into it, particularly
get_bitmask_from_range() and consequently the wide_int_storage code.

...

+static irange_bitmask
+get_bitmask_from_range (tree type,
+ const wide_int , const wide_int )

...

-irange_bitmask
-irange::get_bitmask_from_range () const


My guess is that this is the relevant change: the old function has
external linkage, and is therefore interposable, which inhibits
inlining.  The new function has internal linkage, which allows
inlining.


Even when a function is exported, when not compiled with -fpic/-fPIC
if we know the function is defined in current TU, it can't be interposed,


Ah, I was misremembering the effect of the change.  Rather, it's that if 
we see that a function with internal linkage has only a single caller, 
we try harder to inline it.


Jason



Re: 1.76% performance loss in VRP due to inlining

2024-04-30 Thread Jason Merrill via Gcc
On Fri, Apr 26, 2024 at 5:44 AM Aldy Hernandez via Gcc  wrote:
>
> In implementing prange (pointer ranges), I have found a 1.74% slowdown
> in VRP, even without any code path actually using the code.  I have
> tracked this down to irange::get_bitmask() being compiled differently
> with and without the bare bones patch.  With the patch,
> irange::get_bitmask() has a lot of code inlined into it, particularly
> get_bitmask_from_range() and consequently the wide_int_storage code.
...
> +static irange_bitmask
> +get_bitmask_from_range (tree type,
> + const wide_int , const wide_int )
...
> -irange_bitmask
> -irange::get_bitmask_from_range () const

My guess is that this is the relevant change: the old function has
external linkage, and is therefore interposable, which inhibits
inlining.  The new function has internal linkage, which allows
inlining.

Relatedly, I wonder if we want to build GCC with -fno-semantic-interposition?

Jason



Re: Updated Sourceware infrastructure plans

2024-04-22 Thread Jason Merrill via Gcc
On Mon, Apr 22, 2024 at 11:24 PM Tom Tromey  wrote:

> Jason> Someone mentioned earlier that gerrit was previously tried
> Jason> unsuccessfully.
>
> We tried it and gdb and then abandoned it.  We tried to integrate it
> into the traditional gdb development style, having it send email to
> gdb-patches.  I found these somewhat hard to read and in the end we
> agreed not to use it.
>
> I've come around again to thinking we should probably abandon email
> instead.  For me the main benefit is that gerrit has patch tracking,
> unlike our current system, where losing patches is fairly routine.
>

Indeed.  Though Patchwork is another option for patch tracking, that glibc
seem to be having success with.

Jason> I think this is a common pattern in GCC at least: someone has an
> Jason> idea for a workflow improvement, and gets it working, but it
> Jason> isn't widely adopted.
>
> It essentially has to be mandated, IMO.
>
> For GCC this seems somewhat harder since the community is larger, so
> there's more people to convince.
>

Absolutely, but now with the office hours it seems more feasible to build
momentum (or see that there isn't enough support) without having to wait
until Cauldron.

Jason


Re: Updated Sourceware infrastructure plans

2024-04-22 Thread Jason Merrill via Gcc
On Mon, Apr 22, 2024 at 11:42 AM Tom Tromey  wrote:

> > "Frank" == Frank Ch Eigler  writes:
>
> >> [...]  I suggest that a basic principle for such a system is that it
> >> should be *easy* to obtain and maintain a local copy of the history
> >> of all pull requests.  That includes all versions of a pull request,
> >> if it gets rebased, and all versions of comments, if the system
> >> allows editing comments.  A system that uses git as the source of
> >> truth for all the pull request data and has refs [...]
>
> Frank> Do you know of a system with these characteristics?
>
> Based on:
>
>
> https://gerrit-review.googlesource.com/Documentation/dev-design.html#_notedb
>
> ... it sounds like this is what gerrit does.
>

Someone mentioned earlier that gerrit was previously tried unsuccessfully.
I think this is a common pattern in GCC at least: someone has an idea for a
workflow improvement, and gets it working, but it isn't widely adopted.  I
think this is a problem with the "if you build it he will come" model
rather than with any particular technology; people are more or less
comfortable with their current workflow and uninclined to experiment with
someone else's new thing, even if it could eventually be a big improvement.

I think that the office hours, for both sourceware and the toolchain, offer
a better path for building enthusiasm about a new direction.

Is gerrit still installed?

Jason


[gcc r14-9946] c++: reference list-init, conversion fn [PR113141]

2024-04-12 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:d435571b54b02946c97b5b24f20e5a7058fd96a1

commit r14-9946-gd435571b54b02946c97b5b24f20e5a7058fd96a1
Author: Jason Merrill 
Date:   Fri Apr 12 13:24:44 2024 -0400

c++: reference list-init, conversion fn [PR113141]

The original testcase in PR113141 is an instance of CWG1996; the standard
fails to consider conversion functions when initializing a reference
directly from an initializer-list of one element, but then does consider
them when initializing a temporary.  I have a proposed fix for this defect,
which is implemented here.

DR 1996
PR c++/113141

gcc/cp/ChangeLog:

* call.cc (reference_binding): Check direct binding from
a single-element list.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/initlist-ref1.C: New test.
* g++.dg/cpp0x/initlist-ref2.C: New test.
* g++.dg/cpp0x/initlist-ref3.C: New test.

Co-authored-by: Patrick Palka 

Diff:
---
 gcc/cp/call.cc | 21 +
 gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C | 16 
 gcc/testsuite/g++.dg/cpp0x/initlist-ref2.C | 10 ++
 gcc/testsuite/g++.dg/cpp0x/initlist-ref3.C | 13 +
 4 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 9568b5eb2c4..15b5647298e 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -1596,7 +1596,9 @@ standard_conversion (tree to, tree from, tree expr, bool 
c_cast_p,
   return conv;
 }
 
-/* Returns nonzero if T1 is reference-related to T2.  */
+/* Returns nonzero if T1 is reference-related to T2.
+
+   This is considered when a reference to T1 is initialized by a T2.  */
 
 bool
 reference_related_p (tree t1, tree t2)
@@ -1757,6 +1759,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool 
c_cast_p, int flags,
 }
 
   bool copy_list_init = false;
+  bool single_list_conv = false;
   if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
 {
   maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
@@ -1783,6 +1786,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool 
c_cast_p, int flags,
  from = etype;
  goto skip;
}
+ else if (CLASS_TYPE_P (etype) && TYPE_HAS_CONVERSION (etype))
+   /* CWG1996: jason's proposed drafting adds "or initializing T from E
+  would bind directly".  We check that in the direct binding with
+  conversion code below.  */
+   single_list_conv = true;
}
   /* Otherwise, if T is a reference type, a prvalue temporary of the type
 referenced by T is copy-list-initialized, and the reference is bound
@@ -1907,9 +1915,14 @@ reference_binding (tree rto, tree rfrom, tree expr, bool 
c_cast_p, int flags,
  (possibly cv-qualified) object to the (possibly cv-qualified) same
  object type (or a reference to it), to a (possibly cv-qualified) base
  class of that type (or a reference to it) */
-  else if (CLASS_TYPE_P (from) && !related_p
-  && !(flags & LOOKUP_NO_CONVERSION))
+  else if (!related_p
+  && !(flags & LOOKUP_NO_CONVERSION)
+  && (CLASS_TYPE_P (from) || single_list_conv))
 {
+  tree rexpr = expr;
+  if (single_list_conv)
+   rexpr = CONSTRUCTOR_ELT (expr, 0)->value;
+
   /* [dcl.init.ref]
 
 If the initializer expression
@@ -1923,7 +1936,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool 
c_cast_p, int flags,
 
the reference is bound to the lvalue result of the conversion
in the second case.  */
-  z_candidate *cand = build_user_type_conversion_1 (rto, expr, flags,
+  z_candidate *cand = build_user_type_conversion_1 (rto, rexpr, flags,
complain);
   if (cand)
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C
new file mode 100644
index 000..f893f12dafa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C
@@ -0,0 +1,16 @@
+// PR c++/113141
+// { dg-do compile { target c++11 } }
+
+struct ConvToRef {
+  operator int&();
+};
+
+struct A { int& r; };
+
+void f(A);
+
+int main() {
+  ConvToRef c;
+  A a{{c}};
+  f({{c}});
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-ref2.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-ref2.C
new file mode 100644
index 000..401d868d820
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-ref2.C
@@ -0,0 +1,10 @@
+// CWG1996
+// { dg-do compile { target c++11 } }
+
+struct S { operator struct D &(); } s;
+D {s};   // OK, direct binding
+
+namespace N1 {
+  struct S { operator volatile struct D &(); } s;
+  const D {s};// { dg-error "invalid user-defined|discards qualifiers" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-ref3.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-ref3.C
new file mode 100644
index 

[gcc r14-9795] c++: alias CTAD and template template parm [PR114377]

2024-04-04 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:801e82acd6b4f0cf863529875947e394899ea7b9

commit r14-9795-g801e82acd6b4f0cf863529875947e394899ea7b9
Author: centurion 
Date:   Wed Mar 27 18:36:37 2024 +

c++: alias CTAD and template template parm [PR114377]

To match all the other places that pull a _TEMPLATE_PARM out of a
_DECL (get_template_parm_index, etc.).

This change is too small to be legally significant for copyright.

PR c++/114377

gcc/cp/ChangeLog:

* pt.cc (find_template_parameter_info::found): Use TREE_TYPE for
TEMPLATE_DECL instead of DECL_INITIAL.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias19.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/pt.cc |  3 ++-
 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C | 15 +++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 7b00a8615d2..1425d6116d0 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11032,7 +11032,8 @@ find_template_parameter_info::found (tree parm)
 {
   if (TREE_CODE (parm) == TREE_LIST)
 parm = TREE_VALUE (parm);
-  if (TREE_CODE (parm) == TYPE_DECL)
+  if (TREE_CODE (parm) == TYPE_DECL
+  || TREE_CODE (parm) == TEMPLATE_DECL)
 parm = TREE_TYPE (parm);
   else
 parm = DECL_INITIAL (parm);
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C
new file mode 100644
index 000..1ea79bd7691
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C
@@ -0,0 +1,15 @@
+// PR c++/114377
+// { dg-do compile { target c++20 } }
+
+template  typename Iterator>
+struct K {};
+
+template 
+class Foo {};
+
+template  typename TTP>
+using Bar = Foo>;
+
+void s() {
+Bar(1); // { dg-error "failed|no match" }
+}


Re: How to get the default values for parameters?

2024-04-03 Thread Jason Merrill via Gcc
On Wed, Apr 3, 2024 at 9:35 AM Hanke Zhang via Gcc  wrote:
>
> Hi,
> I'm trying to get the default values for parameters of some functions
> in my GIMPLE-PASS. The example code is here:
>
> enum {
>   edefault1 = 1,
>   edefault2 = 2,
>   edefault3 = 3
> }
>
> void func(int p0, int p1 = edefault1, int p2 = edefault2, int p3 = edefault3) 
> {
>   // do other things
> }
>
> I want to get the value of `p1` here. But I didn't find a way to get it.
>
> And I noticed that the marco `DECL_INITIAL` cannot be applied on
> PARM_DECL. And the comments say that the default values for parameters
> are encoded in the type of the function. But I can't find it.

The TYPE_ARG_TYPES of a FUNCTION_TYPE is a TREE_LIST where the
TREE_PURPOSE is the default argument.

Jason



Re: Patches submission policy change

2024-04-03 Thread Jason Merrill via Gcc
On Wed, Apr 3, 2024 at 6:23 AM Jan Beulich via Gcc  wrote:

> On 03.04.2024 10:57, Richard Biener wrote:
> > On Wed, 3 Apr 2024, Jan Beulich wrote:
> >> On 03.04.2024 10:45, Jakub Jelinek wrote:
> >>> On Wed, Apr 03, 2024 at 10:22:24AM +0200, Christophe Lyon wrote:
>  Any concerns/objections?
> >>>
> >>> I'm all for it, in fact I've been sending it like that myself for years
> >>> even when the policy said not to.  In most cases, the diff for the
> >>> regenerated files is very small and it helps even in patch review to
> >>> actually check if the configure.ac/m4 etc. changes result just in the
> >>> expected changes and not some unrelated ones (e.g. caused by user using
> >>> wrong version of autoconf/automake etc.).
> >>> There can be exceptions, e.g. when in GCC we update from a new version
> >>> of Unicode, the regenerated ucnid.h diff can be large and
> >>> uname2c.h can be huge, such that it can trigger the mailing list size
> >>> limits even when the patch is compressed, see e.g.
> >>> https://gcc.gnu.org/pipermail/gcc-patches/2023-November/636427.html
> >>> https://gcc.gnu.org/pipermail/gcc-patches/2023-November/636426.html
> >>> But I think most configure or Makefile changes should be pretty small,
> >>> usual changes shouldn't rewrite everything in those files.
> >>
> >> Which may then call for a policy saying "include generate script diff-s,
> >> but don't include generated data file ones"? At least on the binutils
> >> side, dealing (for CI) with what e.g. opcodes/*-gen produce ought to be
> >> possible by having something along the lines of "maintainer mode light".
> >
> > I'd say we should send generated files when it fits the mailing list
> > limits (and possibly simply lift those limits?).
>
> Well, that would allow patches making it through, but it would still
> severely increase overall size. I'm afraid more people than not also
> fail to cut down reply context, so we'd further see (needlessly) huge
> replies to patches as well.
>
> Additionally - how does one up front determine "fits the mailing list
> limits"? My mail UI (Thunderbird) doesn't show me the size of a message
> until I've actually sent it.
>
> >  As a last resort
> > do a series splitting the re-generation out (but I guess this would
> > confuse the CI as well and of course for the push you want to squash
> > again).
>
> Yeah, unless the CI would only ever test full series, this wouldn't help.
> It's also imo even more cumbersome than simply stripping the generated
> file parts from emails.
>

Massive patches need special handling either way; I wouldn't lift the
mailing list limits because of this change.

I'm in favor of this change for typical patches.

Jason


[gcc r14-9757] c++: binding reference to comma expr [PR114561]

2024-04-02 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:5d7e9a35024f065b25f61747859c7cb7a770c92b

commit r14-9757-g5d7e9a35024f065b25f61747859c7cb7a770c92b
Author: Jason Merrill 
Date:   Tue Apr 2 10:52:28 2024 -0400

c++: binding reference to comma expr [PR114561]

We represent a reference binding where the referent type is more qualified
by a ck_ref_bind around a ck_qual.  We performed the ck_qual and then tried
to undo it with STRIP_NOPS, but that doesn't work if the conversion is
buried in COMPOUND_EXPR.  So instead let's avoid performing that fake
conversion in the first place.

PR c++/114561
PR c++/114562

gcc/cp/ChangeLog:

* call.cc (convert_like_internal): Avoid adding qualification
conversion in direct reference binding.

gcc/testsuite/ChangeLog:

* g++.dg/conversion/ref10.C: New test.
* g++.dg/conversion/ref11.C: New test.

Diff:
---
 gcc/cp/call.cc  | 23 +--
 gcc/testsuite/g++.dg/conversion/ref10.C |  5 +
 gcc/testsuite/g++.dg/conversion/ref11.C | 33 +
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 9e4c8073600..9568b5eb2c4 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8742,7 +8742,15 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   break;
 };
 
-  expr = convert_like (next_conversion (convs), expr, fn, argnum,
+  conversion *nc = next_conversion (convs);
+  if (convs->kind == ck_ref_bind && nc->kind == ck_qual
+  && !convs->need_temporary_p)
+/* direct_reference_binding might have inserted a ck_qual under
+   this ck_ref_bind for the benefit of conversion sequence ranking.
+   Don't actually perform that conversion.  */
+nc = next_conversion (nc);
+
+  expr = convert_like (nc, expr, fn, argnum,
   convs->kind == ck_ref_bind
   ? issue_conversion_warnings : false,
   c_cast_p, /*nested_p=*/true, complain & ~tf_no_cleanup);
@@ -8820,19 +8828,6 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
   {
tree ref_type = totype;
 
-   /* direct_reference_binding might have inserted a ck_qual under
-  this ck_ref_bind for the benefit of conversion sequence ranking.
-  Ignore the conversion; we'll create our own below.  */
-   if (next_conversion (convs)->kind == ck_qual
-   && !convs->need_temporary_p)
- {
-   gcc_assert (same_type_p (TREE_TYPE (expr),
-next_conversion (convs)->type));
-   /* Strip the cast created by the ck_qual; cp_build_addr_expr
-  below expects an lvalue.  */
-   STRIP_NOPS (expr);
- }
-
if (convs->bad_p && !next_conversion (convs)->bad_p)
  {
tree extype = TREE_TYPE (expr);
diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C 
b/gcc/testsuite/g++.dg/conversion/ref10.C
new file mode 100644
index 000..1913f733a6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref10.C
@@ -0,0 +1,5 @@
+// PR c++/114561
+
+void create(void* u) {
+  const void* const& r = ( (void)0, u );
+}
diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C 
b/gcc/testsuite/g++.dg/conversion/ref11.C
new file mode 100644
index 000..bb9b835034c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref11.C
@@ -0,0 +1,33 @@
+// PR c++/114562
+// { dg-do compile { target c++11 } }
+
+template 
+struct Optional {
+  Optional(T&&);
+};
+
+struct MyClass {
+  MyClass(Optional);
+};
+
+// const void* NONE = nullptr; // Correct Error
+void* NONE = nullptr; // Crash
+
+void beforeParam();
+
+template
+struct Create {
+  template  static T create(U &&) noexcept;
+};
+
+
+template 
+template
+T Create::create(U && u) noexcept {
+  return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue 
reference" }
+  // return T( (u) ); // Correct Error
+}
+
+void test_func() {
+  Create::create(NONE);
+}


gcc-wwwdocs branch master updated. 4f5550e76b8bd55d15479f9556bd25280e7244e0

2024-04-01 Thread Jason Merrill via Gcc-cvs-wwwdocs
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gcc-wwwdocs".

The branch, master has been updated
   via  4f5550e76b8bd55d15479f9556bd25280e7244e0 (commit)
  from  600367e4296b68da0d5e26fdac18c13fad16c169 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -
commit 4f5550e76b8bd55d15479f9556bd25280e7244e0
Author: Jason Merrill 
Date:   Mon Apr 1 12:07:05 2024 -0400

cxx-status: support p2748

diff --git a/htdocs/projects/cxx-status.html b/htdocs/projects/cxx-status.html
index bfef2114..7897635c 100644
--- a/htdocs/projects/cxx-status.html
+++ b/htdocs/projects/cxx-status.html
@@ -139,7 +139,7 @@
 
Disallow binding a returned reference to a temporary 
https://wg21.link/P2748R5;>P2748R5
-   https://gcc.gnu.org/PR114455;>No
+   https://gcc.gnu.org/PR114455;>14

 
 

---

Summary of changes:
 htdocs/projects/cxx-status.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


hooks/post-receive
-- 
gcc-wwwdocs


[gcc r14-9738] c++: C++26 returning reference to temporary

2024-04-01 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:bba118db3f63cb1e3953a014aa3ac2ad89908950

commit r14-9738-gbba118db3f63cb1e3953a014aa3ac2ad89908950
Author: Jason Merrill 
Date:   Thu Mar 28 21:33:57 2024 -0400

c++: C++26 returning reference to temporary

P2748R5 makes it ill-formed to return a reference to temporary in C++26;
implementing this is a simple matter of changing the existing warning to a
permerror.

For most of the tests I just changed dg-warning to dg-message to accept
both; I test the specific diagnostic type in Wreturn-local-addr-5.C.

gcc/cp/ChangeLog:

* typeck.cc (maybe_warn_about_returning_address_of_local):
Permerror in C++26.

gcc/testsuite/ChangeLog:

* g++.dg/conversion/pr16333.C: Change dg-warning to dg-message.
* g++.dg/cpp0x/constexpr-48324.C
* g++.dg/other/pr94326.C
* g++.dg/warn/Wreturn-local-addr-2.C
* g++.old-deja/g++.jason/warning8.C: Likewise.
* g++.dg/cpp1y/auto-fn6.C: Check that others don't complain.
* g++.dg/warn/Wreturn-local-addr-5.C: Expect error in C++26.

Diff:
---
 gcc/cp/typeck.cc | 6 --
 gcc/testsuite/g++.dg/conversion/pr16333.C| 2 +-
 gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C | 2 +-
 gcc/testsuite/g++.dg/cpp1y/auto-fn6.C| 8 
 gcc/testsuite/g++.dg/other/pr94326.C | 2 +-
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C | 4 ++--
 gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C | 3 ++-
 gcc/testsuite/g++.old-deja/g++.jason/warning8.C  | 2 +-
 8 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index f5a0a2273be..88ed38e4f30 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10626,8 +10626,10 @@ maybe_warn_about_returning_address_of_local (tree 
retval, location_t loc)
   || TREE_CODE (whats_returned) == TARGET_EXPR)
 {
   if (TYPE_REF_P (valtype))
-   warning_at (loc, OPT_Wreturn_local_addr,
-   "returning reference to temporary");
+   /* P2748 made this an error in C++26.  */
+   emit_diagnostic (cxx_dialect >= cxx26 ? DK_PERMERROR : DK_WARNING,
+loc, OPT_Wreturn_local_addr,
+"returning reference to temporary");
   else if (TYPE_PTR_P (valtype))
warning_at (loc, OPT_Wreturn_local_addr,
"returning pointer to temporary");
diff --git a/gcc/testsuite/g++.dg/conversion/pr16333.C 
b/gcc/testsuite/g++.dg/conversion/pr16333.C
index a00bc5c167c..d0049304790 100644
--- a/gcc/testsuite/g++.dg/conversion/pr16333.C
+++ b/gcc/testsuite/g++.dg/conversion/pr16333.C
@@ -6,5 +6,5 @@ struct X {
 
 int a[3];
 X foo1 () { return a; }
-const X  () { return a; } // { dg-warning "returning reference to 
temporary" }
+const X  () { return a; } // { dg-message "returning reference to 
temporary" }
 X  () { return a; } // { dg-error "cannot bind non-const lvalue ref" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C
index 37ed0e1d163..f53fd4ddbd3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48324.C
@@ -7,7 +7,7 @@ struct S {
 };
 
 constexpr const int& to_ref(int i) {
-  return S(i).val; // { dg-warning "reference to temporary" }
+  return S(i).val; // { dg-message "reference to temporary" }
 }
 
 constexpr int ary[to_ref(98)] = { }; // { dg-error "25:size of array .ary. is 
not an integral" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C 
b/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C
index 17ca6f22c50..7fada180841 100644
--- a/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn6.C
@@ -8,11 +8,11 @@ char& g(char);
 double&& g(double);
 
 template  auto&& f(T t)
-{ return g(t); }   // { dg-warning "reference to temporary" }
+{ return g(t); }   // { dg-message "reference to temporary" }
 
 int main()
 {
-  ST();
-  ST();
-  ST();
+  ST();  // { dg-message "required from here" }
+  ST(); // { dg-bogus "required from here" }
+  ST(); // { dg-bogus "required from here" }
 }
diff --git a/gcc/testsuite/g++.dg/other/pr94326.C 
b/gcc/testsuite/g++.dg/other/pr94326.C
index 4069c038d52..5df72a648fd 100644
--- a/gcc/testsuite/g++.dg/other/pr94326.C
+++ b/gcc/testsuite/g++.dg/other/pr94326.C
@@ -3,7 +3,7 @@
 // { dg-options "-fcompare-debug" }
 
 template  struct A {
-  const int () { return 0; }   // { dg-warning "returning reference to 
temporary" }
+  const int () { return 0; }   // { dg-message "returning reference to 
temporary" }
   template  void bar(_Kt) { foo(); }
 };
 struct B {
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C 
b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C
index c483601e6b2..a9f984c153d 100644
--- a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-2.C
+++ 

[gcc r14-9713] c++: __is_constructible ref binding [PR100667]

2024-03-28 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:8bb3ef3f6e335e8794590fb712a2661d11d21973

commit r14-9713-g8bb3ef3f6e335e8794590fb712a2661d11d21973
Author: Jason Merrill 
Date:   Wed Mar 27 16:14:01 2024 -0400

c++: __is_constructible ref binding [PR100667]

The requirement that a type argument be complete is excessive in the case of
direct reference binding to the same type, which does not rely on any
properties of the type.  This is LWG 2939.

PR c++/100667

gcc/cp/ChangeLog:

* semantics.cc (same_type_ref_bind_p): New.
(finish_trait_expr): Use it.

gcc/testsuite/ChangeLog:

* g++.dg/ext/is_constructible8.C: New test.

Diff:
---
 gcc/cp/semantics.cc  | 54 
 gcc/testsuite/g++.dg/ext/is_constructible8.C | 31 
 2 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index adb1ba48d29..9838331d2a9 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12607,6 +12607,45 @@ check_trait_type (tree type, int kind = 1)
   return true;
 }
 
+/* True iff the conversion (if any) would be a direct reference
+   binding, not requiring complete types.  This is LWG2939.  */
+
+static bool
+same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2)
+{
+  tree from, to;
+  switch (kind)
+{
+  /* These put the target type first.  */
+case CPTK_IS_CONSTRUCTIBLE:
+case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
+case CPTK_REF_CONVERTS_FROM_TEMPORARY:
+  to = type1;
+  from = type2;
+  break;
+
+  /* These put it second.  */
+case CPTK_IS_CONVERTIBLE:
+case CPTK_IS_NOTHROW_CONVERTIBLE:
+  to = type2;
+  from = type1;
+  break;
+
+default:
+  gcc_unreachable ();
+}
+
+  if (TREE_CODE (to) != REFERENCE_TYPE || !from)
+return false;
+  if (TREE_CODE (from) == TREE_VEC && TREE_VEC_LENGTH (from) == 1)
+from = TREE_VEC_ELT (from, 0);
+  return (TYPE_P (from)
+ && (same_type_ignoring_top_level_qualifiers_p
+ (non_reference (to), non_reference (from;
+}
+
 /* Process a trait expression.  */
 
 tree
@@ -12666,20 +12705,21 @@ finish_trait_expr (location_t loc, cp_trait_kind 
kind, tree type1, tree type2)
return error_mark_node;
   break;
 
-case CPTK_IS_ASSIGNABLE:
 case CPTK_IS_CONSTRUCTIBLE:
-  if (!check_trait_type (type1))
-   return error_mark_node;
-  break;
-
 case CPTK_IS_CONVERTIBLE:
-case CPTK_IS_NOTHROW_ASSIGNABLE:
 case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
 case CPTK_IS_NOTHROW_CONVERTIBLE:
-case CPTK_IS_TRIVIALLY_ASSIGNABLE:
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
 case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
 case CPTK_REF_CONVERTS_FROM_TEMPORARY:
+  /* Don't check completeness for direct reference binding.  */;
+  if (same_type_ref_bind_p (kind, type1, type2))
+   break;
+  gcc_fallthrough ();
+
+case CPTK_IS_ASSIGNABLE:
+case CPTK_IS_NOTHROW_ASSIGNABLE:
+case CPTK_IS_TRIVIALLY_ASSIGNABLE:
   if (!check_trait_type (type1)
  || !check_trait_type (type2))
return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible8.C 
b/gcc/testsuite/g++.dg/ext/is_constructible8.C
new file mode 100644
index 000..a27ec6eddd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible8.C
@@ -0,0 +1,31 @@
+// PR c++/100667
+// { dg-do compile { target c++11 } }
+
+struct T;
+
+#define SA(X) static_assert ((X), #X);
+
+SA (__is_constructible(T&&, T));
+SA (__is_constructible(const T&, T));
+SA (!__is_constructible(T&, T));
+SA (__is_nothrow_constructible(T&&, T));
+SA (__is_nothrow_constructible(const T&, T));
+SA (!__is_nothrow_constructible(T&, T));
+SA (__is_trivially_constructible(T&&, T));
+SA (__is_trivially_constructible(const T&, T));
+SA (!__is_trivially_constructible(T&, T));
+
+SA (__is_convertible(T, T&&));
+SA (__is_convertible(T, const T&));
+SA (!__is_convertible(T, T&));
+SA (__is_nothrow_convertible(T, T&&));
+SA (__is_nothrow_convertible(T, const T&));
+SA (!__is_nothrow_convertible(T, T&));
+
+// All false because either the conversion fails or it doesn't bind a temporary
+SA (!__reference_constructs_from_temporary (T&&, T));
+SA (!__reference_constructs_from_temporary (const T&, T));
+SA (!__reference_constructs_from_temporary (T&, T));
+SA (!__reference_converts_from_temporary (T&&, T));
+SA (!__reference_converts_from_temporary (const T&, T));
+SA (!__reference_converts_from_temporary (T&, T));


Re: AutoFDO tools for GCC

2024-03-27 Thread Jason Merrill via Gcc
On Tue, Mar 26, 2024 at 6:41 PM Andi Kleen via Gcc  wrote:
>
> On Tue, Mar 26, 2024 at 08:45:22AM +0100, Richard Biener wrote:
> > On Mon, Mar 25, 2024 at 9:54 PM Eugene Rozenfeld via Gcc
> >  wrote:
> > >
> > > Hello,
> > >
> > > I've been the AutoFDO maintainer for the last 1.5 years. I've resurrected 
> > > autoprofiledbootstrap build and made a number of other fixes/improvements 
> > > (e.g., discriminator support).
> > >
> > > The tools for AutoFDO (create_gcov, etc.) currently live in 
> > > https://github.com/google/AutoFDO  repo and GCC AutoFDO documentation 
> > > points users to that repo. That repo also has tools for LLVM AutoFDO.
> > > https://github.com/google/AutoFDO  has several submodules: 
> > > https://github.com/google/autofdo/blob/master/.gitmodules
> > >
> > > I got a message from Snehasish (cc'd) that google intends to migrate the 
> > > tools for LLVM to the LLVM repo and wants to archive 
> > > https://github.com/google/AutoFDO. That will be a problem for AutoFDO in 
> > > GCC. The idea to find a different home for GCC AutoFDO tools was 
> > > discussed before on this alias but this becomes more urgent now. One idea 
> > > was to build these tools from GCC repo and another was to produce gcov 
> > > from perf tool directly. Andi (cc'd)  had some early unfinished prototype 
> > > for latter.
> > >
> > > Please let me know if you have thoughts on how we should proceed.
> >
> > I think it makes sense for GCC specific parts to live in the GCC
> > repository alongside gcov tools.  I do wonder how much common code
> > there is
> > between the LLVM and the GCC tooling though and whether it makes sense
> > to keep it common (and working with both frontends)?  The
> > pragmatic solution would have been to fork the repo on github to a
> > place not within the google group ...
>
> In tree would need convincing Google to assign the copyright.

Would it?  Looks like it's under a free license (apache 2), not
everything in the tree is copyright FSF or GPL3.

Jason



[gcc r14-9484] tree-core: clarify clobber comments

2024-03-14 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:efab8c1b692ab080bcee99a6ef7ba6ee43ed

commit r14-9484-gefab8c1b692ab080bcee99a6ef7ba6ee43ed
Author: Jason Merrill 
Date:   Thu Feb 22 10:06:27 2024 +

tree-core: clarify clobber comments

It came up on the mailing list that OBJECT_BEGIN/END are described as
marking object lifetime, but mark the beginning of the constructor and end
of the destructor, whereas the C++ notion of lifetime is between the end of
the constructor and beginning of the destructor.  So let's fix the comments.

gcc/ChangeLog:

* tree-core.h (enum clobber_kind): Clarify CLOBBER_OBJECT_*
comments.

Diff:
---
 gcc/tree-core.h | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index d529712306d..a74fbdf75b4 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -993,9 +993,11 @@ enum clobber_kind {
   CLOBBER_UNDEF,
   /* Beginning of storage duration, e.g. malloc.  */
   CLOBBER_STORAGE_BEGIN,
-  /* Beginning of object lifetime, e.g. C++ constructor.  */
+  /* Beginning of object data, e.g. start of C++ constructor.  This differs
+ from C++ 'lifetime', which starts when initialization is complete; a
+ clobber there would discard the initialization.  */
   CLOBBER_OBJECT_BEGIN,
-  /* End of object lifetime, e.g. C++ destructor.  */
+  /* End of object data, e.g. end of C++ destructor.  */
   CLOBBER_OBJECT_END,
   /* End of storage duration, e.g. free.  */
   CLOBBER_STORAGE_END,


Re: Improvement of CLOBBER descriptions

2024-02-22 Thread Jason Merrill via Gcc

On 2/21/24 10:43, Michael Matz wrote:

Hello,

On Wed, 21 Feb 2024, Daniil Frolov wrote:


Following the recent introduction of more detailed CLOBBER types in GCC, a
minor inconsistency has been identified in the description of
CLOBBER_OBJECT_BEGIN:

   /* Beginning of object lifetime, e.g. C++ constructor.  */
   CLOBBER_OBJECT_BEGIN


The "e.g." comment mixes concepts of the C++ language with a
middle-end/GIMPLE concept, and hence is a bit misleading.  What the
clobbers are intended to convey to the middle-end is the low-level notion
of "storage associated with this and that object is now accessible
(BEGIN)/not accessible anymore (END), for purposes related to that very
object".  The underlying motivation, _why_ that knowledge is interesting
to the middle-end, is to be able to share storage between different
objects.

"purposes related to that object" are any operations on the object:
construction, destruction, access, frobnification.  It's not tied to a
particular frontend language (although it's the language semantics that
dictate when emitting the begin/end clobbers is appropriate).  For the
middle-end the C++ concept of construction/deconstruction are simply
modifications (conceptual or real) of the storage associated with an
object ("object" not in the C++ sense, but from a low-level perspective;
i.e. an "object" doesn't only exist after c++-construction, it comes into
existence before that, even if perhaps in an indeterminate/invalid state
from the frontends perspective).

Initially these clobbers were only emitted when decls went ouf of
scope, and so did have some relation to frontend language semantics
(although a fairly universal one, namely "scope").  The
C++ frontend then found further uses (e.g. after a dtor for an
object _ends_ it's storage can also be reused), and eventually we also
needed the BEGIN clobbers to convey the meaning of "now storage use for
object potentially starts, don't share it with any other object".

If certain frontends find use for more fine-grained definitions of
life-times, then further note kinds need to be invented for those
frontends use.  They likely won't have influence on the middle-end though
(perhaps for some sanitizers such new kinds might be useful?).  But the
current BEGIN/END clobbers need to continue to mark the outermost borders
of storage validity for an object.


Yes.  The current uses of CLOBBER_OBJECT_* also include the period of 
construction/destruction, and we should clarify that in the comment, 
including avoiding the word "lifetime".


Or perhaps they could just be CLOBBER_STORAGE_*, though that would also 
be imprecise, since in various cases the storage duration of an object 
can be longer than beginning of construction to end of destruction; if I 
repeatedly construct and destroy objects in the same storage, I would 
like to have clobbers to indicate the boundaries between them.


But still, I don't think it's useful to distinguish between the two: 
what we want is clobbers to indicate the beginning and end of the use of 
storage to represent a particular object.  We don't need a clobber to 
tell the middle-end when storage begins and ends, it can work that out 
for itself, based in part on when individual objects begin and end.


So, my inclination is to remove STORAGE_* in favor of OBJECT_* and 
adjust the misleading comments for the latter.


As Michael says, emitting a clobber at the end of the constructor or 
beginning of the destructor seems inappropriate, as all clobbers 
indicate that the target does not have a meaningful value at that point. 
 Probably better to use some front-end-local representation that gets 
discarded by genericize.


Jason



Re: lambda coding style

2024-01-11 Thread Jason Merrill via Gcc

On 1/11/24 12:48, Martin Jambor wrote:

On Wed, Jan 10 2024, Jason Merrill via Gcc wrote:

What formatting style do we want for non-trivial lambdas in GCC sources?
   I'm thinking the most consistent choice would be

auto l = [&] (parms) // space between ] (
{  // brace on new line, indented two spaces
  return stuff;
};

By default, recent emacs lines up the { with the previous line, like an
in-class function definition; I talked it into the above indentation with

(defun lambda-offset (elem)
(if (assq 'inline-open c-syntactic-context) '+ 0))
(add-to-hook 'c++-mode-hook '(c-set-offset 'inlambda 'lambda-offset))


Is this really add-to-hook and not add-hook?


Oops! add-to-hook is a custom variant I wrote back in like 1992; for 
add-hook you'll want


(add-hook 'c++-mode-hook
  '(lambda () (c-set-offset 'inlambda 'lambda-offset)))

Jason



Re: lambda coding style

2024-01-10 Thread Jason Merrill via Gcc

On 1/10/24 16:41, Marek Polacek wrote:

On Wed, Jan 10, 2024 at 04:24:42PM -0500, Jason Merrill wrote:

On 1/10/24 15:59, Marek Polacek wrote:

On Wed, Jan 10, 2024 at 02:58:03PM -0500, Jason Merrill via Gcc wrote:

What formatting style do we want for non-trivial lambdas in GCC sources?
I'm thinking the most consistent choice would be

auto l = [&] (parms) // space between ] (
{  // brace on new line, indented two spaces
  return stuff;
};


Sure, why not.  Consistency is what matters.  Thus far we seem
to have been very inconsistent.  ;)

By default, recent emacs lines up the { with the previous line, like an
in-class function definition; I talked it into the above indentation with

(defun lambda-offset (elem)
(if (assq 'inline-open c-syntactic-context) '+ 0))
(add-to-hook 'c++-mode-hook '(c-set-offset 'inlambda 'lambda-offset))

I think we probably want the same formatting for lambdas in function
argument lists, e.g.

algorithm ([] (parms)
{
  return foo;
});


And what about lambdas in conditions:

if (foo ()
  && [&] (params) mutable
 {
 return 42;
 } ())

should the { go just below [?


I think we don't want the { to go below the [ in general; that was the old
emacs default behavior, and it produced lambda bodies with excessive
indentation.

With my adjustment above, emacs indents the { two spaces from the &&, which
seems a bit arbitrary but reasonable.


Fair enough, I think that's better.

I suppose we should add a note wrt lambdas to
https://gcc.gnu.org/codingconventions.html#Cxx_Conventions


Indeed, that's my goal.

Looking through the various lambdas already in the compiler, I see a 
good number already follow my suggested indentation, but a large 
majority omit the space between ] and (, so maybe we don't want it?


Jason



Re: lambda coding style

2024-01-10 Thread Jason Merrill via Gcc

On 1/10/24 15:59, Marek Polacek wrote:

On Wed, Jan 10, 2024 at 02:58:03PM -0500, Jason Merrill via Gcc wrote:

What formatting style do we want for non-trivial lambdas in GCC sources?
I'm thinking the most consistent choice would be

auto l = [&] (parms) // space between ] (
   {  // brace on new line, indented two spaces
 return stuff;
   };


Sure, why not.  Consistency is what matters.  Thus far we seem
to have been very inconsistent.  ;)
  

By default, recent emacs lines up the { with the previous line, like an
in-class function definition; I talked it into the above indentation with

(defun lambda-offset (elem)
   (if (assq 'inline-open c-syntactic-context) '+ 0))
(add-to-hook 'c++-mode-hook '(c-set-offset 'inlambda 'lambda-offset))

I think we probably want the same formatting for lambdas in function
argument lists, e.g.

algorithm ([] (parms)
   {
 return foo;
   });


And what about lambdas in conditions:

if (foo ()
 && [&] (params) mutable
{
 return 42;
} ())

should the { go just below [?


I think we don't want the { to go below the [ in general; that was the 
old emacs default behavior, and it produced lambda bodies with excessive 
indentation.


With my adjustment above, emacs indents the { two spaces from the &&, 
which seems a bit arbitrary but reasonable.


Jason



lambda coding style

2024-01-10 Thread Jason Merrill via Gcc
What formatting style do we want for non-trivial lambdas in GCC sources? 
 I'm thinking the most consistent choice would be


auto l = [&] (parms) // space between ] (
  {  // brace on new line, indented two spaces
return stuff;
  };

By default, recent emacs lines up the { with the previous line, like an 
in-class function definition; I talked it into the above indentation with


(defun lambda-offset (elem)
  (if (assq 'inline-open c-syntactic-context) '+ 0))
(add-to-hook 'c++-mode-hook '(c-set-offset 'inlambda 'lambda-offset))

I think we probably want the same formatting for lambdas in function 
argument lists, e.g.


algorithm ([] (parms)
  {
return foo;
  });

Any other opinions?

Jason



Re: Deprecating -fgnu-tm support for GCC 14 and removing it for GCC 15

2023-12-20 Thread Jason Merrill via Gcc
On Mon, Dec 18, 2023 at 3:04 AM Richard Biener via Gcc 
wrote:

> On Mon, Dec 18, 2023 at 2:35 AM Andrew Pinski via Gcc 
> wrote:
> >
> > On Sun, Dec 17, 2023 at 1:20 PM Eric Gallager 
> wrote:
> > >
> > > On Sat, Dec 16, 2023 at 3:16 PM Andrew Pinski via Gcc 
> wrote:
> > > >
> > > > -fgnu-tm support has not been improved since GCC 5 or earlier. It is
> > > > not even supported with LTO. Does it make sense to deprecate the
> > > > support for GCC 14 and remove it in GCC 15?
> > > >
> > > > Thanks,
> > > > Andrew Pinski
> > >
> > > Personally, since GCC is in stage 3 now, I would push that schedule
> > > back a release and move deprecation to GCC 15, and then only remove it
> > > for GCC 16 if no one objects, but then again I don't actually use
> > > -fgnu-tm myself, so I wouldn't be too upset if the faster schedule is
> > > chosen instead.
> >
> > Considering -fgnu-tm has been broken for LTO ever since LTO was
> > introduced, and broken with -fsanitize=undefined and broken with many
> > code that might use internal functions (known since 2015), I suspect
> > nobody is using this option in production nor even trying it out. If
> > this was stage1, I might even just recommend removing the support. But
> > deprecating it during stage 3 seems like a fair compromise.
>
> Btw, I'm OK with deprecating it for GCC 14.  Can you please propose a
> patch for changes.html and add a diagnostic message when -fgnu-tm is used
> (disabled with -Wno-deprecated)?
>

Deprecation makes sense to me.

But keep in mind that transactional memory is still the subject of research
and standardization efforts, though the current proposal (wg21.link/n4923)
is significantly simpler than the earlier TS that GCC implemented.  I don't
know how much of the current implementation would carry over, but I'd be
cautious about tearing everything out just yet.

Jason


Re: [PATCH v5 2/5] libcpp: add a function to determine UTF-8 validity of a C string

2023-10-23 Thread Jason Merrill via Gcc

On 10/23/23 11:16, David Malcolm wrote:

On Wed, Jan 25, 2023 at 4:09 PM Ben Boeckel via Gcc  wrote:


This simplifies the interface for other UTF-8 validity detections when a
simple "yes" or "no" answer is sufficient.

libcpp/

 * charset.cc: Add `_cpp_valid_utf8_str` which determines whether
 a C string is valid UTF-8 or not.
 * internal.h: Add prototype for `_cpp_valid_utf8_str`.

Signed-off-by: Ben Boeckel 


[going through patches in patchwork]

What's the status of this patch; did this ever get committed?


It was superseded.

Jason



Re: Documenting common C/C++ options

2023-10-10 Thread Jason Merrill via Gcc
On Tue, Oct 10, 2023 at 7:12 AM Florian Weimer via Gcc 
wrote:

> * Richard Earnshaw:
>
> > On 10/10/2023 11:46, Richard Earnshaw (lists) via Gcc wrote:
> >> On 10/10/2023 10:47, Florian Weimer via Gcc wrote:
> >>> Currently, -fsigned-char and -funsigned-char are only documented as C
> >>> language options, although they work for C++ as well (and Objective-C
> >>> and Objective-C++, I assume, but I have not tested this).  There does
> >>> not seem to be a place for this kind of options in the manual.
> >>>
> >>> The options -fshort-enums and -fshort-wchar are documented under
> >>> code-generation options, but this seems to be a bit of a stretch
> because
> >>> (at least for -fshort-wchar), these too seem to be more about front-end
> >>> behavior.
> >>>
> >>> What would be a good way to address this?
> >>>
> >>> Thanks,
> >>> Florian
> >>>
> >>
> >>
> >> All of these are ABI; so where ever it goes, it should be documented
> >> that changing them will potentially cause issues with any
> >> pre-compiled object files having different settings.
>
> > And you can add -f[un]signed-bitfield to that list as well.
>
> There's already a section for those ABI options that are like
> -fshort-enums:
>
> @node Code Gen Options
> @section Options for Code Generation Conventions
>
> Maybe we should move them over there.
>
> But that wasn't really the direction of my question.  I was wondering
> where we should document a future C version of -fpermissive.
>

My permerror patch proposes moving it to the Warning Options node, right
after -pedantic-errors.

Jason


Re: C89 question: Do we need to accept -Wint-conversion warnings

2023-10-10 Thread Jason Merrill via Gcc
On Tue, Oct 10, 2023 at 7:30 AM Florian Weimer via Gcc 
wrote:

> Are these code fragments valid C89 code?
>
>   int i1 = 1;
>   char *p1 = i;
>
>   char c;
>   char *p2 = 
>   int i2 = p2;
>
> Or can we generate errors for them even with -std=gnu89?
>
> (It will still be possible to override this with -fpermissive or
> -Wno-int-conversion.)
>

Given that C89 code is unlikely to be actively maintained, I think we
should be permissive by default in that mode.  People compiling with an old
-std flag are presumably doing it to keep old code compiling, and it seems
appropriate to respect that.

I'm also (though less strongly) inclined to be permissive in C99 mode, and
only introduce the new strictness by default for C11/C17 modes.

Jason


Re: [PATCH v8 0/4] P1689R5 support

2023-09-19 Thread Jason Merrill via Gcc

On 9/1/23 09:04, Ben Boeckel wrote:

Hi,

This patch series adds initial support for ISO C++'s [P1689R5][], a
format for describing C++ module requirements and provisions based on
the source code. This is required because compiling C++ with modules is
not embarrassingly parallel and need to be ordered to ensure that
`import some_module;` can be satisfied in time by making sure that any
TU with `export import some_module;` is compiled first.

[P1689R5]: https://isocpp.org/files/papers/P1689R5.html

I've also added patches to include imported module CMI files and the
module mapper file as dependencies of the compilation. I briefly looked
into adding dependencies on response files as well, but that appeared to
need some code contortions to have a `class mkdeps` available before
parsing the command line or to keep the information around until one was
made.

I'd like feedback on the approach taken here with respect to the
user-visible flags. I'll also note that header units are not supported
at this time because the current `-E` behavior with respect to `import
;` is to search for an appropriate `.gcm` file which is not
something such a "scan" can support. A new mode will likely need to be
created (e.g., replacing `-E` with `-fc++-module-scanning` or something)
where headers are looked up "normally" and processed only as much as
scanning requires.

FWIW, Clang as taken an alternate approach with its `clang-scan-deps`
tool rather than using the compiler directly.

Thanks,

--Ben

---
v7 -> v8:

- rename `DEPS_FMT_` enum variants to `FDEPS_FMT_` to match the
   associated flag
- memory leak fix in the `join` specfunc implementation (also better
   comments), both from Jason
- formatting fix in `mkdeps.cc` for `write_make_modules_deps` assignment
- comments on new functions for P1689R5 implementation


Pushed, thanks!

Jason



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




  1   2   3   4   5   6   7   8   9   10   >