Repository: conan-io/conan

Issue:
Add C++2a standard
GCC 8 was released a few days ago and added some useful C++2a features such as `std::endian`. I really want to migrate all my Conan packages to `-std=c++2a`.

I think `2a` and `gnu2a` should be added to `cppstd` and then be renamed to `20` and `gnu20` after the publication. This would require support for aliases so packages' hashes won't be changed but we still have several years to develop this feature.



Discussion:
We will try to add it in 1.4, but it is already packed so not sure if we are able to do it.
Thanks for the report!
As reported by @leugenea in #2872: GCC 8.1 should be added to *settings.yml*
Hi @lyberta, we have been discussing how to name the `cppstd` and  we should call it "gnu20" and "20". Because if you specify `gcc=8` and `cppstd=gnu20` it already means: The partial support of the gnu20 that gcc8 has. If you change your compiler to gcc 9 in the future,  some features of the language will change and won't be compatible, for sure, but it is already modeled specifying the compiler version.
For me is the same that happened/happens when there was/are not implemented c++17 features in the compilers.
WDYT?

Resolving patch:
diff --git a/conans/client/build/cppstd_flags.py b/conans/client/build/cppstd_flags.py
--- a/conans/client/build/cppstd_flags.py
+++ b/conans/client/build/cppstd_flags.py
@@ -32,11 +32,12 @@ def cppstd_default(compiler, compiler_version):
 
 
 def _clang_cppstd_default(compiler_version):
-    return "gnu98" if Version(compiler_version) < "6.0" else "gnu14"
+    # Official docs are wrong, in 6.0 the default is gnu14 to follow gcc's choice
+    return "gnu98" if Version(compiler_version) < "6" else "gnu14"
 
 
 def _gcc_cppstd_default(compiler_version):
-    return "gnu98" if Version(compiler_version) < "6.1" else "gnu14"
+    return "gnu98" if Version(compiler_version) < "6" else "gnu14"
 
 
 def _visual_cppstd_default(compiler_version):
@@ -46,17 +47,19 @@ def _visual_cppstd_default(compiler_version):
 
 
 def _cppstd_visualstudio(visual_version, cppstd):
-
+    # https://docs.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version
     v14 = None
     v17 = None
+    v20 = None
 
     if Version(visual_version) >= "14":
         v14 = "c++14"
         v17 = "c++latest"
     if Version(visual_version) >= "15":
         v17 = "c++17"
+        v20 = "c++latest"
 
-    flag = {"14": v14, "17": v17}.get(str(cppstd), None)
+    flag = {"14": v14, "17": v17, "20": v20}.get(str(cppstd), None)
     return "/std:%s" % flag if flag else None
 
 
@@ -66,7 +69,7 @@ def _cppstd_apple_clang(clang_version, cppstd):
     https://github.com/Kitware/CMake/blob/master/Modules/Compiler/AppleClang-CXX.cmake
     """
 
-    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = None
+    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = None
 
     if Version(clang_version) >= "4.0":
         v98 = "c++98"
@@ -93,7 +96,8 @@ def _cppstd_apple_clang(clang_version, cppstd):
     flag = {"98": v98, "gnu98": vgnu98,
             "11": v11, "gnu11": vgnu11,
             "14": v14, "gnu14": vgnu14,
-            "17": v17, "gnu17": vgnu17}.get(cppstd, None)
+            "17": v17, "gnu17": vgnu17,
+            "20": v20, "gnu20": vgnu20}.get(cppstd, None)
 
     return "-std=%s" % flag if flag else None
 
@@ -103,8 +107,10 @@ def _cppstd_clang(clang_version, cppstd):
     Inspired in:
     https://github.com/Kitware/CMake/blob/
     1fe2dc5ef2a1f262b125a2ba6a85f624ce150dd2/Modules/Compiler/Clang-CXX.cmake
+
+    https://clang.llvm.org/cxx_status.html
     """
-    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = None
+    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = None
 
     if Version(clang_version) >= "2.1":
         v98 = "c++98"
@@ -131,17 +137,22 @@ def _cppstd_clang(clang_version, cppstd):
         v17 = "c++1z"
         vgnu17 = "gnu++1z"
 
+    if Version(clang_version) >= "6":
+        v20 = "c++2a"
+        vgnu20 = "gnu++2a"
+
     flag = {"98": v98, "gnu98": vgnu98,
             "11": v11, "gnu11": vgnu11,
             "14": v14, "gnu14": vgnu14,
-            "17": v17, "gnu17": vgnu17}.get(cppstd, None)
+            "17": v17, "gnu17": vgnu17,
+            "20": v20, "gnu20": vgnu20}.get(cppstd, None)
     return "-std=%s" % flag if flag else None
 
 
 def _cppstd_gcc(gcc_version, cppstd):
     """https://github.com/Kitware/CMake/blob/master/Modules/Compiler/GNU-CXX.cmake"""
-    # https://gcc.gnu.org/projects/cxx-status.html#cxx98
-    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = None
+    # https://gcc.gnu.org/projects/cxx-status.html
+    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = None
 
     if Version(gcc_version) >= "3.4":
         v98 = "c++98"
@@ -165,8 +176,17 @@ def _cppstd_gcc(gcc_version, cppstd):
         v17 = "c++1z"
         vgnu17 = "gnu++1z"
 
+    if Version(gcc_version) >= "5.2":  # Not sure if even in 5.1 gnu17 is valid, but gnu1z is
+        v17 = "c++17"
+        vgnu17 = "gnu++17"
+
+    if Version(gcc_version) >= "8":
+        v20 = "c++2a"
+        vgnu20 = "gnu++2a"
+
     flag = {"98": v98, "gnu98": vgnu98,
             "11": v11, "gnu11": vgnu11,
             "14": v14, "gnu14": vgnu14,
-            "17": v17, "gnu17": vgnu17}.get(cppstd)
+            "17": v17, "gnu17": vgnu17,
+            "20": v20, "gnu20": vgnu20}.get(cppstd)
     return "-std=%s" % flag if flag else None
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -53,7 +53,8 @@
         version: ["4.1", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9",
                   "5", "5.1", "5.2", "5.3", "5.4", "5.5",
                   "6", "6.1", "6.2", "6.3", "6.4",
-                  "7", "7.1", "7.2", "7.3"]
+                  "7", "7.1", "7.2", "7.3",
+                  "8", "8.1"]
         libcxx: [libstdc++, libstdc++11]
         threads: [None, posix, win32] #  Windows MinGW
         exception: [None, dwarf2, sjlj, seh] # Windows MinGW
@@ -62,7 +63,7 @@
         version: ["8", "9", "10", "11", "12", "14", "15"]
         toolset: [None, v90, v100, v110, v110_xp, v120, v120_xp, v140, v140_xp, v140_clang_c2, LLVM-vs2014, LLVM-vs2014_xp, v141, v141_xp, v141_clang_c2]
     clang:
-        version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "5.0", "6.0"]
+        version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "5.0", "6.0", "7.0"]
         libcxx: [libstdc++, libstdc++11, libc++]
     apple-clang:
         version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0", "9.1"]
diff --git a/conans/client/migrations.py b/conans/client/migrations.py
--- a/conans/client/migrations.py
+++ b/conans/client/migrations.py
@@ -41,17 +41,15 @@ def _make_migrations(self, old_version):
         # VERSION 0.1
         if old_version is None:
             return
-        if old_version < Version("1.2.1"):
+        if old_version < Version("1.4.0"):
             old_settings = """
 # Only for cross building, 'os_build/arch_build' is the system that runs Conan
 os_build: [Windows, WindowsStore, Linux, Macos, FreeBSD, SunOS]
 arch_build: [x86, x86_64, ppc64le, ppc64, armv6, armv7, armv7hf, armv8, sparc, sparcv9, mips, mips64, avr, armv7s, armv7k]
-
 # Only for building cross compilation tools, 'os_target/arch_target' is the system for
 # which the tools generate code
 os_target: [Windows, Linux, Macos, Android, iOS, watchOS, tvOS, FreeBSD, SunOS, Arduino]
 arch_target: [x86, x86_64, ppc64le, ppc64, armv6, armv7, armv7hf, armv8, sparc, sparcv9, mips, mips64, avr, armv7s, armv7k]
-
 # Rest of the settings are "host" settings:
 # - For native building/cross building: Where the library/program will run.
 # - For building cross compilation tools: Where the cross compiler will run.
@@ -96,11 +94,10 @@ def _make_migrations(self, old_version):
         version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "5.0", "6.0"]
         libcxx: [libstdc++, libstdc++11, libc++]
     apple-clang:
-        version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0"]
+        version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0", "9.1"]
         libcxx: [libstdc++, libc++]
-
-build_type: [None, Debug, Release]
-cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17]
+build_type: [None, Debug, Release, RelWithDebInfo, MinSizeRel]
+cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20]
 """
             self._update_settings_yml(old_settings)
 


Test patch:
diff --git a/conans/test/build_helpers/autotools_configure_test.py b/conans/test/build_helpers/autotools_configure_test.py
--- a/conans/test/build_helpers/autotools_configure_test.py
+++ b/conans/test/build_helpers/autotools_configure_test.py
@@ -57,7 +57,7 @@ def test_cppstd(self):
         conanfile = MockConanfile(settings, options)
         be = AutoToolsBuildEnvironment(conanfile)
         expected = be.vars["CXXFLAGS"]
-        self.assertIn("-std=c++1z", expected)
+        self.assertIn("-std=c++17", expected)
 
         # Invalid one for GCC
         settings = MockSettings({"build_type": "Release",
diff --git a/conans/test/build_helpers/cpp_std_flags_test.py b/conans/test/build_helpers/cpp_std_flags_test.py
--- a/conans/test/build_helpers/cpp_std_flags_test.py
+++ b/conans/test/build_helpers/cpp_std_flags_test.py
@@ -41,14 +41,20 @@ def test_gcc_cppstd_flags(self):
 
         self.assertEquals(cppstd_flag("gcc", "7", "11"), '-std=c++11')
         self.assertEquals(cppstd_flag("gcc", "7", "14"), '-std=c++14')
-        self.assertEquals(cppstd_flag("gcc", "7", "17"), '-std=c++1z')
+        self.assertEquals(cppstd_flag("gcc", "7", "17"), '-std=c++17')
+
+        self.assertEquals(cppstd_flag("gcc", "8", "11"), '-std=c++11')
+        self.assertEquals(cppstd_flag("gcc", "8", "14"), '-std=c++14')
+        self.assertEquals(cppstd_flag("gcc", "8", "17"), '-std=c++17')
+        self.assertEquals(cppstd_flag("gcc", "8", "20"), '-std=c++2a')
 
     def test_gcc_cppstd_defaults(self):
         self.assertEquals(cppstd_default("gcc", "4"), "gnu98")
         self.assertEquals(cppstd_default("gcc", "5"), "gnu98")
-        self.assertEquals(cppstd_default("gcc", "6"), "gnu98")
+        self.assertEquals(cppstd_default("gcc", "6"), "gnu14")
         self.assertEquals(cppstd_default("gcc", "6.1"), "gnu14")
         self.assertEquals(cppstd_default("gcc", "7.3"), "gnu14")
+        self.assertEquals(cppstd_default("gcc", "8.1"), "gnu14")
 
     def test_clang_cppstd_flags(self):
         self.assertEquals(cppstd_flag("clang", "2.0", "98"), None)
@@ -84,9 +90,10 @@ def test_clang_cppstd_flags(self):
         self.assertEquals(cppstd_flag("clang", "5.1", "14"), '-std=c++14')
         self.assertEquals(cppstd_flag("clang", "5.1", "17"), '-std=c++17')
 
-        self.assertEquals(cppstd_flag("clang", "7", "11"), '-std=c++11')
-        self.assertEquals(cppstd_flag("clang", "7", "14"), '-std=c++14')
-        self.assertEquals(cppstd_flag("clang", "7", "17"), '-std=c++17')
+        self.assertEquals(cppstd_flag("clang", "6", "11"), '-std=c++11')
+        self.assertEquals(cppstd_flag("clang", "6", "14"), '-std=c++14')
+        self.assertEquals(cppstd_flag("clang", "6", "17"), '-std=c++17')
+        self.assertEquals(cppstd_flag("clang", "6", "20"), '-std=c++2a')
 
     def test_clang_cppstd_defaults(self):
         self.assertEquals(cppstd_default("clang", "2"), "gnu98")
@@ -97,6 +104,7 @@ def test_clang_cppstd_defaults(self):
         self.assertEquals(cppstd_default("clang", "3.5"), "gnu98")
         self.assertEquals(cppstd_default("clang", "5"), "gnu98")
         self.assertEquals(cppstd_default("clang", "5.1"), "gnu98")
+        self.assertEquals(cppstd_default("clang", "6"), "gnu14")
         self.assertEquals(cppstd_default("clang", "7"), "gnu14")
 
     def test_apple_clang_cppstd_flags(self):
@@ -162,6 +170,7 @@ def test_visual_cppstd_flags(self):
         self.assertEquals(cppstd_flag("Visual Studio", "17", "11"), None)
         self.assertEquals(cppstd_flag("Visual Studio", "17", "14"), '/std:c++14')
         self.assertEquals(cppstd_flag("Visual Studio", "17", "17"), '/std:c++17')
+        self.assertEquals(cppstd_flag("Visual Studio", "17", "20"), '/std:c++latest')
 
     def test_visual_cppstd_defaults(self):
         self.assertEquals(cppstd_default("Visual Studio", "11"), None)
diff --git a/conans/test/generators/compiler_args_test.py b/conans/test/generators/compiler_args_test.py
--- a/conans/test/generators/compiler_args_test.py
+++ b/conans/test/generators/compiler_args_test.py
@@ -46,7 +46,7 @@ def gcc_test(self):
         gcc = GCCGenerator(conan_file)
         self.assertEquals('-Dmydefine1 -Ipath/to/include1 cxx_flag1 c_flag1 -m32 -O3 -s -DNDEBUG '
                           '-Wl,-rpath="path/to/lib1" '
-                          '-Lpath/to/lib1 -lmylib -std=gnu++1z', gcc.content)
+                          '-Lpath/to/lib1 -lmylib -std=gnu++17', gcc.content)
 
         settings.arch = "x86_64"
         settings.build_type = "Debug"
@@ -55,14 +55,14 @@ def gcc_test(self):
         gcc = GCCGenerator(conan_file)
         self.assertEquals('-Dmydefine1 -Ipath/to/include1 cxx_flag1 c_flag1 -m64 -g '
                           '-Wl,-rpath="path/to/lib1" -Lpath/to/lib1 -lmylib '
-                          '-D_GLIBCXX_USE_CXX11_ABI=1 -std=gnu++1z',
+                          '-D_GLIBCXX_USE_CXX11_ABI=1 -std=gnu++17',
                           gcc.content)
 
         settings.compiler.libcxx = "libstdc++"
         gcc = GCCGenerator(conan_file)
         self.assertEquals('-Dmydefine1 -Ipath/to/include1 cxx_flag1 c_flag1 -m64 -g '
                           '-Wl,-rpath="path/to/lib1" -Lpath/to/lib1 -lmylib '
-                          '-D_GLIBCXX_USE_CXX11_ABI=0 -std=gnu++1z',
+                          '-D_GLIBCXX_USE_CXX11_ABI=0 -std=gnu++17',
                           gcc.content)
 
         settings.os = "Windows"