Repository: mesonbuild/meson

Issue:
Add support for c++2b and gnu++2b cpp_stds
Add support for the work in progress C++23 support in GCC and Clang

Signed-off-by: Joshua Ashton <joshua@froggi.es>


Discussion:
# [Codecov](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#9053](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (305e099) into [master](https://codecov.io/gh/mesonbuild/meson/commit/3340d373fba559dde43fffae9bb21be37bee7ff1?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (3340d37) will **increase** coverage by `3.10%`.
> The diff coverage is `52.38%`.

[![Impacted file tree graph](https://codecov.io/gh/mesonbuild/meson/pull/9053/graphs/tree.svg?width=650&height=150&src=pr&token=BplKwTJqLg&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

```diff
@@            Coverage Diff             @@
##           master    #9053      +/-   ##
==========================================
+ Coverage   66.51%   69.61%   +3.10%     
==========================================
  Files         376      188     -188     
  Lines       84253    42217   -42036     
  Branches    17508     8766    -8742     
==========================================
- Hits        56040    29391   -26649     
+ Misses      23366    10342   -13024     
+ Partials     4847     2484    -2363     
```


| [Impacted Files](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [mesonbuild/ast/interpreter.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9hc3QvaW50ZXJwcmV0ZXIucHk=) | `80.63% <ø> (ø)` | |
| [mesonbuild/backend/xcodebackend.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9iYWNrZW5kL3hjb2RlYmFja2VuZC5weQ==) | `0.00% <0.00%> (ø)` | |
| [mesonbuild/compilers/cpp.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9jb21waWxlcnMvY3BwLnB5) | `48.05% <ø> (ø)` | |
| [mesonbuild/coredata.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9jb3JlZGF0YS5weQ==) | `83.03% <ø> (-0.38%)` | :arrow_down: |
| [mesonbuild/dependencies/pkgconfig.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9kZXBlbmRlbmNpZXMvcGtnY29uZmlnLnB5) | `71.61% <ø> (ø)` | |
| [mesonbuild/modules/\_\_init\_\_.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9tb2R1bGVzL19faW5pdF9fLnB5) | `95.37% <ø> (ø)` | |
| [mesonbuild/templates/objcpptemplates.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC90ZW1wbGF0ZXMvb2JqY3BwdGVtcGxhdGVzLnB5) | `100.00% <ø> (ø)` | |
| [mesonbuild/interpreter/interpreter.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9pbnRlcnByZXRlci9pbnRlcnByZXRlci5weQ==) | `82.33% <80.00%> (-0.05%)` | :arrow_down: |
| [mesonbuild/backend/ninjabackend.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9iYWNrZW5kL25pbmphYmFja2VuZC5weQ==) | `84.64% <100.00%> (+0.01%)` | :arrow_up: |
| [mesonbuild/interpreterbase/interpreterbase.py](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-bWVzb25idWlsZC9pbnRlcnByZXRlcmJhc2UvaW50ZXJwcmV0ZXJiYXNlLnB5) | `72.99% <100.00%> (ø)` | |
| ... and [199 more](https://codecov.io/gh/mesonbuild/meson/pull/9053/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Last update [aa68440...305e099](https://codecov.io/gh/mesonbuild/meson/pull/9053?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).

This generally looks good to me, can you rebase so that CI can rerun and turn green?
Done.
Seems to fail because the CI's packages are too outdated to have those C++stds in the compilers...

Not super sure what to do about that given it shouldn't really matter.
The unittest itself has a set of "c++11 needs at least this version of gcc, c++14 needs this one". It's in unittests/linuxliketest.py, in a method called `_test_stds_impl` you just need to update that for the new standards.
Thanks
#8140
Still lacking a portable, cross platform, way to specify a cpp_std to select c++20 for a project.
Any updates on this?
> Any updates on this?

Bumping this because I currently have to use this PR branch instead of upstream meson, which causes gtk to fail to build because the version is too old 😕 

It would be nice to see meson implementing some kind of compiler check instead of hard coding the c++ standards though.

Resolving patch:
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -154,6 +154,10 @@ def _find_best_cpp_std(self, cpp_std: str) -> str:
             'gnu++17': 'gnu++1z',
             'c++20': 'c++2a',
             'gnu++20': 'gnu++2a',
+            'c++23': 'c++2b',
+            'gnu++23': 'gnu++2b',
+            'c++26': 'c++2c',
+            'gnu++26': 'gnu++2c',
         }
 
         # Currently, remapping is only supported for Clang, Elbrus and GCC
@@ -222,6 +226,10 @@ def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]:
 
 
 class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
+
+    _CPP23_VERSION = '>=12.0.0'
+    _CPP26_VERSION = '>=17.0.0'
+
     def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
                  info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
                  linker: T.Optional['DynamicLinker'] = None,
@@ -248,11 +256,18 @@ def get_options(self) -> 'MutableKeyedOptionDictType':
             ),
             key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
         })
-        opts[key.evolve('std')].choices = [
+        cppstd_choices = [
             'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z',
             'c++2a', 'c++20', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z',
             'gnu++2a', 'gnu++20',
         ]
+        if version_compare(self.version, self._CPP23_VERSION):
+            cppstd_choices.append('c++23')
+            cppstd_choices.append('gnu++23')
+        if version_compare(self.version, self._CPP26_VERSION):
+            cppstd_choices.append('c++26')
+            cppstd_choices.append('gnu++26')
+        opts[key.evolve('std')].choices = cppstd_choices
         if self.info.is_windows() or self.info.is_cygwin():
             opts.update({
                 key.evolve('winlibs'): coredata.UserArrayOption(
@@ -294,7 +309,11 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler):
 
 
 class AppleClangCPPCompiler(ClangCPPCompiler):
-    pass
+
+    _CPP23_VERSION = '>=13.0.0'
+    # TODO: We don't know which XCode version will include LLVM 17 yet, so
+    # use something absurd.
+    _CPP26_VERSION = '>=99.0.0'
 
 
 class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
@@ -414,6 +433,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType':
         if version_compare(self.version, '>=12.2.0'):
             cppstd_choices.append('c++23')
             cppstd_choices.append('gnu++23')
+        if version_compare(self.version, '>=14.0.0'):
+            cppstd_choices.append('c++26')
+            cppstd_choices.append('gnu++26')
         opts[key].choices = cppstd_choices
         if self.info.is_windows() or self.info.is_cygwin():
             opts.update({
diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py
--- a/unittests/linuxliketests.py
+++ b/unittests/linuxliketests.py
@@ -517,6 +517,15 @@ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None:
         has_cpp20 = (compiler.get_id() not in {'clang', 'gcc'} or
                      compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=10.0.0', None) or
                      compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=10.0.0'))
+        has_cpp2b = (compiler.get_id() not in {'clang', 'gcc'} or
+                     compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=12.0.0', None) or
+                     compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=12.2.0'))
+        has_cpp23 = (compiler.get_id() not in {'clang', 'gcc'} or
+                     compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=17.0.0', None) or
+                     compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=12.2.0'))
+        has_cpp26 = (compiler.get_id() not in {'clang', 'gcc'} or
+                     compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=17.0.0', None) or
+                     compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=14.0.0'))
         has_c18 = (compiler.get_id() not in {'clang', 'gcc'} or
                    compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=8.0.0', '>=11.0') or
                    compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0'))
@@ -533,6 +542,12 @@ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None:
                 continue
             elif '++20' in v and not has_cpp20:
                 continue
+            elif '++2b' in v and not has_cpp2b:
+                continue
+            elif '++23' in v and not has_cpp23:
+                continue
+            elif ('++26' in v or '++2c' in v) and not has_cpp26:
+                continue
             # now C
             elif '17' in v and not has_cpp2a_c17:
                 continue


Test patch: