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;


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

2024-05-29 Thread Jason Merrill
Revised to drop the cgraph change so I can self-approve the remaining patch.

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

-- 8< --

 #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.
---
 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(+)
 create mode 100644 gcc/testsuite/g++.dg/opt/always_inline1.C

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;

base-commit: ff41abdca0ab9993b6170b9b1f46b3a40921f1b0
-- 
2.44.0



[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 Backslas

[pushed] c++: add module extensions

2024-05-29 Thread Jason Merrill
Revised to change mkdeps and the docs.

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

-- 8< --

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.
---
 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 { scan-file dep-1_a.d {\ngcm.cache/m-part\.gcm:| dep-1_a\.o} } }
-// { dg-final { scan-file dep-1_a.d {\n\.PHONY: m:part\.c\+\+m} } }
+// { dg-final { scan-file dep-1_a.d {\n\.PHONY: m:part\.c\+\+-module} } }
diff --git 

Re: [PATCH v2] C/C++: add hints for strerror

2024-05-29 Thread Jason Merrill

Pushed, thanks!

On 2/27/24 20:13, Oskari Pirhonen wrote:

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 
---
v2:
- check for error instead of warning in gcc.dg/spellcheck-stdlib-2.c
- from linaro ci notification email

  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(+)
  create mode 100644 gcc/testsuite/gcc.dg/spellcheck-stdlib-2.c

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 } */
+}




[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: [PATCH v3 #1/2] enable adjustment of return_pc debug attrs

2024-05-28 Thread Jason Merrill

On 5/25/24 08:12, Alexandre Oliva wrote:

On Apr 27, 2023, Alexandre Oliva  wrote:

On Apr 14, 2023, Alexandre Oliva  wrote:

On Mar 23, 2023, Alexandre Oliva  wrote:

This patch introduces infrastructure for targets to add an offset to
the label issued after the call_insn to set the call_return_pc
attribute.  This will be used on rs6000, that sometimes issues another
instruction after the call proper as part of a call insn.



Ping?
https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614452.html


Ping?
Refreshed, retested on ppc64le-linux-gnu.  Ok to install?


I wonder about adding this information to REG_CALL_ARG_LOCATION, but 
doing it this way also seems reasonable.  I'm interested in Jakub's 
input, but the patch is OK in a week if he doesn't get to it.

This patch introduces infrastructure for targets to add an offset to
the label issued after the call_insn to set the call_return_pc
attribute.  This will be used on rs6000, that sometimes issues another
instruction after the call proper as part of a call insn.


for  gcc/ChangeLog

* target.def (call_offset_return_label): New hook.
* gcc/doc/tm.texi.in (TARGET_CALL_OFFSET_RETURN_LABEL): Add
placeholder.
* gcc/doc/tm.texi: Rebuild.
* dwarf2out.cc (struct call_arg_loc_node): Record call_insn
instad of call_arg_loc_note.
(add_AT_lbl_id): Add optional offset argument.
(gen_call_site_die): Compute and pass on a return pc offset.
(gen_subprogram_die): Move call_arg_loc_note computation...
(dwarf2out_var_location): ... from here.  Set call_insn.
---
  gcc/doc/tm.texi|7 +++
  gcc/doc/tm.texi.in |2 ++
  gcc/dwarf2out.cc   |   26 +-
  gcc/target.def |9 +
  4 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index cd50078227d98..8a7aa70d605ba 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5557,6 +5557,13 @@ except the last are treated as named.
  You need not define this hook if it always returns @code{false}.
  @end deftypefn
  
+@deftypefn {Target Hook} int TARGET_CALL_OFFSET_RETURN_LABEL (rtx_insn *@var{call_insn})

+While generating call-site debug info for a CALL insn, or a SEQUENCE
+insn starting with a CALL, this target hook is invoked to compute the
+offset to be added to the debug label emitted after the call to obtain
+the return address that should be recorded as the return PC.
+@end deftypefn
+
  @deftypefn {Target Hook} void TARGET_START_CALL_ARGS (cumulative_args_t 
@var{complete_args})
  This target hook is invoked while generating RTL for a function call,
  after the argument values have been computed, and after stack arguments
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 058bd56487a9a..9e0830758aeea 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3887,6 +3887,8 @@ These machine description macros help implement varargs:
  
  @hook TARGET_STRICT_ARGUMENT_NAMING
  
+@hook TARGET_CALL_OFFSET_RETURN_LABEL

+
  @hook TARGET_START_CALL_ARGS
  
  @hook TARGET_CALL_ARGS

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 5b064ffd78ad1..1092880738df4 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -3593,7 +3593,7 @@ typedef struct var_loc_list_def var_loc_list;
  
  /* Call argument location list.  */

  struct GTY ((chain_next ("%h.next"))) call_arg_loc_node {
-  rtx GTY (()) call_arg_loc_note;
+  rtx_insn * GTY (()) call_insn;
const char * GTY (()) label;
tree GTY (()) block;
bool tail_call_p;
@@ -3777,7 +3777,8 @@ static void remove_addr_table_entry (addr_table_entry *);
  static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool);
  static inline rtx AT_addr (dw_attr_node *);
  static void add_AT_symview (dw_die_ref, enum dwarf_attribute, const char *);
-static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
+static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *,
+  int = 0);
  static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
  static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
  static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
@@ -5353,14 +5354,17 @@ add_AT_symview (dw_die_ref die, enum dwarf_attribute 
attr_kind,
  
  static inline void

  add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind,
-   const char *lbl_id)
+  const char *lbl_id, int offset)
  {
dw_attr_node attr;
  
attr.dw_attr = attr_kind;

attr.dw_attr_val.val_class = dw_val_class_lbl_id;
attr.dw_attr_val.val_entry = NULL;
-  attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
+  if (!offset)
+attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
+  else
+attr.dw_attr_val.v.val_lbl_id = xasprintf ("%s%+i", lbl_id, offset);
if (dwarf_split_debug_info)
  attr.dw_attr_val.val_entry
  = add_addr_table_entry (attr.dw_attr_val.v.val_lbl_id,

Re: [PATCH] c++: canonicity of fn types w/ instantiated eh specs [PR115223]

2024-05-28 Thread Jason Merrill

On 5/25/24 19:18, Patrick Palka wrote:

Bootstrap and regtest on x86_64-pc-linux-gnu in progress,
does this look OK for trunk if successful?


OK.


-- >8 --

When propagating structural equality in build_cp_fntype_variant, we
should consider structural equality of the exception-less variant, not
of the given type which might use structural equality only because of
the (complex) noexcept-spec we're intending to replace, as in
maybe_instantiate_noexcept which calls build_exception_variant using
the function type with a deferred noexcept-spec.  Otherwise we might
pessimisticly use structural equality for a function type with a simple
instantiated noexcept-spec, leading to a failed LTO-specific sanity
check if we later use that (structural-equality) type as the canonical
version of some other variant.

PR c++/115223

gcc/cp/ChangeLog:

* tree.cc (build_cp_fntype_variant): Propagate structural
equality of the exception-less variant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept87.C: New test.
---
  gcc/cp/tree.cc  |  4 
  gcc/testsuite/g++.dg/cpp0x/noexcept87.C | 11 +++
  2 files changed, 15 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept87.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 4d87661b4ad..f810b8cd777 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2796,6 +2796,10 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier 
rqual,
bool complex_eh_spec_p = (cr && cr != noexcept_true_spec
&& !UNPARSED_NOEXCEPT_SPEC_P (cr));
  
+  if (!complex_eh_spec_p && TYPE_RAISES_EXCEPTIONS (type))

+/* We want to consider structural equality of the exception-less
+   variant since we'll be replacing the exception specification.  */
+type = build_cp_fntype_variant (type, rqual, /*raises=*/NULL_TREE, late);
if (TYPE_STRUCTURAL_EQUALITY_P (type) || complex_eh_spec_p)
  /* Propagate structural equality.  And always use structural equality
 for function types with a complex noexcept-spec since their identity
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept87.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept87.C
new file mode 100644
index 000..60b1497472b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept87.C
@@ -0,0 +1,11 @@
+// PR c++/115223
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -flto }
+
+template
+void f() noexcept(bool(T() || true));
+
+void g(int n) { f(); }
+
+using type = void;
+type callDestructorIfNecessary() noexcept {}




Re: [PATCH] c++/modules: Prevent revealing a using-decl affecting cached overloads [PR114867]

2024-05-28 Thread Jason Merrill

On 5/26/24 09:01, Nathaniel Shead wrote:

Is this approach OK?  Alternatively I suppose we could do a deep copy of
the overload list when this occurs to ensure we don't affect existing
referents, would that be preferable?


This strategy makes sense, but I have other concerns:


Bootstrapped and regtested (so far just modules.exp) on
x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?

-- >8 --

Doing 'remove_node' here is not safe, because it not only mutates the
OVERLOAD we're walking over but potentially any other references to this
OVERLOAD that are cached from phase-1 template lookup.  This causes the
attached testcase to fail because the overload set in X::test no longer
contains the 'ns::foo' template once instantiated at the end of the


It looks like ns::foo has been renamed to just f in the testcase.


file.

This patch works around this by simply not removing the old declaration.
This does make the overload list potentially longer than it otherwise
would have been, but only when re-exporting the same set of functions in
a using-decl.  Additionally, because 'ovl_insert' always prepends these
newly inserted overloads, repeated exported using-decls won't continue
to add declarations, as the first exported using-decl will be found
before the original (unexported) declaration.

PR c++/114867

gcc/cp/ChangeLog:

* name-lookup.cc (do_nonmember_using_decl): Don't remove the
existing overload.

gcc/testsuite/ChangeLog:

* g++.dg/modules/using-17_a.C: New test.
* g++.dg/modules/using-17_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/name-lookup.cc | 24 +++---
  gcc/testsuite/g++.dg/modules/using-17_a.C | 31 +++
  gcc/testsuite/g++.dg/modules/using-17_b.C | 13 ++
  3 files changed, 53 insertions(+), 15 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/using-17_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/using-17_b.C

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index f1f8c19feb1..130a0e6b5db 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -5231,25 +5231,19 @@ do_nonmember_using_decl (name_lookup , bool 
fn_scope_p,
  
  	  if (new_fn == old_fn)

{
- /* The function already exists in the current
-namespace.  We will still want to insert it if
-it is revealing a not-revealed thing.  */
+ /* The function already exists in the current namespace.  */
  found = true;
- if (!revealing_p)
-   ;
- else if (old.using_p ())
+ if (exporting)
{
- if (exporting)
+ if (old.using_p ())
/* Update in place.  'tis ok.  */
OVL_EXPORT_P (old.get_using ()) = true;
- ;
-   }
- else if (DECL_MODULE_EXPORT_P (new_fn))
-   ;
- else
-   {
- value = old.remove_node (value);
- found = false;
+ else if (!DECL_MODULE_EXPORT_P (new_fn))
+   /* We need to re-insert this function as an exported
+  declaration.  We can't remove the existing decl
+  because that will change any overloads cached in
+  template functions.  */
+   found = false;


What if we're revealing without exporting?  That is, a using-declaration 
in module purview that isn't exported?  Such a declaration should still 
prevent discarding, which is my understanding of the use of "revealing" 
here.


It seems like the current code already gets that wrong for e.g.

M_1.C:
module;
 struct A {};
 inline int f() { return 42; }
export module M;
 using ::A;
 using ::f;

M_2.C:
import M;
 inline int f();
 struct A a; // { dg-bogus "incomplete" }
int main() {
  return f(); // { dg-bogus "undefined" }
}

It looks like part of the problem is that add_binding_entity is only 
interested in exported usings, but I think it should also handle 
revealing ones.


Jason



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
>



Re: [PATCH] c++: Fix parsing of abstract-declarator starting with ... followed by [ or ( [PR115012]

2024-05-24 Thread Jason Merrill

On 5/9/24 14:12, Jakub Jelinek wrote:


The C++26 P2662R3 Pack indexing paper mentions that both GCC
and MSVC don't handle T...[10] parameter declaration when T
is a pack.  While that will change meaning in C++26, in C++11 .. C++23
this ought to be valid.


Sure, but I don't think it does anyone any favors to start accepting a 
pattern that we know is going to break before long.  Us not accepting it 
was part of the rationale for the paper.



Also, T...(args) as well.


This part of the patch is OK.


The following patch handles those in cp_parser_direct_declarator.

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

2024-05-09  Jakub Jelinek  

PR c++/115012
* parser.cc (cp_parser_direct_declarator): Handle
abstract declarator starting with ... followed by [
or (.

* g++.dg/cpp0x/variadic185.C: New test.
* g++.dg/cpp0x/variadic186.C: New test.

--- gcc/cp/parser.cc.jj 2024-05-09 10:30:58.0 +0200
+++ gcc/cp/parser.cc2024-05-09 16:44:01.250777325 +0200
@@ -23916,7 +23916,12 @@ cp_parser_direct_declarator (cp_parser*
  {
/* Peek at the next token.  */
token = cp_lexer_peek_token (parser->lexer);
-  if (token->type == CPP_OPEN_PAREN)
+  if (token->type == CPP_OPEN_PAREN
+ || (first
+ && dcl_kind != CP_PARSER_DECLARATOR_NAMED
+ && token->type == CPP_ELLIPSIS
+ && cxx_dialect > cxx98
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)))
{
  /* This is either a parameter-declaration-clause, or a
 parenthesized declarator. When we know we are parsing a
@@ -23955,6 +23960,11 @@ cp_parser_direct_declarator (cp_parser*
  
  	 Thus again, we try a parameter-declaration-clause, and if

 that fails, we back out and return.  */
+ bool pack_expansion_p = token->type == CPP_ELLIPSIS;
+
+ if (pack_expansion_p)
+   /* Consume the `...' */
+   cp_lexer_consume_token (parser->lexer);
  
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)

{
@@ -24098,6 +24108,7 @@ cp_parser_direct_declarator (cp_parser*
 attrs,
 parens_loc);
  declarator->attributes = gnu_attrs;
+ declarator->parameter_pack_p |= pack_expansion_p;
  /* Any subsequent parameter lists are to do with
 return type, so are not those of the declared
 function.  */
@@ -24121,7 +24132,7 @@ cp_parser_direct_declarator (cp_parser*
  
  	  /* If this is the first, we can try a parenthesized

 declarator.  */
- if (first)
+ if (first && !pack_expansion_p)
{
  bool saved_in_type_id_in_expr_p;
  
@@ -24156,16 +24167,27 @@ cp_parser_direct_declarator (cp_parser*

  else
break;
}
-  else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
-  && token->type == CPP_OPEN_SQUARE
-  && !cp_next_tokens_can_be_attribute_p (parser))
+  else if (((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
+   && token->type == CPP_OPEN_SQUARE
+   && !cp_next_tokens_can_be_attribute_p (parser))
+  || (first
+  && dcl_kind != CP_PARSER_DECLARATOR_NAMED
+  && token->type == CPP_ELLIPSIS
+  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_SQUARE)
+  && cxx_dialect > cxx98
+  && !cp_nth_tokens_can_be_std_attribute_p (parser, 2)))
{
  /* Parse an array-declarator.  */
  tree bounds, attrs;
+ bool pack_expansion_p = token->type == CPP_ELLIPSIS;
  
  	  if (ctor_dtor_or_conv_p)

*ctor_dtor_or_conv_p = 0;
  
+	  if (pack_expansion_p)

+   /* Consume the `...' */
+   cp_lexer_consume_token (parser->lexer);
+
  open_paren = NULL;
  first = false;
  parser->default_arg_ok_p = false;
@@ -24220,6 +24242,7 @@ cp_parser_direct_declarator (cp_parser*
  attrs = cp_parser_std_attribute_spec_seq (parser);
  declarator = make_array_declarator (declarator, bounds);
  declarator->std_attributes = attrs;
+ declarator->parameter_pack_p |= pack_expansion_p;
}
else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
--- gcc/testsuite/g++.dg/cpp0x/variadic185.C.jj 2024-05-09 15:08:49.070651189 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/variadic185.C2024-05-09 15:07:40.045583153 
+0200
@@ -0,0 +1,39 @@
+// PR c++/115012
+// { dg-do compile { target { c++11 && c++23_down } } }
+// { dg-final { scan-assembler "_Z3fooILi10EJidEEvDpAT__T0_" } }
+// { dg-final { scan-assembler "_Z3barILi10EiEvPT0_" } }
+// { dg-final { scan-assembler "_Z3bazILi10EJidEEvDpAT__T0_" } }
+// { dg-final { scan-assembler 

Re: [PATCH] Add testcase for PR c++/105229: ICE in lookup_template_class_1

2024-05-24 Thread Jason Merrill

On 5/24/24 08:16, Simon Martin wrote:

The test case in PR c++/105229 has been fixed since 11.4 (via PR
c++/106024) - the attached patch simply adds the case to the test suite.

Successfully tested on x86_64-pc-linux-gnu. OK for trunk?


OK, thanks.

BTW, the patch was corrupted by your mail client wrapping long lines; 
can you use git send-email instead in the future?



Thanks! Simon


  PR c++/105229

gcc/testsuite/ChangeLog:

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

---
   gcc/testsuite/g++.dg/parse/crash72.C | 12 
   1 file changed, 12 insertions(+)
   create mode 100644 gcc/testsuite/g++.dg/parse/crash72.C

diff --git a/gcc/testsuite/g++.dg/parse/crash72.C
b/gcc/testsuite/g++.dg/parse/crash72.C
new file mode 100644
index 000..df469e20f28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash72.C
@@ -0,0 +1,12 @@
+// PR c++/105229
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-Wno-missing-template-keyword" }
+
+template  void bar ()
+{
+  []  {}.operator () <> (); // { dg-error "expected
primary-expression" }
+}
+void foo ()
+{
+  bar ();
+}
--
2.44.0





[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.  */
   {


Re: [PATCH] c++/modules: Improve diagnostic when redeclaring builtin in module [PR102345]

2024-05-24 Thread Jason Merrill

On 5/24/24 11:32, Nathaniel Shead wrote:

On Fri, May 24, 2024 at 11:24:38AM -0400, Jason Merrill wrote:

On 5/24/24 11:20, Nathaniel Shead wrote:

This is just a small improvement to a diagnostic.  I thought about also
adding an inform to suggest something like "standard library headers
should be included in the GMF" or somesuch, but I'm not sure that'll be
especially valuable and may be confusing if this particular error is
caused some other way.

Bootstrapped and regtested (so far just modules.exp) on
x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?

-- >8 --

If a user mistakenly includes a standard library header within the
module purview, they currently get a confusing "declaration conflicts
with builtin" error.  This patch updates the message to include "in
module", to help guide the user towards the likely cause.

gcc/cp/ChangeLog:

* module.cc (module_may_redeclare): Update error message.

gcc/testsuite/ChangeLog:

* g++.dg/modules/enum-12.C: Test for updated error.

Signed-off-by: Nathaniel Shead 
---
   gcc/cp/module.cc   | 9 -
   gcc/testsuite/g++.dg/modules/enum-12.C | 2 +-
   2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 6cd7d9e0b93..60cf3ebc468 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19140,7 +19140,14 @@ module_may_redeclare (tree olddecl, tree newdecl)
 decl = newdecl ? newdecl : olddecl;
 location_t loc = newdecl ? DECL_SOURCE_LOCATION (newdecl) : input_location;
 if (DECL_IS_UNDECLARED_BUILTIN (olddecl))
-error_at (loc, "declaration %qD conflicts with builtin", decl);
+{
+  if (newdecl_attached_p)
+   error_at (loc, "declaring %qD in module %qs conflicts with builtin",


Maybe "with builtin in global module"?


Yup, that's even clearer, thanks.




+ decl, new_mod->get_flatname ());
+  else
+   error_at (loc, "declaring %qD in global module conflicts with builtin",


I'm not sure mentioning the global module adds anything in this case?



I'd done it for consistency with the other cases in case we ever somehow
reached this code path, but happy to remove since this should always be
a problem regardless.

So maybe something like this?


OK.


-- >8 --

If a user mistakenly includes a standard library header within the
module purview, they currently get a confusing "declaration conflicts
with builtin" error.  This patch updates the message to include "in
module", to help guide the user towards the likely cause.

gcc/cp/ChangeLog:

* module.cc (module_may_redeclare): Update error message.

gcc/testsuite/ChangeLog:

* g++.dg/modules/enum-12.C: Test for updated error.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc   | 8 +++-
  gcc/testsuite/g++.dg/modules/enum-12.C | 2 +-
  2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 6cd7d9e0b93..3f8f84bb9fd 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19140,7 +19140,13 @@ module_may_redeclare (tree olddecl, tree newdecl)
decl = newdecl ? newdecl : olddecl;
location_t loc = newdecl ? DECL_SOURCE_LOCATION (newdecl) : input_location;
if (DECL_IS_UNDECLARED_BUILTIN (olddecl))
-error_at (loc, "declaration %qD conflicts with builtin", decl);
+{
+  if (newdecl_attached_p)
+   error_at (loc, "declaring %qD in module %qs conflicts with builtin "
+ "in global module", decl, new_mod->get_flatname ());
+  else
+   error_at (loc, "declaration %qD conflicts with builtin", decl);
+}
else if (DECL_LANG_SPECIFIC (old_inner) && DECL_MODULE_IMPORT_P (old_inner))
  {
auto_diagnostic_group d;
diff --git a/gcc/testsuite/g++.dg/modules/enum-12.C 
b/gcc/testsuite/g++.dg/modules/enum-12.C
index 064f220dedf..cf8f445e076 100644
--- a/gcc/testsuite/g++.dg/modules/enum-12.C
+++ b/gcc/testsuite/g++.dg/modules/enum-12.C
@@ -4,7 +4,7 @@
  
  export module foo;

  namespace std {
-  enum class align_val_t : decltype(sizeof(int)) {};  // { dg-error "conflicts with 
builtin" }
+  enum class align_val_t : decltype(sizeof(int)) {};  // { dg-error "in module 
.foo. conflicts with builtin" }
  }
  
  // { dg-prune-output "not writing module" }




Re: [PATCH] c++/modules: Improve diagnostic when redeclaring builtin in module [PR102345]

2024-05-24 Thread Jason Merrill

On 5/24/24 11:20, Nathaniel Shead wrote:

This is just a small improvement to a diagnostic.  I thought about also
adding an inform to suggest something like "standard library headers
should be included in the GMF" or somesuch, but I'm not sure that'll be
especially valuable and may be confusing if this particular error is
caused some other way.

Bootstrapped and regtested (so far just modules.exp) on
x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?

-- >8 --

If a user mistakenly includes a standard library header within the
module purview, they currently get a confusing "declaration conflicts
with builtin" error.  This patch updates the message to include "in
module", to help guide the user towards the likely cause.

gcc/cp/ChangeLog:

* module.cc (module_may_redeclare): Update error message.

gcc/testsuite/ChangeLog:

* g++.dg/modules/enum-12.C: Test for updated error.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc   | 9 -
  gcc/testsuite/g++.dg/modules/enum-12.C | 2 +-
  2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 6cd7d9e0b93..60cf3ebc468 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19140,7 +19140,14 @@ module_may_redeclare (tree olddecl, tree newdecl)
decl = newdecl ? newdecl : olddecl;
location_t loc = newdecl ? DECL_SOURCE_LOCATION (newdecl) : input_location;
if (DECL_IS_UNDECLARED_BUILTIN (olddecl))
-error_at (loc, "declaration %qD conflicts with builtin", decl);
+{
+  if (newdecl_attached_p)
+   error_at (loc, "declaring %qD in module %qs conflicts with builtin",


Maybe "with builtin in global module"?


+ decl, new_mod->get_flatname ());
+  else
+   error_at (loc, "declaring %qD in global module conflicts with builtin",


I'm not sure mentioning the global module adds anything in this case?

Jason



[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 }
+}


Re: [PATCH][14 backport] c++: Fix instantiation of imported temploid friends [PR114275]

2024-05-24 Thread Jason Merrill

On 5/24/24 10:40, Iain Sandoe wrote:




On 24 May 2024, at 14:54, Jason Merrill  wrote:

On 5/24/24 04:06, Nathaniel Shead wrote:

On Thu, May 23, 2024 at 06:41:06PM -0400, Jason Merrill wrote:

On 5/13/24 07:56, Nathaniel Shead wrote:

@@ -11751,9 +11767,16 @@ tsubst_friend_class (tree friend_tmpl, tree args)
  if (tmpl != error_mark_node)
{
  /* The new TMPL is not an instantiation of anything, so we
-forget its origins.  We don't reset CLASSTYPE_TI_TEMPLATE
+forget its origins.  It is also not a specialization of
+anything.  We don't reset CLASSTYPE_TI_TEMPLATE
 for the new type because that is supposed to be the
 corresponding template decl, i.e., TMPL.  */
+ spec_entry elt;
+ elt.tmpl = friend_tmpl;
+ elt.args = CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl));
+ elt.spec = TREE_TYPE (tmpl);
+ type_specializations->remove_elt ();


For GCC 14.2 let's guard this with if (modules_p ()); for GCC 15 it can be
unconditional.  OK.


I'm looking to backport this patch to GCC 14 now that it's been on trunk
some time.  Here's the patch I'm aiming to add (squashed with the
changes from r15-220-gec2365e07537e8) after cherrypicking the
prerequisite commit r15-58-g2faf040335f9b4; is this OK?

Or should I keep it as two separate commits to make the cherrypicking
more obvious? Not entirely sure on the etiquette around this.


It's OK to squash them, but it's typical to use -x (directly or via git
gcc-backport) to mention where a branch change was cherry-picked from, and
in this case it would make sense to edit in the second commit so it's clear
the backport includes both.  OK that way.

Sorry, still a bit confused :)  Do you mean to merge the two commits
together such that there are two "cherry picked from commit ..."s in the
commit message?  Or just list second commit, and mention that it
includes both in the commit message?


I was thinking

(cherry picked from commit a and b)


For the record, I do not think the git hooks with allow that exactly (or, at 
least, if they
do I did not find the right syntax);  what I’ve done in similar cases is to 
keep the main
“cherry picked from” line for the main patch and then add text to the intro 
section
saying that  and  are also included.


Looks like the git_commit.py regex "cherry picked from commit 
(?P\w+)" will ignore everything after the first commit-id, so it 
should be fine.  You just can't pluralize "commit" to "commits".  :)


Jason



Re: [PATCH] c++: extend -Wself-move for mem-init-list [PR109396]

2024-05-24 Thread Jason Merrill

On 5/23/24 19:57, Marek Polacek wrote:

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

-- >8 --
We already warn for:

   x = std::move (x);

which triggers:

   warning: moving 'x' of type 'int' to itself [-Wself-move]

but bug 109396 reports that this doesn't work for a member-initializer-list:

   X() : x(std::move (x))

so this patch amends that.

PR c++/109396

gcc/cp/ChangeLog:

* cp-tree.h (maybe_warn_self_move): Declare.
* init.cc (perform_member_init): Call maybe_warn_self_move.
* typeck.cc (maybe_warn_self_move): No longer static.  Change the
return type to bool.  Also warn when called from
a member-initializer-list.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wself-move2.C: New test.
---
  gcc/cp/cp-tree.h|  1 +
  gcc/cp/init.cc  |  5 ++--
  gcc/cp/typeck.cc| 28 +--
  gcc/testsuite/g++.dg/warn/Wself-move2.C | 37 +
  4 files changed, 60 insertions(+), 11 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wself-move2.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ba9e848c177..ea3fa6f4aac 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8263,6 +8263,7 @@ extern cp_expr build_c_cast   
(location_t loc, tree type,
 cp_expr expr);
  extern tree cp_build_c_cast   (location_t, tree, tree,
 tsubst_flags_t);
+extern bool maybe_warn_self_move   (location_t, tree, tree);
  extern cp_expr build_x_modify_expr(location_t, tree,
 enum tree_code, tree,
 tree, tsubst_flags_t);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 52396d87a8c..4a7ed7f5302 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -999,7 +999,7 @@ perform_member_init (tree member, tree init, hash_set 
)
if (decl == error_mark_node)
  return;
  
-  if ((warn_init_self || warn_uninitialized)

+  if ((warn_init_self || warn_uninitialized || warn_self_move)
&& init
&& TREE_CODE (init) == TREE_LIST
&& TREE_CHAIN (init) == NULL_TREE)
@@ -1013,7 +1013,8 @@ perform_member_init (tree member, tree init, hash_set 
)
warning_at (DECL_SOURCE_LOCATION (current_function_decl),
OPT_Winit_self, "%qD is initialized with itself",
member);
-  else
+  else if (!maybe_warn_self_move (input_location, member,
+ TREE_VALUE (init)))
find_uninit_fields (, , decl);
  }
  
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc

index d7fa6e0dd96..e058ce18276 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -9355,27 +9355,27 @@ cp_build_c_cast (location_t loc, tree type, tree expr,
  
  /* Warn when a value is moved to itself with std::move.  LHS is the target,

 RHS may be the std::move call, and LOC is the location of the whole
-   assignment.  */
+   assignment.  Return true if we warned.  */
  
-static void

+bool
  maybe_warn_self_move (location_t loc, tree lhs, tree rhs)
  {
if (!warn_self_move)
-return;
+return false;
  
/* C++98 doesn't know move.  */

if (cxx_dialect < cxx11)
-return;
+return false;
  
if (processing_template_decl)

-return;
+return false;
  
if (!REFERENCE_REF_P (rhs)

|| TREE_CODE (TREE_OPERAND (rhs, 0)) != CALL_EXPR)
-return;
+return false;
tree fn = TREE_OPERAND (rhs, 0);
if (!is_std_move_p (fn))
-return;
+return false;
  
/* Just a little helper to strip * and various NOPs.  */

auto extract_op = [] (tree ) {
@@ -9393,13 +9393,23 @@ maybe_warn_self_move (location_t loc, tree lhs, tree 
rhs)
tree type = TREE_TYPE (lhs);
tree orig_lhs = lhs;
extract_op (lhs);
-  if (cp_tree_equal (lhs, arg))
+  if (cp_tree_equal (lhs, arg)
+  /* Also warn in a member-initializer-list, as in : i(std::move(i)).  */
+  || (TREE_CODE (lhs) == FIELD_DECL
+ && TREE_CODE (arg) == COMPONENT_REF
+ && cp_tree_equal (TREE_OPERAND (arg, 0), current_class_ref)
+ && TREE_OPERAND (arg, 1) == lhs))
  {
auto_diagnostic_group d;
if (warning_at (loc, OPT_Wself_move,
  "moving %qE of type %qT to itself", orig_lhs, type))
-   inform (loc, "remove % call");
+   {
+ inform (loc, "remove % call");


The patch is OK, but why do we suggest removing std::move?  That just 
changes the warning to self-init.  Maybe drop the inform?


Jason



Re: [PATCH v2] c++/modules: Improve errors for bad module-directives [PR115200]

2024-05-24 Thread Jason Merrill

On 5/23/24 19:58, Nathaniel Shead wrote:

On Thu, May 23, 2024 at 05:11:39PM -0400, Jason Merrill wrote:

On 5/23/24 10:54, Nathaniel Shead wrote:

Bootstrapped and regtested (so far just modules.exp and dg.exp) on
x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?

-- >8 --

This fixes an ICE when a module directive is not given at global scope.
Although not explicitly mentioned, it seems implied from [basic.link] p1
and [module.global.frag] that a module-declaration must appear at the
global scope after preprocessing.  Apart from this the patch also
slightly improves the errors given when accidentally using a module
control-line in other situations where it is not expected.


This could also come up with something like

int module;
int i =
   module; // error, unexpected module directive

Adding a line break seems like confusing advice for this problem; rather,
they need to remove the line break before 'module'.  And possibly add it in
somewhere else, but the problem is that 'module' is the first token on the
line.  And if I put that in a namespace,

namespace A {
   int module;
   int i =
 module; // error, unexpected module directive
}

the problem is the same, but we get a different diagnostic.



True.

FWIW I just used the same wording as in 'cp_parser_import_declaration';
my understanding is it's because you can disambiguate by adding a
newline after the 'module' itself:

   int module;
   int i =
 module
 ;

is OK.  But I'll update this message to be clearer.


I think I'd leave the "must be at global scope" diagnostic to
cp_parser_module_declaration, and assume that if we see a module keyword at
function scope it wasn't intended to be a module directive.



How about this then? Bootstrapped and regtested on x86_64-pc-linux-gnu.


OK, thanks.


-- >8 --

This fixes an ICE when a module directive is not given at global scope.
Although not explicitly mentioned, it seems implied from [basic.link] p1
and [module.global.frag] that a module-declaration must appear at the
global scope after preprocessing.  Apart from this the patch also
slightly improves the errors given when accidentally using a module
control-line in other situations where it is not expected.

PR c++/115200

gcc/cp/ChangeLog:

* parser.cc (cp_parser_error_1): Special-case unexpected module
directives for better diagnostics.
(cp_parser_module_declaration): Check that the module
declaration is at global scope.
(cp_parser_import_declaration): Sync error message with that in
cp_parser_error_1.

gcc/testsuite/ChangeLog:

* g++.dg/modules/mod-decl-1.C: Update error messages.
* g++.dg/modules/mod-decl-6.C: New test.
* g++.dg/modules/mod-decl-7.C: New test.
* g++.dg/modules/mod-decl-8.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/parser.cc  | 26 ---
  gcc/testsuite/g++.dg/modules/mod-decl-1.C |  8 ---
  gcc/testsuite/g++.dg/modules/mod-decl-6.C | 11 ++
  gcc/testsuite/g++.dg/modules/mod-decl-7.C | 11 ++
  gcc/testsuite/g++.dg/modules/mod-decl-8.C | 14 
  5 files changed, 64 insertions(+), 6 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-6.C
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-7.C
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-8.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 476ddc0d63a..779625144db 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -3230,6 +3230,19 @@ cp_parser_error_1 (cp_parser* parser, const char* gmsgid,
return;
  }
  
+  if (cp_token_is_module_directive (token))

+{
+  auto_diagnostic_group d;
+  error_at (token->location, "unexpected module directive");
+  if (token->keyword != RID__EXPORT)
+   inform (token->location, "perhaps insert a line break after"
+   " %qs, or other disambiguation, to prevent this being"
+   " considered a module control-line",
+   (token->keyword == RID__MODULE) ? "module" : "import");
+  cp_parser_skip_to_pragma_eol (parser, token);
+  return;
+}
+
/* If this is actually a conflict marker, report it as such.  */
if (token->type == CPP_LSHIFT
|| token->type == CPP_RSHIFT
@@ -15135,12 +15148,19 @@ cp_parser_module_declaration (cp_parser *parser, 
module_parse mp_state,
parser->lexer->in_pragma = true;
cp_token *token = cp_lexer_consume_token (parser->lexer);
  
+  tree scope = current_scope ();

if (flag_header_unit)
  {
error_at (token->location,
"module-declaration not permitted in header-unit");
goto skip_eol;
  }
+  else if (scope != global_namespace)
+{
+  error_at (token->location, "module-declaration must be at global scope");

Re: [PATCH v2] c++: mark TARGET_EXPRs for function arguments eliding [PR114707]

2024-05-24 Thread Jason Merrill

On 5/23/24 20:32, Marek Polacek wrote:

On Thu, May 23, 2024 at 04:04:13PM -0400, Jason Merrill wrote:

On 5/23/24 10:41, Marek Polacek wrote:

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

-- >8 --
Coming back to our discussion in
<https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
TARGET_EXPRs that initialize a function argument are not marked
TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
on the floor.


But only if TREE_TYPE (TARGET_EXPR_INITIAL is non-void, I think we should
check that here too to be parallel.


Ah yes, definitely.
  

Perhaps most/all affected TARGET_EXPRs will have been handled earlier in the
function under the TREE_ADDRESSABLE check, but I wouldn't rely on that
without an assert.


So like this or you want an assert somewhere too?  dg.exp passed.

-- >8 --
Coming back to our discussion in
<https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
TARGET_EXPRs that initialize a function argument are not marked
TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
on the floor.  To work around it, I added a pset to
replace_placeholders_for_class_temp_r, but it would be best to just rely
on TARGET_EXPR_ELIDING_P.

PR c++/114707

gcc/cp/ChangeLog:

* call.cc (convert_for_arg_passing): Call set_target_expr_eliding.
* typeck2.cc (replace_placeholders_for_class_temp_r): Don't use pset.
(digest_nsdmi_init): Call cp_walk_tree_without_duplicates instead of
cp_walk_tree.
---
  gcc/cp/call.cc|  6 ++
  gcc/cp/typeck2.cc | 20 
  2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index ed68eb3c568..35c024f2c7c 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9437,6 +9437,12 @@ convert_for_arg_passing (tree type, tree val, 
tsubst_flags_t complain)
if (complain & tf_warning)
  warn_for_address_of_packed_member (type, val);
  
+  /* gimplify_arg elides TARGET_EXPRs that initialize a function argument.  */

+  if (TREE_CODE (val) == TARGET_EXPR)
+if (tree init = TARGET_EXPR_INITIAL (val))
+  if (!VOID_TYPE_P (TREE_TYPE (init)))


You can simplify this test to 'if (SIMPLE_TARGET_EXPR_P ...'.  OK with 
that change.


Jason



Re: [PATCH 1/2] c++/modules: Fix treatment of unnamed types

2024-05-24 Thread Jason Merrill

On 5/23/24 21:27, Nathaniel Shead wrote:

On Thu, May 23, 2024 at 03:36:48PM -0400, Jason Merrill wrote:

On 5/23/24 09:27, Nathaniel Shead wrote:

On Mon, May 20, 2024 at 06:00:09PM -0400, Jason Merrill wrote:

On 5/17/24 02:14, Nathaniel Shead wrote:

On Tue, May 14, 2024 at 06:21:48PM -0400, Jason Merrill wrote:

On 5/12/24 22:58, Nathaniel Shead wrote:

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


OK.



I realised as I was looking over this again that I might have spoken too
soon with the header unit example being supported. Doing the following:

 // a.H
 struct { int y; } s;
 decltype(s) f(decltype(s));  // { dg-error "used but never defined" }
 inline auto x = f({ 123 });
 // b.C
 struct {} unrelated;
 import "a.H";
 decltype(s) f(decltype(s) x) {
   return { 456 + x.y };
 }

 // c.C
 import "linkage-3_a.H";
 int main() { auto a = x.y; }

Actually does fail to link, because in 'c.C' we call 'f(.anon_0)' but
the definition 'b.C' is f(.anon_1).

I don't think this is fixable, so I don't think this direction is
workable.


Since namespace-scope anonymous types are TU-local, we don't need to support
that for proper modules, but it's not clear to me that we don't need to
support it for header units.

OTOH, https://eel.is/c++draft/module#import-5.3 allows c.C to import a
different header unit than b.C, in which case the type is different and x
violates the odr.



Right; I think at this stage I don't know how to support this for header
units (and even for module interface units it doesn't actually work;
more on this below), so I think saying that this is actually an ODR
violation is OK.


That said, I think that it might still be worth making header modules
satisfy 'module_has_cmi_p', since that is true to the name, and will be
useful in other places we currently use 'module_p ()': in which case we
could instead make all the callers in 'no_linkage_check' do
'module_maybe_has_cmi_p () && !header_module_p ()'; something like the
following, perhaps?


If we need that condition, it should be its own predicate rather than
expecting callers to do that combined check.

But it's not clear to me how this is different from a type in the GMF of a
named module, which is exactly the maybe_has_cmi case; there we could again
see a different version of the type if another TU includes the header.

Jason



This made me go back and double-check for named modules and it actually
does fail as well; the following sample ICEs, even:

export module M;
struct {} s;
int h(decltype(s));
int x = h(s);  // ICE in write_unnamed_type_name, cp/mangle.cc:1806

So I think maybe the way to go here is to just not treat unnamed types
as something that could possibly be accessed from a different TU, like
the below.  Then we don't need to do the special handling for header
units, since as you say, they're not materially different anyway.
Thoughts?


Sounds good.


(And I've moved the original change to 'module_has_cmi_p' to a separate
patch given it's somewhat unrelated now.)

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk (and
maybe 14.2)?

-- >8 --

In r14-9530 we relaxed "depending on type with no-linkage" errors for
declarations that could actually be accessed from different TUs anyway.
However, this also enabled it for unnamed types, which never work.

In a normal module interface, an unnamed type is TU-local by
[basic.link] p15.2, and so cannot be exposed or the program is
ill-formed.  We don't yet implement this checking but we should assume
that we will later; currently supporting this actually causes ICEs when
attempting to create the mangled name in some situations.

For a header unit, by [module.import] p5.3 it is unspecified whether two
TUs importing a header unit providing such a declaration are importing
the same header unit.  In this case, we would require name mangling
changes to somehow allow the (anonymous) type exported by such a header
unit to correspond across different TUs in the presence of other
anonymous declarations, so for this patch just assume that this case
would be an ODR violation instead.

diff --git a/gcc/testsuite/g++.dg/modules/linkage-2.C 
b/gcc/testsuite/g++.dg/modules/linkage-2.C
index eb4d7b051af..f69bd7ff728 100644
--- a/gcc/testsuite/g++.dg/modules/linkage-2.C
+++ b/gcc/testsuite/g++.dg/modules/linkage-2.C
@@ -13,14 +13,15 @@ namespace {
   return A{};
 }
 decltype(f()) g();  // { dg-error "used but never defined" }
-
-  struct {} s;
-  decltype(s) h();  // { dg-error "used but never defined" }
   }
   export void use() {
 g();
-  h();


The above changes seem undesirable; we should still give that error.



Oh whoops, I don't know why I got rid of those test cases; added back in
and they still correctly error.


+// Additionally, unnamed types have no linkage but are also TU-local,
+// and thus cannot 

Re: [PATCH][14 backport] c++: Fix instantiation of imported temploid friends [PR114275]

2024-05-24 Thread Jason Merrill

On 5/24/24 04:06, Nathaniel Shead wrote:

On Thu, May 23, 2024 at 06:41:06PM -0400, Jason Merrill wrote:

On 5/13/24 07:56, Nathaniel Shead wrote:

@@ -11751,9 +11767,16 @@ tsubst_friend_class (tree friend_tmpl, tree args)
  if (tmpl != error_mark_node)
{
  /* The new TMPL is not an instantiation of anything, so we
-forget its origins.  We don't reset CLASSTYPE_TI_TEMPLATE
+forget its origins.  It is also not a specialization of
+anything.  We don't reset CLASSTYPE_TI_TEMPLATE
 for the new type because that is supposed to be the
 corresponding template decl, i.e., TMPL.  */
+ spec_entry elt;
+ elt.tmpl = friend_tmpl;
+ elt.args = CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl));
+ elt.spec = TREE_TYPE (tmpl);
+ type_specializations->remove_elt ();


For GCC 14.2 let's guard this with if (modules_p ()); for GCC 15 it can be
unconditional.  OK.


I'm looking to backport this patch to GCC 14 now that it's been on trunk
some time.  Here's the patch I'm aiming to add (squashed with the
changes from r15-220-gec2365e07537e8) after cherrypicking the
prerequisite commit r15-58-g2faf040335f9b4; is this OK?

Or should I keep it as two separate commits to make the cherrypicking
more obvious? Not entirely sure on the etiquette around this.


It's OK to squash them, but it's typical to use -x (directly or via git
gcc-backport) to mention where a branch change was cherry-picked from, and
in this case it would make sense to edit in the second commit so it's clear
the backport includes both.  OK that way.


Sorry, still a bit confused :)  Do you mean to merge the two commits
together such that there are two "cherry picked from commit ..."s in the
commit message?  Or just list second commit, and mention that it
includes both in the commit message?


I was thinking

(cherry picked from commit a and b)

but the exact format doesn't matter, just looking for a mention of both 
commits.


Jason



[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};
+}


PING Re: PING Re: [PATCH RFA (cgraph)] c++: pragma target and static init [PR109753]

2024-05-23 Thread Jason Merrill

Ping

On 5/14/24 17:21, Jason Merrill wrote:

Ping

On 5/2/24 09:54, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu, OK for trunk?  14.2?

This two-year-old thread seems relevant:
https://gcc.gnu.org/pipermail/gcc-patches/2022-April/593410.html

-- 8< --

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

  functions.

At least one of the create_same_body_alias/handle_optimize_attribute 
changes

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/ChangeLog:

* cgraph.cc (cgraph_node::create_same_body_alias): Set
semantic_interposition.

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.
---
  gcc/c-family/c-attribs.cc | 4 
  gcc/cgraph.cc | 2 ++
  gcc/cp/decl.cc    | 3 +++
  gcc/testsuite/g++.dg/opt/always_inline1.C | 8 
  4 files changed, 17 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/opt/always_inline1.C

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/cgraph.cc b/gcc/cgraph.cc
index 473d8410bc9..f3bd2fa8ece 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -604,6 +604,8 @@ cgraph_node::create_same_body_alias (tree alias, 
tree decl)

    n = cgraph_node::create_alias (alias, decl);
    n->cpp_implicit_alias = true;
+  /* Aliases don't go through finalize_function.  */
+  n->semantic_interposition = opt_for_fn (decl, 
flag_semantic_interposition);

    if (symtab->cpp_implicit_aliases_done)
  n->resolve_alias (cgraph_node::get (decl));
    return n;
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 378311c0f04..4531d830462 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17796,6 +17796,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;

base-commit: 2f15787f2e1a3afe2c2ad93d4eb0d3c1f73c8fbd






Re: [PATCH][14 backport] c++: Fix instantiation of imported temploid friends [PR114275]

2024-05-23 Thread Jason Merrill

On 5/13/24 07:56, Nathaniel Shead wrote:

@@ -11751,9 +11767,16 @@ tsubst_friend_class (tree friend_tmpl, tree args)
 if (tmpl != error_mark_node)
{
  /* The new TMPL is not an instantiation of anything, so we
-forget its origins.  We don't reset CLASSTYPE_TI_TEMPLATE
+forget its origins.  It is also not a specialization of
+anything.  We don't reset CLASSTYPE_TI_TEMPLATE
 for the new type because that is supposed to be the
 corresponding template decl, i.e., TMPL.  */
+ spec_entry elt;
+ elt.tmpl = friend_tmpl;
+ elt.args = CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl));
+ elt.spec = TREE_TYPE (tmpl);
+ type_specializations->remove_elt ();


For GCC 14.2 let's guard this with if (modules_p ()); for GCC 15 it can be
unconditional.  OK.


I'm looking to backport this patch to GCC 14 now that it's been on trunk
some time.  Here's the patch I'm aiming to add (squashed with the
changes from r15-220-gec2365e07537e8) after cherrypicking the
prerequisite commit r15-58-g2faf040335f9b4; is this OK?

Or should I keep it as two separate commits to make the cherrypicking
more obvious? Not entirely sure on the etiquette around this.


It's OK to squash them, but it's typical to use -x (directly or via git 
gcc-backport) to mention where a branch change was cherry-picked from, 
and in this case it would make sense to edit in the second commit so 
it's clear the backport includes both.  OK that way.


Jason



Re: [PATCH] c++: alias CTAD and copy deduction guide [PR115198]

2024-05-23 Thread Jason Merrill

On 5/23/24 17:42, Patrick Palka wrote:

On Thu, 23 May 2024, Jason Merrill wrote:


On 5/23/24 14:06, Patrick Palka wrote:

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

-- >8 --

Here we're neglecting to update DECL_NAME during the alias CTAD guide
transformation, which causes copy_guide_p to return false for the
transformed copy deduction guide since DECL_NAME is still __dguide_C
with TREE_TYPE C but it should be __dguide_A with TREE_TYPE A
(equivalently C).  This ultimately results in ambiguity during
overload resolution between the copy deduction guide vs copy ctor guide.

This patch makes us update DECL_NAME of a transformed guide accordingly
during alias CTAD.  This eventually needs to be done for inherited CTAD
too, but it's not clear what identifier to use there since it has to be
unique for each derived/base pair.  For

template struct A { ... };
template struct B : A { using A::A; }

at first glance it'd be reasonable to give inherited guides a name of
__dguide_B with TREE_TYPE A, but since that name is already
used B's own guides its TREE_TYPE is already B.


Why can't it be the same __dguide_B with TREE_TYPE B?


Ah because copy_guide_p relies on TREE_TYPE in order to recognize a copy
deduction guide, and with that TREE_TYPE it would still incorrectly
return false for an inherited copy deduction guide, e.g.

   A(A) -> A

gets transformed into

   B(A) -> B

and A != B so copy_guide_p returns false.


Hmm, that seems correct; the transformed candidate is not the copy 
deduction guide for B.



But it just occurred to me that this TREE_TYPE clobbering of the
__dguide_foo identifier already happens if we have two class templates
with the same name in different namespaces, since the identifier
contains only the terminal name.  Maybe this suggests that we should
use a tree flag to track whether a guide is the copy deduction guide
instead of setting TREE_TYPE of DECL_NAME?


Good point.

Jason



Re: [PATCH] c++: alias CTAD and copy deduction guide [PR115198]

2024-05-23 Thread Jason Merrill

On 5/23/24 14:06, Patrick Palka wrote:

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

-- >8 --

Here we're neglecting to update DECL_NAME during the alias CTAD guide
transformation, which causes copy_guide_p to return false for the
transformed copy deduction guide since DECL_NAME is still __dguide_C
with TREE_TYPE C but it should be __dguide_A with TREE_TYPE A
(equivalently C).  This ultimately results in ambiguity during
overload resolution between the copy deduction guide vs copy ctor guide.

This patch makes us update DECL_NAME of a transformed guide accordingly
during alias CTAD.  This eventually needs to be done for inherited CTAD
too, but it's not clear what identifier to use there since it has to be
unique for each derived/base pair.  For

   template struct A { ... };
   template struct B : A { using A::A; }

at first glance it'd be reasonable to give inherited guides a name of
__dguide_B with TREE_TYPE A, but since that name is already
used B's own guides its TREE_TYPE is already B.


Why can't it be the same __dguide_B with TREE_TYPE B?


PR c++/115198

gcc/cp/ChangeLog:

* pt.cc (alias_ctad_tweaks): Update DECL_NAME of a transformed
guide during alias CTAD.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-alias22.C: New test.
---
  gcc/cp/pt.cc   |  9 -
  .../g++.dg/cpp2a/class-deduction-alias22.C | 14 ++
  2 files changed, 22 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 0c4d96cf768..58873057abc 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30304,13 +30304,14 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
   any).  */
  
enum { alias, inherited } ctad_kind;

-  tree atype, fullatparms, utype;
+  tree atype, fullatparms, utype, name;
if (TREE_CODE (tmpl) == TEMPLATE_DECL)
  {
ctad_kind = alias;
atype = TREE_TYPE (tmpl);
fullatparms = DECL_TEMPLATE_PARMS (tmpl);
utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+  name = dguide_name (tmpl);
  }
else
  {
@@ -30318,6 +30319,10 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
atype = NULL_TREE;
fullatparms = TREE_PURPOSE (tmpl);
utype = TREE_VALUE (tmpl);
+  /* FIXME: What name should we give inherited guides?  It needs to be
+unique to the derived/base pair so that we don't clobber an earlier
+setting of TREE_TYPE.  */
+  name = NULL_TREE;
  }
  
tsubst_flags_t complain = tf_warning_or_error;

@@ -30413,6 +30418,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
}
  if (g == error_mark_node)
continue;
+ if (name)
+   DECL_NAME (g) = name;
  if (nfparms == 0)
{
  /* The targs are all non-dependent, so g isn't a template.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
new file mode 100644
index 000..9c6c841166a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
@@ -0,0 +1,14 @@
+// PR c++/115198
+// { dg-do compile { target c++20 } }
+
+template
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+template
+using A = C;
+
+C c;
+A a = c; // { dg-bogus "ambiguous" }




Re: [PATCH] c++/modules: Improve errors for bad module-directives [PR115200]

2024-05-23 Thread Jason Merrill

On 5/23/24 10:54, Nathaniel Shead wrote:

Bootstrapped and regtested (so far just modules.exp and dg.exp) on
x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?

-- >8 --

This fixes an ICE when a module directive is not given at global scope.
Although not explicitly mentioned, it seems implied from [basic.link] p1
and [module.global.frag] that a module-declaration must appear at the
global scope after preprocessing.  Apart from this the patch also
slightly improves the errors given when accidentally using a module
control-line in other situations where it is not expected.


This could also come up with something like

int module;
int i =
  module; // error, unexpected module directive

Adding a line break seems like confusing advice for this problem; 
rather, they need to remove the line break before 'module'.  And 
possibly add it in somewhere else, but the problem is that 'module' is 
the first token on the line.  And if I put that in a namespace,


namespace A {
  int module;
  int i =
module; // error, unexpected module directive
}

the problem is the same, but we get a different diagnostic.

I think I'd leave the "must be at global scope" diagnostic to 
cp_parser_module_declaration, and assume that if we see a module keyword 
at function scope it wasn't intended to be a module directive.



PR c++/115200

gcc/cp/ChangeLog:

* parser.cc (cp_parser_error_1): Special-case unexpected module
directives for better diagnostics.
(cp_parser_module_declaration): Check that the module
declaration is at global scope.

gcc/testsuite/ChangeLog:

* g++.dg/modules/mod-decl-1.C: Update error messages.
* g++.dg/modules/mod-decl-6.C: New test.
* g++.dg/modules/mod-decl-7.C: New test.
* g++.dg/modules/mod-decl-8.C: New test.
* g++.dg/modules/mod-decl-8.h: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/parser.cc  | 32 +++
  gcc/testsuite/g++.dg/modules/mod-decl-1.C |  6 ++---
  gcc/testsuite/g++.dg/modules/mod-decl-6.C | 11 
  gcc/testsuite/g++.dg/modules/mod-decl-7.C | 12 +
  gcc/testsuite/g++.dg/modules/mod-decl-8.C |  9 +++
  gcc/testsuite/g++.dg/modules/mod-decl-8.h |  4 +++
  6 files changed, 71 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-6.C
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-7.C
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-8.C
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-decl-8.h

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 476ddc0d63a..1c0543ba154 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -3230,6 +3230,31 @@ cp_parser_error_1 (cp_parser* parser, const char* gmsgid,
return;
  }
  
+  if (cp_token_is_module_directive (token))

+{
+  cp_token *next = (token->keyword == RID__EXPORT
+   ? cp_lexer_peek_nth_token (parser->lexer, 2) : token);
+
+  auto_diagnostic_group d;
+  error_at (token->location, "unexpected module directive");
+  tree scope = current_scope ();
+  if (next->keyword == RID__MODULE
+ && token->main_source_p
+ && scope != global_namespace)
+   {
+ /* Nicer error for unterminated scopes in GMF includes.  */
+ inform (token->location,
+ "module-declaration must be at global scope");
+ inform (location_of (scope), "scope opened here");
+   }
+  else
+   inform (token->location, "perhaps insert a line break, or other"
+   " disambiguation, to prevent this being considered a"
+   " module control-line");
+  cp_parser_skip_to_pragma_eol (parser, token);
+  return;
+}
+
/* If this is actually a conflict marker, report it as such.  */
if (token->type == CPP_LSHIFT
|| token->type == CPP_RSHIFT
@@ -15135,12 +15160,19 @@ cp_parser_module_declaration (cp_parser *parser, 
module_parse mp_state,
parser->lexer->in_pragma = true;
cp_token *token = cp_lexer_consume_token (parser->lexer);
  
+  tree scope = current_scope ();

if (flag_header_unit)
  {
error_at (token->location,
"module-declaration not permitted in header-unit");
goto skip_eol;
  }
+  else if (scope != global_namespace)
+{
+  error_at (token->location, "module-declaration must be at global scope");
+  inform (DECL_SOURCE_LOCATION (scope), "scope opened here");
+  goto skip_eol;
+}
else if (mp_state == MP_FIRST && !exporting
&& cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
  {
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-1.C 
b/gcc/testsuite/g++.dg/modules/mod-decl-1.C
index 23d34483dd7..84fa31c7024 100644
--- a/gcc/testsuite/g++.dg/modules/mod-decl-1.C
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-1.C
@@ -10,17 +10,17 @@ module foo.second; // { dg-error "only permitted as" }
  
  namespace Foo

  {

[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 }
+}


[pushed] c++: deleting array temporary [PR115187]

2024-05-23 Thread Jason Merrill
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

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.
---
 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(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C

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 }
+}

base-commit: 0b3b6a8df77b0ae15078402ea5fb933d6fccd585
-- 
2.44.0



Re: [PATCH] c++: mark TARGET_EXPRs for function arguments eliding [PR114707]

2024-05-23 Thread Jason Merrill

On 5/23/24 10:41, Marek Polacek wrote:

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

-- >8 --
Coming back to our discussion in
:
TARGET_EXPRs that initialize a function argument are not marked
TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
on the floor.


But only if TREE_TYPE (TARGET_EXPR_INITIAL is non-void, I think we 
should check that here too to be parallel.


Perhaps most/all affected TARGET_EXPRs will have been handled earlier in 
the function under the TREE_ADDRESSABLE check, but I wouldn't rely on 
that without an assert.



To work around it, I added a pset to
replace_placeholders_for_class_temp_r, but it would be best to just rely
on TARGET_EXPR_ELIDING_P.

This patch changes the diagnostic we emit in constexpr-diag1.C: instead
of:

constexpr-diag1.C:20:21: error: temporary of non-literal type 'B' in a constant 
expression

we say:

constexpr-diag1.C:20:23: error: call to non-'constexpr' function 'B::B()'

PR c++/114707

gcc/cp/ChangeLog:

* call.cc (convert_for_arg_passing): Call set_target_expr_eliding.
* typeck2.cc (replace_placeholders_for_class_temp_r): Don't use pset.
(digest_nsdmi_init): Call cp_walk_tree_without_duplicates instead of
cp_walk_tree.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-diag1.C: Adjust dg-error.
---
  gcc/cp/call.cc   |  3 +++
  gcc/cp/typeck2.cc| 20 
  gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C |  2 +-
  3 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index ed68eb3c568..750ecf60fd9 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9437,6 +9437,9 @@ convert_for_arg_passing (tree type, tree val, 
tsubst_flags_t complain)
if (complain & tf_warning)
  warn_for_address_of_packed_member (type, val);
  
+  /* gimplify_arg elides TARGET_EXPRs that initialize a function argument.  */

+  set_target_expr_eliding (val);
+
return val;
  }
  
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc

index 06bad4d3303..7782f38da43 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1409,16 +1409,14 @@ digest_init_flags (tree type, tree init, int flags, 
tsubst_flags_t complain)
 in the context of guaranteed copy elision).  */
  
  static tree

-replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
+replace_placeholders_for_class_temp_r (tree *tp, int *, void *)
  {
tree t = *tp;
-  auto pset = static_cast *>(data);
  
/* We're looking for a TARGET_EXPR nested in the whole expression.  */

if (TREE_CODE (t) == TARGET_EXPR
/* That serves as temporary materialization, not an initializer.  */
-  && !TARGET_EXPR_ELIDING_P (t)
-  && !pset->add (t))
+  && !TARGET_EXPR_ELIDING_P (t))
  {
tree init = TARGET_EXPR_INITIAL (t);
while (TREE_CODE (init) == COMPOUND_EXPR)
@@ -1433,16 +1431,6 @@ replace_placeholders_for_class_temp_r (tree *tp, int *, 
void *data)
  gcc_checking_assert (!find_placeholders (init));
}
  }
-  /* TARGET_EXPRs initializing function arguments are not marked as eliding,
- even though gimplify_arg drops them on the floor.  Don't go replacing
- placeholders in them.  */
-  else if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
-for (int i = 0; i < call_expr_nargs (t); ++i)
-  {
-   tree arg = get_nth_callarg (t, i);
-   if (TREE_CODE (arg) == TARGET_EXPR && !TARGET_EXPR_ELIDING_P (arg))
- pset->add (arg);
-  }
  
return NULL_TREE;

  }
@@ -1490,8 +1478,8 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t 
complain)
   temporary materialization does not occur when initializing an object
   from a prvalue of the same type, therefore we must not replace the
   placeholder with a temporary object so that it can be elided.  */
-  hash_set pset;
-  cp_walk_tree (, replace_placeholders_for_class_temp_r, , nullptr);
+  cp_walk_tree_without_duplicates (, 
replace_placeholders_for_class_temp_r,
+  nullptr);
  
return init;

  }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
index ccb8d81adca..da6fc2030bc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
@@ -17,4 +17,4 @@ constexpr int b = A().f();   // { dg-error "" }
  
  template 

  constexpr int f (T t) { return 42; }
-constexpr int x = f(B());   // { dg-error "non-literal" }
+constexpr int x = f(B());   // { dg-error "call to non-.constexpr." }

base-commit: 2b2476d4d18c92b8aba3567ebccd2100c2f7c258




Re: [PATCH] c++/modules: Ensure all partial specialisations are tracked [PR114947]

2024-05-23 Thread Jason Merrill

On 5/12/24 09:29, Nathaniel Shead wrote:

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

-- >8 --

Constrained partial specialisations aren't all necessarily tracked on
the instantiation table.  The modules code uses a separate
'partial_specializations' table to track them instead to ensure that
they get walked and emitted when emitting a module, but currently this
does not always happen.

The attached testcase fails in two ways.  First, because the partial
specialisation is just a declaration (and not a definition),
'set_defining_module' never ends up getting called on it and so it never
gets added to the partial specialisation table.  We fix this by ensuring
that when partial specializations are created they always get added, and
so we never miss one. To prevent adding partial specialisations multiple
times we split this out as a new function.


Hmm, I wonder if it would make sense to move 
DECL_TEMPLATE_SPECIALIZATIONS from the template's DECL_SIZE into a hash 
table that the modules code could walk instead of managing its own 
separate table?


The patch is OK.


The second way it fails is that when exporting the primary interface for
a module with partitions, we also re-walk the specializations of all
imported partitions to merge them into a single BMI.  So this patch
ensures that after calling 'match_mergeable_specialization' we also
ensure that if the name came from a partition it gets added to the
specialization table so that a dependency is correctly created for it.

PR c++/114947

gcc/cp/ChangeLog:

* cp-tree.h (set_defining_module_for_partial_spec): Declare.
* module.cc (trees_in::decl_value): Track partial specs coming
from partitions.
(set_defining_module): Don't track partial specialisations here
anymore.
(set_defining_module_for_partial_spec): New function.
* pt.cc (process_partial_specialization): Call it.

gcc/testsuite/ChangeLog:

* g++.dg/modules/partial-4_a.C: New test.
* g++.dg/modules/partial-4_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/cp-tree.h   |  1 +
  gcc/cp/module.cc   | 22 ++
  gcc/cp/pt.cc   |  2 ++
  gcc/testsuite/g++.dg/modules/partial-4_a.C |  8 
  gcc/testsuite/g++.dg/modules/partial-4_b.C |  5 +
  5 files changed, 34 insertions(+), 4 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/partial-4_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/partial-4_b.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index db098c32f2d..2580bf05fb2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7418,6 +7418,7 @@ extern unsigned get_importing_module (tree, bool = false) 
ATTRIBUTE_PURE;
  /* Where current instance of the decl got declared/defined/instantiated.  */
  extern void set_instantiating_module (tree);
  extern void set_defining_module (tree);
+extern void set_defining_module_for_partial_spec (tree);
  extern void maybe_key_decl (tree ctx, tree decl);
  extern void propagate_defining_module (tree decl, tree orig);
  extern void remove_defining_module (tree decl);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 520dd710549..3ca963cb3e9 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8416,6 +8416,11 @@ trees_in::decl_value ()
  add_mergeable_specialization (!is_type, , decl, spec_flags);
}
  
+  /* When making a CMI from a partition we're going to need to walk partial

+specializations again, so make sure they're tracked.  */
+  if (state->is_partition () && (spec_flags & 2))
+   set_defining_module_for_partial_spec (inner);
+
if (NAMESPACE_SCOPE_P (decl)
  && (mk == MK_named || mk == MK_unique
  || mk == MK_enum || mk == MK_friend_spec)
@@ -19246,13 +19251,22 @@ set_defining_module (tree decl)
  vec_safe_push (class_members, decl);
}
}
-  else if (DECL_IMPLICIT_TYPEDEF_P (decl)
-  && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
-   /* This is a partial or explicit specialization.  */
-   vec_safe_push (partial_specializations, decl);
  }
  }
  
+/* Also remember DECL if it's a newly declared class template partial

+   specialization, because these are not necessarily added to the
+   instantiation tables.  */
+
+void
+set_defining_module_for_partial_spec (tree decl)
+{
+  if (module_p ()
+  && DECL_IMPLICIT_TYPEDEF_P (decl)
+  && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+vec_safe_push (partial_specializations, decl);
+}
+
  void
  set_originating_module (tree decl, bool friend_p ATTRIBUTE_UNUSED)
  {
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1816bfd1f40..6d33bac90b0 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -5456,6 +5456,8 @@ process_partial_specialization (tree decl)
gcc_checking_assert (!TI_PARTIAL_INFO (tinfo));
TI_PARTIAL_INFO (tinfo) 

Re: [PATCH 2/2] c++/modules: Remember that header units have CMIs

2024-05-23 Thread Jason Merrill

On 5/23/24 09:29, Nathaniel Shead wrote:

And here's that patch.  As far as I can tell there should be no visible
change anymore, so there aren't any testcases.

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


OK.


-- >8 --

This appears to be an oversight in the definition of module_has_cmi_p.
This change will allow us to use the function directly in more places
that need to additional work only if generating a module CMI in the
future, allowing us to do additional work only when we know we need it.

gcc/cp/ChangeLog:

* cp-tree.h (module_has_cmi_p): Also include header units.
(module_maybe_has_cmi_p): Update comment.
* module.cc (set_defining_module): Only need to track
declarations for later exporting if the module may have a CMI.
* name-lookup.cc (pushdecl): Likewise.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/cp-tree.h  | 7 +++
  gcc/cp/module.cc  | 2 +-
  gcc/cp/name-lookup.cc | 2 +-
  3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ba9e848c177..9472759d3c8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7381,7 +7381,7 @@ inline bool module_interface_p ()
  inline bool module_partition_p ()
  { return module_kind & MK_PARTITION; }
  inline bool module_has_cmi_p ()
-{ return module_kind & (MK_INTERFACE | MK_PARTITION); }
+{ return module_kind & (MK_INTERFACE | MK_PARTITION | MK_HEADER); }
  
  inline bool module_purview_p ()

  { return module_kind & MK_PURVIEW; }
@@ -7393,9 +7393,8 @@ inline bool named_module_purview_p ()
  inline bool named_module_attach_p ()
  { return named_module_p () && module_attach_p (); }
  
-/* We don't know if this TU will have a CMI while parsing the GMF,

-   so tentatively assume that it might, for the purpose of determining
-   whether no-linkage decls could be used by an importer.  */
+/* Like module_has_cmi_p, but tentatively assumes that this TU may have a
+   CMI if we haven't seen the module-declaration yet.  */
  inline bool module_maybe_has_cmi_p ()
  { return module_has_cmi_p () || (named_module_p () && !module_purview_p ()); }
  
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc

index 520dd710549..8639ed6f1a2 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19216,7 +19216,7 @@ set_defining_module (tree decl)
gcc_checking_assert (!DECL_LANG_SPECIFIC (decl)
   || !DECL_MODULE_IMPORT_P (decl));
  
-  if (module_p ())

+  if (module_maybe_has_cmi_p ())
  {
/* We need to track all declarations within a module, not just those
 in the module purview, because we don't necessarily know yet if
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 78f08acffaa..f1f8c19feb1 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -4103,7 +4103,7 @@ pushdecl (tree decl, bool hiding)
  
  	  if (level->kind == sk_namespace

  && TREE_PUBLIC (level->this_entity)
- && module_p ())
+ && module_maybe_has_cmi_p ())
maybe_record_mergeable_decl (slot, name, decl);
}
  }




Re: [PATCH 1/2] c++/modules: Fix treatment of unnamed types

2024-05-23 Thread Jason Merrill

On 5/23/24 09:27, Nathaniel Shead wrote:

On Mon, May 20, 2024 at 06:00:09PM -0400, Jason Merrill wrote:

On 5/17/24 02:14, Nathaniel Shead wrote:

On Tue, May 14, 2024 at 06:21:48PM -0400, Jason Merrill wrote:

On 5/12/24 22:58, Nathaniel Shead wrote:

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


OK.



I realised as I was looking over this again that I might have spoken too
soon with the header unit example being supported. Doing the following:

// a.H
struct { int y; } s;
decltype(s) f(decltype(s));  // { dg-error "used but never defined" }
inline auto x = f({ 123 });
// b.C
struct {} unrelated;
import "a.H";
decltype(s) f(decltype(s) x) {
  return { 456 + x.y };
}

// c.C
import "linkage-3_a.H";
int main() { auto a = x.y; }

Actually does fail to link, because in 'c.C' we call 'f(.anon_0)' but
the definition 'b.C' is f(.anon_1).

I don't think this is fixable, so I don't think this direction is
workable.


Since namespace-scope anonymous types are TU-local, we don't need to support
that for proper modules, but it's not clear to me that we don't need to
support it for header units.

OTOH, https://eel.is/c++draft/module#import-5.3 allows c.C to import a
different header unit than b.C, in which case the type is different and x
violates the odr.



Right; I think at this stage I don't know how to support this for header
units (and even for module interface units it doesn't actually work;
more on this below), so I think saying that this is actually an ODR
violation is OK.


That said, I think that it might still be worth making header modules
satisfy 'module_has_cmi_p', since that is true to the name, and will be
useful in other places we currently use 'module_p ()': in which case we
could instead make all the callers in 'no_linkage_check' do
'module_maybe_has_cmi_p () && !header_module_p ()'; something like the
following, perhaps?


If we need that condition, it should be its own predicate rather than
expecting callers to do that combined check.

But it's not clear to me how this is different from a type in the GMF of a
named module, which is exactly the maybe_has_cmi case; there we could again
see a different version of the type if another TU includes the header.

Jason



This made me go back and double-check for named modules and it actually
does fail as well; the following sample ICEs, even:

   export module M;
   struct {} s;
   int h(decltype(s));
   int x = h(s);  // ICE in write_unnamed_type_name, cp/mangle.cc:1806

So I think maybe the way to go here is to just not treat unnamed types
as something that could possibly be accessed from a different TU, like
the below.  Then we don't need to do the special handling for header
units, since as you say, they're not materially different anyway.
Thoughts?


Sounds good.


(And I've moved the original change to 'module_has_cmi_p' to a separate
patch given it's somewhat unrelated now.)

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk (and
maybe 14.2)?

-- >8 --

In r14-9530 we relaxed "depending on type with no-linkage" errors for
declarations that could actually be accessed from different TUs anyway.
However, this also enabled it for unnamed types, which never work.

In a normal module interface, an unnamed type is TU-local by
[basic.link] p15.2, and so cannot be exposed or the program is
ill-formed.  We don't yet implement this checking but we should assume
that we will later; currently supporting this actually causes ICEs when
attempting to create the mangled name in some situations.

For a header unit, by [module.import] p5.3 it is unspecified whether two
TUs importing a header unit providing such a declaration are importing
the same header unit.  In this case, we would require name mangling
changes to somehow allow the (anonymous) type exported by such a header
unit to correspond across different TUs in the presence of other
anonymous declarations, so for this patch just assume that this case
would be an ODR violation instead.

diff --git a/gcc/testsuite/g++.dg/modules/linkage-2.C 
b/gcc/testsuite/g++.dg/modules/linkage-2.C
index eb4d7b051af..f69bd7ff728 100644
--- a/gcc/testsuite/g++.dg/modules/linkage-2.C
+++ b/gcc/testsuite/g++.dg/modules/linkage-2.C
@@ -13,14 +13,15 @@ namespace {
  return A{};
}
decltype(f()) g();  // { dg-error "used but never defined" }
-
-  struct {} s;
-  decltype(s) h();  // { dg-error "used but never defined" }
  }
  
  export void use() {

g();
-  h();


The above changes seem undesirable; we should still give that error.


+// Additionally, unnamed types have no linkage but are also TU-local,
+// and thus cannot be in a module interface unit.
+// We don't yet implement this checking however.
+struct {} s;  // { dg-error "TU-local" "" { xfail *-*-* } }


The comment should clarify that the problem is the non-TU-local var

Re: [PATCH v4] c++: fix constained auto deduction in templ spec scopes [PR114915]

2024-05-22 Thread Jason Merrill

OK, on the right patch this time I hope.

Looks like you still need either FSF copyright assignment or DCO 
certification per https://gcc.gnu.org/contribute.html#legal


On 5/15/24 13:27, Seyed Sajad Kahani wrote:

This patch resolves PR114915 by replacing the logic that fills in the
missing levels in do_auto_deduction in cp/pt.cc.


I miss the text in your original patch that explained the problem more.


The new approach now trims targs if the depth of targs is deeper than desired
(this will only happen in specific contexts), and still fills targs with empty
layers if it has fewer depths than expected.

PR c++/114915


This line needs to start with a tab.


gcc/cp/ChangeLog:

* pt.cc (do_auto_deduction): Handle excess outer template
arguments during constrained auto satisfaction.


This one, too.  These issues are flagged by git gcc-verify, and are 
easier to avoid with git gcc-commit-mklog.



gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-placeholder14.C: New test.
* g++.dg/cpp2a/concepts-placeholder15.C: New test.


This test still needs a variable template partial specialization.

A few coding style nits below.


* g++.dg/cpp2a/concepts-placeholder16.C: New test.
---
  gcc/cp/pt.cc  | 20 ---
  .../g++.dg/cpp2a/concepts-placeholder14.C | 19 +++
  .../g++.dg/cpp2a/concepts-placeholder15.C | 15 +
  .../g++.dg/cpp2a/concepts-placeholder16.C | 33 +++
  4 files changed, 83 insertions(+), 4 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 32640f8e9..ecfda67aa 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -31253,6 +31253,19 @@ do_auto_deduction (tree type, tree init, tree 
auto_node,
full_targs = add_outermost_template_args (tmpl, full_targs);
full_targs = add_to_template_args (full_targs, targs);
  
+  int want = TEMPLATE_TYPE_ORIG_LEVEL (auto_node);

+  int have = TMPL_ARGS_DEPTH (full_targs);
+
+  if (want < have)
+   {
+ // if a constrained auto is declared in an explicit specialization


We generally use C-style /* */ comments, that start with a capital 
letter and end with a period.



+ gcc_assert (context == adc_variable_type || context == adc_return_type
+ || context == adc_decomp_type);


The || should line up with the 'c' on the previous line.


+ tree trimmed_full_args = get_innermost_template_args
+   (full_targs, want);


We try to avoid having arguments to the left of the function name; here 
I'd start the new line with the = instead.



+ full_targs = trimmed_full_args;
+   }
+


Unnecessary tab on this line.


/* HACK: Compensate for callers not always communicating all levels of
 outer template arguments by filling in the outermost missing levels
 with dummy levels before checking satisfaction.  We'll still crash
@@ -31260,11 +31273,10 @@ do_auto_deduction (tree type, tree init, tree 
auto_node,
 these missing levels, but this hack otherwise allows us to handle a
 large subset of possible constraints (including all non-dependent
 constraints).  */
-  if (int missing_levels = (TEMPLATE_TYPE_ORIG_LEVEL (auto_node)
-   - TMPL_ARGS_DEPTH (full_targs)))
+  if (want > have)
{
- tree dummy_levels = make_tree_vec (missing_levels);
- for (int i = 0; i < missing_levels; ++i)
+ tree dummy_levels = make_tree_vec (want - have);
+ for (int i = 0; i < want - have; ++i)
TREE_VEC_ELT (dummy_levels, i) = make_tree_vec (0);
  full_targs = add_to_template_args (dummy_levels, full_targs);
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C
new file mode 100644
index 0..fcdbd7608
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C
@@ -0,0 +1,19 @@
+// PR c++/114915
+// { dg-do compile { target c++20 } }
+
+template
+concept C = __is_same(T, int);
+
+template
+void f() {
+}
+
+template<>
+void f() {
+  C auto x = 1;
+}
+
+int main() {
+  f();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C
new file mode 100644
index 0..b4f73f407
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C
@@ -0,0 +1,15 @@
+// PR c++/114915
+// { dg-do compile { target c++20 } }
+
+template
+concept C = __is_same(T, U);
+
+template
+int x = 0;
+
+template<>
+C auto x = 1.0;
+
+int main() {
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C
new file 

Re: [PATCH] Fix auto deduction for template specialization scopes [114915].

2024-05-22 Thread Jason Merrill

On 5/22/24 12:48, Patrick Palka wrote:

On Wed, 22 May 2024, Jason Merrill wrote:


Thanks for the patch!

Please review https://gcc.gnu.org/contribute.html for more details of the
format patches should have.  In particular, you don't seem to have a copyright
assignment on file with the FSF, so you'll need to either do that or certify
that the contribution is under the DCO.

Also, you need a component tag (c++:) in the subject line, and ChangeLog
entries in the commit message.  Note what contribute.html says about git
gcc-commit-mklog, which makes that a lot simpler.

On 5/1/24 18:52, Seyed Sajad Kahani wrote:

When deducing auto for `adc_return_type`, `adc_variable_type`, and
`adc_decomp_type` contexts (at the usage time), we try to resolve the
outermost template arguments to be used for satisfaction. This is done by
one of the following, depending on the scope:

1. Checking the `DECL_TEMPLATE_INFO` of the current function scope and
extracting DECL_TI_ARGS from it for function scope deductions (pt.cc:31236).
2. Checking the `DECL_TEMPLATE_INFO` of the declaration (alongside with
other conditions) for non-function scope variable declaration deductions
(decl.cc:8527).

Then, we do not retrieve the deeper layers of the template arguments;
instead, we fill the missing levels with dummy levels (pt.cc:31260).

The problem (that is shown in PR114915) is that we do not consider the case
where the deduction happens in a template specialization scope. In this
case, the type is not dependent on the outermost template arguments (which
are the specialization arguments). Yet, we still resolve the outermost
template arguments, and then the number of layers in the template arguments
exceeds the number of levels in the type. This causes the missing levels to
be negative. This leads to the rejection of valid code and ICEs (like
segfault) in the release mode. In the debug mode, it is possible to show as
an assertion failure (when creating a tree_vec with a negative size).
The code that generates the issue is added to the test suite as
`g++.dg/cpp2a/concepts-placeholder14.C`.


This testcase could use more cases, like variable template specialization
(both full and partial) and member functions where not all enclosing classes
are fully specialized.


Note I think the latest version of the patch is
https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651805.html


Oops, thanks!


which has more test coverage and takes a more context oblivious approach
that keeps the innermost arguments if there's an excess, based on some
earlier discussion e.g.
https://gcc.gnu.org/pipermail/gcc-patches/2024-May/650834.html
This should do the right thing at least until we implement explicit
specializations in template scope (CWG 727)




This patch fixes the issue by checking that the template usage, whose
arguments are going to be used for satisfaction, is not a partial or
explicit specialization (and therefore it is an implicit or explicit
instantiation). This check is done in the two only places that affect the
`outer_targs` for the mentioned contexts.


It seems like we want a function to use instead of DECL_TI_ARGS to get the
args for parameters that are actually in scope in the definition that we're
substituting into.  In the case of a full specialization, that would be
NULL_TREE, but it's more complicated for partial specializations.

This function should probably go after outer_template_args in pt.cc.


One might ask why this is not implemented as a simple `missing_level > 0`
check. The reason is that the recovery from the negative `missing_levels`
will not be easy, and it is not clear how to recover from it. Therefore, it
is better to prevent it from happening.


But you still have that check in the patch.  Would it be better as an assert?

Thanks,
Jason








Re: [PATCH] Fix auto deduction for template specialization scopes [114915].

2024-05-22 Thread Jason Merrill

Thanks for the patch!

Please review https://gcc.gnu.org/contribute.html for more details of 
the format patches should have.  In particular, you don't seem to have a 
copyright assignment on file with the FSF, so you'll need to either do 
that or certify that the contribution is under the DCO.


Also, you need a component tag (c++:) in the subject line, and ChangeLog 
entries in the commit message.  Note what contribute.html says about git 
gcc-commit-mklog, which makes that a lot simpler.


On 5/1/24 18:52, Seyed Sajad Kahani wrote:

When deducing auto for `adc_return_type`, `adc_variable_type`, and 
`adc_decomp_type` contexts (at the usage time), we try to resolve the outermost 
template arguments to be used for satisfaction. This is done by one of the 
following, depending on the scope:

1. Checking the `DECL_TEMPLATE_INFO` of the current function scope and 
extracting DECL_TI_ARGS from it for function scope deductions (pt.cc:31236).
2. Checking the `DECL_TEMPLATE_INFO` of the declaration (alongside with other 
conditions) for non-function scope variable declaration deductions 
(decl.cc:8527).

Then, we do not retrieve the deeper layers of the template arguments; instead, 
we fill the missing levels with dummy levels (pt.cc:31260).

The problem (that is shown in PR114915) is that we do not consider the case 
where the deduction happens in a template specialization scope. In this case, 
the type is not dependent on the outermost template arguments (which are the 
specialization arguments). Yet, we still resolve the outermost template 
arguments, and then the number of layers in the template arguments exceeds the 
number of levels in the type. This causes the missing levels to be negative. 
This leads to the rejection of valid code and ICEs (like segfault) in the 
release mode. In the debug mode, it is possible to show as an assertion failure 
(when creating a tree_vec with a negative size).
The code that generates the issue is added to the test suite as 
`g++.dg/cpp2a/concepts-placeholder14.C`.


This testcase could use more cases, like variable template 
specialization (both full and partial) and member functions where not 
all enclosing classes are fully specialized.



This patch fixes the issue by checking that the template usage, whose arguments 
are going to be used for satisfaction, is not a partial or explicit 
specialization (and therefore it is an implicit or explicit instantiation). 
This check is done in the two only places that affect the `outer_targs` for the 
mentioned contexts.


It seems like we want a function to use instead of DECL_TI_ARGS to get 
the args for parameters that are actually in scope in the definition 
that we're substituting into.  In the case of a full specialization, 
that would be NULL_TREE, but it's more complicated for partial 
specializations.


This function should probably go after outer_template_args in pt.cc.


One might ask why this is not implemented as a simple `missing_level > 0` 
check. The reason is that the recovery from the negative `missing_levels` will not 
be easy, and it is not clear how to recover from it. Therefore, it is better to 
prevent it from happening.


But you still have that check in the patch.  Would it be better as an 
assert?


Thanks,
Jason



[PATCH RFC] c++: add module extensions

2024-05-22 Thread Jason Merrill
Tested x86_64-pc-linux-gnu.  Any thoughts about the mkdeps output?

-- 8< --

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

.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++ will use .ccm for parallel consistency?

One issue with .c++m is that libcpp/mkdeps.cc uses it for the phony
dependencies to express module dependencies, so I'm disabling that one for
now.  We probably want to change the extension that mkdeps uses to something
less likely to be an actual file, say .module? .c++-module?

gcc/cp/ChangeLog:

* lang-specs.h: Add module interface extensions.
---
 gcc/cp/lang-specs.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index 7a7f5ff0ab5..74b450fd66e 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -39,6 +39,14 @@ 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.  Do we also want a .C counterpart?
+ Skipping .c++m for now at least to avoid conflicts with .PHONY .c++m
+ files in mkdeps.cc output.  */
+  {".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)}"

base-commit: 1a5e4dd83788ea4c049d354d83ad58a6a3d747e6
prerequisite-patch-id: 3c000c95725bc74cff0b0e33fac97055caa64e7e
-- 
2.44.0



Re: [PATCH] c++: canonicity of fn types w/ complex eh specs [PR115159]

2024-05-22 Thread Jason Merrill

On 5/22/24 09:01, Patrick Palka wrote:

On Tue, 21 May 2024, Jason Merrill wrote:


On 5/21/24 21:55, Patrick Palka wrote:

On Tue, 21 May 2024, Jason Merrill wrote:


On 5/21/24 17:27, Patrick Palka wrote:

On Tue, 21 May 2024, Jason Merrill wrote:


On 5/21/24 15:36, Patrick Palka wrote:

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

Alternatively, I considered fixing this by incrementing
comparing_specializations around the call to comp_except_specs in
cp_check_qualified_type, but generally for types whose identity
depends on whether comparing_specializations is set we need to
use structural equality anyway IIUC.


Why not both?


I figured the latter change isn't necessary/observable since
comparing_specializations would only make a difference for complex
exception specifications, and with this patch we won't even call
cp_check_qualified_type on a complex eh spec.


My concern is that if we're building a function type multiple times with
the
same noexcept-spec, this patch would mean creating multiple equivalent
function types instead of reusing one already created for the same
function.


+  bool complex_p = (cr && cr != noexcept_true_spec
+   && !UNPARSED_NOEXCEPT_SPEC_P (cr));


Why treat unparsed specs differently from parsed ones?


Unparsed specs are unique according to cp_tree_equal, so in turn
function types with unparsed specs are unique, so it should be safe to
treat such types as canonical.  I'm not sure if this optimization
matters though; I'm happy to remove this case.


The idea that this optimization could make a difference raised the concern
above.


Aha, makes sense.  To that end it seems we could strengthen the ce_exact
in comp_except_specs to require == instead of cp_tree_equal equality
when comparing two noexcept-specs; the only ce_exact callers are
cp_check_qualified_type and cxx_type_hash_eq, which should be fine with
that strengthening.  This way, we at least do try to reuse a variant if
the (complex or unparsed) noexcept-spec is exactly the same.


Sounds good.

Given that, we probably still want to move the canonical_eh_spec up in
build_cp_fntype_variant, and pass that to cp_check_qualified_type?


And compare the canonical spec directly from cp_check_qualified_type
instead of using comp_except_specs?  Then IIUC for

   void f() throw(int);
   void g() throw(char);

we'd give g the same function type as f, which seems wrong?


Good point, I was confused about what canonical_eh_spec was doing.  Your 
last patch is OK.


Jason



Re: [PATCH] c++: canonicity of fn types w/ complex eh specs [PR115159]

2024-05-21 Thread Jason Merrill

On 5/21/24 21:55, Patrick Palka wrote:

On Tue, 21 May 2024, Jason Merrill wrote:


On 5/21/24 17:27, Patrick Palka wrote:

On Tue, 21 May 2024, Jason Merrill wrote:


On 5/21/24 15:36, Patrick Palka wrote:

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

Alternatively, I considered fixing this by incrementing
comparing_specializations around the call to comp_except_specs in
cp_check_qualified_type, but generally for types whose identity
depends on whether comparing_specializations is set we need to
use structural equality anyway IIUC.


Why not both?


I figured the latter change isn't necessary/observable since
comparing_specializations would only make a difference for complex
exception specifications, and with this patch we won't even call
cp_check_qualified_type on a complex eh spec.


My concern is that if we're building a function type multiple times with the
same noexcept-spec, this patch would mean creating multiple equivalent
function types instead of reusing one already created for the same function.


+  bool complex_p = (cr && cr != noexcept_true_spec
+   && !UNPARSED_NOEXCEPT_SPEC_P (cr));


Why treat unparsed specs differently from parsed ones?


Unparsed specs are unique according to cp_tree_equal, so in turn
function types with unparsed specs are unique, so it should be safe to
treat such types as canonical.  I'm not sure if this optimization
matters though; I'm happy to remove this case.


The idea that this optimization could make a difference raised the concern
above.


Aha, makes sense.  To that end it seems we could strengthen the ce_exact
in comp_except_specs to require == instead of cp_tree_equal equality
when comparing two noexcept-specs; the only ce_exact callers are
cp_check_qualified_type and cxx_type_hash_eq, which should be fine with
that strengthening.  This way, we at least do try to reuse a variant if
the (complex or unparsed) noexcept-spec is exactly the same.


Sounds good.

Given that, we probably still want to move the canonical_eh_spec up in 
build_cp_fntype_variant, and pass that to cp_check_qualified_type?



Like so?

-- >8 --

Subject: [PATCH] c++: canonicity of fn types w/ complex eh specs [PR115159]

Here the member functions QList::g and QList::h are given the same
function type since their exception specifications are equivalent
according to cp_tree_equal.  In doing so however this means that the
type of QList::h refers to a function parameter from QList::g, which
ends up confusing modules streaming.

I'm not sure if modules can be fixed to handle this situation, but
regardless it seems weird in principle that a function parameter can
escape in such a way.  The analogous situation with a trailing return
type and decltype

   auto g(QList ) -> decltype(f(other));
   auto h(QList ) -> decltype(f(other));

behaves better because we don't canonicalize decltype, and so the
function types of g and h are non-canonical and therefore not shared.

In light of this, it seems natural to treat function types with complex
eh specs as non-canonical as well so that each such function declaration
is given a unique function/method type node.  The main benefit of type
canonicalization is to speed up repeated type comparisons, but it should
rare for us to repeatedly compare two otherwise compatible function
types with complex exception specifications, so foregoing canonicalization
should not cause any problems.

To that end, this patch strengthens the ce_exact case of comp_except_specs
to require identity instead of equivalence of the exception specification
so that build_cp_fntype_variant doesn't reuse a variant when it shouldn't.
And in build_cp_fntype_variant we need to use structural equality for types
with a complex eh spec.  In turn we could simplify the code responsible
for adjusting unparsed eh spec variants.

PR c++/115159

gcc/cp/ChangeLog:

* tree.cc (build_cp_fntype_variant): Always use structural
equality for types with a complex exception specification.
(fixup_deferred_exception_variants): Always use structural
equality for adjusted variants.
* typeck.cc (comp_except_specs): Require == instead of
cp_tree_equal for noexcept-spec comparison in the ce_exact case.

gcc/testsuite/ChangeLog:

* g++.dg/modules/noexcept-2_a.H: New test.
* g++.dg/modules/noexcept-2_b.C: New test.
---
  gcc/cp/tree.cc  | 47 +
  gcc/cp/typeck.cc|  4 +-
  gcc/testsuite/g++.dg/modules/noexcept-2_a.H | 24 +++
  gcc/testsuite/g++.dg/modules/noexcept-2_b.C |  4 ++
  4 files changed, 41 insertions(+), 38 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/noexcept-2_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/noexcept-2_b.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 9d37d255d8d..93a64322418 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tr

Re: [PATCH] c++: canonicity of fn types w/ complex eh specs [PR115159]

2024-05-21 Thread Jason Merrill

On 5/21/24 17:27, Patrick Palka wrote:

On Tue, 21 May 2024, Jason Merrill wrote:


On 5/21/24 15:36, Patrick Palka wrote:

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

Alternatively, I considered fixing this by incrementing
comparing_specializations around the call to comp_except_specs in
cp_check_qualified_type, but generally for types whose identity
depends on whether comparing_specializations is set we need to
use structural equality anyway IIUC.


Why not both?


I figured the latter change isn't necessary/observable since
comparing_specializations would only make a difference for complex
exception specifications, and with this patch we won't even call
cp_check_qualified_type on a complex eh spec.


My concern is that if we're building a function type multiple times with 
the same noexcept-spec, this patch would mean creating multiple 
equivalent function types instead of reusing one already created for the 
same function.



+  bool complex_p = (cr && cr != noexcept_true_spec
+   && !UNPARSED_NOEXCEPT_SPEC_P (cr));


Why treat unparsed specs differently from parsed ones?


Unparsed specs are unique according to cp_tree_equal, so in turn
function types with unparsed specs are unique, so it should be safe to
treat such types as canonical.  I'm not sure if this optimization
matters though; I'm happy to remove this case.


The idea that this optimization could make a difference raised the 
concern above.


Jason



Re: [PATCH] c++: canonicity of fn types w/ complex eh specs [PR115159]

2024-05-21 Thread Jason Merrill

On 5/21/24 15:36, Patrick Palka wrote:

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

Alternatively, I considered fixing this by incrementing
comparing_specializations around the call to comp_except_specs in
cp_check_qualified_type, but generally for types whose identity
depends on whether comparing_specializations is set we need to
use structural equality anyway IIUC.


Why not both?


+  bool complex_p = (cr && cr != noexcept_true_spec
+   && !UNPARSED_NOEXCEPT_SPEC_P (cr));


Why treat unparsed specs differently from parsed ones?

Jason



Re: [PATCH] c++: folding non-dep enumerator from current inst [PR115139]

2024-05-21 Thread Jason Merrill

On 5/17/24 12:05, Patrick Palka wrote:

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


OK for both.


-- >8 --

After the tsubst_copy removal r14-4796-g3e3d73ed5e85e7 GCC 14 ICEs during
fold_non_dependent_expr for 'e1 | e2' ultimately because we no longer exit
early when substituting the CONST_DECLs for e1 and e2 with args=NULL_TREE,
during which we try substituting the class context A (also with
args=NULL_TREE) which ends up ICEing from tsubst_pack_expansion (due to
processing_template_decl being cleared).

Incidentally, the ICE went away on trunk ever since the tsubst_aggr_type
removal r15-123-gf04dc89a991ddc since it made the CONST_DECL case of
tsubst_expr use tsubst to substitute the context, which does short circuit
for empty args and so avoids the ICE.

This patch fixes this ICE for GCC 14 by narrowly restoring the early exit
for empty args that was present in tsubst_copy when substituting an
enumerator CONST_DECL.  We might as well apply this to trunk too, as a
very minor optimization.

PR c++/115139

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr) : Exit early if args
is empty.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent33.C: New test.
---
  gcc/cp/pt.cc|  2 +-
  gcc/testsuite/g++.dg/template/non-dependent33.C | 11 +++
  2 files changed, 12 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/template/non-dependent33.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 32640f8e946..e185e3d8941 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21519,7 +21519,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
  
  	if (DECL_TEMPLATE_PARM_P (t))

  RETURN (RECUR (DECL_INITIAL (t)));
-   if (!uses_template_parms (DECL_CONTEXT (t)))
+   if (!args || !uses_template_parms (DECL_CONTEXT (t)))
  RETURN (t);
  
  	/* Unfortunately, we cannot just call lookup_name here.

diff --git a/gcc/testsuite/g++.dg/template/non-dependent33.C 
b/gcc/testsuite/g++.dg/template/non-dependent33.C
new file mode 100644
index 000..2f1dd8a214c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent33.C
@@ -0,0 +1,11 @@
+// PR c++/115139
+// { dg-do compile { target c++11 } }
+
+template
+class A {
+  enum E {
+e1 = 1,
+e2 = 2,
+e3 = e1 | e2,
+  };
+};




Re: [PATCH] testsuite: Allow for non-SECTION_MERGE systems in gcc.dg/pr115066.c [PR115066]

2024-05-21 Thread Jason Merrill

On 5/21/24 07:36, Rainer Orth wrote:

gcc.dg/pr115066.c currently FAILs on Solaris/SPARC with the native as:

FAIL: gcc.dg/pr115066.c scan-assembler .bytet0xbt# Define macro strx

Instead of the expected

.byte   0xb ! Define macro strx

the assembler output contains

.byte   0x1 ! Define macro

Apparently this happens because the Solaris as/ld combo doesn't support
SHF_MERGE.

While I initially meant to just skip the test on sparc*-*-solaris2* && !gas,
Tom suggested to allow for both forms instead, which is what his patch
does.

Tested on sparc-sun-solaris2.11 and i386-pc-solaris2.11 (as and gas
each) and x86_64-pc-linux-gnu.

Ok for trunk?


OK.



Re: [PATCH v5 2/5] C++: Support clang compatible [[musttail]] (PR83324)

2024-05-21 Thread Jason Merrill

On 5/14/24 19:23, Andi Kleen wrote:

You need a template testcase; I expect it doesn't work in templates with the
current patch.  It's probably enough to copy it in tsubst_expr where we
currently propagate CALL_EXPR_OPERATOR_SYNTAX.


I tried it with the appended test case, everything seems to work without
changes.

Does it cover the cases you were concerned about?


Not fully; this testcase doesn't seem to check for errors if tail-call
fails, only whether the syntax is accepted.  So it would pass if the
attribute were simply ignored.


Okay I'm not clear how I would do that. Pattern match the assembler
in a target specific test case? From looking at the assembler output
everything got tail converted.


Write a testcase where the tail-call optimization can't happen, perhaps 
because the caller and callee disagree on return type:


int f();

double h() { [[gnu::musttail]] return f(); } // error

template 
T g() { [[gnu::musttail]] return f(); }

int main()
{
  g();
  g(); // should error, but doesn't with v6 patch set
}

Jason



Re: [PATCH v2] c++: Strengthen checks on 'main'

2024-05-20 Thread Jason Merrill

On 5/17/24 02:47, Nathaniel Shead wrote:

On Tue, May 14, 2024 at 06:25:29PM -0400, Jason Merrill wrote:

On 5/11/24 08:32, Nathaniel Shead wrote:

I wasn't entirely sure what to do with the 'abi/main.C' testcase here;
is this OK, or should I e.g. lower the linkage error to a pedwarn for
the purposes of this test?


I think it should be a pedwarn anyway, since it's harmless.  The others can
still be errors.


Fair enough; how about this?  OK for trunk if bootstrap + regtest
succeeds?


OK.


-- >8 --

This patch adds some missing requirements for legal main declarations,
as according to [basic.start.main] p2.

gcc/cp/ChangeLog:

* decl.cc (grokfndecl): Check for main functions with language
linkage or module attachment.
(grokvardecl): Check for extern 'C' entities named main.

gcc/testsuite/ChangeLog:

* g++.dg/abi/main.C: Check pedwarn for main with linkage-spec.
* g++.dg/modules/contracts-1_b.C: Don't declare main in named
module.
* g++.dg/modules/contracts-3_b.C: Likewise.
* g++.dg/modules/contracts-4_d.C: Likewise.
* g++.dg/modules/horcrux-1_a.C: Export declarations, so that...
* g++.dg/modules/horcrux-1_b.C: Don't declare main in named
module.
* g++.dg/modules/main-1.C: New test.
* g++.dg/parse/linkage5.C: New test.
* g++.dg/parse/linkage6.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/decl.cc   | 19 +++
  gcc/testsuite/g++.dg/abi/main.C  |  3 ++-
  gcc/testsuite/g++.dg/modules/contracts-1_b.C |  4 
  gcc/testsuite/g++.dg/modules/contracts-3_b.C |  4 
  gcc/testsuite/g++.dg/modules/contracts-4_d.C |  2 --
  gcc/testsuite/g++.dg/modules/horcrux-1_a.C   |  3 +++
  gcc/testsuite/g++.dg/modules/horcrux-1_b.C   |  2 +-
  gcc/testsuite/g++.dg/modules/main-1.C|  5 +
  gcc/testsuite/g++.dg/parse/linkage5.C| 14 ++
  gcc/testsuite/g++.dg/parse/linkage6.C| 13 +
  10 files changed, 53 insertions(+), 16 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/main-1.C
  create mode 100644 gcc/testsuite/g++.dg/parse/linkage5.C
  create mode 100644 gcc/testsuite/g++.dg/parse/linkage6.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 6fcab615d55..a992d54dc8f 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -10788,6 +10788,11 @@ grokfndecl (tree ctype,
  "cannot declare %<::main%> to be %qs", "consteval");
if (!publicp)
error_at (location, "cannot declare %<::main%> to be static");
+  if (current_lang_depth () != 0)
+   pedwarn (location, OPT_Wpedantic, "cannot declare %<::main%> with a"
+" linkage specification");
+  if (module_attach_p ())
+   error_at (location, "cannot attach %<::main%> to a named module");
inlinep = 0;
publicp = 1;
  }
@@ -11287,10 +11292,16 @@ grokvardecl (tree type,
  DECL_INTERFACE_KNOWN (decl) = 1;
  
if (DECL_NAME (decl)

-  && MAIN_NAME_P (DECL_NAME (decl))
-  && scope == global_namespace)
-error_at (DECL_SOURCE_LOCATION (decl),
- "cannot declare %<::main%> to be a global variable");
+  && MAIN_NAME_P (DECL_NAME (decl)))
+{
+  if (scope == global_namespace)
+   error_at (DECL_SOURCE_LOCATION (decl),
+ "cannot declare %<::main%> to be a global variable");
+  else if (DECL_EXTERN_C_P (decl))
+   error_at (DECL_SOURCE_LOCATION (decl),
+ "an entity named % cannot be declared with "
+ "C language linkage");
+}
  
/* Check that the variable can be safely declared as a concept.

   Note that this also forbids explicit specializations.  */
diff --git a/gcc/testsuite/g++.dg/abi/main.C b/gcc/testsuite/g++.dg/abi/main.C
index 4c5f1ea213c..2797a16df5b 100644
--- a/gcc/testsuite/g++.dg/abi/main.C
+++ b/gcc/testsuite/g++.dg/abi/main.C
@@ -1,10 +1,11 @@
  /* { dg-do compile } */
+/* { dg-additional-options "-Wno-error=pedantic" }
  
  /* Check if entry points get implicit C linkage. If they don't, compiler will

   * error on incompatible declarations */
  
  int main();

-extern "C" int main();
+extern "C" int main();  // { dg-warning "linkage specification" }
  
  #ifdef __MINGW32__
  
diff --git a/gcc/testsuite/g++.dg/modules/contracts-1_b.C b/gcc/testsuite/g++.dg/modules/contracts-1_b.C

index 30c15f6928b..aa36c8d6b1b 100644
--- a/gcc/testsuite/g++.dg/modules/contracts-1_b.C
+++ b/gcc/testsuite/g++.dg/modules/contracts-1_b.C
@@ -1,15 +1,11 @@
  // { dg-module-do run }
  // { dg-additional-options "-fmodules-ts -fcontracts 
-fcontract-continuation-mode=on" }
-module;
  #include 
-export module bar;
-// { dg-module-cmi bar }
  import foo;
  
  te

Re: [PATCH v2] c++/modules: Remember that header units have CMIs

2024-05-20 Thread Jason Merrill

On 5/17/24 02:14, Nathaniel Shead wrote:

On Tue, May 14, 2024 at 06:21:48PM -0400, Jason Merrill wrote:

On 5/12/24 22:58, Nathaniel Shead wrote:

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


OK.



I realised as I was looking over this again that I might have spoken too
soon with the header unit example being supported. Doing the following:

   // a.H
   struct { int y; } s;
   decltype(s) f(decltype(s));  // { dg-error "used but never defined" }
   inline auto x = f({ 123 });
   
   // b.C

   struct {} unrelated;
   import "a.H";
   decltype(s) f(decltype(s) x) {
 return { 456 + x.y };
   }

   // c.C
   import "linkage-3_a.H";
   int main() { auto a = x.y; }

Actually does fail to link, because in 'c.C' we call 'f(.anon_0)' but
the definition 'b.C' is f(.anon_1).

I don't think this is fixable, so I don't think this direction is
workable.


Since namespace-scope anonymous types are TU-local, we don't need to 
support that for proper modules, but it's not clear to me that we don't 
need to support it for header units.


OTOH, https://eel.is/c++draft/module#import-5.3 allows c.C to import a 
different header unit than b.C, in which case the type is different and 
x violates the odr.



That said, I think that it might still be worth making header modules
satisfy 'module_has_cmi_p', since that is true to the name, and will be
useful in other places we currently use 'module_p ()': in which case we
could instead make all the callers in 'no_linkage_check' do
'module_maybe_has_cmi_p () && !header_module_p ()'; something like the
following, perhaps?


If we need that condition, it should be its own predicate rather than 
expecting callers to do that combined check.


But it's not clear to me how this is different from a type in the GMF of 
a named module, which is exactly the maybe_has_cmi case; there we could 
again see a different version of the type if another TU includes the header.


Jason



Re: [PATCH] c++: paren aggr CTAD with base classes [PR115114]

2024-05-16 Thread Jason Merrill

On 5/16/24 11:32, Patrick Palka wrote:

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


OK for both.


-- >8 --

We're accidentally ignoring base classes during parenthesized aggregate
CTAD because the TYPE_FIELDS of a template type doesn't contain bases,
so we need to consider them separately.

PR c++/115114

gcc/cp/ChangeLog:

* pt.cc (maybe_aggr_guide): Consider base classes in the paren
init case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-aggr15.C: New test.
---
  gcc/cp/pt.cc  |  7 ++
  .../g++.dg/cpp2a/class-deduction-aggr15.C | 23 +++
  2 files changed, 30 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d83f530ac8d..54d74989903 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30202,6 +30202,13 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
else if (TREE_CODE (init) == TREE_LIST)
  {
int len = list_length (init);
+  for (tree binfo : BINFO_BASE_BINFOS (TYPE_BINFO (template_type)))
+   {
+ if (!len)
+   break;
+ parms = tree_cons (NULL_TREE, BINFO_TYPE (binfo), parms);
+ --len;
+   }
for (tree field = TYPE_FIELDS (template_type);
   len;
   --len, field = DECL_CHAIN (field))
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C
new file mode 100644
index 000..16dc0f52b64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr15.C
@@ -0,0 +1,23 @@
+// PR c++/115114
+// { dg-do compile { target c++20 } }
+
+struct X {} x;
+struct Y {} y;
+
+template
+struct A : T {
+  U m;
+};
+
+using ty1 = decltype(A{x, 42}); // OK
+using ty1 = decltype(A(x, 42)); // OK, used to fail
+using ty1 = A;
+
+template
+struct B : T, V {
+  U m = 42;
+};
+
+using ty2 = decltype(B{x, y}); // OK
+using ty2 = decltype(B(x, y)); // OK, used to fail
+using ty2 = B;




Re: [PATCH] c++: represent all class non-dep assignments as CALL_EXPR

2024-05-16 Thread Jason Merrill

On 5/15/24 13:55, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linu-xgnu, does this look OK
for trunk?


OK.


-- >8 --

Non-dependent compound assignment expressions are currently represented
as CALL_EXPR to the selected operator@= overload.  Non-dependent simple
assignments on the other hand are still represented as MODOP_EXPR, which
doesn't hold on to the selected overload.

That we need to remember the selected operator@= overload ahead of time
is a correctness thing, because they can be declared at namespace scope
and we don't want to consider later-declared namespace scope overloads
at instantiation time.  This doesn't apply to simple operator= because
it can only be declared at class scope, so it's fine to repeat the name
lookup and overload resolution at instantiation time.  But it still
seems desirable for sake of QoI to also avoid this repeated name lookup
and overload resolution for simple assignments along the lines of
r12-6075-g2decd2cabe5a4f.

To that end, this patch makes us represent non-dependent simple
assignments as CALL_EXPR to the selected operator= overload rather than
as MODOP_EXPR.  In order for is_assignment_op_expr_p to recognize such
CALL_EXPR as an assignment expression, cp_get_fndecl_from_callee needs
to look through templated COMPONENT_REF callee corresponding to a member
function call, otherwise ahead of time -Wparentheses warnings stop
working (e.g. g++.dg/warn/Wparentheses-{32,33}.C).

gcc/cp/ChangeLog:

* call.cc (build_new_op): Pass 'overload' to
cp_build_modify_expr.
* cp-tree.h (cp_build_modify_expr): New overload that
takes a tree* out-parameter.
* pt.cc (tsubst_expr) : Propagate
OPT_Wparentheses warning suppression to the result.
* cvt.cc (cp_get_fndecl_from_callee): Use maybe_get_fns
to extract the FUNCTION_DECL from a callee.
* semantics.cc (is_assignment_op_expr_p): Also recognize
templated operator expressions represented as a CALL_EXPR
to operator=.
* typeck.cc (cp_build_modify_expr): Add 'overload'
out-parameter and pass it to build_new_op.
(build_x_modify_expr): Pass 'overload' to cp_build_modify_expr.
---
  gcc/cp/call.cc   |  2 +-
  gcc/cp/cp-tree.h |  3 +++
  gcc/cp/cvt.cc|  5 +++--
  gcc/cp/pt.cc |  2 ++
  gcc/cp/typeck.cc | 18 ++
  5 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index e058da7735f..e3d4cf8949d 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -7473,7 +7473,7 @@ build_new_op (const op_location_t , enum tree_code 
code, int flags,
switch (code)
  {
  case MODIFY_EXPR:
-  return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
+  return cp_build_modify_expr (loc, arg1, code2, arg2, overload, complain);
  
  case INDIRECT_REF:

return cp_build_indirect_ref (loc, arg1, RO_UNARY_STAR, complain);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9a8c8659157..1e565086e80 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8267,6 +8267,9 @@ extern tree cp_build_c_cast   
(location_t, tree, tree,
  extern cp_expr build_x_modify_expr(location_t, tree,
 enum tree_code, tree,
 tree, tsubst_flags_t);
+extern tree cp_build_modify_expr   (location_t, tree,
+enum tree_code, tree,
+tree *, tsubst_flags_t);
  extern tree cp_build_modify_expr  (location_t, tree,
 enum tree_code, tree,
 tsubst_flags_t);
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index db086c017e8..2f4c0f88694 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1015,8 +1015,9 @@ cp_get_fndecl_from_callee (tree fn, bool fold /* = true 
*/)
return f;
  };
  
-  if (TREE_CODE (fn) == FUNCTION_DECL)

-return fn_or_local_alias (fn);
+  if (tree f = maybe_get_fns (fn))
+if (TREE_CODE (f) == FUNCTION_DECL)
+  return fn_or_local_alias (f);
tree type = TREE_TYPE (fn);
if (type == NULL_TREE || !INDIRECT_TYPE_P (type))
  return NULL_TREE;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 32640f8e946..d83f530ac8d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21093,6 +21093,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
if (warning_suppressed_p (t, OPT_Wpessimizing_move))
  /* This also suppresses -Wredundant-move.  */
  suppress_warning (ret, OPT_Wpessimizing_move);
+   if (warning_suppressed_p (t, OPT_Wparentheses))
+ suppress_warning (STRIP_REFERENCE_REF (ret), OPT_Wparentheses);
  }
  
  	RETURN (ret);

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 5f16994300f..75b696e32e0 100644

Re: [PATCH] c++: lvalueness of non-dependent assignment [PR114994]

2024-05-14 Thread Jason Merrill

On 5/11/24 20:46, Patrick Palka wrote:

On Fri, 10 May 2024, Jason Merrill wrote:


On 5/9/24 16:23, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk/14?  For trunk as a follow-up I can implement the
mentionted representation change to use CALL_EXPR instead of
MODOP_EXPR for a non-dependent simple assignment expression that
resolved to an operator= overload.

-- >8 --

r14-4111 made us check non-dependent assignment expressions ahead of
time, as well as give them a type.  Unlike for compound assignment
expressions however, if a simple assignment resolves to an operator
overload we still represent it as a (typed) MODOP_EXPR instead of a
CALL_EXPR to the selected overload.  This, I reckoned, was just a
pessimization (since we'll have to repeat overload resolution at
instantiatiation time) but should be harmless.  (And it should be
easily fixable by giving cp_build_modify_expr an 'overload' parameter).

But it breaks the below testcase ultimately because MODOP_EXPR (of
non-reference type) is always treated as an lvalue according to
lvalue_kind, which is incorrect for the MODOP_EXPR representing x=42.

We can fix this by representing such assignment expressions as CALL_EXPRs
matching what that of compound assignments, but that turns out to
require some tweaking of our -Wparentheses warning logic which seems
unsuitable for backporting.

So this patch instead more conservatively fixes this by refining
lvalue_kind to consider the type of a (simple) MODOP_EXPR as we
already do for COND_EXPR.

PR c++/114994

gcc/cp/ChangeLog:

* tree.cc (lvalue_kind) : Consider the
type of a simple assignment expression.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent32.C: New test.
---
   gcc/cp/tree.cc |  7 +++
   .../g++.dg/template/non-dependent32.C  | 18 ++
   2 files changed, 25 insertions(+)
   create mode 100644 gcc/testsuite/g++.dg/template/non-dependent32.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe817..0b97b789aab 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,6 +275,13 @@ lvalue_kind (const_tree ref)
 /* We expect to see unlowered MODOP_EXPRs only during
 template processing.  */
 gcc_assert (processing_template_decl);
+  if (TREE_CODE (TREE_OPERAND (ref, 1)) == NOP_EXPR
+ && CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0
+   /* As in the COND_EXPR case, but for non-dependent assignment
+  expressions created by build_x_modify_expr.  */
+   goto default_;


This seems overly specific, I'd think the same thing would apply to += and
such?


We shouldn't see += etc of class type here since we already represent
those as CALL_EXPR to the selected operator=, but indeed it could
otherwise apply to +=.  Like so?


OK.


-- >8 --

Subject: [PATCH] c++: lvalueness of non-dependent assignment expr [PR114994]

PR c++/114994

gcc/cp/ChangeLog:

* tree.cc (lvalue_kind) : Consider the
type of a class assignment expression.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent32.C: New test.
---
  gcc/cp/tree.cc |  5 -
  .../g++.dg/template/non-dependent32.C  | 18 ++
  2 files changed, 22 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/template/non-dependent32.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe817..9d37d255d8d 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,7 +275,10 @@ lvalue_kind (const_tree ref)
/* We expect to see unlowered MODOP_EXPRs only during
 template processing.  */
gcc_assert (processing_template_decl);
-  return clk_ordinary;
+  if (CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0
+   goto default_;
+  else
+   return clk_ordinary;
  
  case MODIFY_EXPR:

  case TYPEID_EXPR:
diff --git a/gcc/testsuite/g++.dg/template/non-dependent32.C 
b/gcc/testsuite/g++.dg/template/non-dependent32.C
new file mode 100644
index 000..54252c7dfaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent32.C
@@ -0,0 +1,18 @@
+// PR c++/114994
+// { dg-do compile { target c++11 } }
+
+struct udl_arg {
+  udl_arg operator=(int);
+};
+
+void f(udl_arg&&);
+
+template
+void g() {
+  udl_arg x;
+  f(x=42); // { dg-bogus "cannot bind" }
+}
+
+int main() {
+  g();
+}




Re: [PATCH] c++: Strengthen checks on 'main'

2024-05-14 Thread Jason Merrill

On 5/11/24 08:32, Nathaniel Shead wrote:

I wasn't entirely sure what to do with the 'abi/main.C' testcase here;
is this OK, or should I e.g. lower the linkage error to a pedwarn for
the purposes of this test?


I think it should be a pedwarn anyway, since it's harmless.  The others 
can still be errors.



Bootstrapped and regtested on x86_64-pc-linux-gnu, and lightly checked
with a MinGW32 cross.  OK for trunk?

-- >8 --

This patch adds some missing requirements for legal main declarations,
as according to [basic.start.main] p2.

gcc/cp/ChangeLog:

* decl.cc (grokfndecl): Check for main functions with language
linkage or module attachment.
(grokvardecl): Check for extern 'C' entities named main.

gcc/testsuite/ChangeLog:

* g++.dg/abi/main.C: Rework to avoid declaring main with
language linkage.
* g++.dg/modules/contracts-1_b.C: Don't declare main in named
module.
* g++.dg/modules/contracts-3_b.C: Likewise.
* g++.dg/modules/contracts-4_d.C: Likewise.
* g++.dg/modules/horcrux-1_a.C: Export declarations, so that...
* g++.dg/modules/horcrux-1_b.C: Don't declare main in named
module.
* g++.dg/modules/main-1.C: New test.
* g++.dg/parse/linkage5.C: New test.
* g++.dg/parse/linkage6.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/decl.cc   | 19 ++---
  gcc/testsuite/g++.dg/abi/main.C  | 29 
  gcc/testsuite/g++.dg/modules/contracts-1_b.C |  4 ---
  gcc/testsuite/g++.dg/modules/contracts-3_b.C |  4 ---
  gcc/testsuite/g++.dg/modules/contracts-4_d.C |  2 --
  gcc/testsuite/g++.dg/modules/horcrux-1_a.C   |  3 ++
  gcc/testsuite/g++.dg/modules/horcrux-1_b.C   |  2 +-
  gcc/testsuite/g++.dg/modules/main-1.C|  5 
  gcc/testsuite/g++.dg/parse/linkage5.C| 14 ++
  gcc/testsuite/g++.dg/parse/linkage6.C| 13 +
  10 files changed, 63 insertions(+), 32 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/main-1.C
  create mode 100644 gcc/testsuite/g++.dg/parse/linkage5.C
  create mode 100644 gcc/testsuite/g++.dg/parse/linkage6.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index e02562466a7..5ab3b787d6f 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -10781,6 +10781,11 @@ grokfndecl (tree ctype,
  "cannot declare %<::main%> to be %qs", "consteval");
if (!publicp)
error_at (location, "cannot declare %<::main%> to be static");
+  if (current_lang_depth () != 0)
+   error_at (location, "cannot declare %<::main%> with a"
+ " linkage specification");
+  if (module_attach_p ())
+   error_at (location, "cannot attach %<::main%> to a named module");
inlinep = 0;
publicp = 1;
  }
@@ -11280,10 +11285,16 @@ grokvardecl (tree type,
  DECL_INTERFACE_KNOWN (decl) = 1;
  
if (DECL_NAME (decl)

-  && MAIN_NAME_P (DECL_NAME (decl))
-  && scope == global_namespace)
-error_at (DECL_SOURCE_LOCATION (decl),
- "cannot declare %<::main%> to be a global variable");
+  && MAIN_NAME_P (DECL_NAME (decl)))
+{
+  if (scope == global_namespace)
+   error_at (DECL_SOURCE_LOCATION (decl),
+ "cannot declare %<::main%> to be a global variable");
+  else if (DECL_EXTERN_C_P (decl))
+   error_at (DECL_SOURCE_LOCATION (decl),
+ "an entity named % cannot be declared with "
+ "C language linkage");
+}
  
/* Check that the variable can be safely declared as a concept.

   Note that this also forbids explicit specializations.  */
diff --git a/gcc/testsuite/g++.dg/abi/main.C b/gcc/testsuite/g++.dg/abi/main.C
index 4c5f1ea213c..f3882d70612 100644
--- a/gcc/testsuite/g++.dg/abi/main.C
+++ b/gcc/testsuite/g++.dg/abi/main.C
@@ -1,24 +1,19 @@
  /* { dg-do compile } */
  
-/* Check if entry points get implicit C linkage. If they don't, compiler will

- * error on incompatible declarations */
+/* Check if entry points get implicit C linkage. Determined by checking that
+   the names are unmangled */
  
-int main();

-extern "C" int main();
+int main() {}
  
  #ifdef __MINGW32__

-
-int wmain();
-extern "C" int wmain();
-
-int DllMain();
-extern "C" int DllMain();
-
-int WinMain();
-extern "C" int WinMain();
-
-int wWinMain();
-extern "C" int wWinMain();
-
+int wmain() {}
+int DllMain() {}
+int WinMain() {}
+int wWinMain() {}
  #endif
  
+// { dg-final { scan-assembler-not "_Z4mainv" } }

+// { dg-final { scan-assembler-not "_Z5wmainv" { target *-*-mingw32 } } }
+// { dg-final { scan-assembler-not "_Z7DllMainv" { target *-*-mingw32 } } }
+// { dg-final { scan-assembler-not "_Z7WinMainv" { target *-*-mingw32 } } }
+// { dg-final { scan-assembler-not "_Z8wWinMainv" { target *-*-mingw32 } } }
diff --git a/gcc/testsuite/g++.dg/modules/contracts-1_b.C 
b/gcc/testsuite/g++.dg/modules/contracts-1_b.C
index 

Re: [PATCH] c++/modules: Remember that header units have CMIs

2024-05-14 Thread Jason Merrill

On 5/12/24 22:58, Nathaniel Shead wrote:

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


OK.


-- >8 --

This appears to be an oversight in the definition of module_has_cmi_p;
this comes up transitively in other functions used for e.g. determining
whether a name could potentially be accessed in a different translation
unit.

This change will allow us to use the function directly in more places
that need to additional work only if generating a module CMI in the
future.

gcc/cp/ChangeLog:

* cp-tree.h (module_has_cmi_p): Also true for header units.

gcc/testsuite/ChangeLog:

* g++.dg/modules/linkage-3_a.H: New test.
* g++.dg/modules/linkage-3_b.C: New test.
* g++.dg/modules/linkage-3_c.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/cp-tree.h   |  2 +-
  gcc/testsuite/g++.dg/modules/linkage-3_a.H | 19 +++
  gcc/testsuite/g++.dg/modules/linkage-3_b.C |  9 +
  gcc/testsuite/g++.dg/modules/linkage-3_c.C | 10 ++
  4 files changed, 39 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/linkage-3_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/linkage-3_b.C
  create mode 100644 gcc/testsuite/g++.dg/modules/linkage-3_c.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index db098c32f2d..609904918ba 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7379,7 +7379,7 @@ inline bool module_interface_p ()
  inline bool module_partition_p ()
  { return module_kind & MK_PARTITION; }
  inline bool module_has_cmi_p ()
-{ return module_kind & (MK_INTERFACE | MK_PARTITION); }
+{ return module_kind & (MK_INTERFACE | MK_PARTITION | MK_HEADER); }
  
  inline bool module_purview_p ()

  { return module_kind & MK_PURVIEW; }
diff --git a/gcc/testsuite/g++.dg/modules/linkage-3_a.H 
b/gcc/testsuite/g++.dg/modules/linkage-3_a.H
new file mode 100644
index 000..1e0ebd927e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/linkage-3_a.H
@@ -0,0 +1,19 @@
+// { dg-additional-options "-fmodule-header -Wno-error=c++20-extensions" }
+// { dg-module-cmi {} }
+
+// Like linkage-1, but for header units.
+
+// External linkage definitions must be declared as 'inline' to satisfy
+// [module.import] p6, so we don't need to care about voldemort types in
+// function definitions.
+
+// Strictly speaking this is not required to be supported:
+// [module.import] p5 says that when two different TUs import header-names
+// identifying the same header or source file, it is unspecified whether
+// they import the same header unit, and thus 's' could be a different entity
+// in each TU.  But with out current implementation this seems to reasonable to
+// allow (and it does currently work).
+
+struct { int y; } s;
+decltype(s) f();  // { dg-warning "used but not defined" "" { target 
c++17_down } }
+inline auto x = f();
diff --git a/gcc/testsuite/g++.dg/modules/linkage-3_b.C 
b/gcc/testsuite/g++.dg/modules/linkage-3_b.C
new file mode 100644
index 000..935ef6150ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/linkage-3_b.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts" }
+
+struct {} unrelated;
+
+import "linkage-3_a.H";
+
+decltype(s) f() {
+  return { 123 };
+}
diff --git a/gcc/testsuite/g++.dg/modules/linkage-3_c.C 
b/gcc/testsuite/g++.dg/modules/linkage-3_c.C
new file mode 100644
index 000..be527ff552d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/linkage-3_c.C
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import "linkage-3_a.H";
+
+int main() {
+  auto a = x.y;
+  if (a != 123)
+__builtin_abort();
+}




Re: [PATCH] c++: Optimize in maybe_clone_body aliases even when not at_eof [PR113208]

2024-05-14 Thread Jason Merrill

On 5/13/24 06:19, Jakub Jelinek wrote:

On Fri, May 10, 2024 at 03:59:25PM -0400, Jason Merrill wrote:

2024-05-09  Jakub Jelinek  
Jason Merrill  

PR lto/113208
* cp-tree.h (maybe_optimize_cdtor): Remove.
* decl2.cc (tentative_decl_linkage): Call maybe_make_one_only
for implicit instantiations of maybe in charge ctors/dtors
declared inline.
(import_export_decl): Don't call maybe_optimize_cdtor.
(c_parse_final_cleanups): Formatting fixes.
* optimize.cc (can_alias_cdtor): Adjust condition, for
HAVE_COMDAT_GROUP && DECL_ONE_ONLY && DECL_WEAK return true even
if not DECL_INTERFACE_KNOWN.



--- gcc/cp/optimize.cc.jj   2024-04-25 20:33:30.771858912 +0200
+++ gcc/cp/optimize.cc  2024-05-09 17:10:23.920478922 +0200
@@ -220,10 +220,8 @@ can_alias_cdtor (tree fn)
 gcc_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn));
 /* Don't use aliases for weak/linkonce definitions unless we can put both
symbols in the same COMDAT group.  */
-  return (DECL_INTERFACE_KNOWN (fn)
- && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn))
- && (!DECL_ONE_ONLY (fn)
- || (HAVE_COMDAT_GROUP && DECL_WEAK (fn;
+  return (DECL_WEAK (fn) ? (HAVE_COMDAT_GROUP && DECL_ONE_ONLY (fn))
+: (DECL_INTERFACE_KNOWN (fn) && !DECL_ONE_ONLY (fn)));


Hmm, would

(DECL_ONE_ONLY (fn) ? HAVE_COMDAT_GROUP
  : (DECL_INTERFACE_KNOWN (fn) && !DECL_WEAK (fn)))

make sense instead?  I don't think DECL_WEAK is necessary for COMDAT.


I think it isn't indeed necessary for COMDAT, although e.g. comdat_linkage
will not call make_decl_one_only if !flag_weak.

But I think it is absolutely required for the alias cdtor optimization
in question, because otherwise it would be an ABI change.
Consider older version of GCC or some other compiler emitting
_ZN6vectorI12QualityValueEC1ERKS1_
and
_ZN6vectorI12QualityValueEC2ERKS1_
symbols not as aliases, each in their own comdat groups, so
.text._ZN6vectorI12QualityValueEC1ERKS1_ in _ZN6vectorI12QualityValueEC1ERKS1_
comdat group and
.text._ZN6vectorI12QualityValueEC2ERKS1_ in _ZN6vectorI12QualityValueEC2ERKS1_
comdat group.  And then comes GCC with the above patch without the DECL_WEAK
check in there, and decides to use alias, so
_ZN6vectorI12QualityValueEC1ERKS1_ is an alias to
_ZN6vectorI12QualityValueEC2ERKS1_ and both live in
.text._ZN6vectorI12QualityValueEC2ERKS1_ section in
_ZN6vectorI12QualityValueEC5ERKS1_ comdat group.  If you mix TUs with this,
the linker can keep one of the section sets from the 
_ZN6vectorI12QualityValueEC1ERKS1_
and _ZN6vectorI12QualityValueEC2ERKS1_ and _ZN6vectorI12QualityValueEC5ERKS1_
comdat groups.  If there is no .weak for the symbols, this will fail to
link, one can emit it either the old way or the new way but never both, it
is part of an ABI.
While with .weak, mixing it is possible, worst case one gets some unused
code in the linked binary or shared library.  Of course the desirable case
is that there is no mixing and there is no unused code, but if it happens,
no big deal.  Without .weak it is a big deal.


Makes sense, the patch is OK.

Jason



Re: [PATCH] testsuite: c++: Allow for std::printf in g++.dg/modules/stdio-1_a.H [PR98529]

2024-05-14 Thread Jason Merrill

On 5/13/24 08:10, Rainer Orth wrote:

Hi Nathaniel,


There are a couple of other tests that appear to potentially have a
similar issue:

global-2_a.C
21:// { dg-final { scan-lang-dump-not {Reachable GMF '::printf[^\n']*'
added} module } }

global-3_a.C
15:// { dg-final { scan-lang-dump-not {Reachable GMF '::printf[^'\n]*'
added} module } }


neither module file contains "Reachable GMF" at all, with ::printf or
otherwise.



Yes, I think the test is aiming to check that such a declaration is not
added at all, and so that's correct. But if for some reason on some
system it did add "::std::printf" that would be a bug that would not be
caught by this test.


understood.  However, the question about global-3_a.C remains which
contains no printf at all.


Which I suppose maybe also should be updated in the same way; I guess
they don't fail on Solaris because they aren't actually correctly
testing what they think they are.


Perhaps, but it would be useful to first understand what those tests are
supposed to look like.  WRT global-3_a.C, printf doesn't occur at all,
so this may just be a case of copy-and-paste.

Maybe Nathan, who authored the tests, can shed some light.


Otherwise LGTM.


Thanks.  I'll go ahead and commit the patch as is, asjusting the other
two once it's become clear what they should look like.



Ah, I should have been clearer: I'm not sure I can approve, but I've
CC'd Jason in.


Sorry, I already committed the patch.  I can revert, of course, if
that's inappropriate.  OTOH, it could be considered obvious ;-)


Indeed, it seems obvious to me, thanks.

Jason



Re: [PATCH v2] c++: ICE with reference NSDMI [PR114854]

2024-05-14 Thread Jason Merrill

On 5/14/24 09:48, Marek Polacek wrote:

On Thu, May 09, 2024 at 03:47:54PM -0400, Jason Merrill wrote:

On 5/9/24 12:04, Marek Polacek wrote:

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

-- >8 --
Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:

/* A TARGET_EXPR that expresses direct-initialization should have been
   elided by cp_gimplify_init_expr.  */
gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

the TARGET_EXPR in question is created for the NSDMI in:

class Vector { int m_size; };
struct S {
  const Vector {};
};

where we first need to create a Vector{} temporary, and then bind the
vec reference to it.  The temporary is represented by a TARGET_EXPR
and it cannot be elided.  When we create an object of type S, we get

D.2848 = {.vec=(const struct Vector &) _EXPR }

where the TARGET_EXPR is no longer direct-initializing anything.


Seems like the problem is in convert_like_internal:


 bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
 if (abstract_virtuals_error (NULL_TREE, totype, complain))
   return error_mark_node;
 expr = build_value_init (totype, complain);
 expr = get_target_expr (expr, complain);
 if (expr != error_mark_node)
   {
 TARGET_EXPR_LIST_INIT_P (expr) = true;
=>  TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
   }


My patch for 50930 assumed that if a CONSTRUCTOR represents syntactic
direct-initialization, a resulting TARGET_EXPR is itself the direct
initializer, but that isn't the case here; the temporary is
copy-initialized.

We could calculate direct-initializanity from cand->flags, but perhaps we
can just stop trying to set TARGET_EXPR_DIRECT_INIT_P here at all? We don't
do that for other list-initialization in ck_user, I don't know why I thought
it was needed for {} specifically.  It doesn't seem to be needed for the
50930 testcase.


...and it doesn't seem to be needed for any other test.  Then not setting
the flag in the first place is better than resetting it later, sure.

I thought about leaving a gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P)
in cp_build_addr_expr_1, but since we already have that assert when
gimplifying, I dropped it.

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


OK.


-- >8 --
Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:

   /* A TARGET_EXPR that expresses direct-initialization should have been
  elided by cp_gimplify_init_expr.  */
   gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

the TARGET_EXPR in question is created for the NSDMI in:

   class Vector { int m_size; };
   struct S {
 const Vector {};
   };

where we first need to create a Vector{} temporary, and then bind the
vec reference to it.  The temporary is represented by a TARGET_EXPR
and it cannot be elided.  When we create an object of type S, we get

   D.2848 = {.vec=(const struct Vector &) _EXPR }

where the TARGET_EXPR is no longer direct-initializing anything.

Fixed by not setting TARGET_EXPR_DIRECT_INIT_P in convert_like_internal/ck_user.

PR c++/114854

gcc/cp/ChangeLog:

* call.cc (convert_like_internal) : Don't set
TARGET_EXPR_DIRECT_INIT_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/nsdmi-aggr22.C: New test.
---
  gcc/cp/call.cc|  6 +-
  gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C | 12 
  2 files changed, 13 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index e058da7735f..ed68eb3c568 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8597,16 +8597,12 @@ convert_like_internal (conversion *convs, tree expr, 
tree fn, int argnum,
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)
&& !processing_template_decl)
  {
-   bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
if (abstract_virtuals_error (NULL_TREE, totype, complain))
  return error_mark_node;
expr = build_value_init (totype, complain);
expr = get_target_expr (expr, complain);
if (expr != error_mark_node)
- {
-   TARGET_EXPR_LIST_INIT_P (expr) = true;
-   TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
- }
+ TARGET_EXPR_LIST_INIT_P (expr) = true;
return expr;
  }
  
diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C

new file mode 100644
index 000..a4f9ae19ca9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr22.C
@@ -0,0 +1,12 @@
+// PR c++/114854
+// { dg-do compile { target c++14 } }
+
+struct Vector {
+  int m_size;
+};
+struct S {
+  const Vector {};
+};
+
+void spawn(S);
+void test() { spawn({}); }

base-commit: 0a99ad5c52caa06c113b1889bbe6634812b89be5




[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;


Re: [PATCH v2] c++: DR 569, DR 1693: fun with semicolons [PR113760]

2024-05-14 Thread Jason Merrill

On 5/14/24 12:55, Marek Polacek wrote:

On Thu, May 09, 2024 at 12:44:52PM -0400, Jason Merrill wrote:

On 5/9/24 12:16, Marek Polacek wrote:

+static void
+maybe_warn_extra_semi (location_t loc, extra_semi_kind kind)
+{
+  /* -Wno-extra-semi suppresses all.  */
+  if (warn_extra_semi == 0)
+return;
+
+  gcc_rich_location richloc (loc);
+  richloc.add_fixit_remove ();
+
+  switch (kind)
+{
+case extra_semi_kind::decl:
+  if (warn_extra_semi > 0)
+   warning_at (, OPT_Wextra_semi,
+   "extra %<;%> outside of a function");
+  /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
+effect in C++98.  DR 569 says that spurious semicolons at namespace
+scope should be allowed.  */
+  else if (pedantic && cxx_dialect < cxx11)
+   pedwarn (, OPT_Wextra_semi,
+"extra %<;%> outside of a function only allowed in C++11");


Shouldn't the pedwarn case come first?


Yes, I suppose we want both
-Wpedantic -std=c++98
-Wpedantic -std=c++98 -Wextra-semi
to give pedwarns.  Fixed.
  

+  break;
+
+case extra_semi_kind::member:
+  if (warn_extra_semi > 0)
+   warning_at (, OPT_Wextra_semi, "extra %<;%> inside a struct");
+  /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
+effect in C++98.  DR 1693 added "empty-declaration" to the syntax for
+"member-declaration".  */
+  else if (pedantic && cxx_dialect < cxx11)
+   pedwarn (, OPT_Wextra_semi,
+"extra %<;%> inside a struct only allowed in C++11");


And here.


Fixed too.


+  break;
+
+case extra_semi_kind::in_class_fn_def:
+  /* A single semicolon is valid after a member function definition
+so this is just a warning.  */
+  if (warn_extra_semi > 0)
+   warning_at (, OPT_Wextra_semi,
+   "extra %<;%> after in-class function definition");
+  break;
+
+default:
+  gcc_unreachable ();
+}
+}
+
   /* Declarations [gram.dcl.dcl] */
   /* Parse an optional declaration-sequence.  TOP_LEVEL is true, if this
@@ -15430,11 +15485,11 @@ cp_parser_declaration (cp_parser* parser, tree 
prefix_attrs)
 if (token1->type == CPP_SEMICOLON)
   {
-  cp_lexer_consume_token (parser->lexer);
+  location_t semicolon_loc
+   = cp_lexer_consume_token (parser->lexer)->location;
 /* A declaration consisting of a single semicolon is invalid
-   * before C++11.  Allow it unless we're being pedantic.  */
-  if (cxx_dialect < cxx11)
-   pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
+before C++11.  Allow it unless we're being pedantic.  */
+  maybe_warn_extra_semi (semicolon_loc, extra_semi_kind::decl);
 return;
   }
 else if (cp_lexer_nth_token_is (parser->lexer,
@@ -28121,19 +28176,27 @@ cp_parser_member_declaration (cp_parser* parser)
   struct S { ; };
-[class.mem]
+[class.mem] used to say
 Each member-declaration shall declare at least one member
-name of the class.  */
+name of the class.
+
+but since DR 1693:
+
+A member-declaration does not declare new members of the class
+if it is
+-- [...]
+-- an empty-declaration.
+For any other member-declaration, each declared entity that is not
+an unnamed bit-field is a member of the class, and each such
+member-declaration shall either declare at least one member name of
+the class or declare at least one unnamed bit-field.  */
 if (!decl_specifiers.any_specifiers_p)
{
  cp_token *token = cp_lexer_peek_token (parser->lexer);
- if (cxx_dialect < cxx11 && !in_system_header_at (token->location))
-   {
- gcc_rich_location richloc (token->location);
- richloc.add_fixit_remove ();
- pedwarn (, OPT_Wpedantic, "extra %<;%>");
-   }
+ // ??? Should we check !in_system_header_at in maybe_warn_extra_semi?


The system header check seems to date back to PR 12479.  Apparently it has
not ever proved necessary for the other cases.

Furthermore, all pedwarns are now ignored in system headers unless
-Wsystem-headers is specified, in which case it would seem useful to report
this.

So, my inclination is to drop the system header check entirely at this
point.


Done.

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


OK.


-- >8 --
Prompted by c++/113760, I started looking into a bogus "extra ;"
warning in C++11.  It quickly turned out that if I want to fix
this for good, the fix will not be so small.

This patch touches on DR 569, an extra ; at namespace scope should
be allowed since C++11:

   struct S {
   };
   ; // pedwarn in C++9

Re: [PATCH v5 2/5] C++: Support clang compatible [[musttail]] (PR83324)

2024-05-14 Thread Jason Merrill

On 5/14/24 13:24, Andi Kleen wrote:

Hi Jason,

On Mon, May 06, 2024 at 11:02:20PM -0400, Jason Merrill wrote:

@@ -30189,7 +30207,7 @@ cp_parser_std_attribute (cp_parser *parser, tree 
attr_ns)
   /* Maybe we don't expect to see any arguments for this attribute.  */
   const attribute_spec *as
 = lookup_attribute_spec (TREE_PURPOSE (attribute));
-if (as && as->max_length == 0)
+if ((as && as->max_length == 0) || is_attribute_p ("musttail", attr_id))


I'd prefer to add an attribute to the table, rather than special-case it
here; apart from consistency, it seems likely that someone will later want
to apply it to a function.


Just to clarify. I can add it to the table, but it would be a nop there
for now because the table is not used for statement attributes by
the current parser.


Agreed.


You need a template testcase; I expect it doesn't work in templates with the
current patch.  It's probably enough to copy it in tsubst_expr where we
currently propagate CALL_EXPR_OPERATOR_SYNTAX.


I tried it with the appended test case, everything seems to work without
changes.

Does it cover the cases you were concerned about?


Not fully; this testcase doesn't seem to check for errors if tail-call 
fails, only whether the syntax is accepted.  So it would pass if the 
attribute were simply ignored.


Did you also see this comment?

It seems to me that if we were to pass _attrs to cp_parser_jump_statement, we could handle this entirely in that function rather than adding a flag to finish_return_stmt and check_return_stmt. 


Jason



[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));
 }


Re: [PATCH] c++: add test for DR 2855

2024-05-14 Thread Jason Merrill

On 5/14/24 13:54, Marek Polacek wrote:

Tested x86_64-pc-linux-gnu, OK to add such a test?


OK.


-- >8 --
Let

   int8_t x = 127;

This DR says that while

   x++;

invokes UB,

   ++x;

does not.  The resolution was to make the first one valid.  The
following test verifies that we don't report any errors in a constexpr
context.

DR 2855

gcc/testsuite/ChangeLog:

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

diff --git a/gcc/testsuite/g++.dg/DRs/dr2855.C 
b/gcc/testsuite/g++.dg/DRs/dr2855.C
new file mode 100644
index 000..b4609ceaa15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2855.C
@@ -0,0 +1,16 @@
+// DR 2855, Undefined behavior in postfix increment
+// { dg-do compile { target c++14 } }
+
+using int8_t = signed char;
+
+constexpr int
+f ()
+{
+  int8_t x = 127;
+  x++;
+  int8_t z = 127;
+  ++z;
+  return x + z;
+}
+
+constexpr int i = f();

base-commit: c290e6a0b7a9de5692963affc6627a4af7dc2411




PING Re: [PATCH RFA (cgraph)] c++: pragma target and static init [PR109753]

2024-05-14 Thread Jason Merrill

Ping

On 5/2/24 09:54, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu, OK for trunk?  14.2?

This two-year-old thread seems relevant:
https://gcc.gnu.org/pipermail/gcc-patches/2022-April/593410.html

-- 8< --

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

At least one of the create_same_body_alias/handle_optimize_attribute changes
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/ChangeLog:

* cgraph.cc (cgraph_node::create_same_body_alias): Set
semantic_interposition.

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.
---
  gcc/c-family/c-attribs.cc | 4 
  gcc/cgraph.cc | 2 ++
  gcc/cp/decl.cc| 3 +++
  gcc/testsuite/g++.dg/opt/always_inline1.C | 8 
  4 files changed, 17 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/opt/always_inline1.C

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/cgraph.cc b/gcc/cgraph.cc
index 473d8410bc9..f3bd2fa8ece 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -604,6 +604,8 @@ cgraph_node::create_same_body_alias (tree alias, tree decl)
  
n = cgraph_node::create_alias (alias, decl);

n->cpp_implicit_alias = true;
+  /* Aliases don't go through finalize_function.  */
+  n->semantic_interposition = opt_for_fn (decl, flag_semantic_interposition);
if (symtab->cpp_implicit_aliases_done)
  n->resolve_alias (cgraph_node::get (decl));
return n;
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 378311c0f04..4531d830462 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17796,6 +17796,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;

base-commit: 2f15787f2e1a3afe2c2ad93d4eb0d3c1f73c8fbd




Re: [PATCH v25 20/23] c++: Implement __is_invocable built-in trait

2024-05-10 Thread Jason Merrill

On 5/10/24 12:14, Ken Matsui wrote:

Removed the redundant check and fixed the flow.  Could you please review this
again?


Looks good!  All the compiler trait patches are OK.


-- >8 --

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc |   6 +
  gcc/cp/cp-trait.def  |   1 +
  gcc/cp/cp-tree.h |   2 +
  gcc/cp/method.cc | 135 +
  gcc/cp/semantics.cc  |   5 +
  gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
  gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
  gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 +
  gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 
  gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
  10 files changed, 724 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable1.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable2.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable3.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable4.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428e..6d14ef7dcc7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_FUNCTION:
inform (loc, "  %qT is not a function", t1);
break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
  case CPTK_IS_LAYOUT_COMPATIBLE:
inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d..4e420d5390a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
  DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 52d6841559c..8aa41f7147f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7340,6 +7340,8 @@ extern tree get_copy_assign   (tree);
  extern tree get_default_ctor  (tree);
  extern tree get_dtor  (tree, tsubst_flags_t);
  extern tree build_stub_object (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
  extern tree strip_inheriting_ctors(tree);
  extern tree inherited_ctor_binfo  (tree);
  extern bool base_ctor_omit_inherited_parms(tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb01..0b21656ed61 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,141 @@ build_trait_object (tree type)
return build_stub_object (type);
  }
  
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the

+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree non_ref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (non_ref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (non_ref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = non_ref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P 

Re: [PATCH] c++: Optimize in maybe_clone_body aliases even when not at_eof [PR113208]

2024-05-10 Thread Jason Merrill

On 5/9/24 14:20, Jakub Jelinek wrote:

On Thu, Apr 25, 2024 at 11:30:48AM -0400, Jason Merrill wrote:

Hmm, maybe maybe_clone_body shouldn't clear DECL_SAVED_TREE for aliases, but
rather set it to some stub like void_node?

Though with all these changes, it's probably better to go with your first
patch for GCC 14 and delay this approach to 15.  Your v1 patch is OK for 14.


Ok, here is an updated patch, which sets DECL_SAVED_TREE to void_node for
the aliases together with reversion of the earlier committed patch.

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

2024-05-09  Jakub Jelinek  
Jason Merrill  

PR lto/113208
* cp-tree.h (maybe_optimize_cdtor): Remove.
* decl2.cc (tentative_decl_linkage): Call maybe_make_one_only
for implicit instantiations of maybe in charge ctors/dtors
declared inline.
(import_export_decl): Don't call maybe_optimize_cdtor.
(c_parse_final_cleanups): Formatting fixes.
* optimize.cc (can_alias_cdtor): Adjust condition, for
HAVE_COMDAT_GROUP && DECL_ONE_ONLY && DECL_WEAK return true even
if not DECL_INTERFACE_KNOWN.



--- gcc/cp/optimize.cc.jj   2024-04-25 20:33:30.771858912 +0200
+++ gcc/cp/optimize.cc  2024-05-09 17:10:23.920478922 +0200
@@ -220,10 +220,8 @@ can_alias_cdtor (tree fn)
gcc_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn));
/* Don't use aliases for weak/linkonce definitions unless we can put both
   symbols in the same COMDAT group.  */
-  return (DECL_INTERFACE_KNOWN (fn)
- && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn))
- && (!DECL_ONE_ONLY (fn)
- || (HAVE_COMDAT_GROUP && DECL_WEAK (fn;
+  return (DECL_WEAK (fn) ? (HAVE_COMDAT_GROUP && DECL_ONE_ONLY (fn))
+: (DECL_INTERFACE_KNOWN (fn) && !DECL_ONE_ONLY (fn)));


Hmm, would

(DECL_ONE_ONLY (fn) ? HAVE_COMDAT_GROUP
 : (DECL_INTERFACE_KNOWN (fn) && !DECL_WEAK (fn)))

make sense instead?  I don't think DECL_WEAK is necessary for COMDAT.

Jason



Re: [PATCH] c++: lvalueness of non-dependent assignment [PR114994]

2024-05-10 Thread Jason Merrill

On 5/9/24 16:29, Patrick Palka wrote:

On Thu, 9 May 2024, Patrick Palka wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk/14?  For trunk as a follow-up I can implement the
mentionted representation change to use CALL_EXPR instead of
MODOP_EXPR for a non-dependent simple assignment expression that
resolved to an operator= overload.


FWIW, this is the WIP patch for that including the -Wparentheses
logic adjustments needed to avoid regressing
g++.dg/warn/Wparentheses-{32,33}.C

PR c++/114994

gcc/cp/ChangeLog:

* call.cc (build_new_op): Pass 'overload' to
cp_build_modify_expr.
* cp-tree.h (cp_build_modify_expr): New overload that
takes a tree* out-parameter.
* pt.cc (tsubst_expr) : Propagate
OPT_Wparentheses warning suppression to the result.
* semantics.cc (is_assignment_op_expr_p): Also recognize
templated operator expressions represented as a CALL_EXPR
to operator=.
* typeck.cc (cp_build_modify_expr): Add 'overload'
out-parameter and pass it to build_new_op.
(build_x_modify_expr): Pass 'overload' to cp_build_modify_expr.
---
  gcc/cp/call.cc |  2 +-
  gcc/cp/cp-tree.h   |  3 +++
  gcc/cp/pt.cc   |  2 ++
  gcc/cp/semantics.cc| 11 +++
  gcc/cp/typeck.cc   | 18 ++
  5 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 7c4ecf08c4b..1cd4992330c 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -7473,7 +7473,7 @@ build_new_op (const op_location_t , enum tree_code 
code, int flags,
switch (code)
  {
  case MODIFY_EXPR:
-  return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
+  return cp_build_modify_expr (loc, arg1, code2, arg2, overload, complain);
  
  case INDIRECT_REF:

return cp_build_indirect_ref (loc, arg1, RO_UNARY_STAR, complain);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f82446331b3..505c04c6e52 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8264,6 +8264,9 @@ extern tree cp_build_c_cast   
(location_t, tree, tree,
  extern cp_expr build_x_modify_expr(location_t, tree,
 enum tree_code, tree,
 tree, tsubst_flags_t);
+extern tree cp_build_modify_expr   (location_t, tree,
+enum tree_code, tree,
+tree *, tsubst_flags_t);
  extern tree cp_build_modify_expr  (location_t, tree,
 enum tree_code, tree,
 tsubst_flags_t);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f3d52acaaac..bc71e534cf8 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21091,6 +21091,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
if (warning_suppressed_p (t, OPT_Wpessimizing_move))
  /* This also suppresses -Wredundant-move.  */
  suppress_warning (ret, OPT_Wpessimizing_move);
+   if (warning_suppressed_p (t, OPT_Wparentheses))
+ suppress_warning (STRIP_REFERENCE_REF (ret), OPT_Wparentheses);
  }
  
  	RETURN (ret);

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b8c2bf8771f..e81f2b50d80 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -863,6 +863,17 @@ is_assignment_op_expr_p (tree t)
  return false;
  
tree fndecl = cp_get_callee_fndecl_nofold (call);

+  if (!fndecl
+  && processing_template_decl
+  && TREE_CODE (CALL_EXPR_FN (call)) == COMPONENT_REF)
+{
+  /* Also recognize (non-dependent) templated operator expressions that
+are represented as a direct call to operator=.
+TODO: maybe move this handling to cp_get_fndecl_from_callee for
+benefit of other callers.  */


Please.

Jason



Re: [PATCH] c++: lvalueness of non-dependent assignment [PR114994]

2024-05-10 Thread Jason Merrill

On 5/9/24 16:23, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk/14?  For trunk as a follow-up I can implement the
mentionted representation change to use CALL_EXPR instead of
MODOP_EXPR for a non-dependent simple assignment expression that
resolved to an operator= overload.

-- >8 --

r14-4111 made us check non-dependent assignment expressions ahead of
time, as well as give them a type.  Unlike for compound assignment
expressions however, if a simple assignment resolves to an operator
overload we still represent it as a (typed) MODOP_EXPR instead of a
CALL_EXPR to the selected overload.  This, I reckoned, was just a
pessimization (since we'll have to repeat overload resolution at
instantiatiation time) but should be harmless.  (And it should be
easily fixable by giving cp_build_modify_expr an 'overload' parameter).

But it breaks the below testcase ultimately because MODOP_EXPR (of
non-reference type) is always treated as an lvalue according to
lvalue_kind, which is incorrect for the MODOP_EXPR representing x=42.

We can fix this by representing such assignment expressions as CALL_EXPRs
matching what that of compound assignments, but that turns out to
require some tweaking of our -Wparentheses warning logic which seems
unsuitable for backporting.

So this patch instead more conservatively fixes this by refining
lvalue_kind to consider the type of a (simple) MODOP_EXPR as we
already do for COND_EXPR.

PR c++/114994

gcc/cp/ChangeLog:

* tree.cc (lvalue_kind) : Consider the
type of a simple assignment expression.

gcc/testsuite/ChangeLog:

* g++.dg/template/non-dependent32.C: New test.
---
  gcc/cp/tree.cc |  7 +++
  .../g++.dg/template/non-dependent32.C  | 18 ++
  2 files changed, 25 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/template/non-dependent32.C

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index f1a23ffe817..0b97b789aab 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -275,6 +275,13 @@ lvalue_kind (const_tree ref)
/* We expect to see unlowered MODOP_EXPRs only during
 template processing.  */
gcc_assert (processing_template_decl);
+  if (TREE_CODE (TREE_OPERAND (ref, 1)) == NOP_EXPR
+ && CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0
+   /* As in the COND_EXPR case, but for non-dependent assignment
+  expressions created by build_x_modify_expr.  */
+   goto default_;


This seems overly specific, I'd think the same thing would apply to += 
and such?


Jason



Re: [PATCH v24 20/23] c++: Implement __is_invocable built-in trait

2024-05-10 Thread Jason Merrill

On 5/10/24 10:45, Ken Matsui wrote:

Fixed the incorrect if condition.  Could you please review this again?

-- >8 --

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc |   6 +
  gcc/cp/cp-trait.def  |   1 +
  gcc/cp/cp-tree.h |   2 +
  gcc/cp/method.cc | 139 +
  gcc/cp/semantics.cc  |   5 +
  gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
  gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
  gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 +
  gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 
  gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
  10 files changed, 728 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable1.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable2.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable3.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable4.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428e..6d14ef7dcc7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_FUNCTION:
inform (loc, "  %qT is not a function", t1);
break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
  case CPTK_IS_LAYOUT_COMPATIBLE:
inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d..4e420d5390a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
  DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 52d6841559c..8aa41f7147f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7340,6 +7340,8 @@ extern tree get_copy_assign   (tree);
  extern tree get_default_ctor  (tree);
  extern tree get_dtor  (tree, tsubst_flags_t);
  extern tree build_stub_object (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
  extern tree strip_inheriting_ctors(tree);
  extern tree inherited_ctor_binfo  (tree);
  extern bool base_ctor_omit_inherited_parms(tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb01..bbe91a276e1 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,145 @@ build_trait_object (tree type)
return build_stub_object (type);
  }
  
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the

+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree non_ref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (non_ref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (non_ref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = non_ref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (fn_type);
+}
+
+  

Re: [PATCH v23 20/23] c++: Implement __is_invocable built-in trait

2024-05-10 Thread Jason Merrill

On 5/10/24 07:24, Ken Matsui wrote:

Fixed the reference to pointer to class case.  Ok for trunk?

-- >8 --

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc |   6 +
  gcc/cp/cp-trait.def  |   1 +
  gcc/cp/cp-tree.h |   2 +
  gcc/cp/method.cc | 139 +
  gcc/cp/semantics.cc  |   5 +
  gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
  gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
  gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 +
  gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 
  gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
  10 files changed, 728 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable1.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable2.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable3.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable4.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428e..6d14ef7dcc7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_FUNCTION:
inform (loc, "  %qT is not a function", t1);
break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
  case CPTK_IS_LAYOUT_COMPATIBLE:
inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d..4e420d5390a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
  DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 52d6841559c..8aa41f7147f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7340,6 +7340,8 @@ extern tree get_copy_assign   (tree);
  extern tree get_default_ctor  (tree);
  extern tree get_dtor  (tree, tsubst_flags_t);
  extern tree build_stub_object (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
  extern tree strip_inheriting_ctors(tree);
  extern tree inherited_ctor_binfo  (tree);
  extern bool base_ctor_omit_inherited_parms(tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb01..7e66d67f5d9 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,145 @@ build_trait_object (tree type)
return build_stub_object (type);
  }
  
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the

+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree non_ref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (non_ref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (non_ref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = non_ref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (fn_type);
+}
+
+  if 

Re: [PATCH] c++, mingw, v2: Fix up types of dtor hooks to __cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968]

2024-05-09 Thread Jason Merrill

On 5/9/24 14:46, Jakub Jelinek wrote:

On Thu, May 09, 2024 at 01:05:59PM -0400, Jason Merrill wrote:

I think I'd rather pass ob_parm to start_cleanup_fn, where it can also
replace the flag_use_cxa_atexit check in that function.


Good idea, changed in the following patch.


@@ -9998,7 +10004,8 @@ register_dtor_fn (tree decl)
   {
 /* We must convert CLEANUP to the type that "__cxa_atexit"
 expects.  */
-  cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
+  cleanup = build_nop (ob_parm ? get_cxa_atexit_fn_ptr_type ()
+  : get_atexit_fn_ptr_type (), cleanup);


If we're (now) using the correct type to build the cleanup fn, this
conversion should be unnecessary.


This is the use_dtor case, where cleanup will have METHOD_TYPE, so
I think we need to cast.  But, we can cast always to
get_cxa_atexit_fn_ptr_type () type, because this is in use_dtor guarded code
and use_dtor is ob_parm && CLASS_TYPE_P (type), so when use_dtor is true,
ob_parm is also true.

Ok for trunk if it passes another bootstrap/regtest?


OK.


2024-05-09  Jakub Jelinek  

PR target/114968
gcc/
* target.def (use_atexit_for_cxa_atexit): Remove spurious space
from comment.
(adjust_cdtor_callabi_fntype): New cxx target hook.
* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
function.
* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
* doc/tm.texi: Regenerate.
* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
function.
(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
gcc/cp/
* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
comments.
(get_cxa_atexit_fn_ptr_type): Declare.
* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
build type for atexit argument.
(get_cxa_atexit_fn_ptr_type): New function.
(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
get_atexit_fn_ptr_type when using __cxa_atexit.
(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
rather than get_atexit_fn_ptr_type.
(start_cleanup_fn): Add ob_parm argument, call
get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
on it and create PARM_DECL also based on that argument.
(register_dtor_fn): Adjust start_cleanup_fn caller, use
get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
for use_dtor casts.
* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().

--- gcc/target.def.jj   2024-05-09 10:30:54.926503473 +0200
+++ gcc/target.def  2024-05-09 20:27:16.294780780 +0200
@@ -6498,7 +6498,7 @@ is in effect.  The default is to return
   hook_bool_void_false)
  
  /* Returns true if target may use atexit in the same manner as

-   __cxa_atexit  to register static destructors.  */
+   __cxa_atexit to register static destructors.  */
  DEFHOOK
  (use_atexit_for_cxa_atexit,
   "This hook returns true if the target @code{atexit} function can be used\n\
@@ -6509,6 +6509,17 @@ unloaded. The default is to return false
   bool, (void),
   hook_bool_void_false)
  
+/* Returns modified FUNCTION_TYPE for cdtor callabi.  */

+DEFHOOK
+(adjust_cdtor_callabi_fntype,
+ "This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments\n\
+to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}\n\
+function pointers.  ABIs like mingw32 require special attributes to be added\n\
+to function types pointed to by arguments of these functions.\n\
+The default is to return the passed argument unmodified.",
+ tree, (tree fntype),
+ default_cxx_adjust_cdtor_callabi_fntype)
+
  DEFHOOK
  (adjust_class_at_definition,
  "@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just\n\
--- gcc/targhooks.h.jj  2024-05-09 10:30:54.941503269 +0200
+++ gcc/targhooks.h 2024-05-09 20:27:16.315780505 +0200
@@ -65,6 +65,7 @@ extern machine_mode default_mode_for_suf
  
  extern tree default_cxx_guard_type (void);

  extern tree default_cxx_get_cookie_size (tree);
+extern tree default_cxx_adjust_cdtor_callabi_fntype (tree);
  
  extern bool hook_pass_by_reference_must_pass_in_stack

(cumulative_args_t, const function_arg_info &);
--- gcc/targhooks.cc.jj 2024-05-09 10:30:54.927503459 +0200
+++ gcc/targhooks.cc2024-05-09 20:27:16.338780204 +0200
@@ -329,6 +329,14 @@ default_cxx_get_cookie_size (tree type)
return cookie_size;
  }
  
+/* Returns modified FUNCTION_TYPE for cdtor callabi.  */

+
+tree
+default_cxx_adjust_cdtor_callabi_fntype (tree fntype)
+{
+  return fntype;
+}
+
  /* Return true if a parameter must be passed by reference.  This version
 of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
  
--- gcc/doc/tm.texi

Re: [PATCH v2] c++: failure to suppress -Wsizeof-array-div in template [PR114983]

2024-05-09 Thread Jason Merrill

On 5/9/24 15:28, Marek Polacek wrote:

On Thu, May 09, 2024 at 12:51:28PM -0400, Jason Merrill wrote:

On 5/9/24 12:03, Marek Polacek wrote:

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8787eabb9fd..46cf8a737fb 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20569,6 +20569,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
TREE_SIDE_EFFECTS (r) = 0;
TREE_READONLY (r) = 1;
  }
+   copy_warning (r, t);
SET_EXPR_LOCATION (r, EXPR_LOCATION (t));


copy_warning is defined in terms of locations (as well as TREE_NO_WARNING),
so copying it before setting the location looks wrong.


Sigh.  Since 'r' had no location, this just set TREE_NO_WARNING, also fixing
this test.  But it's not what I meant to do.

Fixed below, thanks.

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


OK.


-- >8 --
-Wsizeof-array-div offers a way to suppress the warning by wrapping
the second operand of the division in parens:

   sizeof (samplesBuffer) / (sizeof(unsigned char))

but this doesn't work in a template, because we fail to propagate
the suppression bits.  Do it, then.

The finish_parenthesized_expr hunk is not needed because suppress_warning
isn't very fine-grained.  But I think it makes sense to be explicit and
not rely on OPT_Wparentheses also suppressing OPT_Wsizeof_array_div.

PR c++/114983

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr) : Use copy_warning.
* semantics.cc (finish_parenthesized_expr): Also suppress
-Wsizeof-array-div.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wsizeof-array-div3.C: New test.
---
  gcc/cp/pt.cc  |  1 +
  gcc/cp/semantics.cc   |  2 ++
  .../g++.dg/warn/Wsizeof-array-div3.C  | 27 +++
  3 files changed, 30 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8787eabb9fd..a7d9fcf930e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20570,6 +20570,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
TREE_READONLY (r) = 1;
  }
SET_EXPR_LOCATION (r, EXPR_LOCATION (t));
+   copy_warning (r, t);
  }
RETURN (r);
}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b8c2bf8771f..71520dcd4fa 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2306,6 +2306,8 @@ finish_parenthesized_expr (cp_expr expr)
/* This inhibits warnings in maybe_warn_unparenthesized_assignment
 and c_common_truthvalue_conversion.  */
suppress_warning (STRIP_REFERENCE_REF (*expr), OPT_Wparentheses);
+  /* And maybe_warn_sizeof_array_div.  */
+  suppress_warning (STRIP_REFERENCE_REF (*expr), OPT_Wsizeof_array_div);
  }
  
if (TREE_CODE (expr) == OFFSET_REF

diff --git a/gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C 
b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C
new file mode 100644
index 000..bfd690325e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C
@@ -0,0 +1,27 @@
+// PR c++/114983
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wsizeof-array-div" }
+
+using size_t = decltype (sizeof (0));
+unsigned int samplesBuffer[40];
+
+template 
+constexpr inline size_t fn1()
+{
+  return ((sizeof(samplesBuffer)) / (sizeof(T))); // { dg-bogus "expression does 
not compute" }
+}
+
+template 
+constexpr inline size_t fn2()
+{
+  return ((sizeof(samplesBuffer)) / sizeof(T)); // { dg-warning "expression does 
not compute" }
+}
+
+size_t
+g ()
+{
+  auto sz = sizeof (samplesBuffer) / (sizeof(unsigned char));
+  sz += fn1();
+  sz += fn2(); // { dg-message "required from here" }
+  return sz;
+}

base-commit: e02b5683e77c2b4317b23be72e43b6e6cc6c8e5b




Re: [PATCH] c++: ICE with reference NSDMI [PR114854]

2024-05-09 Thread Jason Merrill

On 5/9/24 12:04, Marek Polacek wrote:

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

-- >8 --
Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:

   /* A TARGET_EXPR that expresses direct-initialization should have been
  elided by cp_gimplify_init_expr.  */
   gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

the TARGET_EXPR in question is created for the NSDMI in:

   class Vector { int m_size; };
   struct S {
 const Vector {};
   };

where we first need to create a Vector{} temporary, and then bind the
vec reference to it.  The temporary is represented by a TARGET_EXPR
and it cannot be elided.  When we create an object of type S, we get

   D.2848 = {.vec=(const struct Vector &) _EXPR }

where the TARGET_EXPR is no longer direct-initializing anything.


Seems like the problem is in convert_like_internal:


bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
if (abstract_virtuals_error (NULL_TREE, totype, complain))
  return error_mark_node;
expr = build_value_init (totype, complain);
expr = get_target_expr (expr, complain);
if (expr != error_mark_node)
  {
TARGET_EXPR_LIST_INIT_P (expr) = true;
=>  TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
  }


My patch for 50930 assumed that if a CONSTRUCTOR represents syntactic 
direct-initialization, a resulting TARGET_EXPR is itself the direct 
initializer, but that isn't the case here; the temporary is 
copy-initialized.


We could calculate direct-initializanity from cand->flags, but perhaps 
we can just stop trying to set TARGET_EXPR_DIRECT_INIT_P here at all? 
We don't do that for other list-initialization in ck_user, I don't know 
why I thought it was needed for {} specifically.  It doesn't seem to be 
needed for the 50930 testcase.


Jason



Re: [PATCH] c++: nested aggregate/alias CTAD fixes

2024-05-09 Thread Jason Merrill

On 5/8/24 13:49, Patrick Palka wrote:

Bootstrapped and regtested on x86-64-pc-linux-gnu, does this look
OK for trunk and perhaps 14?


OK for both.


-- >8 --

During maybe_aggr_guide with a nested class template and paren init,
like with list init we need to consider the generic template type rather
than the partially instantiated type since only the former has
TYPE_FIELDS.  And in turn we need to partially substitute PARMs in the
paren init case as well.  As a drive-by improvement it seems better to
use outer_template_args instead of DECL_TI_ARGS during this partial
substitution so that we lower instead of substitute the innermost
generic template arguments, which is generally more robust.

And during alias_ctad_tweaks with a nested class template, even though
the guides may be already partially instantiated we still need to
use the full set of arguments, not just the innermost, when substituting
its constraints.

PR c++/114974
PR c++/114901
PR c++/114903

gcc/cp/ChangeLog:

* pt.cc (maybe_aggr_guide): Fix obtaining TYPE_FIELDS in
the paren init case.  Hoist out partial substitution logic
to apply to the paren init case as well.
(alias_ctad_tweaks): Substitute constraints using the full
set of template arguments.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/class-deduction-aggr14.C: New test.
* g++.dg/cpp2a/class-deduction-alias20.C: New test.
* g++.dg/cpp2a/class-deduction-alias21.C: New test.
---
  gcc/cp/pt.cc  | 39 +++
  .../g++.dg/cpp2a/class-deduction-aggr14.C | 11 ++
  .../g++.dg/cpp2a/class-deduction-alias20.C| 22 +++
  .../g++.dg/cpp2a/class-deduction-alias21.C| 38 ++
  4 files changed, 93 insertions(+), 17 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr14.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias20.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias21.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1816bfd1f40..f3d52acaaac 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30192,26 +30192,11 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
if (init == error_mark_node)
return NULL_TREE;
parms = collect_ctor_idx_types (init, parms);
-  /* If we're creating a deduction guide for a member class template,
-we've used the original template pattern type for the reshape_init
-above; this is done because we want PARMS to be a template parameter
-type, something that can be deduced when used as a function template
-parameter.  At this point the outer class template has already been
-partially instantiated (we deferred the deduction until the enclosing
-scope is non-dependent).  Therefore we have to partially instantiate
-PARMS, so that its template level is properly reduced and we don't get
-mismatches when deducing types using the guide with PARMS.  */
-  if (member_template_p)
-   {
- ++processing_template_decl;
- parms = tsubst (parms, DECL_TI_ARGS (tmpl), complain, init);
- --processing_template_decl;
-   }
  }
else if (TREE_CODE (init) == TREE_LIST)
  {
int len = list_length (init);
-  for (tree field = TYPE_FIELDS (type);
+  for (tree field = TYPE_FIELDS (template_type);
   len;
   --len, field = DECL_CHAIN (field))
{
@@ -30226,6 +30211,22 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec *args)
  /* Aggregate initialization doesn't apply to an initializer expression.  
*/
  return NULL_TREE;
  
+  /* If we're creating a deduction guide for a member class template,

+ we've used the original template pattern type for the reshape_init
+ above; this is done because we want PARMS to be a template parameter
+ type, something that can be deduced when used as a function template
+ parameter.  At this point the outer class template has already been
+ partially instantiated (we deferred the deduction until the enclosing
+ scope is non-dependent).  Therefore we have to partially instantiate
+ PARMS, so that its template level is properly reduced and we don't get
+ mismatches when deducing types using the guide with PARMS.  */
+  if (member_template_p)
+{
+  ++processing_template_decl;
+  parms = tsubst (parms, outer_template_args (tmpl), complain, init);
+  --processing_template_decl;
+}
+
if (parms)
  {
tree last = parms;
@@ -30417,7 +30418,11 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
  /* Substitute the associated constraints.  */
  tree ci = get_constraints (f);
  if (ci)
-   ci = tsubst_constraint_info (ci, targs, complain, in_decl);
+   {
+ if (tree outer_targs = outer_template_args (f))
+   ci = tsubst_constraint_info (ci, 

Re: [PATCH] c++, mingw: Fix up types of dtor hooks to __cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968]

2024-05-09 Thread Jason Merrill

On 5/9/24 05:01, Jakub Jelinek wrote:

Hi!

__cxa_atexit/__cxa_thread_atexit/__cxa_throw functions accept function
pointers to usually directly destructors rather than wrappers around
them.
Now, mingw ia32 uses implicitly __attribute__((thiscall)) calling
conventions for METHOD_TYPE (where the this pointer is passed in %ecx
register, the rest on the stack), so these functions use:
in config/os/mingw32/os_defines.h:
  #if defined (__i386__)
  #define _GLIBCXX_CDTOR_CALLABI __thiscall
  #endif
in libsupc++/cxxabi.h
__cxa_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void*) 
_GLIBCXX_NOTHROW;
__cxa_thread_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void *) 
_GLIBCXX_NOTHROW;
__cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *))
__attribute__((__noreturn__));

Now, mingw for some weird reason uses
  #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook_bool_void_true
so it never actually uses __cxa_atexit, but does use __cxa_thread_atexit
and __cxa_throw.  Recent changes for modules result in more detailed
__cxa_*atexit/__cxa_throw prototypes precreated by the compiler, and if
that happens and one also includes , the compiler complains about
mismatches in the prototypes.

One thing is the missing thiscall attribute on the FUNCTION_TYPE, the
other problem is that all of atexit/__cxa_atexit/__cxa_thread_atexit
get function pointer types gets created by a single function,
get_atexit_fn_ptr_type (), which creates it depending on if atexit
or __cxa_atexit will be used as either void(*)(void) or void(*)(void *),
but when using atexit and __cxa_thread_atexit it uses the wrong function
type for __cxa_thread_atexit.

The following patch adds a target hook to add the thiscall attribute to the
function pointers, and splits the get_atexit_fn_ptr_type () function into
get_atexit_fn_ptr_type () and get_cxa_atexit_fn_ptr_type (), the former always
creates shared void(*)(void) type, the latter creates either
void(*)(void*) (on most targets) or void(__attribute__((thiscall))*)(void*)
(on mingw ia32).  So that we don't waiste another GTY global tree for it,
because cleanup_type used for the same purpose for __cxa_throw should be
the same, the code changes it to use that type too.

In register_dtor_fn then based on the decision whether to use atexit,
__cxa_atexit or __cxa_thread_atexit it picks the right function pointer
type, and also if it decides to emit a __tcf_* wrapper for the cleanup,
uses that type for that wrapper so that it agrees on calling convention.

Bootstrapped/regtested on x86_64-linux and i686-linux and Liu Hao tested
it on mingw32, ok for trunk?

2024-05-09  Jakub Jelinek  

PR target/114968
gcc/
* target.def (use_atexit_for_cxa_atexit): Remove spurious space
from comment.
(adjust_cdtor_callabi_fntype): New cxx target hook.
* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
function.
* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
* doc/tm.texi: Regenerate.
* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
function.
(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
gcc/cp/
* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
comments.
(get_cxa_atexit_fn_ptr_type): Declare.
* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
build type for atexit argument.
(get_cxa_atexit_fn_ptr_type): New function.
(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
get_atexit_fn_ptr_type when using __cxa_atexit.
(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
rather than get_atexit_fn_ptr_type.
(start_cleanup_fn): Add fntype argument, don't call
get_atexit_fn_ptr_type for it.
(register_dtor_fn): Adjust start_cleanup_fn caller, use
get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
when ob_parm is true.
* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().

--- gcc/target.def.jj   2024-05-07 21:28:46.554394913 +0200
+++ gcc/target.def  2024-05-08 11:19:39.290798568 +0200
@@ -6498,7 +6498,7 @@ is in effect.  The default is to return
   hook_bool_void_false)
  
  /* Returns true if target may use atexit in the same manner as

-   __cxa_atexit  to register static destructors.  */
+   __cxa_atexit to register static destructors.  */
  DEFHOOK
  (use_atexit_for_cxa_atexit,
   "This hook returns true if the target @code{atexit} function can be used\n\
@@ -6509,6 +6509,17 @@ unloaded. The default is to return false
   bool, (void),
   hook_bool_void_false)
  
+/* Returns modified FUNCTION_TYPE for cdtor callabi.  */

+DEFHOOK
+(adjust_cdtor_callabi_fntype,
+ "This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments\n\
+to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or 

Re: [PATCH] c++: failure to suppress -Wsizeof-array-div in template [PR114983]

2024-05-09 Thread Jason Merrill

On 5/9/24 12:03, Marek Polacek wrote:

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

-- >8 --
-Wsizeof-array-div offers a way to suppress the warning by wrapping
the second operand of the division in parens:

   sizeof (samplesBuffer) / (sizeof(unsigned char))

but this doesn't work in a template, because we fail to propagate
the suppression bits.  Do it, then.

The finish_parenthesized_expr hunk is not needed because suppress_warning
isn't very fine-grained.  But I think it makes sense to be explicit and
not rely on OPT_Wparentheses also suppressing OPT_Wsizeof_array_div.

PR c++/114983

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr) : Use copy_warning.
* semantics.cc (finish_parenthesized_expr): Also suppress
-Wsizeof-array-div.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wsizeof-array-div3.C: New test.
---
  gcc/cp/pt.cc  |  1 +
  gcc/cp/semantics.cc   |  2 ++
  .../g++.dg/warn/Wsizeof-array-div3.C  | 27 +++
  3 files changed, 30 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8787eabb9fd..46cf8a737fb 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20569,6 +20569,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
TREE_SIDE_EFFECTS (r) = 0;
TREE_READONLY (r) = 1;
  }
+   copy_warning (r, t);
SET_EXPR_LOCATION (r, EXPR_LOCATION (t));


copy_warning is defined in terms of locations (as well as 
TREE_NO_WARNING), so copying it before setting the location looks wrong.



  }
RETURN (r);
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b8c2bf8771f..71520dcd4fa 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2306,6 +2306,8 @@ finish_parenthesized_expr (cp_expr expr)
/* This inhibits warnings in maybe_warn_unparenthesized_assignment
 and c_common_truthvalue_conversion.  */
suppress_warning (STRIP_REFERENCE_REF (*expr), OPT_Wparentheses);
+  /* And maybe_warn_sizeof_array_div.  */
+  suppress_warning (STRIP_REFERENCE_REF (*expr), OPT_Wsizeof_array_div);
  }
  
if (TREE_CODE (expr) == OFFSET_REF

diff --git a/gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C 
b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C
new file mode 100644
index 000..bfd690325e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div3.C
@@ -0,0 +1,27 @@
+// PR c++/114983
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wsizeof-array-div" }
+
+using size_t = decltype (sizeof (0));
+unsigned int samplesBuffer[40];
+
+template 
+constexpr inline size_t fn1()
+{
+  return ((sizeof(samplesBuffer)) / (sizeof(T))); // { dg-bogus "expression does 
not compute" }
+}
+
+template 
+constexpr inline size_t fn2()
+{
+  return ((sizeof(samplesBuffer)) / sizeof(T)); // { dg-warning "expression does 
not compute" }
+}
+
+size_t
+g ()
+{
+  auto sz = sizeof (samplesBuffer) / (sizeof(unsigned char));
+  sz += fn1();
+  sz += fn2(); // { dg-message "required from here" }
+  return sz;
+}

base-commit: 2790195500ec523cad9c7292816540e2fc19f456




Re: [PATCH] c++: DR 569, DR 1693: fun with semicolons [PR113760]

2024-05-09 Thread Jason Merrill

On 5/9/24 12:16, Marek Polacek wrote:

In GCC 14, I submitted a minimal fix for the "extra ; warning", pushed
in r14-8967.  That patch mentions a more complete patch for GCC 15.
This is the patch.

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

-- >8 --
Prompted by c++/113760, I started looking into a bogus "extra ;"
warning in C++11.  It quickly turned out that if I want to fix
this for good, the fix will not be so small.

This patch touches on DR 569, an extra ; at namespace scope should
be allowed since C++11:

   struct S {
   };
   ; // pedwarn in C++98

It also touches on DR 1693, which allows superfluous semicolons in
class definitions since C++11:

   struct S {
 int a;
 ; // pedwarn in C++98
   };

Note that a single semicolon is valid after a member function definition:

   struct S {
 void foo () {}; // only warns with -Wextra-semi
   };

There's a new function maybe_warn_extra_semi to handle all of the above
in a single place.  So now they all get a fix-it hint.

-Wextra-semi turns on all "extra ;" diagnostics.  Currently, options
like -Wc++11-compat or -Wc++11-extensions are not considered.

DR 1693
PR c++/113760
DR 569

gcc/c-family/ChangeLog:

* c.opt (Wextra-semi): Initialize to -1.

gcc/cp/ChangeLog:

* parser.cc (extra_semi_kind): New.
(maybe_warn_extra_semi): New.
(cp_parser_declaration): Call maybe_warn_extra_semi.
(cp_parser_member_declaration): Likewise.

gcc/ChangeLog:

* doc/invoke.texi: Update -Wextra-semi documentation.

gcc/testsuite/ChangeLog:

* g++.dg/diagnostic/semicolon1.C: New test.
* g++.dg/diagnostic/semicolon10.C: New test.
* g++.dg/diagnostic/semicolon11.C: New test.
* g++.dg/diagnostic/semicolon12.C: New test.
* g++.dg/diagnostic/semicolon13.C: New test.
* g++.dg/diagnostic/semicolon14.C: New test.
* g++.dg/diagnostic/semicolon15.C: New test.
* g++.dg/diagnostic/semicolon16.C: New test.
* g++.dg/diagnostic/semicolon17.C: New test.
* g++.dg/diagnostic/semicolon2.C: New test.
* g++.dg/diagnostic/semicolon3.C: New test.
* g++.dg/diagnostic/semicolon4.C: New test.
* g++.dg/diagnostic/semicolon5.C: New test.
* g++.dg/diagnostic/semicolon6.C: New test.
* g++.dg/diagnostic/semicolon7.C: New test.
* g++.dg/diagnostic/semicolon8.C: New test.
* g++.dg/diagnostic/semicolon9.C: New test.
---
  gcc/c-family/c.opt|  2 +-
  gcc/cp/parser.cc  | 94 +++
  gcc/doc/invoke.texi   | 29 +-
  gcc/testsuite/g++.dg/diagnostic/semicolon1.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon10.C | 11 +++
  gcc/testsuite/g++.dg/diagnostic/semicolon11.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon12.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon13.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon14.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon15.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon16.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon17.C | 29 ++
  gcc/testsuite/g++.dg/diagnostic/semicolon2.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon3.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon4.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon5.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon6.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon7.C  | 18 
  gcc/testsuite/g++.dg/diagnostic/semicolon8.C  | 11 +++
  gcc/testsuite/g++.dg/diagnostic/semicolon9.C  | 11 +++
  20 files changed, 468 insertions(+), 19 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon1.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon10.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon11.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon12.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon13.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon14.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon15.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon16.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon17.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon2.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon3.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon4.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon5.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon6.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon7.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon8.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon9.C

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 403abc1f26e..fb34c3b7031 100644
--- a/gcc/c-family/c.opt
+++ 

Re: [PATCH v22 20/23] c++: Implement __is_invocable built-in trait

2024-05-09 Thread Jason Merrill

On 5/8/24 01:04, Ken Matsui wrote:

Fixed the reference_wrapper case.  I used non_ref_datum_type to avoid
potentially multiple build_trait_object calls.

-- >8 --

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc |   6 +
  gcc/cp/cp-trait.def  |   1 +
  gcc/cp/cp-tree.h |   2 +
  gcc/cp/method.cc | 142 +
  gcc/cp/semantics.cc  |   5 +
  gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
  gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
  gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 +
  gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 
  gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
  10 files changed, 731 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable1.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable2.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable3.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable4.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428e..6d14ef7dcc7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_FUNCTION:
inform (loc, "  %qT is not a function", t1);
break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
  case CPTK_IS_LAYOUT_COMPATIBLE:
inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d..4e420d5390a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
  DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 52d6841559c..8aa41f7147f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7340,6 +7340,8 @@ extern tree get_copy_assign   (tree);
  extern tree get_default_ctor  (tree);
  extern tree get_dtor  (tree, tsubst_flags_t);
  extern tree build_stub_object (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
  extern tree strip_inheriting_ctors(tree);
  extern tree inherited_ctor_binfo  (tree);
  extern bool base_ctor_omit_inherited_parms(tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb01..1c3233ca5d7 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,148 @@ build_trait_object (tree type)
return build_stub_object (type);
  }
  
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the

+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree non_ref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (non_ref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (non_ref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = non_ref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (fn_type);
+  

Re: [PATCH] c++: Implement C++26 P2893R3 - Variadic friends [PR114459]

2024-05-07 Thread Jason Merrill

On 5/3/24 12:35, Jakub Jelinek wrote:

Hi!

The following patch imeplements the C++26 P2893R3 - Variadic friends
paper.  The paper allows for the friend type declarations to specify
more than one friend type specifier and allows to specify ... at
the end of each.  The patch doesn't introduce tentative parsing of
friend-type-declaration non-terminal, but rather just extends existing
parsing where it is a friend declaration which ends with ; after the
declaration specifiers to the cases where it ends with ...; or , or ...,
In that case it pedwarns for cxx_dialect < cxx26, handles the ... and
if there is , continues in a loop to parse the further friend type
specifiers.

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

2024-05-03  Jakub Jelinek  

PR c++/114459
gcc/c-family/
* c-cppbuiltin.cc (c_cpp_builtins): Predefine
__cpp_variadic_friend=202403L for C++26.
gcc/cp/
* parser.cc (cp_parser_member_declaration): Implement C++26
P2893R3 - Variadic friends.  Parse friend type declarations
with ... or with more than one friend type specifier.
* friend.cc (make_friend_class): Allow TYPE_PACK_EXPANSION.
* pt.cc (instantiate_class_template): Handle PACK_EXPANSION_P
in friend classes.
gcc/testsuite/
* g++.dg/cpp26/feat-cxx26.C (__cpp_variadic_friend): Add test.
* g++.dg/cpp26/variadic-friend1.C: New test.

--- gcc/c-family/c-cppbuiltin.cc.jj 2024-05-02 09:31:17.746298275 +0200
+++ gcc/c-family/c-cppbuiltin.cc2024-05-03 14:50:08.008242950 +0200
@@ -1093,6 +1093,7 @@ c_cpp_builtins (cpp_reader *pfile)
  cpp_define (pfile, "__cpp_placeholder_variables=202306L");
  cpp_define (pfile, "__cpp_structured_bindings=202403L");
  cpp_define (pfile, "__cpp_deleted_function=202403L");
+ cpp_define (pfile, "__cpp_variadic_friend=202403L");
}
if (flag_concepts)
  {
--- gcc/cp/parser.cc.jj 2024-05-03 09:43:47.781511477 +0200
+++ gcc/cp/parser.cc2024-05-03 13:26:38.208088017 +0200
@@ -28102,7 +28102,14 @@ cp_parser_member_declaration (cp_parser*
  goto out;
/* If there is no declarator, then the decl-specifier-seq should
   specify a type.  */


Let's mention C++26 variadic friends in this comment.  OK with that change.


-  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+  || (cp_parser_friend_p (_specifiers)
+ && cxx_dialect >= cxx11
+ && (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ || (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+ && (cp_lexer_nth_token_is (parser->lexer, 2, CPP_SEMICOLON)
+ || cp_lexer_nth_token_is (parser->lexer, 2,
+   CPP_COMMA))
  {
/* If there was no decl-specifier-seq, and the next token is a
 `;', then we have something like:
@@ -28137,44 +28144,81 @@ cp_parser_member_declaration (cp_parser*
{
  /* If the `friend' keyword was present, the friend must
 be introduced with a class-key.  */
-  if (!declares_class_or_enum && cxx_dialect < cxx11)
-pedwarn (decl_spec_token_start->location, OPT_Wpedantic,
- "in C++03 a class-key must be used "
- "when declaring a friend");
-  /* In this case:
+ if (!declares_class_or_enum && cxx_dialect < cxx11)
+   pedwarn (decl_spec_token_start->location, OPT_Wpedantic,
+"in C++03 a class-key must be used "
+"when declaring a friend");
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ && cxx_dialect < cxx26)
+   pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+OPT_Wc__26_extensions,
+"variadic friends or friend type declarations with "
+"multiple types only available with "
+"%<-std=c++2c%> or %<-std=gnu++2c%>");
+ location_t friend_loc = decl_specifiers.locations[ds_friend];
+ do
+   {
+ /* In this case:
  
-		template  struct A {

- friend struct A::B;
-   };
+template  struct A {
+  friend struct A::B;
+};
  
-		  A::B will be represented by a TYPENAME_TYPE, and

- therefore not recognized by check_tag_decl.  */
-  if (!type)
-{
-  type = decl_specifiers.type;
-  if (type && TREE_CODE (type) == TYPE_DECL)
-type = TREE_TYPE (type);
-}
-  /* Warn if an attribute cannot appear here, as per
- [dcl.attr.grammar]/5.  But not when 

Re: [PATCH] c++/modules: Stream unmergeable temporaries by value again [PR114856]

2024-05-07 Thread Jason Merrill

On 5/7/24 01:35, Nathaniel Shead wrote:

On Thu, May 02, 2024 at 01:53:44PM -0400, Jason Merrill wrote:

On 5/2/24 10:40, Patrick Palka wrote:

On Thu, 2 May 2024, Nathaniel Shead wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk/14.2?

Another alternative would be to stream such !DECL_NAME temporaries with
a merge key of MK_unique rather than attempting to find the matching
(nonexistant) field of the class context.


Both approaches sound good to me, hard to say which one is preferable..

The handling of function-scope vs class-scope temporaries seems to start
diverging in:

@@ -8861,28 +8861,6 @@ trees_out::decl_node (tree decl, walk_kind ref)
 return false;
   }
!  tree ctx = CP_DECL_CONTEXT (decl);
!  depset *dep = NULL;
!  if (streaming_p ())
!dep = dep_hash->find_dependency (decl);
!  else if (TREE_CODE (ctx) != FUNCTION_DECL
!  || TREE_CODE (decl) == TEMPLATE_DECL
!  || DECL_IMPLICIT_TYPEDEF_P (decl)
!  || (DECL_LANG_SPECIFIC (decl)
!  && DECL_MODULE_IMPORT_P (decl)))
!{
!  auto kind = (TREE_CODE (decl) == NAMESPACE_DECL
!  && !DECL_NAMESPACE_ALIAS (decl)
!  ? depset::EK_NAMESPACE : depset::EK_DECL);
!  dep = dep_hash->add_dependency (decl, kind);
!}
!
!  if (!dep)
!{
!  /* Some internal entity of context.  Do by value.  */
!  decl_value (decl, NULL);
!  return false;
!}
 if (dep->get_entity_kind () == depset::EK_REDIRECT)
   {

where for a class-scope temporary we add a dependency for it, stream
it by reference, and then stream it by value separately, which seems
unnecessary.

So if we decide to keep the create_temporary_var change, we probably
would want to unify this code path's handling of temporaries (i.e.
don't add_dependency a temporary regardless of its context).

If we decide your partially revert the create_temporary_var change,
your patch LGTM.


Streaming by value sounds right, but as noted an important difference
between reference temps and others is DECL_NAME.  Perhaps the code Patrick
quotes could look at that as well as the context?

Jason



With my patch we would no longer go through the code that Patrick quotes
for class-scope temporaries that I can see; we would instead first hit
the following code in 'tree_node':


   if (DECL_P (t))
 {
   if (DECL_TEMPLATE_PARM_P (t))
{
  tpl_parm_value (t);
  goto done;
}

   if (!DECL_CONTEXT (t))
{
  /* There are a few cases of decls with no context.  We'll write
 these by value, but first assert they are cases we expect.  */
  gcc_checking_assert (ref == WK_normal);
  switch (TREE_CODE (t))
{
default: gcc_unreachable ();

case LABEL_DECL:
  /* CASE_LABEL_EXPRs contain uncontexted LABEL_DECLs.  */
  gcc_checking_assert (!DECL_NAME (t));
  break;

case VAR_DECL:
  /* AGGR_INIT_EXPRs cons up anonymous uncontexted VAR_DECLs.  */
  gcc_checking_assert (!DECL_NAME (t)
   && DECL_ARTIFICIAL (t));
  break;

case PARM_DECL:
  /* REQUIRES_EXPRs have a tree list of uncontexted
 PARM_DECLS.  It'd be nice if they had a
 distinguishing flag to double check.  */
  break;
}
  goto by_value;
}
 }

  skip_normal:
   if (DECL_P (t) && !decl_node (t, ref))
 goto done;

   /* Otherwise by value */
  by_value:
   tree_value (t);


I think modifying what Patrick pointed out should only be necessary if
we maintain these nameless temporaries as having a class context; for
clarity, is that the direction you'd prefer me to go in to solve this?


I was thinking in this code that it seems fragile to require null 
DECL_CONTEXT to identify something produced by 
create_temporary_var/build_local_temp (which should really be merged).
We could even use is_local_temp instead of checking particular qualities 
directly.


But your patch is OK; please just add a comment to the 
make_temporary_var_for_ref_to_temp change indicating that you're setting 
DECL_CONTEXT to make the variable mergeable.


Thanks,
Jason



Re: [PATCH v21 20/23] c++: Implement __is_invocable built-in trait

2024-05-07 Thread Jason Merrill

On 5/3/24 16:52, Ken Matsui wrote:

Fixed datum reference problem.  Ok for trunk?

-- >8 --

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc |   6 +
  gcc/cp/cp-trait.def  |   1 +
  gcc/cp/cp-tree.h |   2 +
  gcc/cp/method.cc | 137 +
  gcc/cp/semantics.cc  |   5 +
  gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
  gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
  gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 +
  gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 
  gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
  10 files changed, 726 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable1.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable2.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable3.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable4.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428e..6d14ef7dcc7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_FUNCTION:
inform (loc, "  %qT is not a function", t1);
break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
  case CPTK_IS_LAYOUT_COMPATIBLE:
inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d..4e420d5390a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
  DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 52d6841559c..8aa41f7147f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7340,6 +7340,8 @@ extern tree get_copy_assign   (tree);
  extern tree get_default_ctor  (tree);
  extern tree get_dtor  (tree, tsubst_flags_t);
  extern tree build_stub_object (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
  extern tree strip_inheriting_ctors(tree);
  extern tree inherited_ctor_binfo  (tree);
  extern bool base_ctor_omit_inherited_parms(tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb01..80791227a0a 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,143 @@ build_trait_object (tree type)
return build_stub_object (type);
  }
  
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the

+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree deref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (deref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (deref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = deref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (fn_type);
+}
+
+  if (is_ptrdatamem && 

Re: [PATCH v5 2/5] C++: Support clang compatible [[musttail]] (PR83324)

2024-05-06 Thread Jason Merrill

On 5/5/24 14:14, Andi Kleen wrote:

This patch implements a clang compatible [[musttail]] attribute for
returns.


Thanks.


musttail is useful as an alternative to computed goto for interpreters.
With computed goto the interpreter function usually ends up very big
which causes problems with register allocation and other per function
optimizations not scaling. With musttail the interpreter can be instead
written as a sequence of smaller functions that call each other. To
avoid unbounded stack growth this requires forcing a sibling call, which
this attribute does. It guarantees an error if the call cannot be tail
called which allows the programmer to fix it instead of risking a stack
overflow. Unlike computed goto it is also type-safe.

It turns out that David Malcolm had already implemented middle/backend
support for a musttail attribute back in 2016, but it wasn't exposed
to any frontend other than a special plugin.

This patch adds a [[gnu::musttail]] attribute for C++ that can be added
to return statements. The return statement must be a direct call
(it does not follow dependencies), which is similar to what clang
implements. It then uses the existing must tail infrastructure.

For compatibility it also detects clang::musttail

One problem is that tree-tailcall usually fails when optimization
is disabled, which implies the attribute only really works with
optimization on. But that seems to be a reasonable limitation.

Passes bootstrap and full test

PR83324

gcc/cp/ChangeLog:

* cp-tree.h (finish_return_stmt): Add musttail_p.
(check_return_expr): Dito.
* parser.cc (cp_parser_statement): Handle [[musttail]].
(cp_parser_std_attribute): Dito.
(cp_parser_init_statement): Dito.
(cp_parser_jump_statement): Dito.
* semantics.cc (finish_return_stmt): Dito.
* typeck.cc (check_return_expr): Handle musttail_p flag.
---
  gcc/cp/cp-tree.h|  4 ++--
  gcc/cp/parser.cc| 30 --
  gcc/cp/semantics.cc |  6 +++---
  gcc/cp/typeck.cc| 20 ++--
  4 files changed, 47 insertions(+), 13 deletions(-)

@@ -12734,9 +12734,27 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
 NULL_TREE, false);
  break;
  
+	case RID_RETURN:

+ {
+   bool musttail_p = false;
+   std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
+   if (lookup_attribute ("gnu", "musttail", std_attrs))
+ {
+   musttail_p = true;
+   std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
+ }
+   // support this for compatibility
+   if (lookup_attribute ("clang", "musttail", std_attrs))
+ {
+   musttail_p = true;
+   std_attrs = remove_attribute ("clang", "musttail", std_attrs);
+ }
+   statement = cp_parser_jump_statement (parser, musttail_p);


It seems to me that if we were to pass _attrs to 
cp_parser_jump_statement, we could handle this entirely in that function 
rather than adding a flag to finish_return_stmt and check_return_stmt.



@@ -30189,7 +30207,7 @@ cp_parser_std_attribute (cp_parser *parser, tree 
attr_ns)
  /* Maybe we don't expect to see any arguments for this attribute.  */
  const attribute_spec *as
= lookup_attribute_spec (TREE_PURPOSE (attribute));
-if (as && as->max_length == 0)
+if ((as && as->max_length == 0) || is_attribute_p ("musttail", attr_id))


I'd prefer to add an attribute to the table, rather than special-case it 
here; apart from consistency, it seems likely that someone will later 
want to apply it to a function.


You need a template testcase; I expect it doesn't work in templates with 
the current patch.  It's probably enough to copy it in tsubst_expr where 
we currently propagate CALL_EXPR_OPERATOR_SYNTAX.


You also need a testcase where the function returns a class; in that 
case the call will often appear as AGGR_INIT_EXPR rather than CALL_EXPR, 
so you'll need to handle that as well.  And see the places that copy 
flags like CALL_EXPR_OPERATOR_SYNTAX between CALL_EXPR and AGGR_INIT_EXPR.


Jason



Re: [PATCH v3] c++/modules: Fix dangling pointer with imported_temploid_friends

2024-05-06 Thread Jason Merrill

On 5/6/24 18:53, Patrick Palka wrote:

On Mon, 6 May 2024, Jason Merrill wrote:


On 5/3/24 07:17, Nathaniel Shead wrote:

On Thu, May 02, 2024 at 02:05:38PM -0400, Jason Merrill wrote:

On 5/1/24 21:34, Nathaniel Shead wrote:

On Thu, May 02, 2024 at 12:15:44AM +1000, Nathaniel Shead wrote:

On Wed, May 01, 2024 at 09:57:38AM -0400, Patrick Palka wrote:


On Wed, 1 May 2024, Nathaniel Shead wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk
(and
later 14.2)?  I don't think making it a GTY root is necessary but
I felt
perhaps better to be safe than sorry.

Potentially another approach would be to use DECL_UID instead like
how
entity_map does; would that be preferable?

-- >8 --

I got notified by Linaro CI and by checking testresults that there
seems
to be some occasional failures in tpl-friend-4_b.C on some
architectures
and standards modes since r15-59-gb5f6a56940e708.  I haven't been
able
to reproduce but looking at the backtrace I suspect the issue is
that
we're adding to the 'imported_temploid_friend' map a decl that is
ultimately discarded, which then has its address reused by a later
decl
causing a failure in the assert in 'set_originating_module'.

This patch attempts to fix the issue in two ways: by ensuring that
we
only store the decl if we know it's a new decl (and hence won't be
discarded), and by making the imported_temploid_friends map a GTY
root
so that even if the decl does get discarded later the address
isn't
reused.

gcc/cp/ChangeLog:

* module.cc (imported_temploid_friends): Mark GTY, and...
(init_modules): ...allocate from GGC.
(trees_in::decl_value): Only write to
imported_temploid_friends
for new decls.

Signed-off-by: Nathaniel Shead 
---
gcc/cp/module.cc | 7 ---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 5b8ff5bc483..37d38bb9654 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2731,7 +2731,7 @@ static keyed_map_t *keyed_table;
   need to be attached to the same module as the temploid.
This maps
   these decls to the temploid they are instantiated them, as
there is
   no other easy way to get this information.  */
-static hash_map *imported_temploid_friends;
+static GTY(()) hash_map *imported_temploid_friends;
//
/* Tree streaming.   The tree streaming is very specific to the
tree
@@ -8327,7 +8327,8 @@ trees_in::decl_value ()
  if (TREE_CODE (inner) == FUNCTION_DECL
  || TREE_CODE (inner) == TYPE_DECL)
if (tree owner = tree_node ())
-  imported_temploid_friends->put (decl, owner);
+  if (is_new)
+   imported_temploid_friends->put (decl, owner);


Hmm, I'm not seeing this code path getting reached for
tpl-friend-4_b.C.
It seems we're instead adding to imported_temploid_friends from
propagate_defining_module, during tsubst_friend_function.

What seems to be happening is that we we first
tsubst_friend_function
'foo' from TPL, and then we tsubst_friend_function 'foo' from
DEF,
which ends up calling duplicate_decls, which ggc_frees this 'foo'
redeclaration that is still present in the imported_temploid_friends
map.

So I don't think marking imported_temploid_friends as a GC root
would
help with this situation.  If we want to keep
imported_temploid_friends
as a tree -> tree map, I think we just need to ensure that a decl
is removed from the map upon getting ggc_free'd from e.g.
duplicate_decls.


Could we instead move the call to propagate_defining_module down a few
lines, after the pushdecl?


Doing that for tsubst_friend_class seems to work OK with my current test
cases, but for tsubst_friend_function doing so causes ICEs in
'module_may_redeclare' within duplicate_decls because the function is
already marked as attached but the originating module information hasn't
been setup yet.


It's unfortunate that we need to add a hash table entry in order to make it
through duplicate_decls, at which point it becomes dead.  Ah, well.


I suppose with tsubst_friend_class it works though because we can't ever
take the pushdecl branch if an existing type exists that we would call
duplicate_decls on.


But it seems simpler to use DECL_UID as the key instead, since those
never get reused even after the decl gets ggc_free'd IIUC.


It still means garbage entries in the hash_map, which is undesirable even
if
it doesn't cause the same kind of breakage.

Incidentally, decl_tree_map is preferable to hash_map when the
key is always a decl.


Ah thanks, didn't know about decl_tree_map.  I feel that I prefer using
DECL_UIDs explicitly here though; it's also consistent with the existing
usage in entity_map_t, and it looks like decl_tree_map is still perhaps
vulnerable to the original issue here (since DECL_UID is only used for
hashing and not for equality, it looks like?).

Though that said, 'decl_constraints' in constraints.cc seems to be u

Re: [PATCH] c++: replace tf_norm with a local flag

2024-05-06 Thread Jason Merrill

On 5/3/24 11:26, Patrick Palka wrote:

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


OK.


-- >8 --

The tf_norm flag controlling whether to build diagnostic information
during constraint normalization doesn't need to be a global tsubst flag,
and is confusingly named.  This patch replaces it with a boolean flag
local to normalization.

gcc/cp/ChangeLog:

* constraint.cc (norm_info::norm_info): Take a boolean parameter
instead of tsubst_flags_t.
(norm_info::generate_diagnostics): Turn this predicate function
into a data member.
(normalize_logical_operation): Adjust after norm_info changes.
(normalize_concept_check): Likewise.
(normalize_atom): Likewise.
(get_normalized_constraints_from_info): Likewise.
(normalize_concept_definition): Likewise.
(normalize_constraint_expression): Likewise.
(normalize_placeholder_type_constraints): Likewise.
(satisfy_nondeclaration_constraints): Likewise.
* cp-tree.h (enum tsubst_flags): Remove tf_norm.
---
  gcc/cp/constraint.cc | 40 
  gcc/cp/cp-tree.h |  3 +--
  2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8a3b5d80ba7..3f0dab79bcd 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -622,33 +622,29 @@ parameter_mapping_equivalent_p (tree t1, tree t2)
  
  struct norm_info : subst_info

  {
-  explicit norm_info (tsubst_flags_t cmp)
-: norm_info (NULL_TREE, cmp)
+  explicit norm_info (bool diag)
+: norm_info (NULL_TREE, diag)
{}
  
/* Construct a top-level context for DECL.  */
  
-  norm_info (tree in_decl, tsubst_flags_t complain)

-: subst_info (tf_warning_or_error | complain, in_decl)
+  norm_info (tree in_decl, bool diag)
+: subst_info (tf_warning_or_error, in_decl),
+  generate_diagnostics (diag)
{
  if (in_decl)
{
initial_parms = DECL_TEMPLATE_PARMS (in_decl);
-   if (generate_diagnostics ())
+   if (generate_diagnostics)
  context = build_tree_list (NULL_TREE, in_decl);
}
  else
initial_parms = current_template_parms;
}
  
-  bool generate_diagnostics() const

-  {
-return complain & tf_norm;
-  }
-
void update_context(tree expr, tree args)
{
-if (generate_diagnostics ())
+if (generate_diagnostics)
{
tree map = build_parameter_mapping (expr, args, ctx_parms ());
context = tree_cons (map, expr, context);
@@ -679,6 +675,10 @@ struct norm_info : subst_info
   template parameters of ORIG_DECL.  */
  
tree initial_parms = NULL_TREE;

+
+  /* Whether to build diagnostic information during normalization.  */
+
+  bool generate_diagnostics;
  };
  
  static tree normalize_expression (tree, tree, norm_info);

@@ -693,7 +693,7 @@ normalize_logical_operation (tree t, tree args, tree_code 
c, norm_info info)
tree t1 = normalize_expression (TREE_OPERAND (t, 1), args, info);
  
/* Build a new info object for the constraint.  */

-  tree ci = info.generate_diagnostics()
+  tree ci = info.generate_diagnostics
  ? build_tree_list (t, info.context)
  : NULL_TREE;
  
@@ -777,7 +777,7 @@ normalize_concept_check (tree check, tree args, norm_info info)

if (!norm_cache)
  norm_cache = hash_table::create_ggc (31);
norm_entry *entry = nullptr;
-  if (!info.generate_diagnostics ())
+  if (!info.generate_diagnostics)
  {
/* Cache the normal form of the substituted concept-id (when not
 diagnosing).  */
@@ -831,7 +831,7 @@ normalize_atom (tree t, tree args, norm_info info)
if (info.in_decl && concept_definition_p (info.in_decl))
  ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P (atom) = true;
  
-  if (!info.generate_diagnostics ())

+  if (!info.generate_diagnostics)
  {
/* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal
 later can cheaply compare two atoms using just pointer equality.  */
@@ -910,7 +910,7 @@ get_normalized_constraints_from_info (tree ci, tree 
in_decl, bool diag = false)
  
/* Substitution errors during normalization are fatal.  */

++processing_template_decl;
-  norm_info info (in_decl, diag ? tf_norm : tf_none);
+  norm_info info (in_decl, diag);
tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci), info);
--processing_template_decl;
  
@@ -1012,7 +1012,7 @@ normalize_concept_definition (tree tmpl, bool diag)

gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl));
++processing_template_decl;
-  norm_info info (tmpl, diag ? tf_norm : tf_none);
+  norm_info info (tmpl, diag);
tree norm = get_normalized_constraints (def, info);
--processing_template_decl;
  
@@ -1035,7 +1035,7 @@ normalize_constraint_expression (tree expr, norm_info info)

if (!expr || expr == error_mark_node)
  

Re: [PATCH v3] c++/modules: Fix dangling pointer with imported_temploid_friends

2024-05-06 Thread Jason Merrill

On 5/3/24 07:17, Nathaniel Shead wrote:

On Thu, May 02, 2024 at 02:05:38PM -0400, Jason Merrill wrote:

On 5/1/24 21:34, Nathaniel Shead wrote:

On Thu, May 02, 2024 at 12:15:44AM +1000, Nathaniel Shead wrote:

On Wed, May 01, 2024 at 09:57:38AM -0400, Patrick Palka wrote:


On Wed, 1 May 2024, Nathaniel Shead wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk (and
later 14.2)?  I don't think making it a GTY root is necessary but I felt
perhaps better to be safe than sorry.

Potentially another approach would be to use DECL_UID instead like how
entity_map does; would that be preferable?

-- >8 --

I got notified by Linaro CI and by checking testresults that there seems
to be some occasional failures in tpl-friend-4_b.C on some architectures
and standards modes since r15-59-gb5f6a56940e708.  I haven't been able
to reproduce but looking at the backtrace I suspect the issue is that
we're adding to the 'imported_temploid_friend' map a decl that is
ultimately discarded, which then has its address reused by a later decl
causing a failure in the assert in 'set_originating_module'.

This patch attempts to fix the issue in two ways: by ensuring that we
only store the decl if we know it's a new decl (and hence won't be
discarded), and by making the imported_temploid_friends map a GTY root
so that even if the decl does get discarded later the address isn't
reused.

gcc/cp/ChangeLog:

* module.cc (imported_temploid_friends): Mark GTY, and...
(init_modules): ...allocate from GGC.
(trees_in::decl_value): Only write to imported_temploid_friends
for new decls.

Signed-off-by: Nathaniel Shead 
---
   gcc/cp/module.cc | 7 ---
   1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 5b8ff5bc483..37d38bb9654 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2731,7 +2731,7 @@ static keyed_map_t *keyed_table;
  need to be attached to the same module as the temploid.  This maps
  these decls to the temploid they are instantiated them, as there is
  no other easy way to get this information.  */
-static hash_map *imported_temploid_friends;
+static GTY(()) hash_map *imported_temploid_friends;
   //
   /* Tree streaming.   The tree streaming is very specific to the tree
@@ -8327,7 +8327,8 @@ trees_in::decl_value ()
 if (TREE_CODE (inner) == FUNCTION_DECL
 || TREE_CODE (inner) == TYPE_DECL)
   if (tree owner = tree_node ())
-  imported_temploid_friends->put (decl, owner);
+  if (is_new)
+   imported_temploid_friends->put (decl, owner);


Hmm, I'm not seeing this code path getting reached for tpl-friend-4_b.C.
It seems we're instead adding to imported_temploid_friends from
propagate_defining_module, during tsubst_friend_function.

What seems to be happening is that we we first tsubst_friend_function
'foo' from TPL, and then we tsubst_friend_function 'foo' from DEF,
which ends up calling duplicate_decls, which ggc_frees this 'foo'
redeclaration that is still present in the imported_temploid_friends map.

So I don't think marking imported_temploid_friends as a GC root would
help with this situation.  If we want to keep imported_temploid_friends
as a tree -> tree map, I think we just need to ensure that a decl
is removed from the map upon getting ggc_free'd from e.g.  duplicate_decls.


Could we instead move the call to propagate_defining_module down a few
lines, after the pushdecl?


Doing that for tsubst_friend_class seems to work OK with my current test
cases, but for tsubst_friend_function doing so causes ICEs in
'module_may_redeclare' within duplicate_decls because the function is
already marked as attached but the originating module information hasn't
been setup yet.


It's unfortunate that we need to add a hash table entry in order to make 
it through duplicate_decls, at which point it becomes dead.  Ah, well.



I suppose with tsubst_friend_class it works though because we can't ever
take the pushdecl branch if an existing type exists that we would call
duplicate_decls on.


But it seems simpler to use DECL_UID as the key instead, since those
never get reused even after the decl gets ggc_free'd IIUC.


It still means garbage entries in the hash_map, which is undesirable even if
it doesn't cause the same kind of breakage.

Incidentally, decl_tree_map is preferable to hash_map when the
key is always a decl.


Ah thanks, didn't know about decl_tree_map.  I feel that I prefer using
DECL_UIDs explicitly here though; it's also consistent with the existing
usage in entity_map_t, and it looks like decl_tree_map is still perhaps
vulnerable to the original issue here (since DECL_UID is only used for
hashing and not for equality, it looks like?).

Though that said, 'decl_constraints' in constraints.cc seems to be using
it fine (well, with a GTY marking) by using 'remove_constraints' within
duplicate_de

Re: [PATCH] c++: Allow IS_FAKE_BASE_TYPE for union types [PR114954]

2024-05-06 Thread Jason Merrill

On 5/6/24 02:32, Nathaniel Shead wrote:

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

-- >8 --

In some circumstances, unions can also have an __as_base type;


Hmm, even though unions can't be bases I guess that is needed for 
something like


union U {
  int i;
private:
  char c[5];
};

struct A {
  [[no_unique_address]] U u;
  char d;
};

static_assert (sizeof (A) == sizeof (U));

The patch is OK.


we need to make sure that IS_FAKE_BASE_TYPE correctly recognises this.

PR c++/114954

gcc/cp/ChangeLog:

* cp-tree.h (IS_FAKE_BASE_TYPE): Also apply to unions.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr114954.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/cp-tree.h|  2 +-
  gcc/testsuite/g++.dg/modules/pr114954.C | 14 ++
  2 files changed, 15 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr114954.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 933504b4821..fa24217eb2b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2616,7 +2616,7 @@ struct GTY(()) lang_type {
  
  /* True iff NODE is the CLASSTYPE_AS_BASE version of some type.  */

  #define IS_FAKE_BASE_TYPE(NODE)   \
-  (TREE_CODE (NODE) == RECORD_TYPE \
+  (RECORD_OR_UNION_TYPE_P (NODE)   \
 && TYPE_CONTEXT (NODE) && CLASS_TYPE_P (TYPE_CONTEXT (NODE))   \
 && CLASSTYPE_AS_BASE (TYPE_CONTEXT (NODE)) == (NODE))
  
diff --git a/gcc/testsuite/g++.dg/modules/pr114954.C b/gcc/testsuite/g++.dg/modules/pr114954.C

new file mode 100644
index 000..a9787140808
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr114954.C
@@ -0,0 +1,14 @@
+// PR c++/114954
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi main }
+
+export module main;
+
+template 
+union U {
+private:
+  char a[N + 1];
+  int b;
+};
+
+U<4> p;




Re: [PATCH] Fix PR c++/105760: ICE in build_deduction_guide for invalid template

2024-05-06 Thread Jason Merrill

On 5/6/24 09:20, Simon Martin wrote:

Hi,

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. OK for trunk?


OK, thanks.


Thanks!

-- Simon

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a78d9d546d6..9acef73e7ac 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2024-05-06  Simon Martin  
+
+   PR c++/105760
+   * pt.c (build_deduction_guide): Check for error_mark_node
+   result from tsubst_arg_types.
+
  2024-05-03  Jason Merrill  

     PR c++/114935
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d68d688016d..da5d9b8a665 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30018,6 +30018,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/ChangeLog b/gcc/testsuite/ChangeLog
index 03c88bbed07..8c606a8fb4f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2024-05-06  Simon Martin  
+
+   PR c++/105760
+   * g++.dg/parse/error66.C: New test.
+
  2024-05-05  Harald Anlauf  

     PR fortran/114827
diff --git a/gcc/testsuite/g++.dg/parse/error66.C 
b/gcc/testsuite/g++.dg/parse/error66.C

new file mode 100644
index 000..82f4b8b8a53
--- /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;





Re: [PATCH] contrib/gcc-changelog/git_check_commit.py: Implement --num-commits

2024-05-06 Thread Jason Merrill

On 5/6/24 09:25, Ken Matsui wrote:

On Thu, Mar 14, 2024 at 12:57 AM Ken Matsui  wrote:


On Fri, Mar 8, 2024 at 8:42 AM Patrick Palka  wrote:


On Wed, 28 Feb 2024, Ken Matsui wrote:


This patch implements a --num-commits (-n) flag for shorthand for
the range of hash~N..hash commits.


Ping.


Ping.  Ok for trunk?


OK.



contrib/ChangeLog:

   * gcc-changelog/git_check_commit.py: Implement --num-commits.


LGTM



Signed-off-by: Ken Matsui 
---
  contrib/gcc-changelog/git_check_commit.py | 15 +++
  1 file changed, 15 insertions(+)

diff --git a/contrib/gcc-changelog/git_check_commit.py 
b/contrib/gcc-changelog/git_check_commit.py
index 8cca9f439a5..22e032e8b38 100755
--- a/contrib/gcc-changelog/git_check_commit.py
+++ b/contrib/gcc-changelog/git_check_commit.py
@@ -22,6 +22,12 @@ import argparse

  from git_repository import parse_git_revisions

+def nonzero_uint(value):
+ivalue = int(value)
+if ivalue <= 0:
+raise argparse.ArgumentTypeError('%s is not a non-zero positive 
integer' % value)
+return ivalue
+
  parser = argparse.ArgumentParser(description='Check git ChangeLog format '
   'of a commit')
  parser.add_argument('revisions', default='HEAD', nargs='?',
@@ -33,8 +39,17 @@ parser.add_argument('-p', '--print-changelog', 
action='store_true',
  help='Print final changelog entires')
  parser.add_argument('-v', '--verbose', action='store_true',
  help='Print verbose information')
+parser.add_argument('-n', '--num-commits', type=nonzero_uint, default=1,
+help='Number of commits to check (i.e. shorthand for '
+'hash~N..hash)')
  args = parser.parse_args()

+if args.num_commits > 1:
+if '..' in args.revisions:
+print('ERR: --num-commits and range of revisions are mutually 
exclusive')
+exit(1)
+args.revisions = '{0}~{1}..{0}'.format(args.revisions, args.num_commits)
+
  retval = 0
  for git_commit in parse_git_revisions(args.git_path, args.revisions):
  res = 'OK' if git_commit.success else 'FAILED'
--
2.44.0










[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_disa

[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_n

[pushed] c++: initializer_list and EH [PR114935]

2024-05-03 Thread Jason Merrill
Tested x86_64-pc-linux-gnu, applying to trunk and 14.

-- 8< --

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.
---
 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(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-eh1.C

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) == TREE_LIST)
+{
+  /* To disable a build_vec_init cleanup, set
+iterator = maxindex.  */
+  d = TREE_PURPOSE (f);
+  i = TREE_VALUE (f);
+  ggc_free (f);
+}
+  return build2 (MODIFY_EXPR, TREE_TYPE (d), d, i);
+}
+
 

Re: [PATCH v20 23/26] c++: Implement __is_invocable built-in trait

2024-05-03 Thread Jason Merrill

On 5/2/24 23:25, Ken Matsui wrote:

Addressed Jason's review comments.  Ok for trunk?

-- >8 --

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc |   6 +
  gcc/cp/cp-trait.def  |   1 +
  gcc/cp/cp-tree.h |   2 +
  gcc/cp/method.cc | 138 +
  gcc/cp/semantics.cc  |   5 +
  gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
  gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
  gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 +
  gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 
  gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
  10 files changed, 727 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable1.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable2.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable3.C
  create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable4.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428e..6d14ef7dcc7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_FUNCTION:
inform (loc, "  %qT is not a function", t1);
break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
  case CPTK_IS_LAYOUT_COMPATIBLE:
inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d..4e420d5390a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
  DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1938ada0268..83dc20e1130 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7338,6 +7338,8 @@ extern tree get_copy_assign   (tree);
  extern tree get_default_ctor  (tree);
  extern tree get_dtor  (tree, tsubst_flags_t);
  extern tree build_stub_object (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
  extern tree strip_inheriting_ctors(tree);
  extern tree inherited_ctor_binfo  (tree);
  extern bool base_ctor_omit_inherited_parms(tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb01..6bd590707b0 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,144 @@ build_trait_object (tree type)
return build_stub_object (type);
  }
  
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the

+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree deref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (deref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (deref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = deref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (fn_type);
+}
+
+  if (is_ptrdatamem && 

  1   2   3   4   5   6   7   8   9   10   >