Repository: spack/spack

Issue:
Installation issue: ncurses@:6.0 needs cppflags=-P, c++14, and const-correctness patch
### Steps to reproduce the issue

```console
$ docker run --rm -it spack/ubuntu-jammy:develop install --keep-stage ncurses@5.9
$ docker run --rm -it spack/ubuntu-jammy:develop install --keep-stage ncurses@6.0
```
The errors are different because there are two issues here, and 6.0 is already patched for one of them but 5.9 isn't.

### Error message

<details><summary>Error message `ncurses@5.9`</summary>

<pre>
==> Installing ncurses-5.9-sxaan6j3extdegdd6jrzvvifrwoyhoso [4/4]
==> No binary for ncurses-5.9-sxaan6j3extdegdd6jrzvvifrwoyhoso found: installing from source
==> Fetching https://mirror.spack.io/_source-cache/archive/90/9046298fb440324c9d4135ecea7879ffed8546dd1b58e59430ea07a4633f563b.tar.gz
==> Applied patch /opt/spack/var/spack/repos/builtin/packages/ncurses/sed_pgi.patch
==> ncurses: Executing phase: 'autoreconf'
==> ncurses: Executing phase: 'configure'
==> ncurses: Executing phase: 'build'
==> Error: ProcessError: Command exited with status 2:
    'make' '-j8'

3 errors found in build log:
     958    /opt/spack/lib/spack/env/gcc/gcc -DHAVE_CONFIG_H -I../ncurses -I.././../ncurses  -D_GNU_SOURCE -DNDEBUG -I. -I../include -I.././../ncurses/../include -I/opt/spack/opt/spack/linux-ubuntu22.04-skylake/gcc-11.4.0/ncurses-5.9-s
            xaan6j3extdegdd6jrzvvifrwoyhoso/include/ncurses -O2 --param max-inline-insns-single=1200 -fPIC -c .././../ncurses/base/lib_getch.c -o ../obj_s/lib_getch.o
     959    /opt/spack/lib/spack/env/gcc/gcc -DHAVE_CONFIG_H -I../ncurses -I.././../ncurses  -D_GNU_SOURCE -DNDEBUG -I. -I../include -I.././../ncurses/../include -I/opt/spack/opt/spack/linux-ubuntu22.04-skylake/gcc-11.4.0/ncurses-5.9-s
            xaan6j3extdegdd6jrzvvifrwoyhoso/include/ncurses -O2 --param max-inline-insns-single=1200 -fPIC -c .././../ncurses/base/lib_getstr.c -o ../obj_s/lib_getstr.o
     960    /opt/spack/lib/spack/env/gcc/gcc -DHAVE_CONFIG_H -I../ncurses -I.././../ncurses  -D_GNU_SOURCE -DNDEBUG -I. -I../include -I.././../ncurses/../include -I/opt/spack/opt/spack/linux-ubuntu22.04-skylake/gcc-11.4.0/ncurses-5.9-s
            xaan6j3extdegdd6jrzvvifrwoyhoso/include/ncurses -O2 --param max-inline-insns-single=1200 -fPIC -c .././../ncurses/base/lib_hline.c -o ../obj_s/lib_hline.o
     961    /opt/spack/lib/spack/env/gcc/gcc -DHAVE_CONFIG_H -I../ncurses -I.././../ncurses  -D_GNU_SOURCE -DNDEBUG -I. -I../include -I.././../ncurses/../include -I/opt/spack/opt/spack/linux-ubuntu22.04-skylake/gcc-11.4.0/ncurses-5.9-s
            xaan6j3extdegdd6jrzvvifrwoyhoso/include/ncurses -O2 --param max-inline-insns-single=1200 -fPIC -c .././../ncurses/base/lib_immedok.c -o ../obj_s/lib_immedok.o
     962    In file included from .././../ncurses/curses.priv.h:283,
     963                     from ../ncurses/lib_gen.c:19:
  >> 964    _13820.c:835:15: error: expected ')' before 'int'
     965    ../include/curses.h:1594:56: note: in definition of macro 'mouse_trafo'
     966     1594 | #define mouse_trafo(y,x,to_screen) wmouse_trafo(stdscr,y,x,to_screen)
     967          |                                                        ^
  >> 968    make[1]: *** [Makefile:1971: ../obj_s/lib_gen.o] Error 1
     969    make[1]: *** Waiting for unfinished jobs....
     970    make[1]: Leaving directory '/tmp/root/spack-stage/spack-stage-ncurses-5.9-sxaan6j3extdegdd6jrzvvifrwoyhoso/spack-src/build_ncurses/ncurses'
  >> 971    make: *** [Makefile:110: all] Error 2

See build log for details:
  /tmp/root/spack-stage/spack-stage-ncurses-5.9-sxaan6j3extdegdd6jrzvvifrwoyhoso/spack-build-out.txt

</pre></details>

<details><summary>Error message `ncurses@6.0`</summary>

<pre>
==> Installing ncurses-6.0-c7wyxoymnujwhlpietieefycs4zjmqxt [4/4]
==> No binary for ncurses-6.0-c7wyxoymnujwhlpietieefycs4zjmqxt found: installing from source
==> Fetching https://mirror.spack.io/_source-cache/archive/f5/f551c24b30ce8bfb6e96d9f59b42fbea30fa3a6123384172f9e7284bcf647260.tar.gz
==> Applied patch /opt/spack/var/spack/repos/builtin/packages/ncurses/patch_gcc_5.txt
==> Applied patch /opt/spack/var/spack/repos/builtin/packages/ncurses/sed_pgi.patch
==> ncurses: Executing phase: 'autoreconf'
==> ncurses: Executing phase: 'configure'
==> ncurses: Executing phase: 'build'
==> Error: ProcessError: Command exited with status 2:
    'make' '-j8'

31 errors found in build log:
     2173    /opt/spack/lib/spack/env/gcc/g++ -DHAVE_CONFIG_H -I. -I.././../c++ -I../include -I.././../c++/../include  -D_GNU_SOURCE -DNDEBUG -O2  -fPIC -c .././../c++/cursesp.cc -o ../obj_s/cursesp.o
     2174    /opt/spack/lib/spack/env/gcc/g++ -DHAVE_CONFIG_H -I. -I.././../c++ -I../include -I.././../c++/../include  -D_GNU_SOURCE -DNDEBUG -O2  -fPIC -c .././../c++/cursslk.cc -o ../obj_s/cursslk.o
     2175    /opt/spack/lib/spack/env/gcc/g++ -DHAVE_CONFIG_H -I. -I.././../c++ -I../include -I.././../c++/../include  -D_GNU_SOURCE -DNDEBUG -O2  -fPIC -c .././../c++/cursesapp.cc -o ../obj_s/cursesapp.o
     2176    /opt/spack/lib/spack/env/gcc/g++ -DHAVE_CONFIG_H -I. -I.././../c++ -I../include -I.././../c++/../include  -D_GNU_SOURCE -DNDEBUG -O2  -fPIC -c .././../c++/cursesmain.cc -o ../obj_s/cursesmain.o
     2177    In file included from .././../c++/cursesw.h:36,
     2178                     from .././../c++/cursesw.cc:43:
  >> 2179    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2180      375 | #define THROWS(s)               throw(s)
     2181          |                                 ^~~~~
     2182    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2183      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2184          |                                                  ^~~~~~
     2185    In file included from .././../c++/cursesw.h:36,
     2186                     from .././../c++/cursespad.cc:36:
  >> 2187    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2188      375 | #define THROWS(s)               throw(s)
     2189          |                                 ^~~~~
     2190    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2191      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2192          |                                                  ^~~~~~
     2193    In file included from .././../c++/cursesw.h:36,
     2194                     from .././../c++/cursslk.h:39,
     2195                     from .././../c++/cursesapp.h:39,
     2196                     from .././../c++/cursesapp.cc:36:
  >> 2197    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2198      375 | #define THROWS(s)               throw(s)
     2199          |                                 ^~~~~
     2200    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2201      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2202          |                                                  ^~~~~~
     2203    In file included from .././../c++/cursesw.h:36,
     2204                     from .././../c++/cursesp.h:39,
     2205                     from .././../c++/cursesp.cc:35:
  >> 2206    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2207      375 | #define THROWS(s)               throw(s)
     2208          |                                 ^~~~~
     2209    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2210      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2211          |                                                  ^~~~~~
     2212    In file included from .././../c++/cursesw.h:36,
     2213                     from .././../c++/cursslk.h:39,
     2214                     from .././../c++/cursslk.cc:35:
  >> 2215    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2216      375 | #define THROWS(s)               throw(s)
     2217          |                                 ^~~~~
     2218    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2219      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2220          |                                                  ^~~~~~
     2221    In file included from .././../c++/cursesw.h:36,
     2222                     from .././../c++/cursesp.h:39,
     2223                     from .././../c++/cursesm.h:39,
     2224                     from .././../c++/cursesm.cc:35:
  >> 2225    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2226      375 | #define THROWS(s)               throw(s)
     2227          |                                 ^~~~~
     2228    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2229      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2230          |                                                  ^~~~~~
     2231    In file included from .././../c++/cursesw.h:36,
     2232                     from .././../c++/cursesp.h:39,
     2233                     from .././../c++/cursesf.h:39,
     2234                     from .././../c++/cursesf.cc:35:
  >> 2235    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2236      375 | #define THROWS(s)               throw(s)
     2237          |                                 ^~~~~
     2238    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2239      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2240          |                                                  ^~~~~~
  >> 2241    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2242      375 | #define THROWS(s)               throw(s)
     2243          |                                 ^~~~~
     2244    .././../c++/cursslk.h:120:45: note: in expansion of macro 'THROWS'
     2245      120 |   inline void Error (const char* msg) const THROWS(NCursesException) {
     2246          |                                             ^~~~~~
  >> 2247    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2248      376 | #define THROW2(s,t)             throw(s,t)
     2249          |                                 ^~~~~
     2250    .././../c++/cursesp.h:89:32: note: in expansion of macro 'THROW2'
     2251       89 |   void OnError (int err) const THROW2(NCursesException const, NCursesPanelException)
     2252          |                                ^~~~~~
  >> 2253    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2254      375 | #define THROWS(s)               throw(s)
     2255          |                                 ^~~~~
     2256    .././../c++/cursslk.h:120:45: note: in expansion of macro 'THROWS'
     2257      120 |   inline void Error (const char* msg) const THROWS(NCursesException) {
     2258          |                                             ^~~~~~
  >> 2259    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2260      375 | #define THROWS(s)               throw(s)
     2261          |                                 ^~~~~
     2262    .././../c++/cursesw.cc:162:51: note: in expansion of macro 'THROWS'
     2263      162 | NCursesWindow::err_handler(const char *msg) const THROWS(NCursesException)
     2264          |                                                   ^~~~~~
  >> 2265    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2266      376 | #define THROW2(s,t)             throw(s,t)
     2267          |                                 ^~~~~
     2268    .././../c++/cursesp.h:89:32: note: in expansion of macro 'THROW2'
     2269       89 |   void OnError (int err) const THROW2(NCursesException const, NCursesPanelException)
     2270          |                                ^~~~~~
  >> 2271    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2272      376 | #define THROW2(s,t)             throw(s,t)
     2273          |                                 ^~~~~
     2274    .././../c++/cursesp.h:89:32: note: in expansion of macro 'THROW2'
     2275       89 |   void OnError (int err) const THROW2(NCursesException const, NCursesPanelException)
     2276          |                                ^~~~~~
  >> 2277    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2278      376 | #define THROW2(s,t)             throw(s,t)
     2279          |                                 ^~~~~
     2280    .././../c++/cursesm.h:56:39: note: in expansion of macro 'THROW2'
     2281       56 |   inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
     2282          |                                       ^~~~~~
  >> 2283    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2284      376 | #define THROW2(s,t)             throw(s,t)
     2285          |                                 ^~~~~
     2286    .././../c++/cursesf.h:64:38: note: in expansion of macro 'THROW2'
     2287       64 |   inline void OnError(int err) const THROW2(NCursesException const, NCursesFormException) {
     2288          |                                      ^~~~~~
  >> 2289    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2290      376 | #define THROW2(s,t)             throw(s,t)
     2291          |                                 ^~~~~
     2292    .././../c++/cursesf.h:112:39: note: in expansion of macro 'THROW2'
     2293      112 |   inline void OnError (int err) const THROW2(NCursesException const, NCursesFormException) {
     2294          |                                       ^~~~~~
  >> 2295    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2296      376 | #define THROW2(s,t)             throw(s,t)
     2297          |                                 ^~~~~
     2298    .././../c++/cursesm.h:256:39: note: in expansion of macro 'THROW2'
     2299      256 |   inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
     2300          |                                       ^~~~~~
  >> 2301    make[1]: *** [Makefile:397: ../obj_s/cursesp.o] Error 1
     2302    make[1]: *** Waiting for unfinished jobs....
  >> 2303    make[1]: *** [Makefile:392: ../obj_s/cursespad.o] Error 1
  >> 2304    ./etip.h:376:33: error: ISO C++17 does not allow dynamic exception specifications
     2305      376 | #define THROW2(s,t)             throw(s,t)
     2306          |                                 ^~~~~
     2307    .././../c++/cursesf.h:394:39: note: in expansion of macro 'THROW2'
     2308      394 |   inline void OnError (int err) const THROW2(NCursesException const, NCursesFormException) {
     2309          |                                       ^~~~~~
  >> 2310    make[1]: *** [Makefile:407: ../obj_s/cursesapp.o] Error 1
  >> 2311    make[1]: *** [Makefile:402: ../obj_s/cursslk.o] Error 1
  >> 2312    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2313      375 | #define THROWS(s)               throw(s)
     2314          |                                 ^~~~~
     2315    .././../c++/cursslk.h:120:45: note: in expansion of macro 'THROWS'
     2316      120 |   inline void Error (const char* msg) const THROWS(NCursesException) {
     2317          |                                             ^~~~~~
  >> 2318    make[1]: *** [Makefile:387: ../obj_s/cursesw.o] Error 1
  >> 2319    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2320      375 | #define THROWS(s)               throw(s)
     2321          |                                 ^~~~~
     2322    .././../c++/cursslk.h:120:45: note: in expansion of macro 'THROWS'
     2323      120 |   inline void Error (const char* msg) const THROWS(NCursesException) {
     2324          |                                             ^~~~~~
  >> 2325    make[1]: *** [Makefile:382: ../obj_s/cursesm.o] Error 1
  >> 2326    make[1]: *** [Makefile:376: ../obj_s/cursesf.o] Error 1
     2327    In file included from .././../c++/cursesw.h:36,
     2328                     from .././../c++/cursslk.h:39,
     2329                     from .././../c++/cursesapp.h:39,
     2330                     from .././../c++/cursesmain.cc:35:
  >> 2331    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2332      375 | #define THROWS(s)               throw(s)
     2333          |                                 ^~~~~
     2334    .././../c++/cursesw.h:777:50: note: in expansion of macro 'THROWS'
     2335      777 |   virtual void   err_handler(const char *) const THROWS(NCursesException);
     2336          |                                                  ^~~~~~
  >> 2337    ./etip.h:375:33: error: ISO C++17 does not allow dynamic exception specifications
     2338      375 | #define THROWS(s)               throw(s)
     2339          |                                 ^~~~~
     2340    .././../c++/cursslk.h:120:45: note: in expansion of macro 'THROWS'
     2341      120 |   inline void Error (const char* msg) const THROWS(NCursesException) {
     2342          |                                             ^~~~~~
  >> 2343    make[1]: *** [Makefile:413: ../obj_s/cursesmain.o] Error 1
     2344    make[1]: Leaving directory '/tmp/root/spack-stage/spack-stage-ncurses-6.0-c7wyxoymnujwhlpietieefycs4zjmqxt/spack-src/build_ncurses/c++'
  >> 2345    make: *** [Makefile:120: all] Error 2

See build log for details:
  /tmp/root/spack-stage/spack-stage-ncurses-6.0-c7wyxoymnujwhlpietieefycs4zjmqxt/spack-build-out.txt

</pre></details>

### Information on your system

* **Spack:** 0.22.0.dev0 (2b1fe995e74fb029a406c6207116bd7305787363)
* **Python:** 3.10.12
* **Platform:** linux-ubuntu22.04-skylake
* **Concretizer:** clingo


### Additional information

`ncurses@5.9`:
[spack-build-env.txt](https://github.com/spack/spack/files/13854399/spack-build-env.txt)
[spack-build-out.txt](https://github.com/spack/spack/files/13854400/spack-build-out.txt)

`ncurses@6.0`:
[spack-build-env.txt](https://github.com/spack/spack/files/13854402/spack-build-env.txt)
[spack-build-out.txt](https://github.com/spack/spack/files/13854403/spack-build-out.txt)

The issue with `-P` is the same as https://github.com/spack/spack/issues/16506.

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have run `spack maintainers <name-of-the-package>` and **@mentioned** any maintainers
- [X] I have uploaded the build log and environment files
- [X] I have searched the issues of this repo and believe this is not a duplicate


Discussion:

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/ncurses/package.py b/var/spack/repos/builtin/packages/ncurses/package.py
--- a/var/spack/repos/builtin/packages/ncurses/package.py
+++ b/var/spack/repos/builtin/packages/ncurses/package.py
@@ -51,7 +51,9 @@ class Ncurses(AutotoolsPackage, GNUMirrorPackage):
 
     depends_on("pkgconfig", type="build")
 
-    patch("patch_gcc_5.txt", when="@6.0%gcc@5.0:")
+    # avoid disallowed const_cast from T* to void* and use reinterpret_cast
+    # Ref: https://lists.gnu.org/archive/html/bug-ncurses/2014-08/msg00008.html
+    patch("0001-Fix-errors-in-type-conversion.patch", when="@:5")
     patch("sed_pgi.patch", when="@:6.0")
     patch("nvhpc_fix_preprocessor_flag.patch", when="@6.0:6.2%nvhpc")
 
@@ -104,6 +106,16 @@ def flag_handler(self, name, flags):
         elif name == "cxxflags":
             flags.append(self.compiler.cxx_pic_flag)
 
+        # ncurses@:6.0 fails in definition of macro 'mouse_trafo' without -P
+        if self.spec.satisfies("@:6.0 %gcc@5.0:"):
+            if name == "cppflags":
+                flags.append("-P")
+
+        # ncurses@:6.0 uses dynamic exception specifications not allowed in c++17
+        if self.spec.satisfies("@:5"):
+            if name == "cxxflags":
+                flags.append(self.compiler.cxx14_flag)
+
         return (flags, None, None)
 
     def configure(self, spec, prefix):


Test patch: