GCC support for extensions from later standards
Hi everyone! I'm working on libc++ and we are currently discussing using language extensions from later standards (https://discourse.llvm.org/t/rfc-use-language-extensions-from-future-standards-in-libc/71898/4). By that I mean things like using `if constexpr` with `-std=c++11`. GCC has quite a lot of these kinds of conforming extensions, but doesn't document them AFAICT. While discussing using these extensions, the question came up what GCCs support policy for these is. Aaron was kind enough to answer these questions for us on the Clang side. Since I couldn't find anything in the documentation, I thought I'd ask here. So, here are my questions: Do you expect that these extensions will ever be removed for some reason? If yes, what could those reasons be? Would you be interested in documenting them? Aaron noted that we should ask the Clang folks before using them, so they can evaluated whether the extension makes sense, since they might not be aware of them, and some might be broken. So I'd be interested whether you would also like us to ask whether you want to actually support these extensions. Thanks, Nikolas
Re: GCC support for extensions from later standards
On 06.08.23 12:19, Jason Merrill wrote: On Wed, Aug 2, 2023 at 12:02 PM Nikolas Klauser wrote: Hi everyone! I'm working on libc++ and we are currently discussing using language extensions from later standards (https://discourse.llvm.org/t/rfc-use-language-extensions-from-future-standards-in-libc/71898/4). By that I mean things like using `if constexpr` with `-std=c++11`. GCC has quite a lot of these kinds of conforming extensions, but doesn't document them AFAICT. While discussing using these extensions, the question came up what GCCs support policy for these is. Aaron was kind enough to answer these questions for us on the Clang side. Since I couldn't find anything in the documentation, I thought I'd ask here. So, here are my questions: Do you expect that these extensions will ever be removed for some reason? If yes, what could those reasons be? Potentially, if they don't actually work properly in earlier standard modes. I recently noticed that while we allow DMI and =default in C++03 mode with a pedwarn, combining them doesn't work. Some of the extensions are needed by libstdc++ and are therefore well tested; these are extremely unlikely to ever be removed. libstdc++ folks, is there a list of these? Would you be interested in documenting them? That would be useful, yes. There is a patch in review to add __has_feature/__has_extension to G++, which would seem like a suitable context for this documentation. Aaron noted that we should ask the Clang folks before using them, so they can evaluated whether the extension makes sense, since they might not be aware of them, and some might be broken. So I'd be interested whether you would also like us to ask whether you want to actually support these extensions. Sounds good. Jason Thanks for the answers! There are a few really interesting extensions that I would like to use: - inline variables - variable templates - `if constexpr` - fold expressions - conditional explicit - static operator() (https://godbolt.org/z/5n9Y4h69n) Is anybody aware of any problems with these extensions? I'd be happy to provide a patch to add these extensions to the documentation, but I couldn't figure out how to build the documentation without building all of gcc. Nikolas
Re: GCC support for extensions from later standards
Luckily most of these aren’t problems for libc++. We only support the latest GCC. We can only use `if constexpr` in C++11, but that is already a win I think. Nikolas > On Aug 8, 2023, at 12:33 AM, Jakub Jelinek wrote: > > On Mon, Aug 07, 2023 at 08:03:05PM -0700, Nikolas Klauser wrote: >> Thanks for the answers! >> >> There are a few really interesting extensions that I would like to use: >> >> - inline variables >> - variable templates >> - `if constexpr` >> - fold expressions >> - conditional explicit >> - static operator() > > There are multiple problems. > > cat /tmp/test.h > #pragma GCC system_header > inline int a = 1; > template int b = N; > void foo () { if constexpr (true) {} } > template bool bar (A... a) { return (... + a); } > struct S { template explicit (N == 42) S (int (&)[N]) {} }; > struct T { static constexpr bool operator () (S const &x, S const &y) { > return false; }; }; > void baz () { auto a = [](int x, int y) static { return x + y; }; } > cat /tmp/test.C > #include "/tmp/test.h" > g++ -S -std=c++11 -o /tmp/test.{s,C} > > The above with GCC 13 doesn't give any warnings, but does with > -Wsystem-headers: > In file included from /tmp/test.C:1: > /tmp/test.h:2:1: warning: inline variables are only available with > ‘-std=c++17’ or ‘-std=gnu++17’ [-Wc++17-extensions] >2 | inline int a = 1; > | ^~ > /tmp/test.h:3:22: warning: variable templates only available with > ‘-std=c++14’ or ‘-std=gnu++14’ [-Wc++14-extensions] >3 | template int b = N; > | ^ > /tmp/test.h: In function ‘void foo()’: > /tmp/test.h:4:18: warning: ‘if constexpr’ only available with ‘-std=c++17’ or > ‘-std=gnu++17’ [-Wc++17-extensions] >4 | void foo () { if constexpr (true) {} } > | ^ > /tmp/test.h: In function ‘bool bar(A ...)’: > /tmp/test.h:5:59: warning: fold-expressions only available with ‘-std=c++17’ > or ‘-std=gnu++17’ [-Wc++17-extensions] >5 | template bool bar (A... a) { return (... + a); } > | ^ > /tmp/test.h: At global scope: > /tmp/test.h:6:29: warning: ‘explicit(bool)’ only available with ‘-std=c++20’ > or ‘-std=gnu++20’ [-Wc++20-extensions] >6 | struct S { template explicit (N == 42) S (int (&)[N]) {} }; > | ^~~~ > /tmp/test.h:7:34: warning: ‘static constexpr bool T::operator()(const S&, > const S&)’ may be a static member function only with ‘-std=c++23’ or > ‘-std=gnu++23’ [-Wc++23-extensions] >7 | struct T { static constexpr bool operator () (S const &x, S const &y) > { return false; }; }; > | ^~~~ > /tmp/test.h: In function ‘void baz()’: > /tmp/test.h:8:41: warning: ‘static’ only valid in lambda with ‘-std=c++23’ or > ‘-std=gnu++23’ [-Wc++23-extensions] >8 | void baz () { auto a = [](int x, int y) static { return x + y; }; } > | ^~ > and with -pedantic-errors -Wsystem-headers even errors: > ./xg++ -B ./ -S /tmp/test.C -std=c++11 -pedantic-errors -Wsystem-headers > In file included from /tmp/test.C:1: > /tmp/test.h:2:1: error: inline variables are only available with ‘-std=c++17’ > or ‘-std=gnu++17’ [-Wc++17-extensions] >2 | inline int a = 1; > | ^~ > /tmp/test.h:3:22: error: variable templates only available with ‘-std=c++14’ > or ‘-std=gnu++14’ [-Wc++14-extensions] >3 | template int b = N; > | ^ > /tmp/test.h: In function ‘void foo()’: > /tmp/test.h:4:18: error: ‘if constexpr’ only available with ‘-std=c++17’ or > ‘-std=gnu++17’ [-Wc++17-extensions] >4 | void foo () { if constexpr (true) {} } > | ^ > /tmp/test.h: In function ‘bool bar(A ...)’: > /tmp/test.h:5:59: error: fold-expressions only available with ‘-std=c++17’ or > ‘-std=gnu++17’ [-Wc++17-extensions] >5 | template bool bar (A... a) { return (... + a); } > | ^ > /tmp/test.h: At global scope: > /tmp/test.h:6:29: error: ‘explicit(bool)’ only available with ‘-std=c++20’ or > ‘-std=gnu++20’ [-Wc++20-extensions] >6 | struct S { template explicit (N == 42) S (int (&)[N]) {} }; > | ^~~~ > /tmp/test.h:7:34: error: ‘static constexpr bool T::operator()(const S&, const > S&)’ may be a static member function only with ‘-std=c++23’ or ‘-std=gnu++23’ > [-Wc++23-extensions] >7 | struct T { static constexpr bool operator () (S const &x, S const &y) > { return false; }; }; &g
Re: GCC support for extensions from later standards
Yes, Clang allows it. Most importantly though: you don’t have to be in a constexpr function for `if constexpr` to be useful. e.g. the Algorithms aren’t constexpr until C++20, but a lot of them have overloads for improving the algorithm based on the iterator category. Having `if constexpr` there instead of enable_ifs seems like quite a nice improvement to me. The main problem is probably that libc++ back-ports a lot of the C++11 stuff to C++03, so in these cases `if constexpr` won’t help. > On Aug 8, 2023, at 9:10 AM, Jonathan Wakely wrote: > > On Tue, 8 Aug 2023 at 17:07, Jonathan Wakely wrote: >> >> On Tue, 8 Aug 2023 at 17:04, Nikolas Klauser wrote: >>> >>> Luckily most of these aren’t problems for libc++. We only support the >>> latest GCC. We can only use `if constexpr` in C++11, but that is already a >>> win I think. >> >> Can you use it in C++11 though? The body of a constexpr function must >> be a single return statement, so if-constexpr isn't allowed. > > Clang allows it with multiple warnings: > > ifc.cc:3:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] > if constexpr (sizeof(i) >= 4) >^ > ifc.cc:3:3: warning: use of this statement in a constexpr function is > a C++14 extension [-Wc++14-extensions] > if constexpr (sizeof(i) >= 4) > ^ > ifc.cc:8:5: warning: multiple return statements in constexpr function > is a C++14 extension [-Wc++14-extensions] > return 0; > ^ > ifc.cc:5:5: note: previous return statement is here > return i << 3; > ^ > > But GCC gives a warning for if-constexpr and then an error for the > invalid function body: > > ifc.cc: In function 'constexpr int f(int)': > ifc.cc:3:6: warning: 'if constexpr' only available with '-std=c++17' > or '-std=gnu++17' [-Wc++17-extensions] > 3 | if constexpr (sizeof(i) >= 4) > | ^ > ifc.cc:9:1: error: body of 'constexpr' function 'constexpr int f(int)' > not a return-statement > 9 | } > | ^